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