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