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