1 //===-- Section.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/Core/Section.h" 11 #include "lldb/Core/Module.h" 12 #include "lldb/Symbol/ObjectFile.h" 13 #include "lldb/Target/Target.h" 14 15 using namespace lldb; 16 using namespace lldb_private; 17 18 Section::Section (const ModuleSP &module_sp, 19 ObjectFile *obj_file, 20 user_id_t sect_id, 21 const ConstString &name, 22 SectionType sect_type, 23 addr_t file_addr, 24 addr_t byte_size, 25 lldb::offset_t file_offset, 26 lldb::offset_t file_size, 27 uint32_t flags) : 28 ModuleChild (module_sp), 29 UserID (sect_id), 30 Flags (flags), 31 m_obj_file (obj_file), 32 m_type (sect_type), 33 m_parent_wp (), 34 m_name (name), 35 m_file_addr (file_addr), 36 m_byte_size (byte_size), 37 m_file_offset (file_offset), 38 m_file_size (file_size), 39 m_children (), 40 m_fake (false), 41 m_encrypted (false), 42 m_thread_specific (false) 43 { 44 // printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s\n", 45 // this, module_sp.get(), sect_id, file_addr, file_addr + byte_size, file_offset, file_offset + file_size, flags, name.GetCString()); 46 } 47 48 Section::Section (const lldb::SectionSP &parent_section_sp, 49 const ModuleSP &module_sp, 50 ObjectFile *obj_file, 51 user_id_t sect_id, 52 const ConstString &name, 53 SectionType sect_type, 54 addr_t file_addr, 55 addr_t byte_size, 56 lldb::offset_t file_offset, 57 lldb::offset_t file_size, 58 uint32_t flags) : 59 ModuleChild (module_sp), 60 UserID (sect_id), 61 Flags (flags), 62 m_obj_file (obj_file), 63 m_type (sect_type), 64 m_parent_wp (), 65 m_name (name), 66 m_file_addr (file_addr), 67 m_byte_size (byte_size), 68 m_file_offset (file_offset), 69 m_file_size (file_size), 70 m_children (), 71 m_fake (false), 72 m_encrypted (false), 73 m_thread_specific (false) 74 { 75 // printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s.%s\n", 76 // this, module_sp.get(), sect_id, file_addr, file_addr + byte_size, file_offset, file_offset + file_size, flags, parent_section_sp->GetName().GetCString(), name.GetCString()); 77 if (parent_section_sp) 78 m_parent_wp = parent_section_sp; 79 } 80 81 Section::~Section() 82 { 83 // printf ("Section::~Section(%p)\n", this); 84 } 85 86 addr_t 87 Section::GetFileAddress () const 88 { 89 SectionSP parent_sp (GetParent ()); 90 if (parent_sp) 91 { 92 // This section has a parent which means m_file_addr is an offset into 93 // the parent section, so the file address for this section is the file 94 // address of the parent plus the offset 95 return parent_sp->GetFileAddress() + m_file_addr; 96 } 97 // This section has no parent, so m_file_addr is the file base address 98 return m_file_addr; 99 } 100 101 bool 102 Section::SetFileAddress (lldb::addr_t file_addr) 103 { 104 SectionSP parent_sp (GetParent ()); 105 if (parent_sp) 106 { 107 if (m_file_addr >= file_addr) 108 return parent_sp->SetFileAddress (m_file_addr - file_addr); 109 return false; 110 } 111 else 112 { 113 // This section has no parent, so m_file_addr is the file base address 114 m_file_addr = file_addr; 115 return true; 116 } 117 } 118 119 lldb::addr_t 120 Section::GetOffset () const 121 { 122 // This section has a parent which means m_file_addr is an offset. 123 SectionSP parent_sp (GetParent ()); 124 if (parent_sp) 125 return m_file_addr; 126 127 // This section has no parent, so there is no offset to be had 128 return 0; 129 } 130 131 addr_t 132 Section::GetLoadBaseAddress (Target *target) const 133 { 134 addr_t load_base_addr = LLDB_INVALID_ADDRESS; 135 SectionSP parent_sp (GetParent ()); 136 if (parent_sp) 137 { 138 load_base_addr = parent_sp->GetLoadBaseAddress (target); 139 if (load_base_addr != LLDB_INVALID_ADDRESS) 140 load_base_addr += GetOffset(); 141 } 142 else 143 { 144 load_base_addr = target->GetSectionLoadList().GetSectionLoadAddress (const_cast<Section *>(this)->shared_from_this()); 145 } 146 return load_base_addr; 147 } 148 149 bool 150 Section::ResolveContainedAddress (addr_t offset, Address &so_addr) const 151 { 152 const size_t num_children = m_children.GetSize(); 153 if (num_children > 0) 154 { 155 for (size_t i=0; i<num_children; i++) 156 { 157 Section* child_section = m_children.GetSectionAtIndex (i).get(); 158 159 addr_t child_offset = child_section->GetOffset(); 160 if (child_offset <= offset && offset - child_offset < child_section->GetByteSize()) 161 return child_section->ResolveContainedAddress (offset - child_offset, so_addr); 162 } 163 } 164 so_addr.SetOffset(offset); 165 so_addr.SetSection(const_cast<Section *>(this)->shared_from_this()); 166 167 #ifdef LLDB_CONFIGURATION_DEBUG 168 // For debug builds, ensure that there are no orphaned (i.e., moduleless) sections. 169 assert(GetModule().get()); 170 #endif 171 return true; 172 } 173 174 bool 175 Section::ContainsFileAddress (addr_t vm_addr) const 176 { 177 const addr_t file_addr = GetFileAddress(); 178 if (file_addr != LLDB_INVALID_ADDRESS) 179 { 180 if (file_addr <= vm_addr) 181 { 182 const addr_t offset = vm_addr - file_addr; 183 return offset < GetByteSize(); 184 } 185 } 186 return false; 187 } 188 189 int 190 Section::Compare (const Section& a, const Section& b) 191 { 192 if (&a == &b) 193 return 0; 194 195 const ModuleSP a_module_sp = a.GetModule(); 196 const ModuleSP b_module_sp = b.GetModule(); 197 if (a_module_sp == b_module_sp) 198 { 199 user_id_t a_sect_uid = a.GetID(); 200 user_id_t b_sect_uid = b.GetID(); 201 if (a_sect_uid < b_sect_uid) 202 return -1; 203 if (a_sect_uid > b_sect_uid) 204 return 1; 205 return 0; 206 } 207 else 208 { 209 // The modules are different, just compare the module pointers 210 if (a_module_sp.get() < b_module_sp.get()) 211 return -1; 212 else 213 return 1; // We already know the modules aren't equal 214 } 215 } 216 217 218 void 219 Section::Dump (Stream *s, Target *target, uint32_t depth) const 220 { 221 // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 222 s->Indent(); 223 s->Printf("0x%8.8" PRIx64 " %-16s ", GetID(), GetSectionTypeAsCString (m_type)); 224 bool resolved = true; 225 addr_t addr = LLDB_INVALID_ADDRESS; 226 227 if (GetByteSize() == 0) 228 s->Printf("%39s", ""); 229 else 230 { 231 if (target) 232 addr = GetLoadBaseAddress (target); 233 234 if (addr == LLDB_INVALID_ADDRESS) 235 { 236 if (target) 237 resolved = false; 238 addr = GetFileAddress(); 239 } 240 241 VMRange range(addr, addr + m_byte_size); 242 range.Dump (s, 0); 243 } 244 245 s->Printf("%c 0x%8.8" PRIx64 " 0x%8.8" PRIx64 " 0x%8.8x ", resolved ? ' ' : '*', m_file_offset, m_file_size, Get()); 246 247 DumpName (s); 248 249 s->EOL(); 250 251 if (depth > 0) 252 m_children.Dump(s, target, false, depth - 1); 253 } 254 255 void 256 Section::DumpName (Stream *s) const 257 { 258 SectionSP parent_sp (GetParent ()); 259 if (parent_sp) 260 { 261 parent_sp->DumpName (s); 262 s->PutChar('.'); 263 } 264 else 265 { 266 // The top most section prints the module basename 267 const char * name = NULL; 268 ModuleSP module_sp (GetModule()); 269 const FileSpec &file_spec = m_obj_file->GetFileSpec(); 270 271 if (m_obj_file) 272 name = file_spec.GetFilename().AsCString(); 273 if ((!name || !name[0]) && module_sp) 274 name = module_sp->GetFileSpec().GetFilename().AsCString(); 275 if (name && name[0]) 276 s->Printf("%s.", name); 277 } 278 m_name.Dump(s); 279 } 280 281 bool 282 Section::IsDescendant (const Section *section) 283 { 284 if (this == section) 285 return true; 286 SectionSP parent_sp (GetParent ()); 287 if (parent_sp) 288 return parent_sp->IsDescendant (section); 289 return false; 290 } 291 292 bool 293 Section::Slide (addr_t slide_amount, bool slide_children) 294 { 295 if (m_file_addr != LLDB_INVALID_ADDRESS) 296 { 297 if (slide_amount == 0) 298 return true; 299 300 m_file_addr += slide_amount; 301 302 if (slide_children) 303 m_children.Slide (slide_amount, slide_children); 304 305 return true; 306 } 307 return false; 308 } 309 310 #pragma mark SectionList 311 312 SectionList::SectionList () : 313 m_sections() 314 { 315 } 316 317 318 SectionList::~SectionList () 319 { 320 } 321 322 SectionList & 323 SectionList::operator = (const SectionList& rhs) 324 { 325 if (this != &rhs) 326 m_sections = rhs.m_sections; 327 return *this; 328 } 329 330 size_t 331 SectionList::AddSection (const lldb::SectionSP& section_sp) 332 { 333 assert (section_sp.get()); 334 size_t section_index = m_sections.size(); 335 m_sections.push_back(section_sp); 336 return section_index; 337 } 338 339 // Warning, this can be slow as it's removing items from a std::vector. 340 bool 341 SectionList::DeleteSection (size_t idx) 342 { 343 if (idx < m_sections.size()) 344 { 345 m_sections.erase (m_sections.begin() + idx); 346 return true; 347 } 348 return false; 349 } 350 351 size_t 352 SectionList::FindSectionIndex (const Section* sect) 353 { 354 iterator sect_iter; 355 iterator begin = m_sections.begin(); 356 iterator end = m_sections.end(); 357 for (sect_iter = begin; sect_iter != end; ++sect_iter) 358 { 359 if (sect_iter->get() == sect) 360 { 361 // The secton was already in this section list 362 return std::distance (begin, sect_iter); 363 } 364 } 365 return UINT32_MAX; 366 } 367 368 size_t 369 SectionList::AddUniqueSection (const lldb::SectionSP& sect_sp) 370 { 371 size_t sect_idx = FindSectionIndex (sect_sp.get()); 372 if (sect_idx == UINT32_MAX) 373 { 374 sect_idx = AddSection (sect_sp); 375 } 376 return sect_idx; 377 } 378 379 bool 380 SectionList::ReplaceSection (user_id_t sect_id, const lldb::SectionSP& sect_sp, uint32_t depth) 381 { 382 iterator sect_iter, end = m_sections.end(); 383 for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter) 384 { 385 if ((*sect_iter)->GetID() == sect_id) 386 { 387 *sect_iter = sect_sp; 388 return true; 389 } 390 else if (depth > 0) 391 { 392 if ((*sect_iter)->GetChildren().ReplaceSection(sect_id, sect_sp, depth - 1)) 393 return true; 394 } 395 } 396 return false; 397 } 398 399 size_t 400 SectionList::GetNumSections (uint32_t depth) const 401 { 402 size_t count = m_sections.size(); 403 if (depth > 0) 404 { 405 const_iterator sect_iter, end = m_sections.end(); 406 for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter) 407 { 408 count += (*sect_iter)->GetChildren().GetNumSections(depth - 1); 409 } 410 } 411 return count; 412 } 413 414 SectionSP 415 SectionList::GetSectionAtIndex (size_t idx) const 416 { 417 SectionSP sect_sp; 418 if (idx < m_sections.size()) 419 sect_sp = m_sections[idx]; 420 return sect_sp; 421 } 422 423 SectionSP 424 SectionList::FindSectionByName (const ConstString §ion_dstr) const 425 { 426 SectionSP sect_sp; 427 // Check if we have a valid section string 428 if (section_dstr && !m_sections.empty()) 429 { 430 const_iterator sect_iter; 431 const_iterator end = m_sections.end(); 432 for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter) 433 { 434 Section *child_section = sect_iter->get(); 435 assert (child_section); 436 if (child_section->GetName() == section_dstr) 437 { 438 sect_sp = *sect_iter; 439 } 440 else 441 { 442 sect_sp = child_section->GetChildren().FindSectionByName(section_dstr); 443 } 444 } 445 } 446 return sect_sp; 447 } 448 449 SectionSP 450 SectionList::FindSectionByID (user_id_t sect_id) const 451 { 452 SectionSP sect_sp; 453 if (sect_id) 454 { 455 const_iterator sect_iter; 456 const_iterator end = m_sections.end(); 457 for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter) 458 { 459 if ((*sect_iter)->GetID() == sect_id) 460 { 461 sect_sp = *sect_iter; 462 break; 463 } 464 else 465 { 466 sect_sp = (*sect_iter)->GetChildren().FindSectionByID (sect_id); 467 } 468 } 469 } 470 return sect_sp; 471 } 472 473 474 SectionSP 475 SectionList::FindSectionByType (SectionType sect_type, bool check_children, size_t start_idx) const 476 { 477 SectionSP sect_sp; 478 size_t num_sections = m_sections.size(); 479 for (size_t idx = start_idx; idx < num_sections; ++idx) 480 { 481 if (m_sections[idx]->GetType() == sect_type) 482 { 483 sect_sp = m_sections[idx]; 484 break; 485 } 486 else if (check_children) 487 { 488 sect_sp = m_sections[idx]->GetChildren().FindSectionByType (sect_type, check_children, 0); 489 if (sect_sp) 490 break; 491 } 492 } 493 return sect_sp; 494 } 495 496 SectionSP 497 SectionList::FindSectionContainingFileAddress (addr_t vm_addr, uint32_t depth) const 498 { 499 SectionSP sect_sp; 500 const_iterator sect_iter; 501 const_iterator end = m_sections.end(); 502 for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter) 503 { 504 Section *sect = sect_iter->get(); 505 if (sect->ContainsFileAddress (vm_addr)) 506 { 507 // The file address is in this section. We need to make sure one of our child 508 // sections doesn't contain this address as well as obeying the depth limit 509 // that was passed in. 510 if (depth > 0) 511 sect_sp = sect->GetChildren().FindSectionContainingFileAddress(vm_addr, depth - 1); 512 513 if (sect_sp.get() == NULL && !sect->IsFake()) 514 sect_sp = *sect_iter; 515 } 516 } 517 return sect_sp; 518 } 519 520 bool 521 SectionList::ContainsSection(user_id_t sect_id) const 522 { 523 return FindSectionByID (sect_id).get() != NULL; 524 } 525 526 void 527 SectionList::Dump (Stream *s, Target *target, bool show_header, uint32_t depth) const 528 { 529 bool target_has_loaded_sections = target && !target->GetSectionLoadList().IsEmpty(); 530 if (show_header && !m_sections.empty()) 531 { 532 s->Indent(); 533 s->Printf( "SectID Type %s Address File Off. File Size Flags Section Name\n", target_has_loaded_sections ? "Load" : "File"); 534 s->Indent(); 535 s->PutCString("---------- ---------------- --------------------------------------- ---------- ---------- ---------- ----------------------------\n"); 536 } 537 538 539 const_iterator sect_iter; 540 const_iterator end = m_sections.end(); 541 for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter) 542 { 543 (*sect_iter)->Dump(s, target_has_loaded_sections ? target : NULL, depth); 544 } 545 546 if (show_header && !m_sections.empty()) 547 s->IndentLess(); 548 549 } 550 551 size_t 552 SectionList::Slide (addr_t slide_amount, bool slide_children) 553 { 554 size_t count = 0; 555 const_iterator pos, end = m_sections.end(); 556 for (pos = m_sections.begin(); pos != end; ++pos) 557 { 558 if ((*pos)->Slide(slide_amount, slide_children)) 559 ++count; 560 } 561 return count; 562 } 563