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