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