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 §ion) 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 §ion,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 §ion_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 §ion_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