1 //===-- Symbol.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/Symbol.h" 11 12 #include "lldb/Core/Module.h" 13 #include "lldb/Core/Section.h" 14 #include "lldb/Core/Stream.h" 15 #include "lldb/Symbol/ObjectFile.h" 16 #include "lldb/Symbol/Symtab.h" 17 #include "lldb/Symbol/Function.h" 18 #include "lldb/Target/Process.h" 19 #include "lldb/Target/Target.h" 20 #include "lldb/Symbol/SymbolVendor.h" 21 22 using namespace lldb; 23 using namespace lldb_private; 24 25 26 Symbol::Symbol() : 27 SymbolContextScope (), 28 m_uid (UINT32_MAX), 29 m_type_data (0), 30 m_type_data_resolved (false), 31 m_is_synthetic (false), 32 m_is_debug (false), 33 m_is_external (false), 34 m_size_is_sibling (false), 35 m_size_is_synthesized (false), 36 m_size_is_valid (false), 37 m_demangled_is_synthesized (false), 38 m_type (eSymbolTypeInvalid), 39 m_mangled (), 40 m_addr_range (), 41 m_flags () 42 { 43 } 44 45 Symbol::Symbol 46 ( 47 uint32_t symID, 48 const char *name, 49 bool name_is_mangled, 50 SymbolType type, 51 bool external, 52 bool is_debug, 53 bool is_trampoline, 54 bool is_artificial, 55 const lldb::SectionSP §ion_sp, 56 addr_t offset, 57 addr_t size, 58 bool size_is_valid, 59 uint32_t flags 60 ) : 61 SymbolContextScope (), 62 m_uid (symID), 63 m_type_data (0), 64 m_type_data_resolved (false), 65 m_is_synthetic (is_artificial), 66 m_is_debug (is_debug), 67 m_is_external (external), 68 m_size_is_sibling (false), 69 m_size_is_synthesized (false), 70 m_size_is_valid (size_is_valid || size > 0), 71 m_demangled_is_synthesized (false), 72 m_type (type), 73 m_mangled (ConstString(name), name_is_mangled), 74 m_addr_range (section_sp, offset, size), 75 m_flags (flags) 76 { 77 } 78 79 Symbol::Symbol 80 ( 81 uint32_t symID, 82 const char *name, 83 bool name_is_mangled, 84 SymbolType type, 85 bool external, 86 bool is_debug, 87 bool is_trampoline, 88 bool is_artificial, 89 const AddressRange &range, 90 bool size_is_valid, 91 uint32_t flags 92 ) : 93 SymbolContextScope (), 94 m_uid (symID), 95 m_type_data (0), 96 m_type_data_resolved (false), 97 m_is_synthetic (is_artificial), 98 m_is_debug (is_debug), 99 m_is_external (external), 100 m_size_is_sibling (false), 101 m_size_is_synthesized (false), 102 m_size_is_valid (size_is_valid || range.GetByteSize() > 0), 103 m_demangled_is_synthesized (false), 104 m_type (type), 105 m_mangled (ConstString(name), name_is_mangled), 106 m_addr_range (range), 107 m_flags (flags) 108 { 109 } 110 111 Symbol::Symbol(const Symbol& rhs): 112 SymbolContextScope (rhs), 113 m_uid (rhs.m_uid), 114 m_type_data (rhs.m_type_data), 115 m_type_data_resolved (rhs.m_type_data_resolved), 116 m_is_synthetic (rhs.m_is_synthetic), 117 m_is_debug (rhs.m_is_debug), 118 m_is_external (rhs.m_is_external), 119 m_size_is_sibling (rhs.m_size_is_sibling), 120 m_size_is_synthesized (false), 121 m_size_is_valid (rhs.m_size_is_valid), 122 m_demangled_is_synthesized (rhs.m_demangled_is_synthesized), 123 m_type (rhs.m_type), 124 m_mangled (rhs.m_mangled), 125 m_addr_range (rhs.m_addr_range), 126 m_flags (rhs.m_flags) 127 { 128 } 129 130 const Symbol& 131 Symbol::operator= (const Symbol& rhs) 132 { 133 if (this != &rhs) 134 { 135 SymbolContextScope::operator= (rhs); 136 m_uid = rhs.m_uid; 137 m_type_data = rhs.m_type_data; 138 m_type_data_resolved = rhs.m_type_data_resolved; 139 m_is_synthetic = rhs.m_is_synthetic; 140 m_is_debug = rhs.m_is_debug; 141 m_is_external = rhs.m_is_external; 142 m_size_is_sibling = rhs.m_size_is_sibling; 143 m_size_is_synthesized = rhs.m_size_is_sibling; 144 m_size_is_valid = rhs.m_size_is_valid; 145 m_demangled_is_synthesized = rhs.m_demangled_is_synthesized; 146 m_type = rhs.m_type; 147 m_mangled = rhs.m_mangled; 148 m_addr_range = rhs.m_addr_range; 149 m_flags = rhs.m_flags; 150 } 151 return *this; 152 } 153 154 void 155 Symbol::Clear() 156 { 157 m_uid = UINT32_MAX; 158 m_mangled.Clear(); 159 m_type_data = 0; 160 m_type_data_resolved = false; 161 m_is_synthetic = false; 162 m_is_debug = false; 163 m_is_external = false; 164 m_size_is_sibling = false; 165 m_size_is_synthesized = false; 166 m_size_is_valid = false; 167 m_demangled_is_synthesized = false; 168 m_type = eSymbolTypeInvalid; 169 m_flags = 0; 170 m_addr_range.Clear(); 171 } 172 173 bool 174 Symbol::ValueIsAddress() const 175 { 176 return m_addr_range.GetBaseAddress().GetSection().get() != NULL; 177 } 178 179 uint32_t 180 Symbol::GetSiblingIndex() const 181 { 182 return m_size_is_sibling ? m_addr_range.GetByteSize() : 0; 183 } 184 185 bool 186 Symbol::IsTrampoline () const 187 { 188 return m_type == eSymbolTypeTrampoline; 189 } 190 191 bool 192 Symbol::IsIndirect () const 193 { 194 return m_type == eSymbolTypeResolver; 195 } 196 197 void 198 Symbol::GetDescription (Stream *s, lldb::DescriptionLevel level, Target *target) const 199 { 200 s->Printf("id = {0x%8.8x}", m_uid); 201 202 if (m_addr_range.GetBaseAddress().GetSection()) 203 { 204 if (ValueIsAddress()) 205 { 206 const lldb::addr_t byte_size = GetByteSize(); 207 if (byte_size > 0) 208 { 209 s->PutCString (", range = "); 210 m_addr_range.Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress); 211 } 212 else 213 { 214 s->PutCString (", address = "); 215 m_addr_range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress); 216 } 217 } 218 else 219 s->Printf (", value = 0x%16.16" PRIx64, m_addr_range.GetBaseAddress().GetOffset()); 220 } 221 else 222 { 223 if (m_size_is_sibling) 224 s->Printf (", sibling = %5" PRIu64, m_addr_range.GetBaseAddress().GetOffset()); 225 else 226 s->Printf (", value = 0x%16.16" PRIx64, m_addr_range.GetBaseAddress().GetOffset()); 227 } 228 if (m_mangled.GetDemangledName()) 229 s->Printf(", name=\"%s\"", m_mangled.GetDemangledName().AsCString()); 230 if (m_mangled.GetMangledName()) 231 s->Printf(", mangled=\"%s\"", m_mangled.GetMangledName().AsCString()); 232 233 } 234 235 void 236 Symbol::Dump(Stream *s, Target *target, uint32_t index) const 237 { 238 // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 239 // s->Indent(); 240 // s->Printf("Symbol[%5u] %6u %c%c %-12s ", 241 s->Printf("[%5u] %6u %c%c%c %-12s ", 242 index, 243 GetID(), 244 m_is_debug ? 'D' : ' ', 245 m_is_synthetic ? 'S' : ' ', 246 m_is_external ? 'X' : ' ', 247 GetTypeAsString()); 248 249 // Make sure the size of the symbol is up to date before dumping 250 GetByteSize(); 251 252 if (ValueIsAddress()) 253 { 254 if (!m_addr_range.GetBaseAddress().Dump(s, NULL, Address::DumpStyleFileAddress)) 255 s->Printf("%*s", 18, ""); 256 257 s->PutChar(' '); 258 259 if (!m_addr_range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress)) 260 s->Printf("%*s", 18, ""); 261 262 const char *format = m_size_is_sibling ? 263 " Sibling -> [%5llu] 0x%8.8x %s\n": 264 " 0x%16.16" PRIx64 " 0x%8.8x %s\n"; 265 s->Printf( format, 266 GetByteSize(), 267 m_flags, 268 m_mangled.GetName().AsCString("")); 269 } 270 else 271 { 272 const char *format = m_size_is_sibling ? 273 "0x%16.16" PRIx64 " Sibling -> [%5llu] 0x%8.8x %s\n": 274 "0x%16.16" PRIx64 " 0x%16.16" PRIx64 " 0x%8.8x %s\n"; 275 s->Printf( format, 276 m_addr_range.GetBaseAddress().GetOffset(), 277 GetByteSize(), 278 m_flags, 279 m_mangled.GetName().AsCString("")); 280 } 281 } 282 283 uint32_t 284 Symbol::GetPrologueByteSize () 285 { 286 if (m_type == eSymbolTypeCode || m_type == eSymbolTypeResolver) 287 { 288 if (!m_type_data_resolved) 289 { 290 m_type_data_resolved = true; 291 292 const Address &base_address = m_addr_range.GetBaseAddress(); 293 Function *function = base_address.CalculateSymbolContextFunction(); 294 if (function) 295 { 296 // Functions have line entries which can also potentially have end of prologue information. 297 // So if this symbol points to a function, use the prologue information from there. 298 m_type_data = function->GetPrologueByteSize(); 299 } 300 else 301 { 302 ModuleSP module_sp (base_address.GetModule()); 303 SymbolContext sc; 304 if (module_sp) 305 { 306 uint32_t resolved_flags = module_sp->ResolveSymbolContextForAddress (base_address, 307 eSymbolContextLineEntry, 308 sc); 309 if (resolved_flags & eSymbolContextLineEntry) 310 { 311 // Default to the end of the first line entry. 312 m_type_data = sc.line_entry.range.GetByteSize(); 313 314 // Set address for next line. 315 Address addr (base_address); 316 addr.Slide (m_type_data); 317 318 // Check the first few instructions and look for one that has a line number that is 319 // different than the first entry. This is also done in Function::GetPrologueByteSize(). 320 uint16_t total_offset = m_type_data; 321 for (int idx = 0; idx < 6; ++idx) 322 { 323 SymbolContext sc_temp; 324 resolved_flags = module_sp->ResolveSymbolContextForAddress (addr, eSymbolContextLineEntry, sc_temp); 325 // Make sure we got line number information... 326 if (!(resolved_flags & eSymbolContextLineEntry)) 327 break; 328 329 // If this line number is different than our first one, use it and we're done. 330 if (sc_temp.line_entry.line != sc.line_entry.line) 331 { 332 m_type_data = total_offset; 333 break; 334 } 335 336 // Slide addr up to the next line address. 337 addr.Slide (sc_temp.line_entry.range.GetByteSize()); 338 total_offset += sc_temp.line_entry.range.GetByteSize(); 339 // If we've gone too far, bail out. 340 if (total_offset >= m_addr_range.GetByteSize()) 341 break; 342 } 343 344 // Sanity check - this may be a function in the middle of code that has debug information, but 345 // not for this symbol. So the line entries surrounding us won't lie inside our function. 346 // In that case, the line entry will be bigger than we are, so we do that quick check and 347 // if that is true, we just return 0. 348 if (m_type_data >= m_addr_range.GetByteSize()) 349 m_type_data = 0; 350 } 351 else 352 { 353 // TODO: expose something in Process to figure out the 354 // size of a function prologue. 355 m_type_data = 0; 356 } 357 } 358 } 359 } 360 return m_type_data; 361 } 362 return 0; 363 } 364 365 bool 366 Symbol::Compare(const ConstString& name, SymbolType type) const 367 { 368 if (type == eSymbolTypeAny || m_type == type) 369 return m_mangled.GetMangledName() == name || m_mangled.GetDemangledName() == name; 370 return false; 371 } 372 373 #define ENUM_TO_CSTRING(x) case eSymbolType##x: return #x; 374 375 const char * 376 Symbol::GetTypeAsString() const 377 { 378 switch (m_type) 379 { 380 ENUM_TO_CSTRING(Invalid); 381 ENUM_TO_CSTRING(Absolute); 382 ENUM_TO_CSTRING(Code); 383 ENUM_TO_CSTRING(Data); 384 ENUM_TO_CSTRING(Trampoline); 385 ENUM_TO_CSTRING(Runtime); 386 ENUM_TO_CSTRING(Exception); 387 ENUM_TO_CSTRING(SourceFile); 388 ENUM_TO_CSTRING(HeaderFile); 389 ENUM_TO_CSTRING(ObjectFile); 390 ENUM_TO_CSTRING(CommonBlock); 391 ENUM_TO_CSTRING(Block); 392 ENUM_TO_CSTRING(Local); 393 ENUM_TO_CSTRING(Param); 394 ENUM_TO_CSTRING(Variable); 395 ENUM_TO_CSTRING(VariableType); 396 ENUM_TO_CSTRING(LineEntry); 397 ENUM_TO_CSTRING(LineHeader); 398 ENUM_TO_CSTRING(ScopeBegin); 399 ENUM_TO_CSTRING(ScopeEnd); 400 ENUM_TO_CSTRING(Additional); 401 ENUM_TO_CSTRING(Compiler); 402 ENUM_TO_CSTRING(Instrumentation); 403 ENUM_TO_CSTRING(Undefined); 404 ENUM_TO_CSTRING(ObjCClass); 405 ENUM_TO_CSTRING(ObjCMetaClass); 406 ENUM_TO_CSTRING(ObjCIVar); 407 default: 408 break; 409 } 410 return "<unknown SymbolType>"; 411 } 412 413 void 414 Symbol::CalculateSymbolContext (SymbolContext *sc) 415 { 416 // Symbols can reconstruct the symbol and the module in the symbol context 417 sc->symbol = this; 418 if (ValueIsAddress()) 419 sc->module_sp = GetAddress().GetModule(); 420 else 421 sc->module_sp.reset(); 422 } 423 424 ModuleSP 425 Symbol::CalculateSymbolContextModule () 426 { 427 if (ValueIsAddress()) 428 return GetAddress().GetModule(); 429 return ModuleSP(); 430 } 431 432 Symbol * 433 Symbol::CalculateSymbolContextSymbol () 434 { 435 return this; 436 } 437 438 void 439 Symbol::DumpSymbolContext (Stream *s) 440 { 441 bool dumped_module = false; 442 if (ValueIsAddress()) 443 { 444 ModuleSP module_sp (GetAddress().GetModule()); 445 if (module_sp) 446 { 447 dumped_module = true; 448 module_sp->DumpSymbolContext(s); 449 } 450 } 451 if (dumped_module) 452 s->PutCString(", "); 453 454 s->Printf("Symbol{0x%8.8x}", GetID()); 455 } 456 457 lldb::addr_t 458 Symbol::GetByteSize () const 459 { 460 return m_addr_range.GetByteSize(); 461 } 462 463