brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.8 KiB · d4bf057 Raw
270 lines · cpp
1//===-- SectionLoadList.cpp -----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Target/SectionLoadList.h"10 11#include "lldb/Core/Module.h"12#include "lldb/Core/Section.h"13#include "lldb/Symbol/Block.h"14#include "lldb/Symbol/Symbol.h"15#include "lldb/Symbol/SymbolContext.h"16#include "lldb/Utility/LLDBLog.h"17#include "lldb/Utility/Log.h"18#include "lldb/Utility/Stream.h"19 20using namespace lldb;21using namespace lldb_private;22 23SectionLoadList::SectionLoadList(const SectionLoadList &rhs)24    : m_addr_to_sect(), m_sect_to_addr(), m_mutex() {25  std::lock_guard<std::recursive_mutex> guard(rhs.m_mutex);26  m_addr_to_sect = rhs.m_addr_to_sect;27  m_sect_to_addr = rhs.m_sect_to_addr;28}29 30void SectionLoadList::operator=(const SectionLoadList &rhs) {31  std::lock(m_mutex, rhs.m_mutex);32  std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex, std::adopt_lock);33  std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex, std::adopt_lock);34  m_addr_to_sect = rhs.m_addr_to_sect;35  m_sect_to_addr = rhs.m_sect_to_addr;36}37 38bool SectionLoadList::IsEmpty() const {39  std::lock_guard<std::recursive_mutex> guard(m_mutex);40  return m_addr_to_sect.empty();41}42 43void SectionLoadList::Clear() {44  std::lock_guard<std::recursive_mutex> guard(m_mutex);45  m_addr_to_sect.clear();46  m_sect_to_addr.clear();47}48 49addr_t50SectionLoadList::GetSectionLoadAddress(const lldb::SectionSP &section) const {51  // TODO: add support for the same section having multiple load addresses52  addr_t section_load_addr = LLDB_INVALID_ADDRESS;53  if (section) {54    std::lock_guard<std::recursive_mutex> guard(m_mutex);55    sect_to_addr_collection::const_iterator pos =56        m_sect_to_addr.find(section.get());57 58    if (pos != m_sect_to_addr.end())59      section_load_addr = pos->second;60  }61  return section_load_addr;62}63 64bool SectionLoadList::SetSectionLoadAddress(const lldb::SectionSP &section,65                                            addr_t load_addr,66                                            bool warn_multiple) {67  Log *log = GetLog(LLDBLog::DynamicLoader);68  ModuleSP module_sp(section->GetModule());69 70  if (module_sp) {71    LLDB_LOGV(log, "(section = {0} ({1}.{2}), load_addr = {3:x}) module = {4}",72              section.get(), module_sp->GetFileSpec(), section->GetName(),73              load_addr, module_sp.get());74 75    if (section->GetByteSize() == 0)76      return false; // No change77 78    // Fill in the section -> load_addr map79    std::lock_guard<std::recursive_mutex> guard(m_mutex);80    sect_to_addr_collection::iterator sta_pos =81        m_sect_to_addr.find(section.get());82    if (sta_pos != m_sect_to_addr.end()) {83      if (load_addr == sta_pos->second)84        return false; // No change...85      else86        sta_pos->second = load_addr;87    } else88      m_sect_to_addr[section.get()] = load_addr;89 90    // Fill in the load_addr -> section map91    addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);92    if (ats_pos != m_addr_to_sect.end()) {93      // Some sections are ok to overlap, and for others we should warn. When94      // we have multiple load addresses that correspond to a section, we will95      // always attribute the section to the be last section that claims it96      // exists at that address. Sometimes it is ok for more that one section97      // to be loaded at a specific load address, and other times it isn't. The98      // "warn_multiple" parameter tells us if we should warn in this case or99      // not. The DynamicLoader plug-in subclasses should know which sections100      // should warn and which shouldn't (darwin shared cache modules all101      // shared the same "__LINKEDIT" sections, so the dynamic loader can pass102      // false for "warn_multiple").103      if (warn_multiple && section != ats_pos->second) {104        ModuleSP module_sp(section->GetModule());105        if (module_sp) {106          ModuleSP curr_module_sp(ats_pos->second->GetModule());107          if (curr_module_sp) {108            module_sp->ReportWarning(109                "address {0:x16} maps to more than one section: {1}.{2} and "110                "{3}.{4}",111                load_addr, module_sp->GetFileSpec().GetFilename().GetCString(),112                section->GetName().GetCString(),113                curr_module_sp->GetFileSpec().GetFilename().GetCString(),114                ats_pos->second->GetName().GetCString());115          }116        }117      }118      ats_pos->second = section;119    } else {120      // Remove the old address->section entry, if121      // there is one.122      for (const auto &entry : m_addr_to_sect) {123        if (entry.second == section) {124          const auto &it_pos = m_addr_to_sect.find(entry.first);125          m_addr_to_sect.erase(it_pos);126          break;127        }128      }129      m_addr_to_sect[load_addr] = section;130    }131    return true; // Changed132 133  } else {134    if (log) {135      LLDB_LOGF(136          log,137          "SectionLoadList::%s (section = %p (%s), load_addr = 0x%16.16" PRIx64138          ") error: module has been deleted",139          __FUNCTION__, static_cast<void *>(section.get()),140          section->GetName().AsCString(), load_addr);141    }142  }143  return false;144}145 146size_t SectionLoadList::SetSectionUnloaded(const lldb::SectionSP &section_sp) {147  size_t unload_count = 0;148 149  if (section_sp) {150    Log *log = GetLog(LLDBLog::DynamicLoader);151 152    if (log && log->GetVerbose()) {153      ModuleSP module_sp = section_sp->GetModule();154      std::string module_name("<Unknown>");155      if (module_sp) {156        const FileSpec &module_file_spec(157            section_sp->GetModule()->GetFileSpec());158        module_name = module_file_spec.GetPath();159      }160      LLDB_LOGF(log, "SectionLoadList::%s (section = %p (%s.%s))", __FUNCTION__,161                static_cast<void *>(section_sp.get()), module_name.c_str(),162                section_sp->GetName().AsCString());163    }164 165    std::lock_guard<std::recursive_mutex> guard(m_mutex);166 167    sect_to_addr_collection::iterator sta_pos =168        m_sect_to_addr.find(section_sp.get());169    if (sta_pos != m_sect_to_addr.end()) {170      ++unload_count;171      addr_t load_addr = sta_pos->second;172      m_sect_to_addr.erase(sta_pos);173 174      addr_to_sect_collection::iterator ats_pos =175          m_addr_to_sect.find(load_addr);176      if (ats_pos != m_addr_to_sect.end())177        m_addr_to_sect.erase(ats_pos);178    }179  }180  return unload_count;181}182 183bool SectionLoadList::SetSectionUnloaded(const lldb::SectionSP &section_sp,184                                         addr_t load_addr) {185  Log *log = GetLog(LLDBLog::DynamicLoader);186 187  if (log && log->GetVerbose()) {188    ModuleSP module_sp = section_sp->GetModule();189    std::string module_name("<Unknown>");190    if (module_sp) {191      const FileSpec &module_file_spec(section_sp->GetModule()->GetFileSpec());192      module_name = module_file_spec.GetPath();193    }194    LLDB_LOGF(195        log,196        "SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64197        ")",198        __FUNCTION__, static_cast<void *>(section_sp.get()),199        module_name.c_str(), section_sp->GetName().AsCString(), load_addr);200  }201  bool erased = false;202  std::lock_guard<std::recursive_mutex> guard(m_mutex);203  sect_to_addr_collection::iterator sta_pos =204      m_sect_to_addr.find(section_sp.get());205  if (sta_pos != m_sect_to_addr.end()) {206    erased = true;207    m_sect_to_addr.erase(sta_pos);208  }209 210  addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);211  if (ats_pos != m_addr_to_sect.end()) {212    erased = true;213    m_addr_to_sect.erase(ats_pos);214  }215 216  return erased;217}218 219bool SectionLoadList::ResolveLoadAddress(addr_t load_addr, Address &so_addr,220                                         bool allow_section_end) const {221  // First find the top level section that this load address exists in222  std::lock_guard<std::recursive_mutex> guard(m_mutex);223  if (!m_addr_to_sect.empty()) {224    addr_to_sect_collection::const_iterator pos =225        m_addr_to_sect.lower_bound(load_addr);226    if (pos != m_addr_to_sect.end()) {227      if (load_addr != pos->first && pos != m_addr_to_sect.begin())228        --pos;229      const addr_t pos_load_addr = pos->first;230      if (load_addr >= pos_load_addr) {231        addr_t offset = load_addr - pos_load_addr;232        if (offset < pos->second->GetByteSize() + (allow_section_end ? 1 : 0)) {233          // We have found the top level section, now we need to find the234          // deepest child section.235          return pos->second->ResolveContainedAddress(offset, so_addr,236                                                      allow_section_end);237        }238      }239    } else {240      // There are no entries that have an address that is >= load_addr, so we241      // need to check the last entry on our collection.242      addr_to_sect_collection::const_reverse_iterator rpos =243          m_addr_to_sect.rbegin();244      if (load_addr >= rpos->first) {245        addr_t offset = load_addr - rpos->first;246        if (offset <247            rpos->second->GetByteSize() + (allow_section_end ? 1 : 0)) {248          // We have found the top level section, now we need to find the249          // deepest child section.250          return rpos->second->ResolveContainedAddress(offset, so_addr,251                                                       allow_section_end);252        }253      }254    }255  }256  so_addr.Clear();257  return false;258}259 260void SectionLoadList::Dump(Stream &s, Target *target) {261  std::lock_guard<std::recursive_mutex> guard(m_mutex);262  addr_to_sect_collection::const_iterator pos, end;263  for (pos = m_addr_to_sect.begin(), end = m_addr_to_sect.end(); pos != end;264       ++pos) {265    s.Printf("addr = 0x%16.16" PRIx64 ", section = %p: ", pos->first,266             static_cast<void *>(pos->second.get()));267    pos->second->Dump(s.AsRawOstream(), s.GetIndentLevel(), target, 0);268  }269}270