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 uint32_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 void 188 Symbol::GetDescription (Stream *s, lldb::DescriptionLevel level, Target *target) const 189 { 190 s->Printf("id = {0x%8.8x}", m_uid); 191 192 if (m_addr_range.GetBaseAddress().GetSection()) 193 { 194 if (ValueIsAddress()) 195 { 196 const lldb::addr_t byte_size = GetByteSize(); 197 if (byte_size > 0) 198 { 199 s->PutCString (", range = "); 200 m_addr_range.Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress); 201 } 202 else 203 { 204 s->PutCString (", address = "); 205 m_addr_range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress); 206 } 207 } 208 else 209 s->Printf (", value = 0x%16.16llx", m_addr_range.GetBaseAddress().GetOffset()); 210 } 211 else 212 { 213 if (m_size_is_sibling) 214 s->Printf (", sibling = %5llu", m_addr_range.GetBaseAddress().GetOffset()); 215 else 216 s->Printf (", value = 0x%16.16llx", m_addr_range.GetBaseAddress().GetOffset()); 217 } 218 if (m_mangled.GetDemangledName()) 219 s->Printf(", name=\"%s\"", m_mangled.GetDemangledName().AsCString()); 220 if (m_mangled.GetMangledName()) 221 s->Printf(", mangled=\"%s\"", m_mangled.GetMangledName().AsCString()); 222 223 } 224 225 void 226 Symbol::Dump(Stream *s, Target *target, uint32_t index) const 227 { 228 // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 229 // s->Indent(); 230 // s->Printf("Symbol[%5u] %6u %c%c %-12s ", 231 s->Printf("[%5u] %6u %c%c%c %-12s ", 232 index, 233 GetID(), 234 m_is_debug ? 'D' : ' ', 235 m_is_synthetic ? 'S' : ' ', 236 m_is_external ? 'X' : ' ', 237 GetTypeAsString()); 238 239 // Make sure the size of the symbol is up to date before dumping 240 GetByteSize(); 241 242 if (ValueIsAddress()) 243 { 244 if (!m_addr_range.GetBaseAddress().Dump(s, NULL, Address::DumpStyleFileAddress)) 245 s->Printf("%*s", 18, ""); 246 247 s->PutChar(' '); 248 249 if (!m_addr_range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress)) 250 s->Printf("%*s", 18, ""); 251 252 const char *format = m_size_is_sibling ? 253 " Sibling -> [%5llu] 0x%8.8x %s\n": 254 " 0x%16.16llx 0x%8.8x %s\n"; 255 s->Printf( format, 256 GetByteSize(), 257 m_flags, 258 m_mangled.GetName().AsCString("")); 259 } 260 else 261 { 262 const char *format = m_size_is_sibling ? 263 "0x%16.16llx Sibling -> [%5llu] 0x%8.8x %s\n": 264 "0x%16.16llx 0x%16.16llx 0x%8.8x %s\n"; 265 s->Printf( format, 266 m_addr_range.GetBaseAddress().GetOffset(), 267 GetByteSize(), 268 m_flags, 269 m_mangled.GetName().AsCString("")); 270 } 271 } 272 273 uint32_t 274 Symbol::GetPrologueByteSize () 275 { 276 if (m_type == eSymbolTypeCode) 277 { 278 if (!m_type_data_resolved) 279 { 280 m_type_data_resolved = true; 281 ModuleSP module_sp (m_addr_range.GetBaseAddress().GetModule()); 282 SymbolContext sc; 283 if (module_sp && module_sp->ResolveSymbolContextForAddress (m_addr_range.GetBaseAddress(), 284 eSymbolContextLineEntry, 285 sc)) 286 { 287 m_type_data = sc.line_entry.range.GetByteSize(); 288 // Sanity check - this may be a function in the middle of code that has debug information, but 289 // not for this symbol. So the line entries surrounding us won't lie inside our function. 290 // In that case, the line entry will be bigger than we are, so we do that quick check and 291 // if that is true, we just return 0. 292 if (m_type_data >= m_addr_range.GetByteSize()) 293 m_type_data = 0; 294 } 295 else 296 { 297 // TODO: expose something in Process to figure out the 298 // size of a function prologue. 299 } 300 } 301 return m_type_data; 302 } 303 return 0; 304 } 305 306 bool 307 Symbol::Compare(const ConstString& name, SymbolType type) const 308 { 309 if (type == eSymbolTypeAny || m_type == type) 310 return m_mangled.GetMangledName() == name || m_mangled.GetDemangledName() == name; 311 return false; 312 } 313 314 #define ENUM_TO_CSTRING(x) case eSymbolType##x: return #x; 315 316 const char * 317 Symbol::GetTypeAsString() const 318 { 319 switch (m_type) 320 { 321 ENUM_TO_CSTRING(Invalid); 322 ENUM_TO_CSTRING(Absolute); 323 ENUM_TO_CSTRING(Code); 324 ENUM_TO_CSTRING(Data); 325 ENUM_TO_CSTRING(Trampoline); 326 ENUM_TO_CSTRING(Runtime); 327 ENUM_TO_CSTRING(Exception); 328 ENUM_TO_CSTRING(SourceFile); 329 ENUM_TO_CSTRING(HeaderFile); 330 ENUM_TO_CSTRING(ObjectFile); 331 ENUM_TO_CSTRING(CommonBlock); 332 ENUM_TO_CSTRING(Block); 333 ENUM_TO_CSTRING(Local); 334 ENUM_TO_CSTRING(Param); 335 ENUM_TO_CSTRING(Variable); 336 ENUM_TO_CSTRING(VariableType); 337 ENUM_TO_CSTRING(LineEntry); 338 ENUM_TO_CSTRING(LineHeader); 339 ENUM_TO_CSTRING(ScopeBegin); 340 ENUM_TO_CSTRING(ScopeEnd); 341 ENUM_TO_CSTRING(Additional); 342 ENUM_TO_CSTRING(Compiler); 343 ENUM_TO_CSTRING(Instrumentation); 344 ENUM_TO_CSTRING(Undefined); 345 ENUM_TO_CSTRING(ObjCClass); 346 ENUM_TO_CSTRING(ObjCMetaClass); 347 ENUM_TO_CSTRING(ObjCIVar); 348 default: 349 break; 350 } 351 return "<unknown SymbolType>"; 352 } 353 354 355 void 356 Symbol::CalculateSymbolContext (SymbolContext *sc) 357 { 358 // Symbols can reconstruct the symbol and the module in the symbol context 359 sc->symbol = this; 360 if (ValueIsAddress()) 361 sc->module_sp = GetAddress().GetModule(); 362 else 363 sc->module_sp.reset(); 364 } 365 366 ModuleSP 367 Symbol::CalculateSymbolContextModule () 368 { 369 if (ValueIsAddress()) 370 return GetAddress().GetModule(); 371 return ModuleSP(); 372 } 373 374 Symbol * 375 Symbol::CalculateSymbolContextSymbol () 376 { 377 return this; 378 } 379 380 381 void 382 Symbol::DumpSymbolContext (Stream *s) 383 { 384 bool dumped_module = false; 385 if (ValueIsAddress()) 386 { 387 ModuleSP module_sp (GetAddress().GetModule()); 388 if (module_sp) 389 { 390 dumped_module = true; 391 module_sp->DumpSymbolContext(s); 392 } 393 } 394 if (dumped_module) 395 s->PutCString(", "); 396 397 s->Printf("Symbol{0x%8.8x}", GetID()); 398 } 399 400 401 lldb::addr_t 402 Symbol::GetByteSize () const 403 { 404 addr_t byte_size = m_addr_range.GetByteSize(); 405 if (byte_size == 0 && !m_calculated_size) 406 { 407 const_cast<Symbol*>(this)->m_calculated_size = true; 408 if (ValueIsAddress()) 409 { 410 ModuleSP module_sp (GetAddress().GetModule()); 411 if (module_sp) 412 { 413 ObjectFile *objfile = module_sp->GetObjectFile(); 414 if (objfile) 415 { 416 Symtab *symtab = objfile->GetSymtab(); 417 if (symtab) 418 { 419 const_cast<Symbol*>(this)->SetByteSize (symtab->CalculateSymbolSize (const_cast<Symbol *>(this))); 420 byte_size = m_addr_range.GetByteSize(); 421 } 422 } 423 } 424 } 425 } 426 return byte_size; 427 } 428 429