Home | History | Annotate | Download | only in Target
      1 //===-- SectionLoadList.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/Target/SectionLoadList.h"
     11 
     12 // C Includes
     13 // C++ Includes
     14 // Other libraries and framework includes
     15 // Project includes
     16 #include "lldb/Core/Log.h"
     17 #include "lldb/Core/Module.h"
     18 #include "lldb/Core/Section.h"
     19 #include "lldb/Core/Stream.h"
     20 #include "lldb/Symbol/Block.h"
     21 #include "lldb/Symbol/Symbol.h"
     22 #include "lldb/Symbol/SymbolContext.h"
     23 
     24 using namespace lldb;
     25 using namespace lldb_private;
     26 
     27 
     28 bool
     29 SectionLoadList::IsEmpty() const
     30 {
     31     Mutex::Locker locker(m_mutex);
     32     return m_addr_to_sect.empty();
     33 }
     34 
     35 void
     36 SectionLoadList::Clear ()
     37 {
     38     Mutex::Locker locker(m_mutex);
     39     m_addr_to_sect.clear();
     40     m_sect_to_addr.clear();
     41 }
     42 
     43 addr_t
     44 SectionLoadList::GetSectionLoadAddress (const lldb::SectionSP &section) const
     45 {
     46     // TODO: add support for the same section having multiple load addresses
     47     addr_t section_load_addr = LLDB_INVALID_ADDRESS;
     48     if (section)
     49     {
     50         Mutex::Locker locker(m_mutex);
     51         sect_to_addr_collection::const_iterator pos = m_sect_to_addr.find (section.get());
     52 
     53         if (pos != m_sect_to_addr.end())
     54             section_load_addr = pos->second;
     55     }
     56     return section_load_addr;
     57 }
     58 
     59 bool
     60 SectionLoadList::SetSectionLoadAddress (const lldb::SectionSP &section, addr_t load_addr, bool warn_multiple)
     61 {
     62     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));
     63 
     64     if (log)
     65     {
     66         const FileSpec &module_file_spec (section->GetModule()->GetFileSpec());
     67         log->Printf ("SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64 ")",
     68                      __FUNCTION__,
     69                      section.get(),
     70                      module_file_spec.GetPath().c_str(),
     71                      section->GetName().AsCString(),
     72                      load_addr);
     73     }
     74 
     75     if (section->GetByteSize() == 0)
     76         return false; // No change
     77 
     78     // Fill in the section -> load_addr map
     79     Mutex::Locker locker(m_mutex);
     80     sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section.get());
     81     if (sta_pos != m_sect_to_addr.end())
     82     {
     83         if (load_addr == sta_pos->second)
     84             return false; // No change...
     85         else
     86             sta_pos->second = load_addr;
     87     }
     88     else
     89         m_sect_to_addr[section.get()] = load_addr;
     90 
     91     // Fill in the load_addr -> section map
     92     addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
     93     if (ats_pos != m_addr_to_sect.end())
     94     {
     95         // Some sections are ok to overlap, and for others we should warn. When
     96         // we have multiple load addresses that correspond to a section, we will
     97         // allways attribute the section to the be last section that claims it
     98         // exists at that address. Sometimes it is ok for more that one section
     99         // to be loaded at a specific load address, and other times it isn't.
    100         // The "warn_multiple" parameter tells us if we should warn in this case
    101         // or not. The DynamicLoader plug-in subclasses should know which
    102         // sections should warn and which shouldn't (darwin shared cache modules
    103         // all shared the same "__LINKEDIT" sections, so the dynamic loader can
    104         // pass false for "warn_multiple").
    105         if (warn_multiple && section != ats_pos->second)
    106         {
    107             ModuleSP module_sp (section->GetModule());
    108             if (module_sp)
    109             {
    110                 ModuleSP curr_module_sp (ats_pos->second->GetModule());
    111                 if (curr_module_sp)
    112                 {
    113                     module_sp->ReportWarning ("address 0x%16.16" PRIx64 " maps to more than one section: %s.%s and %s.%s",
    114                                               load_addr,
    115                                               module_sp->GetFileSpec().GetFilename().GetCString(),
    116                                               section->GetName().GetCString(),
    117                                               curr_module_sp->GetFileSpec().GetFilename().GetCString(),
    118                                               ats_pos->second->GetName().GetCString());
    119                 }
    120             }
    121         }
    122         ats_pos->second = section;
    123     }
    124     else
    125         m_addr_to_sect[load_addr] = section;
    126 
    127     return true;    // Changed
    128 }
    129 
    130 size_t
    131 SectionLoadList::SetSectionUnloaded (const lldb::SectionSP &section_sp)
    132 {
    133     size_t unload_count = 0;
    134 
    135     if (section_sp)
    136     {
    137         Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));
    138 
    139         if (log)
    140         {
    141             const FileSpec &module_file_spec (section_sp->GetModule()->GetFileSpec());
    142             log->Printf ("SectionLoadList::%s (section = %p (%s.%s))",
    143                          __FUNCTION__,
    144                          section_sp.get(),
    145                          module_file_spec.GetPath().c_str(),
    146                          section_sp->GetName().AsCString());
    147         }
    148 
    149         Mutex::Locker locker(m_mutex);
    150 
    151         sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section_sp.get());
    152         if (sta_pos != m_sect_to_addr.end())
    153         {
    154             ++unload_count;
    155             addr_t load_addr = sta_pos->second;
    156             m_sect_to_addr.erase (sta_pos);
    157 
    158             addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
    159             if (ats_pos != m_addr_to_sect.end())
    160                 m_addr_to_sect.erase (ats_pos);
    161         }
    162     }
    163     return unload_count;
    164 }
    165 
    166 bool
    167 SectionLoadList::SetSectionUnloaded (const lldb::SectionSP &section_sp, addr_t load_addr)
    168 {
    169     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));
    170 
    171     if (log)
    172     {
    173         const FileSpec &module_file_spec (section_sp->GetModule()->GetFileSpec());
    174         log->Printf ("SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64 ")",
    175                      __FUNCTION__,
    176                      section_sp.get(),
    177                      module_file_spec.GetPath().c_str(),
    178                      section_sp->GetName().AsCString(),
    179                      load_addr);
    180     }
    181     bool erased = false;
    182     Mutex::Locker locker(m_mutex);
    183     sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section_sp.get());
    184     if (sta_pos != m_sect_to_addr.end())
    185     {
    186         erased = true;
    187         m_sect_to_addr.erase (sta_pos);
    188     }
    189 
    190     addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
    191     if (ats_pos != m_addr_to_sect.end())
    192     {
    193         erased = true;
    194         m_addr_to_sect.erase (ats_pos);
    195     }
    196 
    197     return erased;
    198 }
    199 
    200 
    201 bool
    202 SectionLoadList::ResolveLoadAddress (addr_t load_addr, Address &so_addr) const
    203 {
    204     // First find the top level section that this load address exists in
    205     Mutex::Locker locker(m_mutex);
    206     if (!m_addr_to_sect.empty())
    207     {
    208         addr_to_sect_collection::const_iterator pos = m_addr_to_sect.lower_bound (load_addr);
    209         if (pos != m_addr_to_sect.end())
    210         {
    211             if (load_addr != pos->first && pos != m_addr_to_sect.begin())
    212                 --pos;
    213             const addr_t pos_load_addr = pos->first;
    214             if (load_addr >= pos_load_addr)
    215             {
    216                 addr_t offset = load_addr - pos_load_addr;
    217                 if (offset < pos->second->GetByteSize())
    218                 {
    219                     // We have found the top level section, now we need to find the
    220                     // deepest child section.
    221                     return pos->second->ResolveContainedAddress (offset, so_addr);
    222                 }
    223             }
    224         }
    225         else
    226         {
    227             // There are no entries that have an address that is >= load_addr,
    228             // so we need to check the last entry on our collection.
    229             addr_to_sect_collection::const_reverse_iterator rpos = m_addr_to_sect.rbegin();
    230             if (load_addr >= rpos->first)
    231             {
    232                 addr_t offset = load_addr - rpos->first;
    233                 if (offset < rpos->second->GetByteSize())
    234                 {
    235                     // We have found the top level section, now we need to find the
    236                     // deepest child section.
    237                     return rpos->second->ResolveContainedAddress (offset, so_addr);
    238                 }
    239             }
    240         }
    241     }
    242     so_addr.Clear();
    243     return false;
    244 }
    245 
    246 void
    247 SectionLoadList::Dump (Stream &s, Target *target)
    248 {
    249     Mutex::Locker locker(m_mutex);
    250     addr_to_sect_collection::const_iterator pos, end;
    251     for (pos = m_addr_to_sect.begin(), end = m_addr_to_sect.end(); pos != end; ++pos)
    252     {
    253         s.Printf("addr = 0x%16.16" PRIx64 ", section = %p: ", pos->first, pos->second.get());
    254         pos->second->Dump (&s, target, 0);
    255     }
    256 }
    257 
    258 
    259