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 (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 (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 } 281 else 282 { 283 // TODO: expose something in Process to figure out the 284 // size of a function prologue. 285 } 286 } 287 return m_type_data; 288 } 289 return 0; 290 } 291 292 bool 293 Symbol::Compare(const ConstString& name, SymbolType type) const 294 { 295 if (type == eSymbolTypeAny || m_type == type) 296 return m_mangled.GetMangledName() == name || m_mangled.GetDemangledName() == name; 297 return false; 298 } 299 300 #define ENUM_TO_CSTRING(x) case eSymbolType##x: return #x; 301 302 const char * 303 Symbol::GetTypeAsString() const 304 { 305 switch (m_type) 306 { 307 ENUM_TO_CSTRING(Invalid); 308 ENUM_TO_CSTRING(Absolute); 309 ENUM_TO_CSTRING(Code); 310 ENUM_TO_CSTRING(Data); 311 ENUM_TO_CSTRING(Trampoline); 312 ENUM_TO_CSTRING(Runtime); 313 ENUM_TO_CSTRING(Exception); 314 ENUM_TO_CSTRING(SourceFile); 315 ENUM_TO_CSTRING(HeaderFile); 316 ENUM_TO_CSTRING(ObjectFile); 317 ENUM_TO_CSTRING(CommonBlock); 318 ENUM_TO_CSTRING(Block); 319 ENUM_TO_CSTRING(Local); 320 ENUM_TO_CSTRING(Param); 321 ENUM_TO_CSTRING(Variable); 322 ENUM_TO_CSTRING(VariableType); 323 ENUM_TO_CSTRING(LineEntry); 324 ENUM_TO_CSTRING(LineHeader); 325 ENUM_TO_CSTRING(ScopeBegin); 326 ENUM_TO_CSTRING(ScopeEnd); 327 ENUM_TO_CSTRING(Additional); 328 ENUM_TO_CSTRING(Compiler); 329 ENUM_TO_CSTRING(Instrumentation); 330 ENUM_TO_CSTRING(Undefined); 331 ENUM_TO_CSTRING(ObjCClass); 332 ENUM_TO_CSTRING(ObjCMetaClass); 333 ENUM_TO_CSTRING(ObjCIVar); 334 default: 335 break; 336 } 337 return "<unknown SymbolType>"; 338 } 339 340 341 void 342 Symbol::CalculateSymbolContext (SymbolContext *sc) 343 { 344 // Symbols can reconstruct the symbol and the module in the symbol context 345 sc->symbol = this; 346 if (ValueIsAddress()) 347 sc->module_sp = GetAddress().GetModule(); 348 else 349 sc->module_sp.reset(); 350 } 351 352 ModuleSP 353 Symbol::CalculateSymbolContextModule () 354 { 355 if (ValueIsAddress()) 356 return GetAddress().GetModule(); 357 return ModuleSP(); 358 } 359 360 Symbol * 361 Symbol::CalculateSymbolContextSymbol () 362 { 363 return this; 364 } 365 366 367 void 368 Symbol::DumpSymbolContext (Stream *s) 369 { 370 bool dumped_module = false; 371 if (ValueIsAddress()) 372 { 373 ModuleSP module_sp (GetAddress().GetModule()); 374 if (module_sp) 375 { 376 dumped_module = true; 377 module_sp->DumpSymbolContext(s); 378 } 379 } 380 if (dumped_module) 381 s->PutCString(", "); 382 383 s->Printf("Symbol{0x%8.8x}", GetID()); 384 } 385 386 387 lldb::addr_t 388 Symbol::GetByteSize () const 389 { 390 addr_t byte_size = m_addr_range.GetByteSize(); 391 if (byte_size == 0 && !m_calculated_size) 392 { 393 const_cast<Symbol*>(this)->m_calculated_size = true; 394 if (ValueIsAddress()) 395 { 396 ModuleSP module_sp (GetAddress().GetModule()); 397 if (module_sp) 398 { 399 ObjectFile *objfile = module_sp->GetObjectFile(); 400 if (objfile) 401 { 402 Symtab *symtab = objfile->GetSymtab(); 403 if (symtab) 404 { 405 const_cast<Symbol*>(this)->SetByteSize (symtab->CalculateSymbolSize (const_cast<Symbol *>(this))); 406 byte_size = m_addr_range.GetByteSize(); 407 } 408 } 409 } 410 } 411 } 412 return byte_size; 413 } 414 415