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: ", (int)sizeof(void*) * 2, 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", (int)sizeof(void*) * 2, 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 return this->GetCompileUnit()->GetModule(); 391 } 392 393 CompileUnit * 394 Function::CalculateSymbolContextCompileUnit () 395 { 396 return this->GetCompileUnit(); 397 } 398 399 Function * 400 Function::CalculateSymbolContextFunction () 401 { 402 return this; 403 } 404 405 //Symbol * 406 //Function::CalculateSymbolContextSymbol () 407 //{ 408 // return // TODO: find the symbol for the function??? 409 //} 410 411 412 void 413 Function::DumpSymbolContext(Stream *s) 414 { 415 m_comp_unit->DumpSymbolContext(s); 416 s->Printf(", Function{0x%8.8x}", GetID()); 417 } 418 419 size_t 420 Function::MemorySize () const 421 { 422 size_t mem_size = sizeof(Function) + m_block.MemorySize(); 423 return mem_size; 424 } 425 426 clang::DeclContext * 427 Function::GetClangDeclContext() 428 { 429 SymbolContext sc; 430 431 CalculateSymbolContext (&sc); 432 433 if (!sc.module_sp) 434 return NULL; 435 436 SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor(); 437 438 if (!sym_vendor) 439 return NULL; 440 441 SymbolFile *sym_file = sym_vendor->GetSymbolFile(); 442 443 if (!sym_file) 444 return NULL; 445 446 return sym_file->GetClangDeclContextForTypeUID (sc, m_uid); 447 } 448 449 Type* 450 Function::GetType() 451 { 452 return m_type; 453 } 454 455 const Type* 456 Function::GetType() const 457 { 458 return m_type; 459 } 460 461 clang_type_t 462 Function::GetReturnClangType () 463 { 464 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetClangFullType())); 465 const clang::FunctionType *function_type = llvm::dyn_cast<clang::FunctionType> (clang_type); 466 if (function_type) 467 return function_type->getResultType().getAsOpaquePtr(); 468 return NULL; 469 } 470 471 int 472 Function::GetArgumentCount () 473 { 474 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetClangFullType())); 475 assert (clang_type->isFunctionType()); 476 if (!clang_type->isFunctionProtoType()) 477 return -1; 478 479 const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast<clang::FunctionProtoType>(clang_type); 480 if (function_proto_type != NULL) 481 return function_proto_type->getNumArgs(); 482 483 return 0; 484 } 485 486 clang_type_t 487 Function::GetArgumentTypeAtIndex (size_t idx) 488 { 489 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetClangFullType())); 490 const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast<clang::FunctionProtoType>(clang_type); 491 if (function_proto_type) 492 { 493 unsigned num_args = function_proto_type->getNumArgs(); 494 if (idx >= num_args) 495 return NULL; 496 497 return (function_proto_type->arg_type_begin())[idx].getAsOpaquePtr(); 498 } 499 return NULL; 500 } 501 502 bool 503 Function::IsVariadic () 504 { 505 const clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetClangFullType())->getTypePtr(); 506 assert (clang_type->isFunctionType()); 507 if (!clang_type->isFunctionProtoType()) 508 return false; 509 510 const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast<clang::FunctionProtoType>(clang_type); 511 if (function_proto_type) 512 return function_proto_type->isVariadic(); 513 514 return false; 515 } 516 517 uint32_t 518 Function::GetPrologueByteSize () 519 { 520 if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize)) 521 { 522 m_flags.Set(flagsCalculatedPrologueSize); 523 LineTable* line_table = m_comp_unit->GetLineTable (); 524 if (line_table) 525 { 526 LineEntry line_entry; 527 if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), line_entry)) 528 { 529 // We need to take the delta of the end of the first line entry 530 // as a file address and the start file address of the function 531 // in case the first line entry doesn't start at the beginning 532 // of the function. 533 const addr_t func_start_file_addr = m_range.GetBaseAddress().GetFileAddress(); 534 const addr_t line_entry_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress() + line_entry.range.GetByteSize(); 535 if (line_entry_end_file_addr > func_start_file_addr) 536 m_prologue_byte_size = line_entry_end_file_addr - func_start_file_addr; 537 } 538 } 539 } 540 return m_prologue_byte_size; 541 } 542 543 544 545