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