ClangUserExpression.cpp revision 05a5a1bcbed5c0f31fed29153bb2912d71836e91
1//===-- ClangUserExpression.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// C Includes 11#include <stdio.h> 12#if HAVE_SYS_TYPES_H 13# include <sys/types.h> 14#endif 15 16// C++ Includes 17#include <cstdlib> 18#include <string> 19#include <map> 20 21#include "lldb/Core/ConstString.h" 22#include "lldb/Core/Log.h" 23#include "lldb/Core/StreamString.h" 24#include "lldb/Core/ValueObjectConstResult.h" 25#include "lldb/Expression/ASTSplitConsumer.h" 26#include "lldb/Expression/ASTResultSynthesizer.h" 27#include "lldb/Expression/ClangExpressionDeclMap.h" 28#include "lldb/Expression/ClangExpressionParser.h" 29#include "lldb/Expression/ClangFunction.h" 30#include "lldb/Expression/ClangUserExpression.h" 31#include "lldb/Host/Host.h" 32#include "lldb/Symbol/VariableList.h" 33#include "lldb/Target/ExecutionContext.h" 34#include "lldb/Target/Process.h" 35#include "lldb/Target/StackFrame.h" 36#include "lldb/Target/Target.h" 37#include "lldb/Target/ThreadPlan.h" 38#include "lldb/Target/ThreadPlanCallUserExpression.h" 39 40using namespace lldb_private; 41 42ClangUserExpression::ClangUserExpression (const char *expr, 43 const char *expr_prefix) : 44 m_expr_text(expr), 45 m_expr_prefix(expr_prefix ? expr_prefix : ""), 46 m_transformed_text(), 47 m_jit_addr(LLDB_INVALID_ADDRESS), 48 m_cplusplus(false), 49 m_objectivec(false), 50 m_needs_object_ptr(false), 51 m_const_object(false), 52 m_desired_type(NULL, NULL) 53{ 54} 55 56ClangUserExpression::~ClangUserExpression () 57{ 58} 59 60clang::ASTConsumer * 61ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough) 62{ 63 return new ASTResultSynthesizer(passthrough, 64 m_desired_type); 65} 66 67void 68ClangUserExpression::ScanContext(ExecutionContext &exe_ctx) 69{ 70 if (!exe_ctx.frame) 71 return; 72 73 VariableList *vars = exe_ctx.frame->GetVariableList(false); 74 75 if (!vars) 76 return; 77 78 lldb::VariableSP this_var(vars->FindVariable(ConstString("this"))); 79 lldb::VariableSP self_var(vars->FindVariable(ConstString("self"))); 80 81 if (this_var.get()) 82 { 83 Type *this_type = this_var->GetType(); 84 85 lldb::clang_type_t pointer_target_type; 86 87 if (ClangASTContext::IsPointerType(this_type->GetClangType(), 88 &pointer_target_type)) 89 { 90 TypeFromUser target_ast_type(pointer_target_type, this_type->GetClangAST()); 91 92 if (target_ast_type.IsDefined()) 93 m_cplusplus = true; 94 95 if (target_ast_type.IsConst()) 96 m_const_object = true; 97 } 98 } 99 else if (self_var.get()) 100 { 101 m_objectivec = true; 102 } 103} 104 105// This is a really nasty hack, meant to fix Objective-C expressions of the form 106// (int)[myArray count]. Right now, because the type information for count is 107// not available, [myArray count] returns id, which can't be directly cast to 108// int without causing a clang error. 109static void 110ApplyObjcCastHack(std::string &expr) 111{ 112#define OBJC_CAST_HACK_FROM "(int)[" 113#define OBJC_CAST_HACK_TO "(int)(long long)[" 114 115 size_t from_offset; 116 117 while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos) 118 expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO); 119 120#undef OBJC_CAST_HACK_TO 121#undef OBJC_CAST_HACK_FROM 122} 123 124// Another hack, meant to allow use of unichar despite it not being available in 125// the type information. Although we could special-case it in type lookup, 126// hopefully we'll figure out a way to #include the same environment as is 127// present in the original source file rather than try to hack specific type 128// definitions in as needed. 129static void 130ApplyUnicharHack(std::string &expr) 131{ 132#define UNICHAR_HACK_FROM "unichar" 133#define UNICHAR_HACK_TO "unsigned short" 134 135 size_t from_offset; 136 137 while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos) 138 expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO); 139 140#undef UNICHAR_HACK_TO 141#undef UNICHAR_HACK_FROM 142} 143 144bool 145ClangUserExpression::Parse (Stream &error_stream, 146 ExecutionContext &exe_ctx, 147 TypeFromUser desired_type, 148 lldb::ClangExpressionVariableSP *const_result) 149{ 150 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 151 152 ScanContext(exe_ctx); 153 154 StreamString m_transformed_stream; 155 156 //////////////////////////////////// 157 // Generate the expression 158 // 159 160 ApplyObjcCastHack(m_expr_text); 161 //ApplyUnicharHack(m_expr_text); 162 163 if (m_cplusplus) 164 { 165 m_transformed_stream.Printf("%s \n" 166 "typedef unsigned short unichar; \n" 167 "void \n" 168 "$__lldb_class::%s(void *$__lldb_arg) %s\n" 169 "{ \n" 170 " %s; \n" 171 "} \n", 172 m_expr_prefix.c_str(), 173 FunctionName(), 174 (m_const_object ? "const" : ""), 175 m_expr_text.c_str()); 176 177 m_needs_object_ptr = true; 178 } 179 else if(m_objectivec) 180 { 181 const char *function_name = FunctionName(); 182 183 m_transformed_stream.Printf("%s \n" 184 "@interface $__lldb_objc_class ($__lldb_category) \n" 185 "-(void)%s:(void *)$__lldb_arg; \n" 186 "@end \n" 187 "@implementation $__lldb_objc_class ($__lldb_category) \n" 188 "-(void)%s:(void *)$__lldb_arg \n" 189 "{ \n" 190 " %s; \n" 191 "} \n" 192 "@end \n", 193 m_expr_prefix.c_str(), 194 function_name, 195 function_name, 196 m_expr_text.c_str()); 197 198 m_needs_object_ptr = true; 199 } 200 else 201 { 202 m_transformed_stream.Printf("%s \n" 203 "typedef unsigned short unichar;\n" 204 "void \n" 205 "%s(void *$__lldb_arg) \n" 206 "{ \n" 207 " %s; \n" 208 "} \n", 209 m_expr_prefix.c_str(), 210 FunctionName(), 211 m_expr_text.c_str()); 212 } 213 214 m_transformed_text = m_transformed_stream.GetData(); 215 216 217 if (log) 218 log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); 219 220 //////////////////////////////////// 221 // Set up the target and compiler 222 // 223 224 Target *target = exe_ctx.target; 225 226 if (!target) 227 { 228 error_stream.PutCString ("error: invalid target\n"); 229 return false; 230 } 231 232 ConstString target_triple; 233 234 target->GetTargetTriple (target_triple); 235 236 if (!target_triple) 237 target_triple = Host::GetTargetTriple (); 238 239 if (!target_triple) 240 { 241 error_stream.PutCString ("error: invalid target triple\n"); 242 return false; 243 } 244 245 ////////////////////////// 246 // Parse the expression 247 // 248 249 m_desired_type = desired_type; 250 251 m_expr_decl_map.reset(new ClangExpressionDeclMap()); 252 253 m_expr_decl_map->WillParse(exe_ctx); 254 255 ClangExpressionParser parser(target_triple.GetCString(), *this); 256 257 unsigned num_errors = parser.Parse (error_stream); 258 259 if (num_errors) 260 { 261 error_stream.Printf ("error: %d errors parsing expression\n", num_errors); 262 263 m_expr_decl_map->DidParse(); 264 265 return false; 266 } 267 268 /////////////////////////////////////////////// 269 // Convert the output of the parser to DWARF 270 // 271 272 m_dwarf_opcodes.reset(new StreamString); 273 m_dwarf_opcodes->SetByteOrder (lldb::eByteOrderHost); 274 m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary); 275 276 m_local_variables.reset(new ClangExpressionVariableList()); 277 278 Error dwarf_error = parser.MakeDWARF (); 279 280 if (dwarf_error.Success()) 281 { 282 if (log) 283 log->Printf("Code can be interpreted."); 284 285 m_expr_decl_map->DidParse(); 286 287 return true; 288 } 289 290 ////////////////////////////////// 291 // JIT the output of the parser 292 // 293 294 m_dwarf_opcodes.reset(); 295 296 lldb::addr_t jit_end; 297 298 Error jit_error = parser.MakeJIT (m_jit_addr, jit_end, exe_ctx, const_result); 299 300 m_expr_decl_map->DidParse(); 301 302 if (jit_error.Success()) 303 { 304 return true; 305 } 306 else 307 { 308 error_stream.Printf ("error: expression can't be interpreted or run\n", num_errors); 309 return false; 310 } 311} 312 313bool 314ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream, 315 ExecutionContext &exe_ctx, 316 lldb::addr_t &struct_address, 317 lldb::addr_t &object_ptr, 318 lldb::addr_t &cmd_ptr) 319{ 320 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 321 322 if (m_jit_addr != LLDB_INVALID_ADDRESS) 323 { 324 Error materialize_error; 325 326 if (m_needs_object_ptr) 327 { 328 ConstString object_name; 329 330 if (m_cplusplus) 331 { 332 object_name.SetCString("this"); 333 } 334 else if (m_objectivec) 335 { 336 object_name.SetCString("self"); 337 } 338 else 339 { 340 error_stream.Printf("Need object pointer but don't know the language\n"); 341 return false; 342 } 343 344 if (!(m_expr_decl_map->GetObjectPointer(object_ptr, object_name, exe_ctx, materialize_error))) 345 { 346 error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString()); 347 return false; 348 } 349 350 if (m_objectivec) 351 { 352 ConstString cmd_name("_cmd"); 353 354 if (!(m_expr_decl_map->GetObjectPointer(cmd_ptr, cmd_name, exe_ctx, materialize_error, true))) 355 { 356 error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString()); 357 return false; 358 } 359 } 360 } 361 362 if (!m_expr_decl_map->Materialize(exe_ctx, struct_address, materialize_error)) 363 { 364 error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString()); 365 return false; 366 } 367 368 if (log) 369 { 370 log->Printf("-- [ClangUserExpression::PrepareToExecuteJITExpression] Materializing for execution --"); 371 372 log->Printf(" Function address : 0x%llx", (uint64_t)m_jit_addr); 373 374 if (m_needs_object_ptr) 375 log->Printf(" Object pointer : 0x%llx", (uint64_t)object_ptr); 376 377 log->Printf(" Structure address : 0x%llx", (uint64_t)struct_address); 378 379 StreamString args; 380 381 Error dump_error; 382 383 if (struct_address) 384 { 385 if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error)) 386 { 387 log->Printf(" Couldn't extract variable values : %s", dump_error.AsCString("unknown error")); 388 } 389 else 390 { 391 log->Printf(" Structure contents:\n%s", args.GetData()); 392 } 393 } 394 } 395 } 396 return true; 397} 398 399ThreadPlan * 400ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream, 401 ExecutionContext &exe_ctx) 402{ 403 lldb::addr_t struct_address; 404 405 lldb::addr_t object_ptr = NULL; 406 lldb::addr_t cmd_ptr = NULL; 407 408 PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr); 409 410 // FIXME: This should really return a ThreadPlanCallUserExpression, in order to make sure that we don't release the 411 // ClangUserExpression resources before the thread plan finishes execution in the target. But because we are 412 // forcing unwind_on_error to be true here, in practical terms that can't happen. 413 414 return ClangFunction::GetThreadPlanToCallFunction (exe_ctx, 415 m_jit_addr, 416 struct_address, 417 error_stream, 418 true, 419 true, 420 (m_needs_object_ptr ? &object_ptr : NULL), 421 (m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL); 422} 423 424bool 425ClangUserExpression::FinalizeJITExecution (Stream &error_stream, 426 ExecutionContext &exe_ctx, 427 lldb::ClangExpressionVariableSP &result) 428{ 429 Error expr_error; 430 431 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 432 433 if (log) 434 { 435 log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --"); 436 437 StreamString args; 438 439 Error dump_error; 440 441 if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error)) 442 { 443 log->Printf(" Couldn't extract variable values : %s", dump_error.AsCString("unknown error")); 444 } 445 else 446 { 447 log->Printf(" Structure contents:\n%s", args.GetData()); 448 } 449 } 450 451 if (!m_expr_decl_map->Dematerialize(exe_ctx, result, expr_error)) 452 { 453 error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error")); 454 return false; 455 } 456 return true; 457} 458 459lldb::ExecutionResults 460ClangUserExpression::Execute (Stream &error_stream, 461 ExecutionContext &exe_ctx, 462 bool discard_on_error, 463 ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me, 464 lldb::ClangExpressionVariableSP &result) 465{ 466 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 467 468 if (m_dwarf_opcodes.get()) 469 { 470 // TODO execute the JITted opcodes 471 472 error_stream.Printf("We don't currently support executing DWARF expressions"); 473 474 return lldb::eExecutionSetupError; 475 } 476 else if (m_jit_addr != LLDB_INVALID_ADDRESS) 477 { 478 lldb::addr_t struct_address; 479 480 lldb::addr_t object_ptr = NULL; 481 lldb::addr_t cmd_ptr = NULL; 482 483 if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr)) 484 return lldb::eExecutionSetupError; 485 486 const bool stop_others = true; 487 const bool try_all_threads = true; 488 489 Address wrapper_address (NULL, m_jit_addr); 490 lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (*(exe_ctx.thread), 491 wrapper_address, 492 struct_address, 493 stop_others, 494 discard_on_error, 495 (m_needs_object_ptr ? &object_ptr : NULL), 496 ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL), 497 shared_ptr_to_me)); 498 499 if (call_plan_sp == NULL || !call_plan_sp->ValidatePlan (NULL)) 500 return lldb::eExecutionSetupError; 501 502 call_plan_sp->SetPrivate(true); 503 504 uint32_t single_thread_timeout_usec = 10000000; 505 506 if (log) 507 log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --"); 508 509 lldb::ExecutionResults execution_result = exe_ctx.process->RunThreadPlan (exe_ctx, 510 call_plan_sp, 511 stop_others, 512 try_all_threads, 513 discard_on_error, 514 single_thread_timeout_usec, 515 error_stream); 516 517 if (log) 518 log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --"); 519 520 if (execution_result == lldb::eExecutionInterrupted) 521 { 522 if (discard_on_error) 523 error_stream.Printf ("Expression execution was interrupted. The process has been returned to the state before execution."); 524 else 525 error_stream.Printf ("Expression execution was interrupted. The process has been left at the point where it was interrupted."); 526 527 return execution_result; 528 } 529 else if (execution_result != lldb::eExecutionCompleted) 530 { 531 error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result)); 532 return execution_result; 533 } 534 535 if (FinalizeJITExecution (error_stream, exe_ctx, result)) 536 return lldb::eExecutionCompleted; 537 else 538 return lldb::eExecutionSetupError; 539 } 540 else 541 { 542 error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function is present"); 543 return lldb::eExecutionSetupError; 544 } 545} 546 547StreamString & 548ClangUserExpression::DwarfOpcodeStream () 549{ 550 if (!m_dwarf_opcodes.get()) 551 m_dwarf_opcodes.reset(new StreamString()); 552 553 return *m_dwarf_opcodes.get(); 554} 555 556lldb::ExecutionResults 557ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, 558 bool discard_on_error, 559 const char *expr_cstr, 560 const char *expr_prefix, 561 lldb::ValueObjectSP &result_valobj_sp) 562{ 563 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 564 565 Error error; 566 lldb::ExecutionResults execution_results = lldb::eExecutionSetupError; 567 568 if (exe_ctx.process == NULL) 569 { 570 error.SetErrorString ("Must have a process to evaluate expressions."); 571 572 result_valobj_sp.reset (new ValueObjectConstResult (error)); 573 return lldb::eExecutionSetupError; 574 } 575 576 if (!exe_ctx.process->GetDynamicCheckers()) 577 { 578 if (log) 579 log->Printf("== [ClangUserExpression::Evaluate] Installing dynamic checkers =="); 580 581 DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); 582 583 StreamString install_errors; 584 585 if (!dynamic_checkers->Install(install_errors, exe_ctx)) 586 { 587 if (install_errors.GetString().empty()) 588 error.SetErrorString ("couldn't install checkers, unknown error"); 589 else 590 error.SetErrorString (install_errors.GetString().c_str()); 591 592 result_valobj_sp.reset (new ValueObjectConstResult (error)); 593 return lldb::eExecutionSetupError; 594 } 595 596 exe_ctx.process->SetDynamicCheckers(dynamic_checkers); 597 598 if (log) 599 log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers =="); 600 } 601 602 ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix)); 603 604 StreamString error_stream; 605 606 lldb::ClangExpressionVariableSP const_result; 607 608 if (log) 609 log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr); 610 611 if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), &const_result)) 612 { 613 if (error_stream.GetString().empty()) 614 error.SetErrorString ("expression failed to parse, unknown error"); 615 else 616 error.SetErrorString (error_stream.GetString().c_str()); 617 } 618 else 619 { 620 lldb::ClangExpressionVariableSP expr_result; 621 622 if (const_result.get()) 623 { 624 if (log) 625 log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant =="); 626 627 result_valobj_sp = const_result->GetValueObject(); 628 } 629 else 630 { 631 error_stream.GetString().clear(); 632 633 if (log) 634 log->Printf("== [ClangUserExpression::Evaluate] Executing expression =="); 635 636 execution_results = user_expression_sp->Execute (error_stream, 637 exe_ctx, 638 discard_on_error, 639 user_expression_sp, 640 expr_result); 641 642 if (execution_results != lldb::eExecutionCompleted) 643 { 644 if (log) 645 log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally =="); 646 647 if (error_stream.GetString().empty()) 648 error.SetErrorString ("expression failed to execute, unknown error"); 649 else 650 error.SetErrorString (error_stream.GetString().c_str()); 651 } 652 else 653 { 654 if (expr_result) 655 { 656 result_valobj_sp = expr_result->GetValueObject(); 657 658 if (log) 659 log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString(exe_ctx.GetBestExecutionContextScope())); 660 } 661 else 662 { 663 if (log) 664 log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result =="); 665 666 error.SetErrorString ("Expression did not return a result"); 667 } 668 } 669 } 670 } 671 672 if (result_valobj_sp.get() == NULL) 673 result_valobj_sp.reset (new ValueObjectConstResult (error)); 674 675 return execution_results; 676} 677