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/CompileUnit.h" 14 #include "lldb/Symbol/LineTable.h" 15 #include "lldb/Symbol/SymbolVendor.h" 16 #include "lldb/Symbol/ClangASTContext.h" 17 #include "clang/AST/Type.h" 18 #include "clang/AST/CanonicalType.h" 19 20 using namespace lldb_private; 21 22 //---------------------------------------------------------------------- 23 // Basic function information is contained in the FunctionInfo class. 24 // It is designed to contain the name, linkage name, and declaration 25 // location. 26 //---------------------------------------------------------------------- 27 FunctionInfo::FunctionInfo (const char *name, const Declaration *decl_ptr) : 28 m_name(name), 29 m_declaration(decl_ptr) 30 { 31 } 32 33 34 FunctionInfo::FunctionInfo (const ConstString& name, const Declaration *decl_ptr) : 35 m_name(name), 36 m_declaration(decl_ptr) 37 { 38 } 39 40 41 FunctionInfo::~FunctionInfo() 42 { 43 } 44 45 void 46 FunctionInfo::Dump(Stream *s) const 47 { 48 if (m_name) 49 *s << ", name = \"" << m_name << "\""; 50 m_declaration.Dump(s); 51 } 52 53 54 int 55 FunctionInfo::Compare(const FunctionInfo& a, const FunctionInfo& b) 56 { 57 int result = ConstString::Compare(a.GetName(), b.GetName()); 58 if (result) 59 return result; 60 61 return Declaration::Compare(a.m_declaration, b.m_declaration); 62 } 63 64 65 Declaration& 66 FunctionInfo::GetDeclaration() 67 { 68 return m_declaration; 69 } 70 71 const Declaration& 72 FunctionInfo::GetDeclaration() const 73 { 74 return m_declaration; 75 } 76 77 const ConstString& 78 FunctionInfo::GetName() const 79 { 80 return m_name; 81 } 82 83 size_t 84 FunctionInfo::MemorySize() const 85 { 86 return m_name.MemorySize() + m_declaration.MemorySize(); 87 } 88 89 90 InlineFunctionInfo::InlineFunctionInfo 91 ( 92 const char *name, 93 const char *mangled, 94 const Declaration *decl_ptr, 95 const Declaration *call_decl_ptr 96 ) : 97 FunctionInfo(name, decl_ptr), 98 m_mangled(mangled, true), 99 m_call_decl (call_decl_ptr) 100 { 101 } 102 103 InlineFunctionInfo::InlineFunctionInfo 104 ( 105 const ConstString& name, 106 const Mangled &mangled, 107 const Declaration *decl_ptr, 108 const Declaration *call_decl_ptr 109 ) : 110 FunctionInfo(name, decl_ptr), 111 m_mangled(mangled), 112 m_call_decl (call_decl_ptr) 113 { 114 } 115 116 InlineFunctionInfo::~InlineFunctionInfo() 117 { 118 } 119 120 int 121 InlineFunctionInfo::Compare(const InlineFunctionInfo& a, const InlineFunctionInfo& b) 122 { 123 124 int result = FunctionInfo::Compare(a, b); 125 if (result) 126 return result; 127 // only compare the mangled names if both have them 128 return Mangled::Compare(a.m_mangled, a.m_mangled); 129 } 130 131 void 132 InlineFunctionInfo::Dump(Stream *s) const 133 { 134 FunctionInfo::Dump(s); 135 if (m_mangled) 136 m_mangled.Dump(s); 137 } 138 139 void 140 InlineFunctionInfo::DumpStopContext (Stream *s) const 141 { 142 // s->Indent("[inlined] "); 143 s->Indent(); 144 if (m_mangled) 145 s->PutCString (m_mangled.GetName().AsCString()); 146 else 147 s->PutCString (m_name.AsCString()); 148 } 149 150 Declaration & 151 InlineFunctionInfo::GetCallSite () 152 { 153 return m_call_decl; 154 } 155 156 const Declaration & 157 InlineFunctionInfo::GetCallSite () const 158 { 159 return m_call_decl; 160 } 161 162 163 Mangled& 164 InlineFunctionInfo::GetMangled() 165 { 166 return m_mangled; 167 } 168 169 const Mangled& 170 InlineFunctionInfo::GetMangled() const 171 { 172 return m_mangled; 173 } 174 175 size_t 176 InlineFunctionInfo::MemorySize() const 177 { 178 return FunctionInfo::MemorySize() + m_mangled.MemorySize(); 179 } 180 181 //---------------------------------------------------------------------- 182 // 183 //---------------------------------------------------------------------- 184 Function::Function 185 ( 186 CompileUnit *comp_unit, 187 lldb::user_id_t func_uid, 188 lldb::user_id_t type_uid, 189 const Mangled &mangled, 190 Type * type, 191 const AddressRange& range 192 ) : 193 UserID(func_uid), 194 m_comp_unit(comp_unit), 195 m_type_uid(type_uid), 196 m_type(type), 197 m_mangled(mangled), 198 m_blocks(this, range), 199 m_frame_base(), 200 m_flags(), 201 m_prologue_byte_size(0) 202 { 203 assert(comp_unit != NULL); 204 } 205 206 Function::Function 207 ( 208 CompileUnit *comp_unit, 209 lldb::user_id_t func_uid, 210 lldb::user_id_t type_uid, 211 const char *mangled, 212 Type *type, 213 const AddressRange &range 214 ) : 215 UserID(func_uid), 216 m_comp_unit(comp_unit), 217 m_type_uid(type_uid), 218 m_type(type), 219 m_mangled(mangled, true), 220 m_blocks(this, range), 221 m_frame_base(), 222 m_flags(), 223 m_prologue_byte_size(0) 224 { 225 assert(comp_unit != NULL); 226 } 227 228 229 Function::~Function() 230 { 231 } 232 233 const AddressRange & 234 Function::GetAddressRange() 235 { 236 return GetBlocks(true).GetAddressRange(); 237 } 238 239 BlockList & 240 Function::GetBlocks(bool can_create) 241 { 242 if (m_blocks.IsEmpty() && can_create) 243 { 244 SymbolContext sc; 245 CalculateSymbolContext(&sc); 246 assert(sc.module_sp); 247 sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc); 248 } 249 return m_blocks; 250 } 251 252 CompileUnit* 253 Function::GetCompileUnit() 254 { 255 return m_comp_unit; 256 } 257 258 const CompileUnit* 259 Function::GetCompileUnit() const 260 { 261 return m_comp_unit; 262 } 263 264 265 void 266 Function::GetDescription(Stream *s, lldb::DescriptionLevel level, Process *process) 267 { 268 Type* func_type = GetType(); 269 *s << '"' << func_type->GetName() << "\", id = " << (const UserID&)*this; 270 *s << ", range = "; 271 GetAddressRange().Dump(s, process, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress); 272 } 273 274 void 275 Function::Dump(Stream *s, bool show_context) const 276 { 277 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 278 s->Indent(); 279 *s << "Function" << (const UserID&)*this; 280 281 m_mangled.Dump(s); 282 283 // FunctionInfo::Dump(s); 284 if (m_type) 285 { 286 *s << ", type = " << (void*)m_type; 287 /// << " ("; 288 ///m_type->DumpTypeName(s); 289 ///s->PutChar(')'); 290 } 291 else if (m_type_uid != LLDB_INVALID_UID) 292 *s << ", type_uid = " << m_type_uid; 293 294 s->EOL(); 295 // Dump the root object 296 if (!m_blocks.IsEmpty()) 297 m_blocks.Dump(s, Block::RootID, INT_MAX, show_context); 298 } 299 300 301 void 302 Function::CalculateSymbolContext(SymbolContext* sc) 303 { 304 sc->function = this; 305 m_comp_unit->CalculateSymbolContext(sc); 306 } 307 308 void 309 Function::DumpSymbolContext(Stream *s) 310 { 311 m_comp_unit->DumpSymbolContext(s); 312 s->Printf(", Function{0x%8.8x}", GetID()); 313 } 314 315 size_t 316 Function::MemorySize () const 317 { 318 size_t mem_size = sizeof(Function) + m_blocks.MemorySize(); 319 return mem_size; 320 } 321 322 Type* 323 Function::GetType() 324 { 325 return m_type; 326 } 327 328 const Type* 329 Function::GetType() const 330 { 331 return m_type; 332 } 333 334 Type 335 Function::GetReturnType () 336 { 337 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType())); 338 assert (clang_type->isFunctionType()); 339 clang::FunctionType *function_type = dyn_cast<clang::FunctionType> (clang_type); 340 clang::QualType fun_return_qualtype = function_type->getResultType(); 341 342 const ConstString fun_return_name(Type::GetClangTypeName(fun_return_qualtype.getAsOpaquePtr())); 343 344 SymbolContext sc; 345 CalculateSymbolContext (&sc); 346 // Null out everything below the CompUnit 'cause we don't actually know these. 347 348 size_t bit_size = ClangASTContext::GetTypeBitSize ((GetType()->GetClangASTContext().getASTContext()), &fun_return_qualtype); 349 Type return_type (0, GetType()->GetSymbolFile(), fun_return_name, bit_size, sc.comp_unit, 0, Type::eTypeUIDSynthetic, Declaration(), fun_return_qualtype.getAsOpaquePtr()); 350 return return_type; 351 } 352 353 int 354 Function::GetArgumentCount () 355 { 356 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType())); 357 assert (clang_type->isFunctionType()); 358 if (!clang_type->isFunctionProtoType()) 359 return -1; 360 361 const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type); 362 if (function_proto_type != NULL) 363 return function_proto_type->getNumArgs(); 364 365 return 0; 366 } 367 368 const Type 369 Function::GetArgumentTypeAtIndex (size_t idx) 370 { 371 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType())); 372 assert (clang_type->isFunctionType()); 373 if (!clang_type->isFunctionProtoType()) 374 return Type(); 375 376 const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type); 377 if (function_proto_type != NULL) 378 { 379 unsigned num_args = function_proto_type->getNumArgs(); 380 if (idx >= num_args) 381 return Type(); 382 clang::QualType arg_qualtype = (function_proto_type->arg_type_begin())[idx]; 383 384 const ConstString arg_return_name(Type::GetClangTypeName(arg_qualtype.getAsOpaquePtr())); 385 SymbolContext sc; 386 CalculateSymbolContext (&sc); 387 // Null out everything below the CompUnit 'cause we don't actually know these. 388 389 size_t bit_size = ClangASTContext::GetTypeBitSize ((GetType()->GetClangASTContext().getASTContext()), &arg_qualtype); 390 Type arg_type (0, GetType()->GetSymbolFile(), arg_return_name, bit_size, sc.comp_unit, 0, Type::eTypeUIDSynthetic, Declaration(), arg_qualtype.getAsOpaquePtr()); 391 return arg_type; 392 } 393 394 return Type(); 395 } 396 397 const char * 398 Function::GetArgumentNameAtIndex (size_t idx) 399 { 400 clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetOpaqueClangQualType())->getTypePtr(); 401 assert (clang_type->isFunctionType()); 402 if (!clang_type->isFunctionProtoType()) 403 return NULL; 404 return NULL; 405 } 406 407 bool 408 Function::IsVariadic () 409 { 410 const clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetOpaqueClangQualType())->getTypePtr(); 411 assert (clang_type->isFunctionType()); 412 if (!clang_type->isFunctionProtoType()) 413 return false; 414 415 const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type); 416 if (function_proto_type != NULL) 417 { 418 return function_proto_type->isVariadic(); 419 } 420 421 return false; 422 } 423 424 uint32_t 425 Function::GetPrologueByteSize () 426 { 427 if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize)) 428 { 429 m_flags.Set(flagsCalculatedPrologueSize); 430 LineTable* line_table = m_comp_unit->GetLineTable (); 431 if (line_table) 432 { 433 LineEntry line_entry; 434 if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), line_entry)) 435 m_prologue_byte_size = line_entry.range.GetByteSize(); 436 } 437 } 438 return m_prologue_byte_size; 439 } 440 441 442 443