llvm-project/lldb/source/Target/SectionLoadList.cpp
Jason Molenda fb36a54ef6
[lldb] Rename formatv verbose log call, misc log cleanups [NFC] (#186951)
lldb had three preprocessor defines for logging,

LLDB_LOG  - formatv style argument
LLDB_LOGF - printf style argument
LLDB_LOGV - formatv style argument, only when verbose enabled

If you weren't looking at Log.h and the definition of these three, and
wanted to log something with formatv, it was easy to use LLDB_LOGV by
accident. We just had a situation where an important log statement
wasn't logging and it turned out to be this. This is fragile if you
aren't looking at the header directly, so I'd like to make this more
explicit. My proposal:

LLDB_LOG  - formatv style argument
LLDB_LOG_VERBOSE - formatv style argument, only when verbose enabled 
LLDB_LOGF - printf style argument
LLDB_LOGF_VERBOSE - printf style argument, only when verbose enabled

The new fouth one is to remove several places where we do `if (log &&
log->GetVerbose()) LLDB_LOGF (...)` in the sources today, and make both
styles consistent.

This PR implements that change, mechanically changing all LLDB_LOGV's to
LLDB_LOG_VERBOSE.

It also updates many of the `if (log && log->GetVerbose()) LLDB_LOGF`'s.
Some uses of this conditional expression do extra calculations in
addition to logging, and so those were left as-is so we're not doing
throwaway work when running without verbose logging.

There were many instances throughout lldb where callers are still doing
`if (log) LLDB_LOG*(...)`, a remnant of when all calls were to the `Log`
object's `Printf()` method, and you had to check if your local Log*
pointer was non-nullptr before calling the method. I removed those,
again keeping ones where work for logging is done in the block of code.

The code changes are all mechanical and uninteresting, but the question
of whether this naming change is widely agreed on is maybe worth
discussing.
2026-03-18 16:31:33 -07:00

269 lines
9.8 KiB
C++

//===-- SectionLoadList.cpp -----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Stream.h"
using namespace lldb;
using namespace lldb_private;
SectionLoadList::SectionLoadList(const SectionLoadList &rhs)
: m_addr_to_sect(), m_sect_to_addr(), m_mutex() {
std::lock_guard<std::recursive_mutex> guard(rhs.m_mutex);
m_addr_to_sect = rhs.m_addr_to_sect;
m_sect_to_addr = rhs.m_sect_to_addr;
}
void SectionLoadList::operator=(const SectionLoadList &rhs) {
std::lock(m_mutex, rhs.m_mutex);
std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex, std::adopt_lock);
std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex, std::adopt_lock);
m_addr_to_sect = rhs.m_addr_to_sect;
m_sect_to_addr = rhs.m_sect_to_addr;
}
bool SectionLoadList::IsEmpty() const {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
return m_addr_to_sect.empty();
}
void SectionLoadList::Clear() {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
m_addr_to_sect.clear();
m_sect_to_addr.clear();
}
addr_t
SectionLoadList::GetSectionLoadAddress(const lldb::SectionSP &section) const {
// TODO: add support for the same section having multiple load addresses
addr_t section_load_addr = LLDB_INVALID_ADDRESS;
if (section) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
sect_to_addr_collection::const_iterator pos =
m_sect_to_addr.find(section.get());
if (pos != m_sect_to_addr.end())
section_load_addr = pos->second;
}
return section_load_addr;
}
bool SectionLoadList::SetSectionLoadAddress(const lldb::SectionSP &section,
addr_t load_addr,
bool warn_multiple) {
Log *log = GetLog(LLDBLog::DynamicLoader);
ModuleSP module_sp(section->GetModule());
if (module_sp) {
LLDB_LOG_VERBOSE(
log, "(section = {0} ({1}.{2}), load_addr = {3:x}) module = {4}",
section.get(), module_sp->GetFileSpec(), section->GetName(), load_addr,
module_sp.get());
if (section->GetByteSize() == 0)
return false; // No change
// Fill in the section -> load_addr map
std::lock_guard<std::recursive_mutex> guard(m_mutex);
sect_to_addr_collection::iterator sta_pos =
m_sect_to_addr.find(section.get());
if (sta_pos != m_sect_to_addr.end()) {
if (load_addr == sta_pos->second)
return false; // No change...
else
sta_pos->second = load_addr;
} else
m_sect_to_addr[section.get()] = load_addr;
// Fill in the load_addr -> section map
addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
if (ats_pos != m_addr_to_sect.end()) {
// Some sections are ok to overlap, and for others we should warn. When
// we have multiple load addresses that correspond to a section, we will
// always attribute the section to the be last section that claims it
// exists at that address. Sometimes it is ok for more that one section
// to be loaded at a specific load address, and other times it isn't. The
// "warn_multiple" parameter tells us if we should warn in this case or
// not. The DynamicLoader plug-in subclasses should know which sections
// should warn and which shouldn't (darwin shared cache modules all
// shared the same "__LINKEDIT" sections, so the dynamic loader can pass
// false for "warn_multiple").
if (warn_multiple && section != ats_pos->second) {
ModuleSP module_sp(section->GetModule());
if (module_sp) {
ModuleSP curr_module_sp(ats_pos->second->GetModule());
if (curr_module_sp) {
module_sp->ReportWarning(
"address {0:x16} maps to more than one section: {1}.{2} and "
"{3}.{4}",
load_addr, module_sp->GetFileSpec().GetFilename().GetCString(),
section->GetName().GetCString(),
curr_module_sp->GetFileSpec().GetFilename().GetCString(),
ats_pos->second->GetName().GetCString());
}
}
}
ats_pos->second = section;
} else {
// Remove the old address->section entry, if
// there is one.
for (const auto &entry : m_addr_to_sect) {
if (entry.second == section) {
const auto &it_pos = m_addr_to_sect.find(entry.first);
m_addr_to_sect.erase(it_pos);
break;
}
}
m_addr_to_sect[load_addr] = section;
}
return true; // Changed
} else {
LLDB_LOGF(
log,
"SectionLoadList::%s (section = %p (%s), load_addr = 0x%16.16" PRIx64
") error: module has been deleted",
__FUNCTION__, static_cast<void *>(section.get()),
section->GetName().AsCString(), load_addr);
}
return false;
}
size_t SectionLoadList::SetSectionUnloaded(const lldb::SectionSP &section_sp) {
size_t unload_count = 0;
if (section_sp) {
Log *log = GetLog(LLDBLog::DynamicLoader);
if (log && log->GetVerbose()) {
ModuleSP module_sp = section_sp->GetModule();
std::string module_name("<Unknown>");
if (module_sp) {
const FileSpec &module_file_spec(
section_sp->GetModule()->GetFileSpec());
module_name = module_file_spec.GetPath();
}
LLDB_LOGF(log, "SectionLoadList::%s (section = %p (%s.%s))", __FUNCTION__,
static_cast<void *>(section_sp.get()), module_name.c_str(),
section_sp->GetName().AsCString());
}
std::lock_guard<std::recursive_mutex> guard(m_mutex);
sect_to_addr_collection::iterator sta_pos =
m_sect_to_addr.find(section_sp.get());
if (sta_pos != m_sect_to_addr.end()) {
++unload_count;
addr_t load_addr = sta_pos->second;
m_sect_to_addr.erase(sta_pos);
addr_to_sect_collection::iterator ats_pos =
m_addr_to_sect.find(load_addr);
if (ats_pos != m_addr_to_sect.end())
m_addr_to_sect.erase(ats_pos);
}
}
return unload_count;
}
bool SectionLoadList::SetSectionUnloaded(const lldb::SectionSP &section_sp,
addr_t load_addr) {
Log *log = GetLog(LLDBLog::DynamicLoader);
if (log && log->GetVerbose()) {
ModuleSP module_sp = section_sp->GetModule();
std::string module_name("<Unknown>");
if (module_sp) {
const FileSpec &module_file_spec(section_sp->GetModule()->GetFileSpec());
module_name = module_file_spec.GetPath();
}
LLDB_LOGF(
log,
"SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64
")",
__FUNCTION__, static_cast<void *>(section_sp.get()),
module_name.c_str(), section_sp->GetName().AsCString(), load_addr);
}
bool erased = false;
std::lock_guard<std::recursive_mutex> guard(m_mutex);
sect_to_addr_collection::iterator sta_pos =
m_sect_to_addr.find(section_sp.get());
if (sta_pos != m_sect_to_addr.end()) {
erased = true;
m_sect_to_addr.erase(sta_pos);
}
addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
if (ats_pos != m_addr_to_sect.end()) {
erased = true;
m_addr_to_sect.erase(ats_pos);
}
return erased;
}
bool SectionLoadList::ResolveLoadAddress(addr_t load_addr, Address &so_addr,
bool allow_section_end) const {
// First find the top level section that this load address exists in
std::lock_guard<std::recursive_mutex> guard(m_mutex);
if (!m_addr_to_sect.empty()) {
addr_to_sect_collection::const_iterator pos =
m_addr_to_sect.lower_bound(load_addr);
if (pos != m_addr_to_sect.end()) {
if (load_addr != pos->first && pos != m_addr_to_sect.begin())
--pos;
const addr_t pos_load_addr = pos->first;
if (load_addr >= pos_load_addr) {
addr_t offset = load_addr - pos_load_addr;
if (offset < pos->second->GetByteSize() + (allow_section_end ? 1 : 0)) {
// We have found the top level section, now we need to find the
// deepest child section.
return pos->second->ResolveContainedAddress(offset, so_addr,
allow_section_end);
}
}
} else {
// There are no entries that have an address that is >= load_addr, so we
// need to check the last entry on our collection.
addr_to_sect_collection::const_reverse_iterator rpos =
m_addr_to_sect.rbegin();
if (load_addr >= rpos->first) {
addr_t offset = load_addr - rpos->first;
if (offset <
rpos->second->GetByteSize() + (allow_section_end ? 1 : 0)) {
// We have found the top level section, now we need to find the
// deepest child section.
return rpos->second->ResolveContainedAddress(offset, so_addr,
allow_section_end);
}
}
}
}
so_addr.Clear();
return false;
}
void SectionLoadList::Dump(Stream &s, Target *target) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
addr_to_sect_collection::const_iterator pos, end;
for (pos = m_addr_to_sect.begin(), end = m_addr_to_sect.end(); pos != end;
++pos) {
s.Printf("addr = 0x%16.16" PRIx64 ", section = %p: ", pos->first,
static_cast<void *>(pos->second.get()));
pos->second->Dump(s.AsRawOstream(), s.GetIndentLevel(), target, 0);
}
}