ClangExpressionDeclMap.cpp revision 336a0002b94c7f23573ec613c4d4ac89a67fd299
1//===-- ClangExpressionDeclMap.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/ClangExpressionDeclMap.h" 11 12// C Includes 13// C++ Includes 14// Other libraries and framework includes 15// Project includes 16#include "lldb/lldb-private.h" 17#include "lldb/Core/Address.h" 18#include "lldb/Core/Error.h" 19#include "lldb/Core/Log.h" 20#include "lldb/Core/Module.h" 21#include "lldb/Expression/ClangASTSource.h" 22#include "lldb/Symbol/ClangASTContext.h" 23#include "lldb/Symbol/CompileUnit.h" 24#include "lldb/Symbol/Function.h" 25#include "lldb/Symbol/ObjectFile.h" 26#include "lldb/Symbol/SymbolContext.h" 27#include "lldb/Symbol/Type.h" 28#include "lldb/Symbol/TypeList.h" 29#include "lldb/Symbol/Variable.h" 30#include "lldb/Symbol/VariableList.h" 31#include "lldb/Target/Process.h" 32#include "lldb/Target/StackFrame.h" 33#include "lldb/Target/ExecutionContext.h" 34 35using namespace lldb_private; 36using namespace clang; 37 38ClangExpressionDeclMap::ClangExpressionDeclMap(ExecutionContext *exe_ctx) : 39 m_exe_ctx(exe_ctx), 40 m_struct_laid_out(false), 41 m_materialized_location(0) 42{ 43 if (exe_ctx && exe_ctx->frame) 44 m_sym_ctx = new SymbolContext(exe_ctx->frame->GetSymbolContext(lldb::eSymbolContextEverything)); 45 else 46 m_sym_ctx = NULL; 47} 48 49ClangExpressionDeclMap::~ClangExpressionDeclMap() 50{ 51 uint32_t num_tuples = m_tuples.size (); 52 uint32_t tuple_index; 53 54 for (tuple_index = 0; tuple_index < num_tuples; ++tuple_index) 55 delete m_tuples[tuple_index].m_value; 56 57 if (m_sym_ctx) 58 delete m_sym_ctx; 59} 60 61bool 62ClangExpressionDeclMap::GetIndexForDecl (uint32_t &index, 63 const clang::Decl *decl) 64{ 65 uint32_t num_tuples = m_tuples.size (); 66 uint32_t tuple_index; 67 68 for (tuple_index = 0; tuple_index < num_tuples; ++tuple_index) 69 { 70 if (m_tuples[tuple_index].m_decl == decl) 71 { 72 index = tuple_index; 73 return true; 74 } 75 } 76 77 return false; 78} 79 80// Interface for IRForTarget 81 82bool 83ClangExpressionDeclMap::AddValueToStruct (llvm::Value *value, 84 const clang::NamedDecl *decl, 85 std::string &name, 86 void *type, 87 size_t size, 88 off_t alignment) 89{ 90 m_struct_laid_out = false; 91 92 StructMemberIterator iter; 93 94 for (iter = m_members.begin(); 95 iter != m_members.end(); 96 ++iter) 97 { 98 if (iter->m_decl == decl) 99 return true; 100 } 101 102 StructMember member; 103 104 member.m_value = value; 105 member.m_decl = decl; 106 member.m_name = name; 107 member.m_type = type; 108 member.m_offset = 0; 109 member.m_size = size; 110 member.m_alignment = alignment; 111 112 m_members.push_back(member); 113 114 return true; 115} 116 117bool 118ClangExpressionDeclMap::DoStructLayout () 119{ 120 if (m_struct_laid_out) 121 return true; 122 123 StructMemberIterator iter; 124 125 off_t cursor = 0; 126 127 m_struct_alignment = 0; 128 m_struct_size = 0; 129 130 for (iter = m_members.begin(); 131 iter != m_members.end(); 132 ++iter) 133 { 134 if (iter == m_members.begin()) 135 m_struct_alignment = iter->m_alignment; 136 137 if (cursor % iter->m_alignment) 138 cursor += (iter->m_alignment - (cursor % iter->m_alignment)); 139 140 iter->m_offset = cursor; 141 cursor += iter->m_size; 142 } 143 144 m_struct_size = cursor; 145 146 m_struct_laid_out = true; 147 return true; 148} 149 150bool ClangExpressionDeclMap::GetStructInfo (uint32_t &num_elements, 151 size_t &size, 152 off_t &alignment) 153{ 154 if (!m_struct_laid_out) 155 return false; 156 157 num_elements = m_members.size(); 158 size = m_struct_size; 159 alignment = m_struct_alignment; 160 161 return true; 162} 163 164bool 165ClangExpressionDeclMap::GetStructElement (const clang::NamedDecl *&decl, 166 llvm::Value *&value, 167 off_t &offset, 168 uint32_t index) 169{ 170 if (!m_struct_laid_out) 171 return false; 172 173 if (index >= m_members.size()) 174 return false; 175 176 decl = m_members[index].m_decl; 177 value = m_members[index].m_value; 178 offset = m_members[index].m_offset; 179 180 return true; 181} 182 183// Interface for DwarfExpression 184Value 185*ClangExpressionDeclMap::GetValueForIndex (uint32_t index) 186{ 187 if (index >= m_tuples.size ()) 188 return NULL; 189 190 return m_tuples[index].m_value; 191} 192 193// Interface for CommandObjectExpression 194lldb::addr_t 195ClangExpressionDeclMap::Materialize (ExecutionContext *exe_ctx, Error &err) 196{ 197 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); 198 199 if (!m_struct_laid_out) 200 { 201 err.SetErrorString("Structure hasn't been laid out yet"); 202 return LLDB_INVALID_ADDRESS; 203 } 204 205 if (m_materialized_location) 206 { 207 exe_ctx->process->DeallocateMemory(m_materialized_location); 208 m_materialized_location = 0; 209 } 210 211 if (!exe_ctx) 212 { 213 err.SetErrorString("Received null execution context"); 214 return LLDB_INVALID_ADDRESS; 215 } 216 217 const SymbolContext &sym_ctx(exe_ctx->frame->GetSymbolContext(lldb::eSymbolContextEverything)); 218 219 StructMemberIterator iter; 220 221 lldb::addr_t mem = exe_ctx->process->AllocateMemory(m_struct_alignment + m_struct_size, 222 lldb::ePermissionsReadable | lldb::ePermissionsWritable, 223 err); 224 225 if (mem == LLDB_INVALID_ADDRESS) 226 return LLDB_INVALID_ADDRESS; 227 228 m_materialized_location = mem; 229 230 lldb::addr_t aligned_mem = mem; 231 232 if (aligned_mem % m_struct_alignment) 233 { 234 aligned_mem += (m_struct_alignment - (aligned_mem % m_struct_alignment)); 235 } 236 237 for (iter = m_members.begin(); 238 iter != m_members.end(); 239 ++iter) 240 { 241 uint32_t tuple_index; 242 243 if (!GetIndexForDecl(tuple_index, iter->m_decl)) 244 { 245 if (iter->m_name.find("___clang_expr_result") == std::string::npos) 246 { 247 err.SetErrorStringWithFormat("Unexpected variable %s", iter->m_name.c_str()); 248 return false; 249 } 250 251 if (log) 252 log->Printf("Found special result variable %s", iter->m_name.c_str()); 253 254 continue; 255 } 256 257 Tuple &tuple(m_tuples[tuple_index]); 258 259 if (!MaterializeOneVariable(*exe_ctx, sym_ctx, iter->m_name.c_str(), tuple.m_orig_type, tuple.m_ast_context, aligned_mem + iter->m_offset, err)) 260 return false; 261 } 262 263 return aligned_mem; 264} 265 266Variable* 267ClangExpressionDeclMap::FindVariableInScope(const SymbolContext &sym_ctx, 268 const char *name, 269 void *type, 270 clang::ASTContext *ast_context) 271{ 272 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); 273 274 Function *function(m_sym_ctx->function); 275 Block *block(m_sym_ctx->block); 276 277 if (!function || !block) 278 { 279 if (log) 280 log->Printf("function = %p, block = %p", function, block); 281 return NULL; 282 } 283 284 BlockList& blocks(function->GetBlocks(true)); 285 286 ConstString name_cs(name); 287 288 lldb::user_id_t current_block_id; 289 290 for (current_block_id = block->GetID(); 291 current_block_id != Block::InvalidID; 292 current_block_id = blocks.GetParent(current_block_id)) 293 { 294 Block *current_block(blocks.GetBlockByID(current_block_id)); 295 296 lldb::VariableListSP var_list = current_block->GetVariableList(false, true); 297 298 if (!var_list) 299 continue; 300 301 lldb::VariableSP var = var_list->FindVariable(name_cs); 302 303 if (!var) 304 continue; 305 306 // var->GetType()->GetClangAST() is the program's AST context and holds 307 // var->GetType()->GetOpaqueClangQualType(). 308 309 // type is m_type for one of the struct members, which was added by 310 // AddValueToStruct. That type was extracted from the AST context of 311 // the compiler in IRForTarget. The original for the type was copied 312 // out of the program's AST context by AddOneVariable. 313 314 // So that we can compare these two without having to copy back 315 // something we already had in the original AST context, we maintain 316 // m_orig_type and m_ast_context (which are passed into 317 // MaterializeOneVariable by Materialize) for each variable. 318 319 if (!type) 320 return var.get(); 321 322 if (ast_context == var->GetType()->GetClangAST()) 323 { 324 if (!ClangASTContext::AreTypesSame(ast_context, type, var->GetType()->GetOpaqueClangQualType())) 325 continue; 326 } 327 else 328 { 329 if (log) 330 log->PutCString("Skipping a candidate variable because of different AST contexts"); 331 continue; 332 } 333 334 return var.get(); 335 } 336 337 { 338 CompileUnit *compile_unit = m_sym_ctx->comp_unit; 339 340 if (!compile_unit) 341 { 342 if (log) 343 log->Printf("compile_unit = %p", compile_unit); 344 return NULL; 345 } 346 347 lldb::VariableListSP var_list = compile_unit->GetVariableList(true); 348 349 if (!var_list) 350 return NULL; 351 352 lldb::VariableSP var = var_list->FindVariable(name_cs); 353 354 if (!var) 355 return NULL; 356 357 if (!type) 358 return var.get(); 359 360 if (ast_context == var->GetType()->GetClangAST()) 361 { 362 if (!ClangASTContext::AreTypesSame(ast_context, type, var->GetType()->GetOpaqueClangQualType())) 363 return NULL; 364 } 365 else 366 { 367 if (log) 368 log->PutCString("Skipping a candidate variable because of different AST contexts"); 369 return NULL; 370 } 371 372 return var.get(); 373 } 374 375 return NULL; 376} 377 378bool 379ClangExpressionDeclMap::MaterializeOneVariable(ExecutionContext &exe_ctx, 380 const SymbolContext &sym_ctx, 381 const char *name, 382 void *type, 383 clang::ASTContext *ast_context, 384 lldb::addr_t addr, 385 Error &err) 386{ 387 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); 388 389 Variable *var = FindVariableInScope(sym_ctx, name, type, ast_context); 390 391 if (!var) 392 { 393 err.SetErrorStringWithFormat("Couldn't find %s with appropriate type", name); 394 return false; 395 } 396 397 log->Printf("Materializing %s with type %p", name, type); 398 399 std::auto_ptr<Value> location_value(GetVariableValue(exe_ctx, 400 var, 401 ast_context)); 402 403 if (!location_value.get()) 404 { 405 err.SetErrorStringWithFormat("Couldn't get value for %s", name); 406 return false; 407 } 408 409 if (location_value->GetValueType() == Value::eValueTypeLoadAddress) 410 { 411 lldb::addr_t src_addr = location_value->GetScalar().ULongLong(); 412 413 size_t bit_size = ClangASTContext::GetTypeBitSize(ast_context, type); 414 size_t byte_size = bit_size % 8 ? ((bit_size + 8) / 8) : (bit_size / 8); 415 416 DataBufferHeap data; 417 data.SetByteSize(byte_size); 418 419 Error error; 420 if (exe_ctx.process->ReadMemory (src_addr, data.GetBytes(), byte_size, error) != byte_size) 421 { 422 err.SetErrorStringWithFormat ("Couldn't read a composite type from the target: %s", error.AsCString()); 423 return false; 424 } 425 426 if (exe_ctx.process->WriteMemory (addr, data.GetBytes(), byte_size, error) != byte_size) 427 { 428 err.SetErrorStringWithFormat ("Couldn't write a composite type to the target: %s", error.AsCString()); 429 return false; 430 } 431 432 if (log) 433 log->Printf("Copied from 0x%llx to 0x%llx", (uint64_t)src_addr, (uint64_t)addr); 434 } 435 else 436 { 437 StreamString ss; 438 439 location_value->Dump(&ss); 440 441 err.SetErrorStringWithFormat("%s has a value of unhandled type: %s", name, ss.GetString().c_str()); 442 } 443 444 return true; 445} 446 447// Interface for ClangASTSource 448void 449ClangExpressionDeclMap::GetDecls(NameSearchContext &context, 450 const char *name) 451{ 452 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); 453 454 if (log) 455 log->Printf("Hunting for a definition for %s", name); 456 457 // Back out in all cases where we're not fully initialized 458 if (!m_exe_ctx || !m_exe_ctx->frame || !m_sym_ctx) 459 return; 460 461 Function *function = m_sym_ctx->function; 462 463 if (!function) 464 { 465 if (log) 466 log->Printf("Can't evaluate an expression when not in a function"); 467 return; 468 } 469 470 ConstString name_cs(name); 471 472 Function *fn = m_sym_ctx->FindFunctionByName(name_cs.GetCString()); 473 474 if (fn) 475 AddOneFunction(context, fn); 476 477 Variable *var = FindVariableInScope(*m_sym_ctx, name); 478 479 if (var) 480 AddOneVariable(context, var); 481} 482 483Value * 484ClangExpressionDeclMap::GetVariableValue(ExecutionContext &exe_ctx, 485 Variable *var, 486 clang::ASTContext *target_ast_context, 487 void **opaque_type, 488 clang::ASTContext **found_ast_context) 489{ 490 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); 491 492 Type *var_type = var->GetType(); 493 494 if (!var_type) 495 { 496 if (log) 497 log->PutCString("Skipped a definition because it has no type"); 498 return NULL; 499 } 500 501 void *var_opaque_type = var_type->GetOpaqueClangQualType(); 502 503 if (!var_opaque_type) 504 { 505 if (log) 506 log->PutCString("Skipped a definition because it has no Clang type"); 507 return NULL; 508 } 509 510 TypeList *type_list = var_type->GetTypeList(); 511 512 if (!type_list) 513 { 514 if (log) 515 log->PutCString("Skipped a definition because the type has no associated type list"); 516 return NULL; 517 } 518 519 clang::ASTContext *exe_ast_ctx = type_list->GetClangASTContext().getASTContext(); 520 521 if (!exe_ast_ctx) 522 { 523 if (log) 524 log->PutCString("There is no AST context for the current execution context"); 525 return NULL; 526 } 527 528 DWARFExpression &var_location_expr = var->LocationExpression(); 529 530 std::auto_ptr<Value> var_location(new Value); 531 532 Error err; 533 534 if (!var_location_expr.Evaluate(&exe_ctx, exe_ast_ctx, NULL, *var_location.get(), &err)) 535 { 536 if (log) 537 log->Printf("Error evaluating location: %s", err.AsCString()); 538 return NULL; 539 } 540 541 clang::ASTContext *var_ast_context = type_list->GetClangASTContext().getASTContext(); 542 543 void *type_to_use; 544 545 if (target_ast_context) 546 type_to_use = ClangASTContext::CopyType(target_ast_context, var_ast_context, var_opaque_type); 547 else 548 type_to_use = var_opaque_type; 549 550 if (var_location.get()->GetContextType() == Value::eContextTypeInvalid) 551 var_location.get()->SetContext(Value::eContextTypeOpaqueClangQualType, type_to_use); 552 553 if (var_location.get()->GetValueType() == Value::eValueTypeFileAddress) 554 { 555 SymbolContext var_sc; 556 var->CalculateSymbolContext(&var_sc); 557 558 if (!var_sc.module_sp) 559 return NULL; 560 561 ObjectFile *object_file = var_sc.module_sp->GetObjectFile(); 562 563 if (!object_file) 564 return NULL; 565 566 Address so_addr(var_location->GetScalar().ULongLong(), object_file->GetSectionList()); 567 568 lldb::addr_t load_addr = so_addr.GetLoadAddress(m_exe_ctx->process); 569 570 var_location->GetScalar() = load_addr; 571 var_location->SetValueType(Value::eValueTypeLoadAddress); 572 } 573 574 if (opaque_type) 575 *opaque_type = var_opaque_type; 576 577 if (found_ast_context) 578 *found_ast_context = var_ast_context; 579 580 return var_location.release(); 581} 582 583void 584ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, 585 Variable* var) 586{ 587 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); 588 589 void *var_opaque_type = NULL; 590 clang::ASTContext *var_ast_context = NULL; 591 592 Value *var_location = GetVariableValue(*m_exe_ctx, 593 var, 594 context.GetASTContext(), 595 &var_opaque_type, 596 &var_ast_context); 597 598 NamedDecl *var_decl = context.AddVarDecl(var_opaque_type); 599 600 Tuple tuple; 601 602 tuple.m_decl = var_decl; 603 tuple.m_value = var_location; 604 tuple.m_orig_type = var_opaque_type; 605 tuple.m_ast_context = var_ast_context; 606 607 m_tuples.push_back(tuple); 608 609 if (log) 610 log->PutCString("Found variable"); 611} 612 613void 614ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, 615 Function* fun) 616{ 617 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); 618 619 Type *fun_type = fun->GetType(); 620 621 if (!fun_type) 622 { 623 if (log) 624 log->PutCString("Skipped a function because it has no type"); 625 return; 626 } 627 628 void *fun_opaque_type = fun_type->GetOpaqueClangQualType(); 629 630 if (!fun_opaque_type) 631 { 632 if (log) 633 log->PutCString("Skipped a function because it has no Clang type"); 634 return; 635 } 636 637 std::auto_ptr<Value> fun_location(new Value); 638 639 const Address &fun_address = fun->GetAddressRange().GetBaseAddress(); 640 lldb::addr_t load_addr = fun_address.GetLoadAddress(m_exe_ctx->process); 641 fun_location->SetValueType(Value::eValueTypeLoadAddress); 642 fun_location->GetScalar() = load_addr; 643 644 TypeList *type_list = fun_type->GetTypeList(); 645 clang::ASTContext *fun_ast_context = type_list->GetClangASTContext().getASTContext(); 646 void *copied_type = ClangASTContext::CopyType(context.GetASTContext(), fun_ast_context, fun_opaque_type); 647 648 NamedDecl *fun_decl = context.AddFunDecl(copied_type); 649 650 Tuple tuple; 651 652 tuple.m_decl = fun_decl; 653 tuple.m_value = fun_location.release(); 654 tuple.m_orig_type = fun_opaque_type; 655 tuple.m_ast_context = fun_ast_context; 656 657 m_tuples.push_back(tuple); 658 659 if (log) 660 log->PutCString("Found function"); 661} 662