Function.cpp revision 6f01c93497df194b6f2194630a81e87d806ce0e0
1//===-- Function.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/Symbol/Function.h" 11#include "lldb/Core/Module.h" 12#include "lldb/Core/Section.h" 13#include "lldb/Host/Host.h" 14#include "lldb/Symbol/ClangASTType.h" 15#include "lldb/Symbol/ClangASTContext.h" 16#include "lldb/Symbol/CompileUnit.h" 17#include "lldb/Symbol/LineTable.h" 18#include "lldb/Symbol/SymbolFile.h" 19#include "lldb/Symbol/SymbolVendor.h" 20#include "clang/AST/Type.h" 21#include "clang/AST/CanonicalType.h" 22#include "llvm/Support/Casting.h" 23 24using namespace lldb; 25using namespace lldb_private; 26 27//---------------------------------------------------------------------- 28// Basic function information is contained in the FunctionInfo class. 29// It is designed to contain the name, linkage name, and declaration 30// location. 31//---------------------------------------------------------------------- 32FunctionInfo::FunctionInfo (const char *name, const Declaration *decl_ptr) : 33 m_name(name), 34 m_declaration(decl_ptr) 35{ 36} 37 38 39FunctionInfo::FunctionInfo (const ConstString& name, const Declaration *decl_ptr) : 40 m_name(name), 41 m_declaration(decl_ptr) 42{ 43} 44 45 46FunctionInfo::~FunctionInfo() 47{ 48} 49 50void 51FunctionInfo::Dump(Stream *s, bool show_fullpaths) const 52{ 53 if (m_name) 54 *s << ", name = \"" << m_name << "\""; 55 m_declaration.Dump(s, show_fullpaths); 56} 57 58 59int 60FunctionInfo::Compare(const FunctionInfo& a, const FunctionInfo& b) 61{ 62 int result = ConstString::Compare(a.GetName(), b.GetName()); 63 if (result) 64 return result; 65 66 return Declaration::Compare(a.m_declaration, b.m_declaration); 67} 68 69 70Declaration& 71FunctionInfo::GetDeclaration() 72{ 73 return m_declaration; 74} 75 76const Declaration& 77FunctionInfo::GetDeclaration() const 78{ 79 return m_declaration; 80} 81 82const ConstString& 83FunctionInfo::GetName() const 84{ 85 return m_name; 86} 87 88size_t 89FunctionInfo::MemorySize() const 90{ 91 return m_name.MemorySize() + m_declaration.MemorySize(); 92} 93 94 95InlineFunctionInfo::InlineFunctionInfo 96( 97 const char *name, 98 const char *mangled, 99 const Declaration *decl_ptr, 100 const Declaration *call_decl_ptr 101) : 102 FunctionInfo(name, decl_ptr), 103 m_mangled(ConstString(mangled), true), 104 m_call_decl (call_decl_ptr) 105{ 106} 107 108InlineFunctionInfo::InlineFunctionInfo 109( 110 const ConstString& name, 111 const Mangled &mangled, 112 const Declaration *decl_ptr, 113 const Declaration *call_decl_ptr 114) : 115 FunctionInfo(name, decl_ptr), 116 m_mangled(mangled), 117 m_call_decl (call_decl_ptr) 118{ 119} 120 121InlineFunctionInfo::~InlineFunctionInfo() 122{ 123} 124 125int 126InlineFunctionInfo::Compare(const InlineFunctionInfo& a, const InlineFunctionInfo& b) 127{ 128 129 int result = FunctionInfo::Compare(a, b); 130 if (result) 131 return result; 132 // only compare the mangled names if both have them 133 return Mangled::Compare(a.m_mangled, a.m_mangled); 134} 135 136void 137InlineFunctionInfo::Dump(Stream *s, bool show_fullpaths) const 138{ 139 FunctionInfo::Dump(s, show_fullpaths); 140 if (m_mangled) 141 m_mangled.Dump(s); 142} 143 144void 145InlineFunctionInfo::DumpStopContext (Stream *s) const 146{ 147// s->Indent("[inlined] "); 148 s->Indent(); 149 if (m_mangled) 150 s->PutCString (m_mangled.GetName().AsCString()); 151 else 152 s->PutCString (m_name.AsCString()); 153} 154 155 156const ConstString & 157InlineFunctionInfo::GetName () const 158{ 159 if (m_mangled) 160 return m_mangled.GetName(); 161 return m_name; 162} 163 164 165Declaration & 166InlineFunctionInfo::GetCallSite () 167{ 168 return m_call_decl; 169} 170 171const Declaration & 172InlineFunctionInfo::GetCallSite () const 173{ 174 return m_call_decl; 175} 176 177 178Mangled& 179InlineFunctionInfo::GetMangled() 180{ 181 return m_mangled; 182} 183 184const Mangled& 185InlineFunctionInfo::GetMangled() const 186{ 187 return m_mangled; 188} 189 190size_t 191InlineFunctionInfo::MemorySize() const 192{ 193 return FunctionInfo::MemorySize() + m_mangled.MemorySize(); 194} 195 196//---------------------------------------------------------------------- 197// 198//---------------------------------------------------------------------- 199Function::Function 200( 201 CompileUnit *comp_unit, 202 lldb::user_id_t func_uid, 203 lldb::user_id_t type_uid, 204 const Mangled &mangled, 205 Type * type, 206 const AddressRange& range 207) : 208 UserID (func_uid), 209 m_comp_unit (comp_unit), 210 m_type_uid (type_uid), 211 m_type (type), 212 m_mangled (mangled), 213 m_block (func_uid), 214 m_range (range), 215 m_frame_base (), 216 m_flags (), 217 m_prologue_byte_size (0) 218{ 219 m_block.SetParentScope(this); 220 assert(comp_unit != NULL); 221} 222 223Function::Function 224( 225 CompileUnit *comp_unit, 226 lldb::user_id_t func_uid, 227 lldb::user_id_t type_uid, 228 const char *mangled, 229 Type *type, 230 const AddressRange &range 231) : 232 UserID (func_uid), 233 m_comp_unit (comp_unit), 234 m_type_uid (type_uid), 235 m_type (type), 236 m_mangled (ConstString(mangled), true), 237 m_block (func_uid), 238 m_range (range), 239 m_frame_base (), 240 m_flags (), 241 m_prologue_byte_size (0) 242{ 243 m_block.SetParentScope(this); 244 assert(comp_unit != NULL); 245} 246 247 248Function::~Function() 249{ 250} 251 252void 253Function::GetStartLineSourceInfo (FileSpec &source_file, uint32_t &line_no) 254{ 255 line_no = 0; 256 source_file.Clear(); 257 258 if (m_comp_unit == NULL) 259 return; 260 261 if (m_type != NULL && m_type->GetDeclaration().GetLine() != 0) 262 { 263 source_file = m_type->GetDeclaration().GetFile(); 264 line_no = m_type->GetDeclaration().GetLine(); 265 } 266 else 267 { 268 LineTable *line_table = m_comp_unit->GetLineTable(); 269 if (line_table == NULL) 270 return; 271 272 LineEntry line_entry; 273 if (line_table->FindLineEntryByAddress (GetAddressRange().GetBaseAddress(), line_entry, NULL)) 274 { 275 line_no = line_entry.line; 276 source_file = line_entry.file; 277 } 278 } 279} 280 281void 282Function::GetEndLineSourceInfo (FileSpec &source_file, uint32_t &line_no) 283{ 284 line_no = 0; 285 source_file.Clear(); 286 287 // The -1 is kind of cheesy, but I want to get the last line entry for the given function, not the 288 // first entry of the next. 289 Address scratch_addr(GetAddressRange().GetBaseAddress()); 290 scratch_addr.SetOffset (scratch_addr.GetOffset() + GetAddressRange().GetByteSize() - 1); 291 292 LineTable *line_table = m_comp_unit->GetLineTable(); 293 if (line_table == NULL) 294 return; 295 296 LineEntry line_entry; 297 if (line_table->FindLineEntryByAddress (scratch_addr, line_entry, NULL)) 298 { 299 line_no = line_entry.line; 300 source_file = line_entry.file; 301 } 302} 303 304Block & 305Function::GetBlock (bool can_create) 306{ 307 if (!m_block.BlockInfoHasBeenParsed() && can_create) 308 { 309 SymbolContext sc; 310 CalculateSymbolContext(&sc); 311 if (sc.module_sp) 312 { 313 sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc); 314 } 315 else 316 { 317 Host::SystemLog (Host::eSystemLogError, 318 "error: unable to find module shared pointer for function '%s' in %s%s%s\n", 319 GetName().GetCString(), 320 m_comp_unit->GetDirectory().GetCString(), 321 m_comp_unit->GetDirectory() ? "/" : "", 322 m_comp_unit->GetFilename().GetCString()); 323 } 324 m_block.SetBlockInfoHasBeenParsed (true, true); 325 } 326 return m_block; 327} 328 329CompileUnit* 330Function::GetCompileUnit() 331{ 332 return m_comp_unit; 333} 334 335const CompileUnit* 336Function::GetCompileUnit() const 337{ 338 return m_comp_unit; 339} 340 341 342void 343Function::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target) 344{ 345 Type* func_type = GetType(); 346 const char *name = func_type ? func_type->GetName().AsCString() : "<unknown>"; 347 348 *s << "id = " << (const UserID&)*this << ", name = \"" << name << "\", range = "; 349 350 Address::DumpStyle fallback_style; 351 if (level == eDescriptionLevelVerbose) 352 fallback_style = Address::DumpStyleModuleWithFileAddress; 353 else 354 fallback_style = Address::DumpStyleFileAddress; 355 GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, fallback_style); 356} 357 358void 359Function::Dump(Stream *s, bool show_context) const 360{ 361 s->Printf("%p: ", this); 362 s->Indent(); 363 *s << "Function" << (const UserID&)*this; 364 365 m_mangled.Dump(s); 366 367 if (m_type) 368 { 369 s->Printf(", type = %p", m_type); 370 } 371 else if (m_type_uid != LLDB_INVALID_UID) 372 { 373 s->Printf(", type_uid = 0x%8.8llx", m_type_uid); 374 } 375 376 s->EOL(); 377 // Dump the root object 378 if (m_block.BlockInfoHasBeenParsed ()) 379 m_block.Dump(s, m_range.GetBaseAddress().GetFileAddress(), INT_MAX, show_context); 380} 381 382 383void 384Function::CalculateSymbolContext(SymbolContext* sc) 385{ 386 sc->function = this; 387 m_comp_unit->CalculateSymbolContext(sc); 388} 389 390ModuleSP 391Function::CalculateSymbolContextModule () 392{ 393 SectionSP section_sp (m_range.GetBaseAddress().GetSection()); 394 if (section_sp) 395 { 396 SectionSP linked_section_sp (section_sp->GetLinkedSection()); 397 if (linked_section_sp) 398 return linked_section_sp->GetModule(); 399 else 400 return section_sp->GetModule(); 401 } 402 403 return this->GetCompileUnit()->GetModule(); 404} 405 406CompileUnit * 407Function::CalculateSymbolContextCompileUnit () 408{ 409 return this->GetCompileUnit(); 410} 411 412Function * 413Function::CalculateSymbolContextFunction () 414{ 415 return this; 416} 417 418//Symbol * 419//Function::CalculateSymbolContextSymbol () 420//{ 421// return // TODO: find the symbol for the function??? 422//} 423 424 425void 426Function::DumpSymbolContext(Stream *s) 427{ 428 m_comp_unit->DumpSymbolContext(s); 429 s->Printf(", Function{0x%8.8llx}", GetID()); 430} 431 432size_t 433Function::MemorySize () const 434{ 435 size_t mem_size = sizeof(Function) + m_block.MemorySize(); 436 return mem_size; 437} 438 439clang::DeclContext * 440Function::GetClangDeclContext() 441{ 442 SymbolContext sc; 443 444 CalculateSymbolContext (&sc); 445 446 if (!sc.module_sp) 447 return NULL; 448 449 SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor(); 450 451 if (!sym_vendor) 452 return NULL; 453 454 SymbolFile *sym_file = sym_vendor->GetSymbolFile(); 455 456 if (!sym_file) 457 return NULL; 458 459 return sym_file->GetClangDeclContextForTypeUID (sc, m_uid); 460} 461 462Type* 463Function::GetType() 464{ 465 if (m_type == NULL) 466 { 467 SymbolContext sc; 468 469 CalculateSymbolContext (&sc); 470 471 if (!sc.module_sp) 472 return NULL; 473 474 SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor(); 475 476 if (sym_vendor == NULL) 477 return NULL; 478 479 SymbolFile *sym_file = sym_vendor->GetSymbolFile(); 480 481 if (sym_file == NULL) 482 return NULL; 483 484 m_type = sym_file->ResolveTypeUID(m_type_uid); 485 } 486 return m_type; 487} 488 489const Type* 490Function::GetType() const 491{ 492 return m_type; 493} 494 495clang_type_t 496Function::GetReturnClangType () 497{ 498 Type *type = GetType(); 499 if (type) 500 { 501 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(type->GetClangFullType())); 502 const clang::FunctionType *function_type = llvm::dyn_cast<clang::FunctionType> (clang_type); 503 if (function_type) 504 return function_type->getResultType().getAsOpaquePtr(); 505 } 506 return NULL; 507} 508 509int 510Function::GetArgumentCount () 511{ 512 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetClangFullType())); 513 assert (clang_type->isFunctionType()); 514 if (!clang_type->isFunctionProtoType()) 515 return -1; 516 517 const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast<clang::FunctionProtoType>(clang_type); 518 if (function_proto_type != NULL) 519 return function_proto_type->getNumArgs(); 520 521 return 0; 522} 523 524clang_type_t 525Function::GetArgumentTypeAtIndex (size_t idx) 526{ 527 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetClangFullType())); 528 const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast<clang::FunctionProtoType>(clang_type); 529 if (function_proto_type) 530 { 531 unsigned num_args = function_proto_type->getNumArgs(); 532 if (idx >= num_args) 533 return NULL; 534 535 return (function_proto_type->arg_type_begin())[idx].getAsOpaquePtr(); 536 } 537 return NULL; 538} 539 540bool 541Function::IsVariadic () 542{ 543 const clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetClangFullType())->getTypePtr(); 544 assert (clang_type->isFunctionType()); 545 if (!clang_type->isFunctionProtoType()) 546 return false; 547 548 const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast<clang::FunctionProtoType>(clang_type); 549 if (function_proto_type) 550 return function_proto_type->isVariadic(); 551 552 return false; 553} 554 555uint32_t 556Function::GetPrologueByteSize () 557{ 558 if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize)) 559 { 560 m_flags.Set(flagsCalculatedPrologueSize); 561 LineTable* line_table = m_comp_unit->GetLineTable (); 562 if (line_table) 563 { 564 LineEntry first_line_entry; 565 uint32_t first_line_entry_idx = UINT32_MAX; 566 if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), first_line_entry, &first_line_entry_idx)) 567 { 568 // Make sure the first line entry isn't already the end of the prologue 569 addr_t prologue_end_file_addr = LLDB_INVALID_ADDRESS; 570 if (first_line_entry.is_prologue_end) 571 { 572 prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress(); 573 } 574 else 575 { 576 // Check the first few instructions and look for one that has 577 // is_prologue_end set to true. 578 const uint32_t last_line_entry_idx = first_line_entry_idx + 6; 579 LineEntry line_entry; 580 for (uint32_t idx = first_line_entry_idx + 1; idx < last_line_entry_idx; ++idx) 581 { 582 if (line_table->GetLineEntryAtIndex (idx, line_entry)) 583 { 584 if (line_entry.is_prologue_end) 585 { 586 prologue_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress(); 587 break; 588 } 589 } 590 } 591 } 592 593 // If we didn't find the end of the prologue in the line tables, 594 // then just use the end address of the first line table entry 595 if (prologue_end_file_addr == LLDB_INVALID_ADDRESS) 596 { 597 prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress() + first_line_entry.range.GetByteSize(); 598 } 599 const addr_t func_start_file_addr = m_range.GetBaseAddress().GetFileAddress(); 600 const addr_t func_end_file_addr = func_start_file_addr + m_range.GetByteSize(); 601 602 // Verify that this prologue end file address in the function's 603 // address range just to be sure 604 if (func_start_file_addr < prologue_end_file_addr && prologue_end_file_addr < func_end_file_addr) 605 { 606 m_prologue_byte_size = prologue_end_file_addr - func_start_file_addr; 607 } 608 } 609 } 610 } 611 return m_prologue_byte_size; 612} 613 614 615 616