CompileUnit.cpp revision 12bec71b323dc520f0e985a86e09c4712559e115
1//===-- CompileUnit.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/CompileUnit.h" 11#include "lldb/Symbol/LineTable.h" 12#include "lldb/Core/Module.h" 13#include "lldb/Symbol/SymbolVendor.h" 14#include "lldb/Symbol/VariableList.h" 15 16using namespace lldb; 17using namespace lldb_private; 18 19CompileUnit::CompileUnit (Module *module, void *user_data, const char *pathname, const lldb::user_id_t cu_sym_id, Language::Type language) : 20 ModuleChild(module), 21 FileSpec (pathname), 22 UserID(cu_sym_id), 23 Language (language), 24 m_user_data (user_data), 25 m_flags (0), 26 m_functions (), 27 m_support_files (), 28 m_line_table_ap (), 29 m_variables() 30{ 31 assert(module != NULL); 32} 33 34CompileUnit::CompileUnit (Module *module, void *user_data, const FileSpec &fspec, const lldb::user_id_t cu_sym_id, Language::Type language) : 35 ModuleChild(module), 36 FileSpec (fspec), 37 UserID(cu_sym_id), 38 Language (language), 39 m_user_data (user_data), 40 m_flags (0), 41 m_functions (), 42 m_support_files (), 43 m_line_table_ap (), 44 m_variables() 45{ 46 assert(module != NULL); 47} 48 49CompileUnit::~CompileUnit () 50{ 51} 52 53void 54CompileUnit::CalculateSymbolContext(SymbolContext* sc) 55{ 56 sc->comp_unit = this; 57 GetModule()->CalculateSymbolContext(sc); 58} 59 60void 61CompileUnit::DumpSymbolContext(Stream *s) 62{ 63 GetModule()->DumpSymbolContext(s); 64 s->Printf(", CompileUnit{0x%8.8x}", GetID()); 65} 66 67 68void 69CompileUnit::GetDescription(Stream *s, lldb::DescriptionLevel level) const 70{ 71 *s << '"' << (const FileSpec&)*this << "\", id = " << (const UserID&)*this 72 << ", language = " << (const Language&)*this; 73} 74 75 76//---------------------------------------------------------------------- 77// Dump the current contents of this object. No functions that cause on 78// demand parsing of functions, globals, statics are called, so this 79// is a good function to call to get an idea of the current contents of 80// the CompileUnit object. 81//---------------------------------------------------------------------- 82void 83CompileUnit::Dump(Stream *s, bool show_context) const 84{ 85 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 86 s->Indent(); 87 *s << "CompileUnit" << (const UserID&)*this 88 << ", language = " << (const Language&)*this 89 << ", file='" << (const FileSpec&)*this << "'\n"; 90 91// m_types.Dump(s); 92 93 if (m_variables.get()) 94 { 95 s->IndentMore(); 96 m_variables->Dump(s, show_context); 97 s->IndentLess(); 98 } 99 100 if (!m_functions.empty()) 101 { 102 s->IndentMore(); 103 std::vector<FunctionSP>::const_iterator pos; 104 std::vector<FunctionSP>::const_iterator end = m_functions.end(); 105 for (pos = m_functions.begin(); pos != end; ++pos) 106 { 107 (*pos)->Dump(s, show_context); 108 } 109 110 s->IndentLess(); 111 s->EOL(); 112 } 113} 114 115//---------------------------------------------------------------------- 116// Add a function to this compile unit 117//---------------------------------------------------------------------- 118void 119CompileUnit::AddFunction(FunctionSP& funcSP) 120{ 121 // TODO: order these by address 122 m_functions.push_back(funcSP); 123} 124 125FunctionSP 126CompileUnit::GetFunctionAtIndex (size_t idx) 127{ 128 FunctionSP funcSP; 129 if (idx < m_functions.size()) 130 funcSP = m_functions[idx]; 131 return funcSP; 132} 133 134//---------------------------------------------------------------------- 135// Find functions using the a Mangled::Tokens token list. This 136// function currently implements an interative approach designed to find 137// all instances of certain functions. It isn't designed to the the 138// quickest way to lookup functions as it will need to iterate through 139// all functions and see if they match, though it does provide a powerful 140// and context sensitive way to search for all functions with a certain 141// name, all functions in a namespace, or all functions of a template 142// type. See Mangled::Tokens::Parse() comments for more information. 143// 144// The function prototype will need to change to return a list of 145// results. It was originally used to help debug the Mangled class 146// and the Mangled::Tokens::MatchesQuery() function and it currently 147// will print out a list of matching results for the functions that 148// are currently in this compile unit. 149// 150// A FindFunctions method should be called prior to this that takes 151// a regular function name (const char * or ConstString as a parameter) 152// before resorting to this slower but more complete function. The 153// other FindFunctions method should be able to take advantage of any 154// accelerator tables available in the debug information (which is 155// parsed by the SymbolFile parser plug-ins and registered with each 156// Module). 157//---------------------------------------------------------------------- 158//void 159//CompileUnit::FindFunctions(const Mangled::Tokens& tokens) 160//{ 161// if (!m_functions.empty()) 162// { 163// Stream s(stdout); 164// std::vector<FunctionSP>::const_iterator pos; 165// std::vector<FunctionSP>::const_iterator end = m_functions.end(); 166// for (pos = m_functions.begin(); pos != end; ++pos) 167// { 168// const ConstString& demangled = (*pos)->Mangled().Demangled(); 169// if (demangled) 170// { 171// const Mangled::Tokens& func_tokens = (*pos)->Mangled().GetTokens(); 172// if (func_tokens.MatchesQuery (tokens)) 173// s << "demangled MATCH found: " << demangled << "\n"; 174// } 175// } 176// } 177//} 178 179FunctionSP 180CompileUnit::FindFunctionByUID (lldb::user_id_t func_uid) 181{ 182 FunctionSP funcSP; 183 if (!m_functions.empty()) 184 { 185 std::vector<FunctionSP>::const_iterator pos; 186 std::vector<FunctionSP>::const_iterator end = m_functions.end(); 187 for (pos = m_functions.begin(); pos != end; ++pos) 188 { 189 if ((*pos)->GetID() == func_uid) 190 { 191 funcSP = *pos; 192 break; 193 } 194 } 195 } 196 return funcSP; 197} 198 199 200LineTable* 201CompileUnit::GetLineTable() 202{ 203 if (m_line_table_ap.get() == NULL) 204 { 205 if (m_flags.IsClear(flagsParsedLineTable)) 206 { 207 m_flags.Set(flagsParsedLineTable); 208 SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor(); 209 if (symbol_vendor) 210 { 211 SymbolContext sc; 212 CalculateSymbolContext(&sc); 213 symbol_vendor->ParseCompileUnitLineTable(sc); 214 } 215 } 216 } 217 return m_line_table_ap.get(); 218} 219 220void 221CompileUnit::SetLineTable(LineTable* line_table) 222{ 223 if (line_table == NULL) 224 m_flags.Clear(flagsParsedLineTable); 225 else 226 m_flags.Set(flagsParsedLineTable); 227 m_line_table_ap.reset(line_table); 228} 229 230VariableListSP 231CompileUnit::GetVariableList(bool can_create) 232{ 233 if (m_variables.get() == NULL && can_create) 234 { 235 SymbolContext sc; 236 CalculateSymbolContext(&sc); 237 assert(sc.module_sp); 238 sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); 239 } 240 241 return m_variables; 242} 243 244uint32_t 245CompileUnit::FindLineEntry (uint32_t start_idx, uint32_t line, const FileSpec* file_spec_ptr, LineEntry *line_entry_ptr) 246{ 247 uint32_t file_idx = 0; 248 249 if (file_spec_ptr) 250 { 251 file_idx = GetSupportFiles().FindFileIndex (1, *file_spec_ptr); 252 if (file_idx == UINT32_MAX) 253 return UINT32_MAX; 254 } 255 else 256 { 257 // All the line table entries actually point to the version of the Compile 258 // Unit that is in the support files (the one at 0 was artifically added.) 259 // So prefer the one further on in the support files if it exists... 260 FileSpecList &support_files = GetSupportFiles(); 261 file_idx = support_files.FindFileIndex (1, support_files.GetFileSpecAtIndex(0)); 262 if (file_idx == UINT32_MAX) 263 file_idx = 0; 264 } 265 LineTable *line_table = GetLineTable(); 266 if (line_table) 267 return line_table->FindLineEntryIndexByFileIndex (start_idx, file_idx, line, true, line_entry_ptr); 268 return UINT32_MAX; 269} 270 271 272 273 274uint32_t 275CompileUnit::ResolveSymbolContext 276( 277 const FileSpec& file_spec, 278 uint32_t line, 279 bool check_inlines, 280 bool exact, 281 uint32_t resolve_scope, 282 SymbolContextList &sc_list 283) 284{ 285 const uint32_t prev_size = sc_list.GetSize(); 286 bool file_spec_matches_cu_file_spec = FileSpec::Compare(file_spec, this, !file_spec.GetDirectory().IsEmpty()) == 0; 287 if (check_inlines || file_spec_matches_cu_file_spec) 288 { 289 SymbolContext sc(GetModule()); 290 sc.comp_unit = this; 291 292 uint32_t file_idx = UINT32_MAX; 293 294 // If we are looking for inline functions only and we don't 295 // find it in the support files, we are done. 296 297 if (check_inlines) 298 { 299 file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec); 300 if (file_idx == UINT32_MAX) 301 return 0; 302 } 303 304 if (line != 0) 305 { 306 LineTable *line_table = sc.comp_unit->GetLineTable(); 307 308 if (line_table != NULL) 309 { 310 // We will have already looked up the file index if 311 // we are searching for inline entries. 312 if (!check_inlines) 313 file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec); 314 315 if (file_idx != UINT32_MAX) 316 { 317 uint32_t found_line; 318 319 uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_idx, line, exact, &sc.line_entry); 320 found_line = sc.line_entry.line; 321 322 while (line_idx != UINT_MAX) 323 { 324 sc_list.Append(sc); 325 line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_idx, found_line, true, &sc.line_entry); 326 } 327 } 328 } 329 } 330 else if (file_spec_matches_cu_file_spec && !check_inlines) 331 { 332 // only append the context if we aren't looking for inline call sites 333 // by file and line and if the file spec matches that of the compile unit 334 sc_list.Append(sc); 335 } 336 337 } 338 return sc_list.GetSize() - prev_size; 339} 340 341void 342CompileUnit::SetVariableList(VariableListSP &variables) 343{ 344 m_variables = variables; 345} 346 347FileSpecList& 348CompileUnit::GetSupportFiles () 349{ 350 if (m_support_files.GetSize() == 0) 351 { 352 if (m_flags.IsClear(flagsParsedSupportFiles)) 353 { 354 m_flags.Set(flagsParsedSupportFiles); 355 SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor(); 356 if (symbol_vendor) 357 { 358 SymbolContext sc; 359 CalculateSymbolContext(&sc); 360 symbol_vendor->ParseCompileUnitSupportFiles(sc, m_support_files); 361 } 362 } 363 } 364 return m_support_files; 365} 366 367void * 368CompileUnit::GetUserData () const 369{ 370 return m_user_data; 371} 372 373 374