diff options
Diffstat (limited to 'source/Core/Section.cpp')
-rw-r--r-- | source/Core/Section.cpp | 562 |
1 files changed, 562 insertions, 0 deletions
diff --git a/source/Core/Section.cpp b/source/Core/Section.cpp new file mode 100644 index 000000000000..e2a084ceb2f2 --- /dev/null +++ b/source/Core/Section.cpp @@ -0,0 +1,562 @@ +//===-- Section.cpp ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Section.h" +#include "lldb/Core/Module.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; + +Section::Section (const ModuleSP &module_sp, + ObjectFile *obj_file, + user_id_t sect_id, + const ConstString &name, + SectionType sect_type, + addr_t file_addr, + addr_t byte_size, + lldb::offset_t file_offset, + lldb::offset_t file_size, + uint32_t flags) : + ModuleChild (module_sp), + UserID (sect_id), + Flags (flags), + m_obj_file (obj_file), + m_type (sect_type), + m_parent_wp (), + m_name (name), + m_file_addr (file_addr), + m_byte_size (byte_size), + m_file_offset (file_offset), + m_file_size (file_size), + m_children (), + m_fake (false), + m_encrypted (false), + m_thread_specific (false) +{ +// 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", +// this, module_sp.get(), sect_id, file_addr, file_addr + byte_size, file_offset, file_offset + file_size, flags, name.GetCString()); +} + +Section::Section (const lldb::SectionSP &parent_section_sp, + const ModuleSP &module_sp, + ObjectFile *obj_file, + user_id_t sect_id, + const ConstString &name, + SectionType sect_type, + addr_t file_addr, + addr_t byte_size, + lldb::offset_t file_offset, + lldb::offset_t file_size, + uint32_t flags) : + ModuleChild (module_sp), + UserID (sect_id), + Flags (flags), + m_obj_file (obj_file), + m_type (sect_type), + m_parent_wp (), + m_name (name), + m_file_addr (file_addr), + m_byte_size (byte_size), + m_file_offset (file_offset), + m_file_size (file_size), + m_children (), + m_fake (false), + m_encrypted (false), + m_thread_specific (false) +{ +// 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", +// 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()); + if (parent_section_sp) + m_parent_wp = parent_section_sp; +} + +Section::~Section() +{ +// printf ("Section::~Section(%p)\n", this); +} + +addr_t +Section::GetFileAddress () const +{ + SectionSP parent_sp (GetParent ()); + if (parent_sp) + { + // This section has a parent which means m_file_addr is an offset into + // the parent section, so the file address for this section is the file + // address of the parent plus the offset + return parent_sp->GetFileAddress() + m_file_addr; + } + // This section has no parent, so m_file_addr is the file base address + return m_file_addr; +} + +bool +Section::SetFileAddress (lldb::addr_t file_addr) +{ + SectionSP parent_sp (GetParent ()); + if (parent_sp) + { + if (m_file_addr >= file_addr) + return parent_sp->SetFileAddress (m_file_addr - file_addr); + return false; + } + else + { + // This section has no parent, so m_file_addr is the file base address + m_file_addr = file_addr; + return true; + } +} + +lldb::addr_t +Section::GetOffset () const +{ + // This section has a parent which means m_file_addr is an offset. + SectionSP parent_sp (GetParent ()); + if (parent_sp) + return m_file_addr; + + // This section has no parent, so there is no offset to be had + return 0; +} + +addr_t +Section::GetLoadBaseAddress (Target *target) const +{ + addr_t load_base_addr = LLDB_INVALID_ADDRESS; + SectionSP parent_sp (GetParent ()); + if (parent_sp) + { + load_base_addr = parent_sp->GetLoadBaseAddress (target); + if (load_base_addr != LLDB_INVALID_ADDRESS) + load_base_addr += GetOffset(); + } + else + { + load_base_addr = target->GetSectionLoadList().GetSectionLoadAddress (const_cast<Section *>(this)->shared_from_this()); + } + return load_base_addr; +} + +bool +Section::ResolveContainedAddress (addr_t offset, Address &so_addr) const +{ + const size_t num_children = m_children.GetSize(); + if (num_children > 0) + { + for (size_t i=0; i<num_children; i++) + { + Section* child_section = m_children.GetSectionAtIndex (i).get(); + + addr_t child_offset = child_section->GetOffset(); + if (child_offset <= offset && offset - child_offset < child_section->GetByteSize()) + return child_section->ResolveContainedAddress (offset - child_offset, so_addr); + } + } + so_addr.SetOffset(offset); + so_addr.SetSection(const_cast<Section *>(this)->shared_from_this()); + +#ifdef LLDB_CONFIGURATION_DEBUG + // For debug builds, ensure that there are no orphaned (i.e., moduleless) sections. + assert(GetModule().get()); +#endif + return true; +} + +bool +Section::ContainsFileAddress (addr_t vm_addr) const +{ + const addr_t file_addr = GetFileAddress(); + if (file_addr != LLDB_INVALID_ADDRESS) + { + if (file_addr <= vm_addr) + { + const addr_t offset = vm_addr - file_addr; + return offset < GetByteSize(); + } + } + return false; +} + +int +Section::Compare (const Section& a, const Section& b) +{ + if (&a == &b) + return 0; + + const ModuleSP a_module_sp = a.GetModule(); + const ModuleSP b_module_sp = b.GetModule(); + if (a_module_sp == b_module_sp) + { + user_id_t a_sect_uid = a.GetID(); + user_id_t b_sect_uid = b.GetID(); + if (a_sect_uid < b_sect_uid) + return -1; + if (a_sect_uid > b_sect_uid) + return 1; + return 0; + } + else + { + // The modules are different, just compare the module pointers + if (a_module_sp.get() < b_module_sp.get()) + return -1; + else + return 1; // We already know the modules aren't equal + } +} + + +void +Section::Dump (Stream *s, Target *target, uint32_t depth) const +{ +// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); + s->Indent(); + s->Printf("0x%8.8" PRIx64 " %-16s ", GetID(), GetSectionTypeAsCString (m_type)); + bool resolved = true; + addr_t addr = LLDB_INVALID_ADDRESS; + + if (GetByteSize() == 0) + s->Printf("%39s", ""); + else + { + if (target) + addr = GetLoadBaseAddress (target); + + if (addr == LLDB_INVALID_ADDRESS) + { + if (target) + resolved = false; + addr = GetFileAddress(); + } + + VMRange range(addr, addr + m_byte_size); + range.Dump (s, 0); + } + + s->Printf("%c 0x%8.8" PRIx64 " 0x%8.8" PRIx64 " 0x%8.8x ", resolved ? ' ' : '*', m_file_offset, m_file_size, Get()); + + DumpName (s); + + s->EOL(); + + if (depth > 0) + m_children.Dump(s, target, false, depth - 1); +} + +void +Section::DumpName (Stream *s) const +{ + SectionSP parent_sp (GetParent ()); + if (parent_sp) + { + parent_sp->DumpName (s); + s->PutChar('.'); + } + else + { + // The top most section prints the module basename + const char * name = NULL; + ModuleSP module_sp (GetModule()); + const FileSpec &file_spec = m_obj_file->GetFileSpec(); + + if (m_obj_file) + name = file_spec.GetFilename().AsCString(); + if ((!name || !name[0]) && module_sp) + name = module_sp->GetFileSpec().GetFilename().AsCString(); + if (name && name[0]) + s->Printf("%s.", name); + } + m_name.Dump(s); +} + +bool +Section::IsDescendant (const Section *section) +{ + if (this == section) + return true; + SectionSP parent_sp (GetParent ()); + if (parent_sp) + return parent_sp->IsDescendant (section); + return false; +} + +bool +Section::Slide (addr_t slide_amount, bool slide_children) +{ + if (m_file_addr != LLDB_INVALID_ADDRESS) + { + if (slide_amount == 0) + return true; + + m_file_addr += slide_amount; + + if (slide_children) + m_children.Slide (slide_amount, slide_children); + + return true; + } + return false; +} + +#pragma mark SectionList + +SectionList::SectionList () : + m_sections() +{ +} + + +SectionList::~SectionList () +{ +} + +SectionList & +SectionList::operator = (const SectionList& rhs) +{ + if (this != &rhs) + m_sections = rhs.m_sections; + return *this; +} + +size_t +SectionList::AddSection (const lldb::SectionSP& section_sp) +{ + assert (section_sp.get()); + size_t section_index = m_sections.size(); + m_sections.push_back(section_sp); + return section_index; +} + +// Warning, this can be slow as it's removing items from a std::vector. +bool +SectionList::DeleteSection (size_t idx) +{ + if (idx < m_sections.size()) + { + m_sections.erase (m_sections.begin() + idx); + return true; + } + return false; +} + +size_t +SectionList::FindSectionIndex (const Section* sect) +{ + iterator sect_iter; + iterator begin = m_sections.begin(); + iterator end = m_sections.end(); + for (sect_iter = begin; sect_iter != end; ++sect_iter) + { + if (sect_iter->get() == sect) + { + // The secton was already in this section list + return std::distance (begin, sect_iter); + } + } + return UINT32_MAX; +} + +size_t +SectionList::AddUniqueSection (const lldb::SectionSP& sect_sp) +{ + size_t sect_idx = FindSectionIndex (sect_sp.get()); + if (sect_idx == UINT32_MAX) + { + sect_idx = AddSection (sect_sp); + } + return sect_idx; +} + +bool +SectionList::ReplaceSection (user_id_t sect_id, const lldb::SectionSP& sect_sp, uint32_t depth) +{ + iterator sect_iter, end = m_sections.end(); + for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter) + { + if ((*sect_iter)->GetID() == sect_id) + { + *sect_iter = sect_sp; + return true; + } + else if (depth > 0) + { + if ((*sect_iter)->GetChildren().ReplaceSection(sect_id, sect_sp, depth - 1)) + return true; + } + } + return false; +} + +size_t +SectionList::GetNumSections (uint32_t depth) const +{ + size_t count = m_sections.size(); + if (depth > 0) + { + const_iterator sect_iter, end = m_sections.end(); + for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter) + { + count += (*sect_iter)->GetChildren().GetNumSections(depth - 1); + } + } + return count; +} + +SectionSP +SectionList::GetSectionAtIndex (size_t idx) const +{ + SectionSP sect_sp; + if (idx < m_sections.size()) + sect_sp = m_sections[idx]; + return sect_sp; +} + +SectionSP +SectionList::FindSectionByName (const ConstString §ion_dstr) const +{ + SectionSP sect_sp; + // Check if we have a valid section string + if (section_dstr && !m_sections.empty()) + { + const_iterator sect_iter; + const_iterator end = m_sections.end(); + for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter) + { + Section *child_section = sect_iter->get(); + assert (child_section); + if (child_section->GetName() == section_dstr) + { + sect_sp = *sect_iter; + } + else + { + sect_sp = child_section->GetChildren().FindSectionByName(section_dstr); + } + } + } + return sect_sp; +} + +SectionSP +SectionList::FindSectionByID (user_id_t sect_id) const +{ + SectionSP sect_sp; + if (sect_id) + { + const_iterator sect_iter; + const_iterator end = m_sections.end(); + for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter) + { + if ((*sect_iter)->GetID() == sect_id) + { + sect_sp = *sect_iter; + break; + } + else + { + sect_sp = (*sect_iter)->GetChildren().FindSectionByID (sect_id); + } + } + } + return sect_sp; +} + + +SectionSP +SectionList::FindSectionByType (SectionType sect_type, bool check_children, size_t start_idx) const +{ + SectionSP sect_sp; + size_t num_sections = m_sections.size(); + for (size_t idx = start_idx; idx < num_sections; ++idx) + { + if (m_sections[idx]->GetType() == sect_type) + { + sect_sp = m_sections[idx]; + break; + } + else if (check_children) + { + sect_sp = m_sections[idx]->GetChildren().FindSectionByType (sect_type, check_children, 0); + if (sect_sp) + break; + } + } + return sect_sp; +} + +SectionSP +SectionList::FindSectionContainingFileAddress (addr_t vm_addr, uint32_t depth) const +{ + SectionSP sect_sp; + const_iterator sect_iter; + const_iterator end = m_sections.end(); + for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter) + { + Section *sect = sect_iter->get(); + if (sect->ContainsFileAddress (vm_addr)) + { + // The file address is in this section. We need to make sure one of our child + // sections doesn't contain this address as well as obeying the depth limit + // that was passed in. + if (depth > 0) + sect_sp = sect->GetChildren().FindSectionContainingFileAddress(vm_addr, depth - 1); + + if (sect_sp.get() == NULL && !sect->IsFake()) + sect_sp = *sect_iter; + } + } + return sect_sp; +} + +bool +SectionList::ContainsSection(user_id_t sect_id) const +{ + return FindSectionByID (sect_id).get() != NULL; +} + +void +SectionList::Dump (Stream *s, Target *target, bool show_header, uint32_t depth) const +{ + bool target_has_loaded_sections = target && !target->GetSectionLoadList().IsEmpty(); + if (show_header && !m_sections.empty()) + { + s->Indent(); + s->Printf( "SectID Type %s Address File Off. File Size Flags Section Name\n", target_has_loaded_sections ? "Load" : "File"); + s->Indent(); + s->PutCString("---------- ---------------- --------------------------------------- ---------- ---------- ---------- ----------------------------\n"); + } + + + const_iterator sect_iter; + const_iterator end = m_sections.end(); + for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter) + { + (*sect_iter)->Dump(s, target_has_loaded_sections ? target : NULL, depth); + } + + if (show_header && !m_sections.empty()) + s->IndentLess(); + +} + +size_t +SectionList::Slide (addr_t slide_amount, bool slide_children) +{ + size_t count = 0; + const_iterator pos, end = m_sections.end(); + for (pos = m_sections.begin(); pos != end; ++pos) + { + if ((*pos)->Slide(slide_amount, slide_children)) + ++count; + } + return count; +} |