Files
clang-p2996/lldb/source/Target/SectionLoadList.cpp
Greg Clayton c859e2d524 Full core file support has been added for mach-o core files.
Tracking modules down when you have a UUID and a path has been improved.

DynamicLoaderDarwinKernel no longer parses mach-o load commands and it
now uses the memory based modules now that we can load modules from memory.

Added a target setting named "target.exec-search-paths" which can be used
to supply a list of directories to use when trying to look for executables.
This allows one or more directories to be used when searching for modules
that may not exist in the SDK/PDK. The target automatically adds the directory
for the main executable to this list so this should help us in tracking down
shared libraries and other binaries. 

llvm-svn: 150426
2012-02-13 23:10:39 +00:00

244 lines
7.8 KiB
C++

//===-- SectionLoadList.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Target/SectionLoadList.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
using namespace lldb;
using namespace lldb_private;
bool
SectionLoadList::IsEmpty() const
{
Mutex::Locker locker(m_mutex);
return m_addr_to_sect.empty();
}
void
SectionLoadList::Clear ()
{
Mutex::Locker locker(m_mutex);
m_addr_to_sect.clear();
m_sect_to_addr.clear();
}
addr_t
SectionLoadList::GetSectionLoadAddress (const Section *section) const
{
// TODO: add support for the same section having multiple load addresses
addr_t section_load_addr = LLDB_INVALID_ADDRESS;
if (section)
{
Mutex::Locker locker(m_mutex);
sect_to_addr_collection::const_iterator pos = m_sect_to_addr.find (section);
if (pos != m_sect_to_addr.end())
section_load_addr = pos->second;
}
return section_load_addr;
}
bool
SectionLoadList::SetSectionLoadAddress (const Section *section, addr_t load_addr)
{
LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));
if (log)
{
const FileSpec &module_file_spec (section->GetModule()->GetFileSpec());
log->Printf ("SectionLoadList::%s (section = %p (%s%s%s.%s), load_addr = 0x%16.16llx)",
__FUNCTION__,
section,
module_file_spec.GetDirectory().AsCString(),
module_file_spec.GetDirectory() ? "/" : "",
module_file_spec.GetFilename().AsCString(),
section->GetName().AsCString(),
load_addr);
}
if (section->GetByteSize() == 0)
return false; // No change
Mutex::Locker locker(m_mutex);
sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section);
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] = 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 (section != ats_pos->second)
{
Module *module = section->GetModule();
if (module)
{
module->ReportWarning ("address 0x%16.16llx maps to more than one section: %s.%s and %s.%s",
load_addr,
module->GetFileSpec().GetFilename().GetCString(),
section->GetName().GetCString(),
ats_pos->second->GetModule()->GetFileSpec().GetFilename().GetCString(),
ats_pos->second->GetName().GetCString());
}
}
ats_pos->second = section;
}
else
m_addr_to_sect[load_addr] = section;
return true; // Changed
}
size_t
SectionLoadList::SetSectionUnloaded (const Section *section)
{
LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));
if (log)
{
const FileSpec &module_file_spec (section->GetModule()->GetFileSpec());
log->Printf ("SectionLoadList::%s (section = %p (%s%s%s.%s))",
__FUNCTION__,
section,
module_file_spec.GetDirectory().AsCString(),
module_file_spec.GetDirectory() ? "/" : "",
module_file_spec.GetFilename().AsCString(),
section->GetName().AsCString());
}
size_t unload_count = 0;
Mutex::Locker locker(m_mutex);
sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section);
if (sta_pos != m_sect_to_addr.end())
{
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 Section *section, addr_t load_addr)
{
LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));
if (log)
{
const FileSpec &module_file_spec (section->GetModule()->GetFileSpec());
log->Printf ("SectionLoadList::%s (section = %p (%s%s%s.%s), load_addr = 0x%16.16llx)",
__FUNCTION__,
section,
module_file_spec.GetDirectory().AsCString(),
module_file_spec.GetDirectory() ? "/" : "",
module_file_spec.GetFilename().AsCString(),
section->GetName().AsCString(),
load_addr);
}
bool erased = false;
Mutex::Locker locker(m_mutex);
sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section);
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) const
{
// First find the top level section that this load address exists in
Mutex::Locker locker(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;
if (load_addr >= pos->first)
{
addr_t offset = load_addr - pos->first;
if (offset < pos->second->GetByteSize())
{
// We have found the top level section, now we need to find the
// deepest child section.
return pos->second->ResolveContainedAddress (offset, so_addr);
}
}
}
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())
{
// We have found the top level section, now we need to find the
// deepest child section.
return rpos->second->ResolveContainedAddress (offset, so_addr);
}
}
}
}
so_addr.Clear();
return false;
}
void
SectionLoadList::Dump (Stream &s, Target *target)
{
Mutex::Locker locker(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.16llx, section = %p: ", pos->first, pos->second);
pos->second->Dump (&s, target, 0);
}
}