1 //===-- SymbolFileSymtab.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 "SymbolFileSymtab.h" 11 #include "lldb/Core/Module.h" 12 #include "lldb/Core/PluginManager.h" 13 #include "lldb/Core/RegularExpression.h" 14 #include "lldb/Core/Timer.h" 15 #include "lldb/Symbol/ObjectFile.h" 16 #include "lldb/Symbol/Symtab.h" 17 #include "lldb/Symbol/ObjectFile.h" 18 #include "lldb/Symbol/Symbol.h" 19 #include "lldb/Symbol/CompileUnit.h" 20 #include "lldb/Symbol/SymbolContext.h" 21 #include "lldb/Symbol/Function.h" 22 23 using namespace lldb; 24 using namespace lldb_private; 25 26 void 27 SymbolFileSymtab::Initialize() 28 { 29 PluginManager::RegisterPlugin (GetPluginNameStatic(), 30 GetPluginDescriptionStatic(), 31 CreateInstance); 32 } 33 34 void 35 SymbolFileSymtab::Terminate() 36 { 37 PluginManager::UnregisterPlugin (CreateInstance); 38 } 39 40 41 const char * 42 SymbolFileSymtab::GetPluginNameStatic() 43 { 44 return "symbol-file.symtab"; 45 } 46 47 const char * 48 SymbolFileSymtab::GetPluginDescriptionStatic() 49 { 50 return "Reads debug symbols from an object file's symbol table."; 51 } 52 53 54 SymbolFile* 55 SymbolFileSymtab::CreateInstance (ObjectFile* obj_file) 56 { 57 return new SymbolFileSymtab(obj_file); 58 } 59 60 SymbolFileSymtab::SymbolFileSymtab(ObjectFile* obj_file) : 61 SymbolFile(obj_file), 62 m_source_indexes(), 63 m_func_indexes(), 64 m_code_indexes(), 65 m_objc_class_name_to_index () 66 { 67 } 68 69 SymbolFileSymtab::~SymbolFileSymtab() 70 { 71 } 72 73 ClangASTContext & 74 SymbolFileSymtab::GetClangASTContext () 75 { 76 ClangASTContext &ast = m_obj_file->GetModule()->GetClangASTContext(); 77 78 return ast; 79 } 80 81 uint32_t 82 SymbolFileSymtab::CalculateAbilities () 83 { 84 uint32_t abilities = 0; 85 if (m_obj_file) 86 { 87 const Symtab *symtab = m_obj_file->GetSymtab(); 88 if (symtab) 89 { 90 //---------------------------------------------------------------------- 91 // The snippet of code below will get the indexes the module symbol 92 // table entries that are code, data, or function related (debug info), 93 // sort them by value (address) and dump the sorted symbols. 94 //---------------------------------------------------------------------- 95 if (symtab->AppendSymbolIndexesWithType(eSymbolTypeSourceFile, m_source_indexes)) 96 { 97 abilities |= CompileUnits; 98 } 99 100 if (symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, Symtab::eDebugYes, Symtab::eVisibilityAny, m_func_indexes)) 101 { 102 symtab->SortSymbolIndexesByValue(m_func_indexes, true); 103 abilities |= Functions; 104 } 105 106 if (symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, Symtab::eDebugNo, Symtab::eVisibilityAny, m_code_indexes)) 107 { 108 symtab->SortSymbolIndexesByValue(m_code_indexes, true); 109 abilities |= Labels; 110 } 111 112 if (symtab->AppendSymbolIndexesWithType(eSymbolTypeData, m_data_indexes)) 113 { 114 symtab->SortSymbolIndexesByValue(m_data_indexes, true); 115 abilities |= GlobalVariables; 116 } 117 118 lldb_private::Symtab::IndexCollection objc_class_indexes; 119 if (symtab->AppendSymbolIndexesWithType (eSymbolTypeObjCClass, objc_class_indexes)) 120 { 121 abilities |= RuntimeTypes; 122 symtab->AppendSymbolNamesToMap (objc_class_indexes, 123 true, 124 true, 125 m_objc_class_name_to_index); 126 m_objc_class_name_to_index.Sort(); 127 } 128 } 129 } 130 return abilities; 131 } 132 133 uint32_t 134 SymbolFileSymtab::GetNumCompileUnits() 135 { 136 // If we don't have any source file symbols we will just have one compile unit for 137 // the entire object file 138 if (m_source_indexes.empty()) 139 return 0; 140 141 // If we have any source file symbols we will logically orgnize the object symbols 142 // using these. 143 return m_source_indexes.size(); 144 } 145 146 CompUnitSP 147 SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx) 148 { 149 CompUnitSP cu_sp; 150 151 // If we don't have any source file symbols we will just have one compile unit for 152 // the entire object file 153 // if (m_source_indexes.empty()) 154 // { 155 // const FileSpec &obj_file_spec = m_obj_file->GetFileSpec(); 156 // if (obj_file_spec) 157 // cu_sp.reset(new CompileUnit(m_obj_file->GetModule(), NULL, obj_file_spec, 0, eLanguageTypeUnknown)); 158 // 159 // } 160 /* else */ if (idx < m_source_indexes.size()) 161 { 162 const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]); 163 if (cu_symbol) 164 cu_sp.reset(new CompileUnit(m_obj_file->GetModule(), NULL, cu_symbol->GetMangled().GetName().AsCString(), 0, eLanguageTypeUnknown)); 165 } 166 return cu_sp; 167 } 168 169 size_t 170 SymbolFileSymtab::ParseCompileUnitFunctions (const SymbolContext &sc) 171 { 172 size_t num_added = 0; 173 // We must at least have a valid compile unit 174 assert (sc.comp_unit != NULL); 175 const Symtab *symtab = m_obj_file->GetSymtab(); 176 const Symbol *curr_symbol = NULL; 177 const Symbol *next_symbol = NULL; 178 // const char *prefix = m_obj_file->SymbolPrefix(); 179 // if (prefix == NULL) 180 // prefix == ""; 181 // 182 // const uint32_t prefix_len = strlen(prefix); 183 184 // If we don't have any source file symbols we will just have one compile unit for 185 // the entire object file 186 if (m_source_indexes.empty()) 187 { 188 // The only time we will have a user ID of zero is when we don't have 189 // and source file symbols and we declare one compile unit for the 190 // entire object file 191 if (!m_func_indexes.empty()) 192 { 193 194 } 195 196 if (!m_code_indexes.empty()) 197 { 198 // StreamFile s(stdout); 199 // symtab->Dump(&s, m_code_indexes); 200 201 uint32_t idx = 0; // Index into the indexes 202 const uint32_t num_indexes = m_code_indexes.size(); 203 for (idx = 0; idx < num_indexes; ++idx) 204 { 205 uint32_t symbol_idx = m_code_indexes[idx]; 206 curr_symbol = symtab->SymbolAtIndex(symbol_idx); 207 if (curr_symbol) 208 { 209 // Union of all ranges in the function DIE (if the function is discontiguous) 210 AddressRange func_range(curr_symbol->GetValue(), 0); 211 if (func_range.GetBaseAddress().IsSectionOffset()) 212 { 213 uint32_t symbol_size = curr_symbol->GetByteSize(); 214 if (symbol_size != 0 && !curr_symbol->GetSizeIsSibling()) 215 func_range.SetByteSize(symbol_size); 216 else if (idx + 1 < num_indexes) 217 { 218 next_symbol = symtab->SymbolAtIndex(m_code_indexes[idx + 1]); 219 if (next_symbol) 220 { 221 func_range.SetByteSize(next_symbol->GetValue().GetOffset() - curr_symbol->GetValue().GetOffset()); 222 } 223 } 224 225 FunctionSP func_sp(new Function(sc.comp_unit, 226 symbol_idx, // UserID is the DIE offset 227 LLDB_INVALID_UID, // We don't have any type info for this function 228 curr_symbol->GetMangled(), // Linker/mangled name 229 NULL, // no return type for a code symbol... 230 func_range)); // first address range 231 232 if (func_sp.get() != NULL) 233 { 234 sc.comp_unit->AddFunction(func_sp); 235 ++num_added; 236 } 237 } 238 } 239 } 240 241 } 242 } 243 else 244 { 245 // We assume we 246 } 247 return num_added; 248 } 249 250 bool 251 SymbolFileSymtab::ParseCompileUnitLineTable (const SymbolContext &sc) 252 { 253 return false; 254 } 255 256 bool 257 SymbolFileSymtab::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files) 258 { 259 return false; 260 } 261 262 size_t 263 SymbolFileSymtab::ParseFunctionBlocks (const SymbolContext &sc) 264 { 265 return 0; 266 } 267 268 269 size_t 270 SymbolFileSymtab::ParseTypes (const SymbolContext &sc) 271 { 272 return 0; 273 } 274 275 276 size_t 277 SymbolFileSymtab::ParseVariablesForContext (const SymbolContext& sc) 278 { 279 return 0; 280 } 281 282 Type* 283 SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid) 284 { 285 return NULL; 286 } 287 288 lldb::clang_type_t 289 SymbolFileSymtab::ResolveClangOpaqueTypeDefinition (lldb::clang_type_t clang_Type) 290 { 291 return NULL; 292 } 293 294 ClangNamespaceDecl 295 SymbolFileSymtab::FindNamespace (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl) 296 { 297 return ClangNamespaceDecl(); 298 } 299 300 uint32_t 301 SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) 302 { 303 if (m_obj_file->GetSymtab() == NULL) 304 return 0; 305 306 uint32_t resolved_flags = 0; 307 if (resolve_scope & eSymbolContextSymbol) 308 { 309 sc.symbol = m_obj_file->GetSymtab()->FindSymbolContainingFileAddress(so_addr.GetFileAddress()); 310 if (sc.symbol) 311 resolved_flags |= eSymbolContextSymbol; 312 } 313 return resolved_flags; 314 } 315 316 uint32_t 317 SymbolFileSymtab::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) 318 { 319 return 0; 320 } 321 322 uint32_t 323 SymbolFileSymtab::FindGlobalVariables(const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables) 324 { 325 return 0; 326 } 327 328 uint32_t 329 SymbolFileSymtab::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables) 330 { 331 return 0; 332 } 333 334 uint32_t 335 SymbolFileSymtab::FindFunctions(const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool append, SymbolContextList& sc_list) 336 { 337 Timer scoped_timer (__PRETTY_FUNCTION__, 338 "SymbolFileSymtab::FindFunctions (name = '%s')", 339 name.GetCString()); 340 // If we ever support finding STABS or COFF debug info symbols, 341 // we will need to add support here. We are not trying to find symbols 342 // here, just "lldb_private::Function" objects that come from complete 343 // debug information. Any symbol queries should go through the symbol 344 // table itself in the module's object file. 345 return 0; 346 } 347 348 uint32_t 349 SymbolFileSymtab::FindFunctions(const RegularExpression& regex, bool append, SymbolContextList& sc_list) 350 { 351 Timer scoped_timer (__PRETTY_FUNCTION__, 352 "SymbolFileSymtab::FindFunctions (regex = '%s')", 353 regex.GetText()); 354 // If we ever support finding STABS or COFF debug info symbols, 355 // we will need to add support here. We are not trying to find symbols 356 // here, just "lldb_private::Function" objects that come from complete 357 // debug information. Any symbol queries should go through the symbol 358 // table itself in the module's object file. 359 return 0; 360 } 361 362 static int CountMethodArgs(const char *method_signature) 363 { 364 int num_args = 0; 365 366 for (const char *colon_pos = strchr(method_signature, ':'); 367 colon_pos != NULL; 368 colon_pos = strchr(colon_pos + 1, ':')) 369 { 370 num_args++; 371 } 372 373 return num_args; 374 } 375 376 uint32_t 377 SymbolFileSymtab::FindTypes (const lldb_private::SymbolContext& sc, 378 const lldb_private::ConstString &name, 379 const ClangNamespaceDecl *namespace_decl, 380 bool append, 381 uint32_t max_matches, 382 lldb_private::TypeList& types) 383 { 384 if (!append) 385 types.Clear(); 386 387 if (!m_objc_class_name_to_index.IsEmpty()) 388 { 389 TypeMap::iterator iter = m_objc_class_types.find(name); 390 391 if (iter != m_objc_class_types.end()) 392 { 393 types.Insert(iter->second); 394 return 1; 395 } 396 397 const Symtab::NameToIndexMap::Entry *match = m_objc_class_name_to_index.FindFirstValueForName(name.GetCString()); 398 399 if (match == NULL) 400 return 0; 401 402 const bool isForwardDecl = true; 403 const bool isInternal = true; 404 405 ClangASTContext &ast = GetClangASTContext(); 406 407 lldb::clang_type_t objc_object_type = ast.CreateObjCClass (name.AsCString(), 408 ast.GetTranslationUnitDecl(), 409 isForwardDecl, 410 isInternal); 411 412 ast.StartTagDeclarationDefinition (objc_object_type); 413 414 std::string regex_str("^[-+]\\["); // Make sure it starts with "+[" or "-[" 415 regex_str.append(name.AsCString()); // Followed by the class name 416 regex_str.append("[ \\(]"); // Followed by a space or '(' (for a category) 417 RegularExpression regex(regex_str.c_str()); 418 419 Symtab::IndexCollection indices; 420 421 lldb::clang_type_t unknown_type = ast.GetUnknownAnyType(); 422 std::vector<lldb::clang_type_t> arg_types; 423 424 if (m_obj_file->GetSymtab()->FindAllSymbolsMatchingRexExAndType (regex, eSymbolTypeCode, Symtab::eDebugNo, Symtab::eVisibilityAny, indices) != 0) 425 { 426 for (Symtab::IndexCollection::iterator pos = indices.begin(), end = indices.end(); 427 pos != end; 428 ++pos) 429 { 430 Symbol *symbol = m_obj_file->GetSymtab()->SymbolAtIndex(*pos); 431 432 if (!symbol) 433 continue; 434 435 const char *signature = symbol->GetName().AsCString(); 436 437 //printf ("%s: adding '%s'\n", name.GetCString(), signature); 438 int num_args = CountMethodArgs(signature); 439 440 while (arg_types.size() < num_args) 441 arg_types.push_back(unknown_type); 442 443 bool is_variadic = false; 444 unsigned type_quals = 0; 445 446 lldb::clang_type_t method_type = ast.CreateFunctionType (unknown_type, 447 arg_types.data(), 448 num_args, 449 is_variadic, 450 type_quals); 451 452 ast.AddMethodToObjCObjectType (objc_object_type, 453 signature, 454 method_type, 455 eAccessPublic); 456 } 457 } 458 459 ast.CompleteTagDeclarationDefinition (objc_object_type); 460 461 Declaration decl; 462 463 lldb::TypeSP type(new Type (indices[0], 464 this, 465 name, 466 0, // byte_size 467 NULL, // SymbolContextScope* 468 0, // encoding_uid 469 Type::eEncodingInvalid, 470 decl, 471 objc_object_type, 472 Type::eResolveStateFull)); 473 474 m_objc_class_types[name] = type; 475 476 types.Insert(type); 477 478 return 1; 479 } 480 481 return 0; 482 } 483 // 484 //uint32_t 485 //SymbolFileSymtab::FindTypes(const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, TypeList& types) 486 //{ 487 // return 0; 488 //} 489 490 491 //------------------------------------------------------------------ 492 // PluginInterface protocol 493 //------------------------------------------------------------------ 494 const char * 495 SymbolFileSymtab::GetPluginName() 496 { 497 return "SymbolFileSymtab"; 498 } 499 500 const char * 501 SymbolFileSymtab::GetShortPluginName() 502 { 503 return GetPluginNameStatic(); 504 } 505 506 uint32_t 507 SymbolFileSymtab::GetPluginVersion() 508 { 509 return 1; 510 } 511