#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"
#ifdef MS_DEBUGGER
#include "lldb/Target/ProcessStatus.h"
#endif
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;
#ifdef MS_DEBUGGER
m_device_section_list = rhs.m_device_section_list;
m_is_child = rhs.m_is_child;
#endif
}
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;
#ifdef MS_DEBUGGER
m_device_section_list = rhs.m_device_section_list;
m_is_child = rhs.m_is_child;
#endif
}
bool SectionLoadList::IsEmpty() const {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
#ifdef MS_DEBUGGER
if (ProcessStatus::Instance().IsStopInDevice() && m_device_section_list) {
return m_device_section_list->IsEmpty();
}
#endif
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();
#ifdef MS_DEBUGGER
m_device_section_list.reset();
m_is_child = false;
#endif
}
addr_t
SectionLoadList::GetSectionLoadAddress(const lldb::SectionSP §ion) const {
addr_t section_load_addr = LLDB_INVALID_ADDRESS;
if (section) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
#ifdef MS_DEBUGGER
auto module = section->GetModule();
if (m_device_section_list && module &&
module->GetArchitecture().GetTriple().getArch() == llvm::Triple::hiipu64) {
return m_device_section_list->GetSectionLoadAddress(section);
}
#endif
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 §ion,
addr_t load_addr,
bool warn_multiple) {
Log *log = GetLog(LLDBLog::DynamicLoader);
ModuleSP module_sp(section->GetModule());
if (module_sp) {
LLDB_LOGV(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;
#ifdef MS_DEBUGGER
if (!m_device_section_list && !m_is_child) {
m_device_section_list.reset(new SectionLoadList(true));
}
if (m_device_section_list && module_sp->GetArchitecture().GetTriple().getArch() == llvm::Triple::hiipu64) {
return m_device_section_list->SetSectionLoadAddress(section, load_addr, warn_multiple);
}
#endif
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;
else
sta_pos->second = load_addr;
} else
m_sect_to_addr[section.get()] = load_addr;
addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
if (ats_pos != m_addr_to_sect.end()) {
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 {
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;
} else {
if (log) {
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 §ion_sp) {
size_t unload_count = 0;
if (section_sp) {
#ifdef MS_DEBUGGER
ModuleSP module_sp(section_sp->GetModule());
if (!m_device_section_list && !m_is_child) {
m_device_section_list.reset(new SectionLoadList(true));
}
if (m_device_section_list && module_sp &&
module_sp->GetArchitecture().GetTriple().getArch() == llvm::Triple::hiipu64) {
return m_device_section_list->SetSectionUnloaded(section_sp);
}
#endif
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 §ion_sp,
addr_t load_addr) {
Log *log = GetLog(LLDBLog::DynamicLoader);
#ifdef MS_DEBUGGER
if (!section_sp) {
LLDB_LOG(log, "SectionLoadList::{0}: empty section", __FUNCTION__);
return false;
}
ModuleSP module_sp(section_sp->GetModule());
if (!m_device_section_list && !m_is_child) {
m_device_section_list.reset(new SectionLoadList(true));
}
if (m_device_section_list && module_sp &&
module_sp->GetArchitecture().GetTriple().getArch() == llvm::Triple::hiipu64) {
return m_device_section_list->SetSectionUnloaded(section_sp, load_addr);
}
#endif
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 {
#ifdef MS_DEBUGGER
if (m_device_section_list && ProcessStatus::Instance().IsStopInDevice()) {
LLDB_LOG(GetLog(LLDBLog::DynamicLoader), "ResolveLoadAddress with Device, load_addr={0:x}", load_addr);
return m_device_section_list->ResolveLoadAddress(load_addr, so_addr, allow_section_end);
}
bool found = false;
#endif
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)) {
#ifdef MS_DEBUGGER
found = pos->second->ResolveContainedAddress(offset, so_addr,
allow_section_end);
#else
return pos->second->ResolveContainedAddress(offset, so_addr,
allow_section_end);
#endif
}
}
} else {
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)) {
#ifdef MS_DEBUGGER
found = rpos->second->ResolveContainedAddress(offset, so_addr,
allow_section_end);
#else
return rpos->second->ResolveContainedAddress(offset, so_addr,
allow_section_end);
#endif
}
}
}
}
#ifdef MS_DEBUGGER
if (found) {
return true;
}
if (m_device_section_list) {
return m_device_section_list->ResolveLoadAddress(load_addr, so_addr, allow_section_end);
}
#endif
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);
}
#ifdef MS_DEBUGGER
if (m_device_section_list) {
m_device_section_list->Dump(s, target);
}
#endif
}