Path: blob/main/contrib/llvm-project/lldb/source/Target/SectionLoadList.cpp
39587 views
//===-- SectionLoadList.cpp -----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Target/SectionLoadList.h"910#include "lldb/Core/Module.h"11#include "lldb/Core/Section.h"12#include "lldb/Symbol/Block.h"13#include "lldb/Symbol/Symbol.h"14#include "lldb/Symbol/SymbolContext.h"15#include "lldb/Utility/LLDBLog.h"16#include "lldb/Utility/Log.h"17#include "lldb/Utility/Stream.h"1819using namespace lldb;20using namespace lldb_private;2122SectionLoadList::SectionLoadList(const SectionLoadList &rhs)23: m_addr_to_sect(), m_sect_to_addr(), m_mutex() {24std::lock_guard<std::recursive_mutex> guard(rhs.m_mutex);25m_addr_to_sect = rhs.m_addr_to_sect;26m_sect_to_addr = rhs.m_sect_to_addr;27}2829void SectionLoadList::operator=(const SectionLoadList &rhs) {30std::lock(m_mutex, rhs.m_mutex);31std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex, std::adopt_lock);32std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex, std::adopt_lock);33m_addr_to_sect = rhs.m_addr_to_sect;34m_sect_to_addr = rhs.m_sect_to_addr;35}3637bool SectionLoadList::IsEmpty() const {38std::lock_guard<std::recursive_mutex> guard(m_mutex);39return m_addr_to_sect.empty();40}4142void SectionLoadList::Clear() {43std::lock_guard<std::recursive_mutex> guard(m_mutex);44m_addr_to_sect.clear();45m_sect_to_addr.clear();46}4748addr_t49SectionLoadList::GetSectionLoadAddress(const lldb::SectionSP §ion) const {50// TODO: add support for the same section having multiple load addresses51addr_t section_load_addr = LLDB_INVALID_ADDRESS;52if (section) {53std::lock_guard<std::recursive_mutex> guard(m_mutex);54sect_to_addr_collection::const_iterator pos =55m_sect_to_addr.find(section.get());5657if (pos != m_sect_to_addr.end())58section_load_addr = pos->second;59}60return section_load_addr;61}6263bool SectionLoadList::SetSectionLoadAddress(const lldb::SectionSP §ion,64addr_t load_addr,65bool warn_multiple) {66Log *log = GetLog(LLDBLog::DynamicLoader);67ModuleSP module_sp(section->GetModule());6869if (module_sp) {70LLDB_LOGV(log, "(section = {0} ({1}.{2}), load_addr = {3:x}) module = {4}",71section.get(), module_sp->GetFileSpec(), section->GetName(),72load_addr, module_sp.get());7374if (section->GetByteSize() == 0)75return false; // No change7677// Fill in the section -> load_addr map78std::lock_guard<std::recursive_mutex> guard(m_mutex);79sect_to_addr_collection::iterator sta_pos =80m_sect_to_addr.find(section.get());81if (sta_pos != m_sect_to_addr.end()) {82if (load_addr == sta_pos->second)83return false; // No change...84else85sta_pos->second = load_addr;86} else87m_sect_to_addr[section.get()] = load_addr;8889// Fill in the load_addr -> section map90addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);91if (ats_pos != m_addr_to_sect.end()) {92// Some sections are ok to overlap, and for others we should warn. When93// we have multiple load addresses that correspond to a section, we will94// always attribute the section to the be last section that claims it95// exists at that address. Sometimes it is ok for more that one section96// to be loaded at a specific load address, and other times it isn't. The97// "warn_multiple" parameter tells us if we should warn in this case or98// not. The DynamicLoader plug-in subclasses should know which sections99// should warn and which shouldn't (darwin shared cache modules all100// shared the same "__LINKEDIT" sections, so the dynamic loader can pass101// false for "warn_multiple").102if (warn_multiple && section != ats_pos->second) {103ModuleSP module_sp(section->GetModule());104if (module_sp) {105ModuleSP curr_module_sp(ats_pos->second->GetModule());106if (curr_module_sp) {107module_sp->ReportWarning(108"address {0:x16} maps to more than one section: {1}.{2} and "109"{3}.{4}",110load_addr, module_sp->GetFileSpec().GetFilename().GetCString(),111section->GetName().GetCString(),112curr_module_sp->GetFileSpec().GetFilename().GetCString(),113ats_pos->second->GetName().GetCString());114}115}116}117ats_pos->second = section;118} else {119// Remove the old address->section entry, if120// there is one.121for (const auto &entry : m_addr_to_sect) {122if (entry.second == section) {123const auto &it_pos = m_addr_to_sect.find(entry.first);124m_addr_to_sect.erase(it_pos);125break;126}127}128m_addr_to_sect[load_addr] = section;129}130return true; // Changed131132} else {133if (log) {134LLDB_LOGF(135log,136"SectionLoadList::%s (section = %p (%s), load_addr = 0x%16.16" PRIx64137") error: module has been deleted",138__FUNCTION__, static_cast<void *>(section.get()),139section->GetName().AsCString(), load_addr);140}141}142return false;143}144145size_t SectionLoadList::SetSectionUnloaded(const lldb::SectionSP §ion_sp) {146size_t unload_count = 0;147148if (section_sp) {149Log *log = GetLog(LLDBLog::DynamicLoader);150151if (log && log->GetVerbose()) {152ModuleSP module_sp = section_sp->GetModule();153std::string module_name("<Unknown>");154if (module_sp) {155const FileSpec &module_file_spec(156section_sp->GetModule()->GetFileSpec());157module_name = module_file_spec.GetPath();158}159LLDB_LOGF(log, "SectionLoadList::%s (section = %p (%s.%s))", __FUNCTION__,160static_cast<void *>(section_sp.get()), module_name.c_str(),161section_sp->GetName().AsCString());162}163164std::lock_guard<std::recursive_mutex> guard(m_mutex);165166sect_to_addr_collection::iterator sta_pos =167m_sect_to_addr.find(section_sp.get());168if (sta_pos != m_sect_to_addr.end()) {169++unload_count;170addr_t load_addr = sta_pos->second;171m_sect_to_addr.erase(sta_pos);172173addr_to_sect_collection::iterator ats_pos =174m_addr_to_sect.find(load_addr);175if (ats_pos != m_addr_to_sect.end())176m_addr_to_sect.erase(ats_pos);177}178}179return unload_count;180}181182bool SectionLoadList::SetSectionUnloaded(const lldb::SectionSP §ion_sp,183addr_t load_addr) {184Log *log = GetLog(LLDBLog::DynamicLoader);185186if (log && log->GetVerbose()) {187ModuleSP module_sp = section_sp->GetModule();188std::string module_name("<Unknown>");189if (module_sp) {190const FileSpec &module_file_spec(section_sp->GetModule()->GetFileSpec());191module_name = module_file_spec.GetPath();192}193LLDB_LOGF(194log,195"SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64196")",197__FUNCTION__, static_cast<void *>(section_sp.get()),198module_name.c_str(), section_sp->GetName().AsCString(), load_addr);199}200bool erased = false;201std::lock_guard<std::recursive_mutex> guard(m_mutex);202sect_to_addr_collection::iterator sta_pos =203m_sect_to_addr.find(section_sp.get());204if (sta_pos != m_sect_to_addr.end()) {205erased = true;206m_sect_to_addr.erase(sta_pos);207}208209addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);210if (ats_pos != m_addr_to_sect.end()) {211erased = true;212m_addr_to_sect.erase(ats_pos);213}214215return erased;216}217218bool SectionLoadList::ResolveLoadAddress(addr_t load_addr, Address &so_addr,219bool allow_section_end) const {220// First find the top level section that this load address exists in221std::lock_guard<std::recursive_mutex> guard(m_mutex);222if (!m_addr_to_sect.empty()) {223addr_to_sect_collection::const_iterator pos =224m_addr_to_sect.lower_bound(load_addr);225if (pos != m_addr_to_sect.end()) {226if (load_addr != pos->first && pos != m_addr_to_sect.begin())227--pos;228const addr_t pos_load_addr = pos->first;229if (load_addr >= pos_load_addr) {230addr_t offset = load_addr - pos_load_addr;231if (offset < pos->second->GetByteSize() + (allow_section_end ? 1 : 0)) {232// We have found the top level section, now we need to find the233// deepest child section.234return pos->second->ResolveContainedAddress(offset, so_addr,235allow_section_end);236}237}238} else {239// There are no entries that have an address that is >= load_addr, so we240// need to check the last entry on our collection.241addr_to_sect_collection::const_reverse_iterator rpos =242m_addr_to_sect.rbegin();243if (load_addr >= rpos->first) {244addr_t offset = load_addr - rpos->first;245if (offset <246rpos->second->GetByteSize() + (allow_section_end ? 1 : 0)) {247// We have found the top level section, now we need to find the248// deepest child section.249return rpos->second->ResolveContainedAddress(offset, so_addr,250allow_section_end);251}252}253}254}255so_addr.Clear();256return false;257}258259void SectionLoadList::Dump(Stream &s, Target *target) {260std::lock_guard<std::recursive_mutex> guard(m_mutex);261addr_to_sect_collection::const_iterator pos, end;262for (pos = m_addr_to_sect.begin(), end = m_addr_to_sect.end(); pos != end;263++pos) {264s.Printf("addr = 0x%16.16" PRIx64 ", section = %p: ", pos->first,265static_cast<void *>(pos->second.get()));266pos->second->Dump(s.AsRawOstream(), s.GetIndentLevel(), target, 0);267}268}269270271