1254721Semaste//===-- CompileUnit.cpp -----------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/Symbol/CompileUnit.h" 11254721Semaste#include "lldb/Core/Module.h" 12254721Semaste#include "lldb/Core/Language.h" 13254721Semaste#include "lldb/Symbol/LineTable.h" 14254721Semaste#include "lldb/Symbol/SymbolVendor.h" 15254721Semaste#include "lldb/Symbol/VariableList.h" 16254721Semaste 17254721Semasteusing namespace lldb; 18254721Semasteusing namespace lldb_private; 19254721Semaste 20254721SemasteCompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, const lldb::user_id_t cu_sym_id, lldb::LanguageType language) : 21254721Semaste ModuleChild(module_sp), 22254721Semaste FileSpec (pathname, false), 23254721Semaste UserID(cu_sym_id), 24254721Semaste m_user_data (user_data), 25254721Semaste m_language (language), 26254721Semaste m_flags (0), 27254721Semaste m_functions (), 28254721Semaste m_support_files (), 29254721Semaste m_line_table_ap (), 30254721Semaste m_variables() 31254721Semaste{ 32254721Semaste if (language != eLanguageTypeUnknown) 33254721Semaste m_flags.Set(flagsParsedLanguage); 34254721Semaste assert(module_sp); 35254721Semaste} 36254721Semaste 37254721SemasteCompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &fspec, const lldb::user_id_t cu_sym_id, lldb::LanguageType language) : 38254721Semaste ModuleChild(module_sp), 39254721Semaste FileSpec (fspec), 40254721Semaste UserID(cu_sym_id), 41254721Semaste m_user_data (user_data), 42254721Semaste m_language (language), 43254721Semaste m_flags (0), 44254721Semaste m_functions (), 45254721Semaste m_support_files (), 46254721Semaste m_line_table_ap (), 47254721Semaste m_variables() 48254721Semaste{ 49254721Semaste if (language != eLanguageTypeUnknown) 50254721Semaste m_flags.Set(flagsParsedLanguage); 51254721Semaste assert(module_sp); 52254721Semaste} 53254721Semaste 54254721SemasteCompileUnit::~CompileUnit () 55254721Semaste{ 56254721Semaste} 57254721Semaste 58254721Semastevoid 59254721SemasteCompileUnit::CalculateSymbolContext(SymbolContext* sc) 60254721Semaste{ 61254721Semaste sc->comp_unit = this; 62254721Semaste GetModule()->CalculateSymbolContext(sc); 63254721Semaste} 64254721Semaste 65254721SemasteModuleSP 66254721SemasteCompileUnit::CalculateSymbolContextModule () 67254721Semaste{ 68254721Semaste return GetModule(); 69254721Semaste} 70254721Semaste 71254721SemasteCompileUnit * 72254721SemasteCompileUnit::CalculateSymbolContextCompileUnit () 73254721Semaste{ 74254721Semaste return this; 75254721Semaste} 76254721Semaste 77254721Semastevoid 78254721SemasteCompileUnit::DumpSymbolContext(Stream *s) 79254721Semaste{ 80254721Semaste GetModule()->DumpSymbolContext(s); 81254721Semaste s->Printf(", CompileUnit{0x%8.8" PRIx64 "}", GetID()); 82254721Semaste} 83254721Semaste 84254721Semaste 85254721Semastevoid 86254721SemasteCompileUnit::GetDescription(Stream *s, lldb::DescriptionLevel level) const 87254721Semaste{ 88254721Semaste Language language(m_language); 89254721Semaste *s << "id = " << (const UserID&)*this << ", file = \"" << (const FileSpec&)*this << "\", language = \"" << language << '"'; 90254721Semaste} 91254721Semaste 92254721Semaste 93254721Semaste//---------------------------------------------------------------------- 94254721Semaste// Dump the current contents of this object. No functions that cause on 95254721Semaste// demand parsing of functions, globals, statics are called, so this 96254721Semaste// is a good function to call to get an idea of the current contents of 97254721Semaste// the CompileUnit object. 98254721Semaste//---------------------------------------------------------------------- 99254721Semastevoid 100254721SemasteCompileUnit::Dump(Stream *s, bool show_context) const 101254721Semaste{ 102254721Semaste s->Printf("%p: ", this); 103254721Semaste s->Indent(); 104254721Semaste *s << "CompileUnit" << (const UserID&)*this 105254721Semaste << ", language = \"" << (const Language&)*this 106254721Semaste << "\", file = '" << (const FileSpec&)*this << "'\n"; 107254721Semaste 108254721Semaste// m_types.Dump(s); 109254721Semaste 110254721Semaste if (m_variables.get()) 111254721Semaste { 112254721Semaste s->IndentMore(); 113254721Semaste m_variables->Dump(s, show_context); 114254721Semaste s->IndentLess(); 115254721Semaste } 116254721Semaste 117254721Semaste if (!m_functions.empty()) 118254721Semaste { 119254721Semaste s->IndentMore(); 120254721Semaste std::vector<FunctionSP>::const_iterator pos; 121254721Semaste std::vector<FunctionSP>::const_iterator end = m_functions.end(); 122254721Semaste for (pos = m_functions.begin(); pos != end; ++pos) 123254721Semaste { 124254721Semaste (*pos)->Dump(s, show_context); 125254721Semaste } 126254721Semaste 127254721Semaste s->IndentLess(); 128254721Semaste s->EOL(); 129254721Semaste } 130254721Semaste} 131254721Semaste 132254721Semaste//---------------------------------------------------------------------- 133254721Semaste// Add a function to this compile unit 134254721Semaste//---------------------------------------------------------------------- 135254721Semastevoid 136254721SemasteCompileUnit::AddFunction(FunctionSP& funcSP) 137254721Semaste{ 138254721Semaste // TODO: order these by address 139254721Semaste m_functions.push_back(funcSP); 140254721Semaste} 141254721Semaste 142254721SemasteFunctionSP 143254721SemasteCompileUnit::GetFunctionAtIndex (size_t idx) 144254721Semaste{ 145254721Semaste FunctionSP funcSP; 146254721Semaste if (idx < m_functions.size()) 147254721Semaste funcSP = m_functions[idx]; 148254721Semaste return funcSP; 149254721Semaste} 150254721Semaste 151254721Semaste//---------------------------------------------------------------------- 152254721Semaste// Find functions using the a Mangled::Tokens token list. This 153254721Semaste// function currently implements an interative approach designed to find 154254721Semaste// all instances of certain functions. It isn't designed to the the 155254721Semaste// quickest way to lookup functions as it will need to iterate through 156254721Semaste// all functions and see if they match, though it does provide a powerful 157254721Semaste// and context sensitive way to search for all functions with a certain 158254721Semaste// name, all functions in a namespace, or all functions of a template 159254721Semaste// type. See Mangled::Tokens::Parse() comments for more information. 160254721Semaste// 161254721Semaste// The function prototype will need to change to return a list of 162254721Semaste// results. It was originally used to help debug the Mangled class 163254721Semaste// and the Mangled::Tokens::MatchesQuery() function and it currently 164254721Semaste// will print out a list of matching results for the functions that 165254721Semaste// are currently in this compile unit. 166254721Semaste// 167254721Semaste// A FindFunctions method should be called prior to this that takes 168254721Semaste// a regular function name (const char * or ConstString as a parameter) 169254721Semaste// before resorting to this slower but more complete function. The 170254721Semaste// other FindFunctions method should be able to take advantage of any 171254721Semaste// accelerator tables available in the debug information (which is 172254721Semaste// parsed by the SymbolFile parser plug-ins and registered with each 173254721Semaste// Module). 174254721Semaste//---------------------------------------------------------------------- 175254721Semaste//void 176254721Semaste//CompileUnit::FindFunctions(const Mangled::Tokens& tokens) 177254721Semaste//{ 178254721Semaste// if (!m_functions.empty()) 179254721Semaste// { 180254721Semaste// Stream s(stdout); 181254721Semaste// std::vector<FunctionSP>::const_iterator pos; 182254721Semaste// std::vector<FunctionSP>::const_iterator end = m_functions.end(); 183254721Semaste// for (pos = m_functions.begin(); pos != end; ++pos) 184254721Semaste// { 185254721Semaste// const ConstString& demangled = (*pos)->Mangled().Demangled(); 186254721Semaste// if (demangled) 187254721Semaste// { 188254721Semaste// const Mangled::Tokens& func_tokens = (*pos)->Mangled().GetTokens(); 189254721Semaste// if (func_tokens.MatchesQuery (tokens)) 190254721Semaste// s << "demangled MATCH found: " << demangled << "\n"; 191254721Semaste// } 192254721Semaste// } 193254721Semaste// } 194254721Semaste//} 195254721Semaste 196254721SemasteFunctionSP 197254721SemasteCompileUnit::FindFunctionByUID (lldb::user_id_t func_uid) 198254721Semaste{ 199254721Semaste FunctionSP funcSP; 200254721Semaste if (!m_functions.empty()) 201254721Semaste { 202254721Semaste std::vector<FunctionSP>::const_iterator pos; 203254721Semaste std::vector<FunctionSP>::const_iterator end = m_functions.end(); 204254721Semaste for (pos = m_functions.begin(); pos != end; ++pos) 205254721Semaste { 206254721Semaste if ((*pos)->GetID() == func_uid) 207254721Semaste { 208254721Semaste funcSP = *pos; 209254721Semaste break; 210254721Semaste } 211254721Semaste } 212254721Semaste } 213254721Semaste return funcSP; 214254721Semaste} 215254721Semaste 216254721Semaste 217254721Semastelldb::LanguageType 218254721SemasteCompileUnit::GetLanguage() 219254721Semaste{ 220254721Semaste if (m_language == eLanguageTypeUnknown) 221254721Semaste { 222254721Semaste if (m_flags.IsClear(flagsParsedLanguage)) 223254721Semaste { 224254721Semaste m_flags.Set(flagsParsedLanguage); 225254721Semaste SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor(); 226254721Semaste if (symbol_vendor) 227254721Semaste { 228254721Semaste SymbolContext sc; 229254721Semaste CalculateSymbolContext(&sc); 230254721Semaste m_language = symbol_vendor->ParseCompileUnitLanguage(sc); 231254721Semaste } 232254721Semaste } 233254721Semaste } 234254721Semaste return m_language; 235254721Semaste} 236254721Semaste 237254721SemasteLineTable* 238254721SemasteCompileUnit::GetLineTable() 239254721Semaste{ 240254721Semaste if (m_line_table_ap.get() == NULL) 241254721Semaste { 242254721Semaste if (m_flags.IsClear(flagsParsedLineTable)) 243254721Semaste { 244254721Semaste m_flags.Set(flagsParsedLineTable); 245254721Semaste SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor(); 246254721Semaste if (symbol_vendor) 247254721Semaste { 248254721Semaste SymbolContext sc; 249254721Semaste CalculateSymbolContext(&sc); 250254721Semaste symbol_vendor->ParseCompileUnitLineTable(sc); 251254721Semaste } 252254721Semaste } 253254721Semaste } 254254721Semaste return m_line_table_ap.get(); 255254721Semaste} 256254721Semaste 257254721Semastevoid 258254721SemasteCompileUnit::SetLineTable(LineTable* line_table) 259254721Semaste{ 260254721Semaste if (line_table == NULL) 261254721Semaste m_flags.Clear(flagsParsedLineTable); 262254721Semaste else 263254721Semaste m_flags.Set(flagsParsedLineTable); 264254721Semaste m_line_table_ap.reset(line_table); 265254721Semaste} 266254721Semaste 267254721SemasteVariableListSP 268254721SemasteCompileUnit::GetVariableList(bool can_create) 269254721Semaste{ 270254721Semaste if (m_variables.get() == NULL && can_create) 271254721Semaste { 272254721Semaste SymbolContext sc; 273254721Semaste CalculateSymbolContext(&sc); 274254721Semaste assert(sc.module_sp); 275254721Semaste sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); 276254721Semaste } 277254721Semaste 278254721Semaste return m_variables; 279254721Semaste} 280254721Semaste 281254721Semasteuint32_t 282254721SemasteCompileUnit::FindLineEntry (uint32_t start_idx, uint32_t line, const FileSpec* file_spec_ptr, bool exact, LineEntry *line_entry_ptr) 283254721Semaste{ 284254721Semaste uint32_t file_idx = 0; 285254721Semaste 286254721Semaste if (file_spec_ptr) 287254721Semaste { 288254721Semaste file_idx = GetSupportFiles().FindFileIndex (1, *file_spec_ptr, true); 289254721Semaste if (file_idx == UINT32_MAX) 290254721Semaste return UINT32_MAX; 291254721Semaste } 292254721Semaste else 293254721Semaste { 294254721Semaste // All the line table entries actually point to the version of the Compile 295254721Semaste // Unit that is in the support files (the one at 0 was artifically added.) 296254721Semaste // So prefer the one further on in the support files if it exists... 297254721Semaste FileSpecList &support_files = GetSupportFiles(); 298254721Semaste const bool full = true; 299254721Semaste file_idx = support_files.FindFileIndex (1, support_files.GetFileSpecAtIndex(0), full); 300254721Semaste if (file_idx == UINT32_MAX) 301254721Semaste file_idx = 0; 302254721Semaste } 303254721Semaste LineTable *line_table = GetLineTable(); 304254721Semaste if (line_table) 305254721Semaste return line_table->FindLineEntryIndexByFileIndex (start_idx, file_idx, line, exact, line_entry_ptr); 306254721Semaste return UINT32_MAX; 307254721Semaste} 308254721Semaste 309254721Semaste 310254721Semaste 311254721Semaste 312254721Semasteuint32_t 313254721SemasteCompileUnit::ResolveSymbolContext 314254721Semaste( 315254721Semaste const FileSpec& file_spec, 316254721Semaste uint32_t line, 317254721Semaste bool check_inlines, 318254721Semaste bool exact, 319254721Semaste uint32_t resolve_scope, 320254721Semaste SymbolContextList &sc_list 321254721Semaste) 322254721Semaste{ 323254721Semaste // First find all of the file indexes that match our "file_spec". If 324254721Semaste // "file_spec" has an empty directory, then only compare the basenames 325254721Semaste // when finding file indexes 326254721Semaste std::vector<uint32_t> file_indexes; 327263363Semaste const bool full_match = (bool)file_spec.GetDirectory(); 328254721Semaste bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, *this, full_match); 329254721Semaste 330254721Semaste // If we are not looking for inlined functions and our file spec doesn't 331254721Semaste // match then we are done... 332254721Semaste if (file_spec_matches_cu_file_spec == false && check_inlines == false) 333254721Semaste return 0; 334254721Semaste 335254721Semaste uint32_t file_idx = GetSupportFiles().FindFileIndex (1, file_spec, true); 336254721Semaste while (file_idx != UINT32_MAX) 337254721Semaste { 338254721Semaste file_indexes.push_back (file_idx); 339254721Semaste file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec, true); 340254721Semaste } 341254721Semaste 342254721Semaste const size_t num_file_indexes = file_indexes.size(); 343254721Semaste if (num_file_indexes == 0) 344254721Semaste return 0; 345254721Semaste 346254721Semaste const uint32_t prev_size = sc_list.GetSize(); 347254721Semaste 348254721Semaste SymbolContext sc(GetModule()); 349254721Semaste sc.comp_unit = this; 350254721Semaste 351254721Semaste 352254721Semaste if (line != 0) 353254721Semaste { 354254721Semaste LineTable *line_table = sc.comp_unit->GetLineTable(); 355254721Semaste 356254721Semaste if (line_table != NULL) 357254721Semaste { 358254721Semaste uint32_t found_line; 359254721Semaste uint32_t line_idx; 360254721Semaste 361254721Semaste if (num_file_indexes == 1) 362254721Semaste { 363254721Semaste // We only have a single support file that matches, so use 364254721Semaste // the line table function that searches for a line entries 365254721Semaste // that match a single support file index 366254721Semaste LineEntry line_entry; 367254721Semaste line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_indexes.front(), line, exact, &line_entry); 368254721Semaste 369254721Semaste // If "exact == true", then "found_line" will be the same 370254721Semaste // as "line". If "exact == false", the "found_line" will be the 371254721Semaste // closest line entry with a line number greater than "line" and 372254721Semaste // we will use this for our subsequent line exact matches below. 373254721Semaste found_line = line_entry.line; 374254721Semaste 375254721Semaste while (line_idx != UINT32_MAX) 376254721Semaste { 377254721Semaste // If they only asked for the line entry, then we're done, we can just copy that over. 378254721Semaste // But if they wanted more than just the line number, fill it in. 379254721Semaste if (resolve_scope == eSymbolContextLineEntry) 380254721Semaste { 381254721Semaste sc.line_entry = line_entry; 382254721Semaste } 383254721Semaste else 384254721Semaste { 385254721Semaste line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc, resolve_scope); 386254721Semaste } 387254721Semaste 388254721Semaste sc_list.Append(sc); 389254721Semaste line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_indexes.front(), found_line, true, &line_entry); 390254721Semaste } 391254721Semaste } 392254721Semaste else 393254721Semaste { 394254721Semaste // We found multiple support files that match "file_spec" so use 395254721Semaste // the line table function that searches for a line entries 396254721Semaste // that match a multiple support file indexes. 397254721Semaste LineEntry line_entry; 398254721Semaste line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_indexes, line, exact, &line_entry); 399254721Semaste 400254721Semaste // If "exact == true", then "found_line" will be the same 401254721Semaste // as "line". If "exact == false", the "found_line" will be the 402254721Semaste // closest line entry with a line number greater than "line" and 403254721Semaste // we will use this for our subsequent line exact matches below. 404254721Semaste found_line = line_entry.line; 405254721Semaste 406254721Semaste while (line_idx != UINT32_MAX) 407254721Semaste { 408254721Semaste if (resolve_scope == eSymbolContextLineEntry) 409254721Semaste { 410254721Semaste sc.line_entry = line_entry; 411254721Semaste } 412254721Semaste else 413254721Semaste { 414254721Semaste line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc, resolve_scope); 415254721Semaste } 416254721Semaste 417254721Semaste sc_list.Append(sc); 418254721Semaste line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_indexes, found_line, true, &line_entry); 419254721Semaste } 420254721Semaste } 421254721Semaste } 422254721Semaste } 423254721Semaste else if (file_spec_matches_cu_file_spec && !check_inlines) 424254721Semaste { 425254721Semaste // only append the context if we aren't looking for inline call sites 426254721Semaste // by file and line and if the file spec matches that of the compile unit 427254721Semaste sc_list.Append(sc); 428254721Semaste } 429254721Semaste return sc_list.GetSize() - prev_size; 430254721Semaste} 431254721Semaste 432254721Semastevoid 433254721SemasteCompileUnit::SetVariableList(VariableListSP &variables) 434254721Semaste{ 435254721Semaste m_variables = variables; 436254721Semaste} 437254721Semaste 438254721SemasteFileSpecList& 439254721SemasteCompileUnit::GetSupportFiles () 440254721Semaste{ 441254721Semaste if (m_support_files.GetSize() == 0) 442254721Semaste { 443254721Semaste if (m_flags.IsClear(flagsParsedSupportFiles)) 444254721Semaste { 445254721Semaste m_flags.Set(flagsParsedSupportFiles); 446254721Semaste SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor(); 447254721Semaste if (symbol_vendor) 448254721Semaste { 449254721Semaste SymbolContext sc; 450254721Semaste CalculateSymbolContext(&sc); 451254721Semaste symbol_vendor->ParseCompileUnitSupportFiles(sc, m_support_files); 452254721Semaste } 453254721Semaste } 454254721Semaste } 455254721Semaste return m_support_files; 456254721Semaste} 457254721Semaste 458254721Semastevoid * 459254721SemasteCompileUnit::GetUserData () const 460254721Semaste{ 461254721Semaste return m_user_data; 462254721Semaste} 463254721Semaste 464254721Semaste 465