Add MemoryRegionInfo to SB API

Summary:
This adds new SB API calls and classes to allow a user of the SB API to obtain a full list of memory regions accessible within the process. Adding this to the API makes it possible use the API for tasks like scanning memory for blocks allocated with a header and footer to track down memory leaks, otherwise just inspecting every address is impractical especially for 64 bit processes.

These changes only add the API itself and a base implementation of GetMemoryRegions() to lldb_private::Process::GetMemoryRegions.
I will submit separate patches to fill in lldb_private::Process::GetMemoryRegionInfoList and GetMemoryRegionInfo for individual platforms.

The original discussion about this is here:
http://lists.llvm.org/pipermail/lldb-dev/2016-May/010203.html

Reviewers: clayborg

Subscribers: lldb-commits

Differential Revision: http://reviews.llvm.org/D20565

llvm-svn: 273547
This commit is contained in:
Howard Hellyer 2016-06-23 08:35:37 +00:00
parent 89fb6643e9
commit 2603684372
13 changed files with 587 additions and 0 deletions

View File

@ -43,6 +43,8 @@
#include "lldb/API/SBLaunchInfo.h"
#include "lldb/API/SBLineEntry.h"
#include "lldb/API/SBListener.h"
#include "lldb/API/SBMemoryRegionInfo.h"
#include "lldb/API/SBMemoryRegionInfoList.h"
#include "lldb/API/SBModule.h"
#include "lldb/API/SBModuleSpec.h"
#include "lldb/API/SBPlatform.h"

View File

@ -59,6 +59,8 @@ class LLDB_API SBLanguageRuntime;
class LLDB_API SBLaunchInfo;
class LLDB_API SBLineEntry;
class LLDB_API SBListener;
class LLDB_API SBMemoryRegionInfo;
class LLDB_API SBMemoryRegionInfoList;
class LLDB_API SBModule;
class LLDB_API SBModuleSpec;
class LLDB_API SBModuleSpecList;

View File

@ -0,0 +1,107 @@
//===-- SBMemoryRegionInfo.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_SBMemoryRegionInfo_h_
#define LLDB_SBMemoryRegionInfo_h_
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBData.h"
namespace lldb {
class LLDB_API SBMemoryRegionInfo
{
public:
SBMemoryRegionInfo ();
SBMemoryRegionInfo (const lldb::SBMemoryRegionInfo &rhs);
~SBMemoryRegionInfo ();
const lldb::SBMemoryRegionInfo &
operator = (const lldb::SBMemoryRegionInfo &rhs);
void
Clear();
//------------------------------------------------------------------
/// Get the base address of this memory range.
///
/// @return
/// The base address of this memory range.
//------------------------------------------------------------------
lldb::addr_t
GetRegionBase ();
//------------------------------------------------------------------
/// Get the end address of this memory range.
///
/// @return
/// The base address of this memory range.
//------------------------------------------------------------------
lldb::addr_t
GetRegionEnd ();
//------------------------------------------------------------------
/// Check if this memory address is marked readable to the process.
///
/// @return
/// true if this memory address is marked readable
//------------------------------------------------------------------
bool
IsReadable ();
//------------------------------------------------------------------
/// Check if this memory address is marked writable to the process.
///
/// @return
/// true if this memory address is marked writable
//------------------------------------------------------------------
bool
IsWritable ();
//------------------------------------------------------------------
/// Check if this memory address is marked executable to the process.
///
/// @return
/// true if this memory address is marked executable
//------------------------------------------------------------------
bool
IsExecutable ();
bool
operator == (const lldb::SBMemoryRegionInfo &rhs) const;
bool
operator != (const lldb::SBMemoryRegionInfo &rhs) const;
bool
GetDescription (lldb::SBStream &description);
private:
friend class SBProcess;
friend class SBMemoryRegionInfoList;
lldb_private::MemoryRegionInfo &
ref();
const lldb_private::MemoryRegionInfo &
ref() const;
SBMemoryRegionInfo (const lldb_private::MemoryRegionInfo *lldb_object_ptr);
lldb::MemoryRegionInfoUP m_opaque_ap;
};
} // namespace lldb
#endif // LLDB_SBMemoryRegionInfo_h_

View File

@ -0,0 +1,63 @@
//===-- SBMemoryRegionInfoList.h --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_SBMemoryRegionInfoList_h_
#define LLDB_SBMemoryRegionInfoList_h_
#include "lldb/API/SBDefines.h"
class MemoryRegionInfoListImpl;
namespace lldb {
class LLDB_API SBMemoryRegionInfoList
{
public:
SBMemoryRegionInfoList ();
SBMemoryRegionInfoList (const lldb::SBMemoryRegionInfoList &rhs);
const SBMemoryRegionInfoList &
operator = (const SBMemoryRegionInfoList &rhs);
~SBMemoryRegionInfoList ();
uint32_t
GetSize () const;
bool
GetMemoryRegionAtIndex (uint32_t idx, SBMemoryRegionInfo &region_info);
void
Append (lldb::SBMemoryRegionInfo &region);
void
Append (lldb::SBMemoryRegionInfoList &region_list);
void
Clear ();
protected:
const MemoryRegionInfoListImpl *
operator->() const;
const MemoryRegionInfoListImpl &
operator*() const;
private:
std::unique_ptr<MemoryRegionInfoListImpl> m_opaque_ap;
};
} // namespace lldb
#endif // LLDB_SBMemoryRegionInfoList_h_

View File

@ -393,6 +393,34 @@ public:
lldb::SBError
SaveCore(const char *file_name);
//------------------------------------------------------------------
/// Query the address load_addr and store the details of the memory
/// region that contains it in the supplied SBMemoryRegionInfo object.
/// To iterate over all memory regions use GetMemoryRegionList.
///
/// @param[in] load_addr
/// The address to be queried.
///
/// @param[out] region_info
/// A reference to an SBMemoryRegionInfo object that will contain
/// the details of the memory region containing load_addr.
///
/// @return
/// An error object describes any errors that occurred while
/// querying load_addr.
//------------------------------------------------------------------
lldb::SBError
GetMemoryRegionInfo (lldb::addr_t load_addr, lldb::SBMemoryRegionInfo &region_info);
//------------------------------------------------------------------
/// Return the list of memory regions within the process.
///
/// @return
/// A list of all witin the process memory regions.
//------------------------------------------------------------------
lldb::SBMemoryRegionInfoList
GetMemoryRegions();
protected:
friend class SBAddress;
friend class SBBreakpoint;

View File

@ -76,6 +76,7 @@ protected:
friend class SBInstruction;
friend class SBInstructionList;
friend class SBLineEntry;
friend class SBMemoryRegionInfo;
friend class SBModule;
friend class SBModuleSpec;
friend class SBModuleSpecList;

View File

@ -122,6 +122,21 @@ namespace lldb_private
m_execute = (permissions & lldb::ePermissionsExecutable) ? eYes : eNo;
}
bool
operator == (const MemoryRegionInfo &rhs) const
{
return m_range == rhs.m_range &&
m_read == rhs.m_read &&
m_write == rhs.m_write &&
m_execute == rhs.m_execute;
}
bool
operator != (const MemoryRegionInfo &rhs) const
{
return !(*this == rhs);
}
protected:
RangeType m_range;
OptionalBool m_read;

View File

@ -2446,6 +2446,14 @@ public:
return error;
}
virtual Error
GetMemoryRegions (std::vector<lldb::MemoryRegionInfoSP>&)
{
Error error;
error.SetErrorString ("Process::GetMemoryRegions() not supported");
return error;
}
virtual Error
GetWatchpointSupportInfo (uint32_t &num)
{

View File

@ -356,6 +356,8 @@ namespace lldb {
typedef std::weak_ptr<lldb_private::Listener> ListenerWP;
typedef std::shared_ptr<lldb_private::LogChannel> LogChannelSP;
typedef std::shared_ptr<lldb_private::MemoryHistory> MemoryHistorySP;
typedef std::shared_ptr<lldb_private::MemoryRegionInfo> MemoryRegionInfoSP;
typedef std::unique_ptr<lldb_private::MemoryRegionInfo> MemoryRegionInfoUP;
typedef std::shared_ptr<lldb_private::Module> ModuleSP;
typedef std::weak_ptr<lldb_private::Module> ModuleWP;
typedef std::shared_ptr<lldb_private::ObjectFile> ObjectFileSP;

View File

@ -35,6 +35,8 @@ add_lldb_library(liblldb SHARED
SBLaunchInfo.cpp
SBLineEntry.cpp
SBListener.cpp
SBMemoryRegionInfo.cpp
SBMemoryRegionInfoList.cpp
SBModule.cpp
SBModuleSpec.cpp
SBPlatform.cpp

View File

@ -0,0 +1,121 @@
//===-- SBMemoryRegionInfo.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/API/SBDefines.h"
#include "lldb/API/SBError.h"
#include "lldb/API/SBMemoryRegionInfo.h"
#include "lldb/API/SBStream.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Target/MemoryRegionInfo.h"
using namespace lldb;
using namespace lldb_private;
SBMemoryRegionInfo::SBMemoryRegionInfo () :
m_opaque_ap (new MemoryRegionInfo())
{
}
SBMemoryRegionInfo::SBMemoryRegionInfo (const MemoryRegionInfo *lldb_object_ptr) :
m_opaque_ap (new MemoryRegionInfo())
{
if (lldb_object_ptr)
ref() = *lldb_object_ptr;
}
SBMemoryRegionInfo::SBMemoryRegionInfo(const SBMemoryRegionInfo &rhs) :
m_opaque_ap (new MemoryRegionInfo())
{
ref() = rhs.ref();
}
const SBMemoryRegionInfo &
SBMemoryRegionInfo::operator = (const SBMemoryRegionInfo &rhs)
{
if (this != &rhs)
{
ref() = rhs.ref();
}
return *this;
}
SBMemoryRegionInfo::~SBMemoryRegionInfo ()
{
}
void
SBMemoryRegionInfo::Clear()
{
m_opaque_ap->Clear();
}
bool
SBMemoryRegionInfo::operator == (const SBMemoryRegionInfo &rhs) const
{
return ref() == rhs.ref();
}
bool
SBMemoryRegionInfo::operator != (const SBMemoryRegionInfo &rhs) const
{
return ref() != rhs.ref();
}
MemoryRegionInfo &
SBMemoryRegionInfo::ref()
{
return *m_opaque_ap;
}
const MemoryRegionInfo &
SBMemoryRegionInfo::ref() const
{
return *m_opaque_ap;
}
lldb::addr_t
SBMemoryRegionInfo::GetRegionBase () {
return m_opaque_ap->GetRange().GetRangeBase();
}
lldb::addr_t
SBMemoryRegionInfo::GetRegionEnd () {
return m_opaque_ap->GetRange().GetRangeEnd();
}
bool
SBMemoryRegionInfo::IsReadable () {
return m_opaque_ap->GetReadable() == MemoryRegionInfo::eYes;
}
bool
SBMemoryRegionInfo::IsWritable () {
return m_opaque_ap->GetWritable() == MemoryRegionInfo::eYes;
}
bool
SBMemoryRegionInfo::IsExecutable () {
return m_opaque_ap->GetExecutable() == MemoryRegionInfo::eYes;
}
bool
SBMemoryRegionInfo::GetDescription (SBStream &description)
{
Stream &strm = description.ref();
const addr_t load_addr = m_opaque_ap->GetRange().base;
strm.Printf ("[0x%16.16" PRIx64 "-0x%16.16" PRIx64 " ", load_addr, load_addr + m_opaque_ap->GetRange().size);
strm.Printf (m_opaque_ap->GetReadable() ? "R" : "-");
strm.Printf (m_opaque_ap->GetWritable() ? "W" : "-");
strm.Printf (m_opaque_ap->GetExecutable() ? "X" : "-");
strm.Printf ("]");
return true;
}

View File

@ -0,0 +1,162 @@
//===-- SBMemoryRegionInfoList.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/API/SBMemoryRegionInfo.h"
#include "lldb/API/SBMemoryRegionInfoList.h"
#include "lldb/API/SBStream.h"
#include "lldb/Core/Log.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include <vector>
using namespace lldb;
using namespace lldb_private;
class MemoryRegionInfoListImpl
{
public:
MemoryRegionInfoListImpl () :
m_regions()
{
}
MemoryRegionInfoListImpl (const MemoryRegionInfoListImpl& rhs) :
m_regions(rhs.m_regions)
{
}
MemoryRegionInfoListImpl&
operator = (const MemoryRegionInfoListImpl& rhs)
{
if (this == &rhs)
return *this;
m_regions = rhs.m_regions;
return *this;
}
uint32_t
GetSize ()
{
return m_regions.size();
}
void
Append (const lldb::SBMemoryRegionInfo& sb_region)
{
m_regions.push_back(sb_region);
}
void
Append (const MemoryRegionInfoListImpl& list)
{
for (auto val : list.m_regions)
Append (val);
}
void
Clear ()
{
m_regions.clear();
}
bool
GetMemoryRegionInfoAtIndex (uint32_t index, SBMemoryRegionInfo &region_info)
{
if (index >= GetSize())
return false;
region_info = m_regions[index];
return true;
}
private:
std::vector<lldb::SBMemoryRegionInfo> m_regions;
};
SBMemoryRegionInfoList::SBMemoryRegionInfoList () :
m_opaque_ap (new MemoryRegionInfoListImpl())
{
}
SBMemoryRegionInfoList::SBMemoryRegionInfoList (const SBMemoryRegionInfoList& rhs) :
m_opaque_ap (new MemoryRegionInfoListImpl(*rhs.m_opaque_ap))
{
}
SBMemoryRegionInfoList::~SBMemoryRegionInfoList ()
{
}
const SBMemoryRegionInfoList &
SBMemoryRegionInfoList::operator = (const SBMemoryRegionInfoList &rhs)
{
if (this != &rhs)
{
*m_opaque_ap = *rhs.m_opaque_ap;
}
return *this;
}
uint32_t
SBMemoryRegionInfoList::GetSize() const
{
return m_opaque_ap->GetSize();
}
bool
SBMemoryRegionInfoList::GetMemoryRegionAtIndex (uint32_t idx, SBMemoryRegionInfo &region_info)
{
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
bool result = m_opaque_ap->GetMemoryRegionInfoAtIndex(idx, region_info);
if (log)
{
SBStream sstr;
region_info.GetDescription (sstr);
log->Printf ("SBMemoryRegionInfoList::GetMemoryRegionAtIndex (this.ap=%p, idx=%d) => SBMemoryRegionInfo (this.ap=%p, '%s')",
static_cast<void*>(m_opaque_ap.get()), idx,
static_cast<void*>(region_info.m_opaque_ap.get()), sstr.GetData());
}
return result;
}
void
SBMemoryRegionInfoList::Clear()
{
m_opaque_ap->Clear();
}
void
SBMemoryRegionInfoList::Append(SBMemoryRegionInfo &sb_region)
{
m_opaque_ap->Append(sb_region);
}
void
SBMemoryRegionInfoList::Append(SBMemoryRegionInfoList &sb_region_list)
{
m_opaque_ap->Append(*sb_region_list);
}
const MemoryRegionInfoListImpl *
SBMemoryRegionInfoList::operator->() const
{
return m_opaque_ap.get();
}
const MemoryRegionInfoListImpl&
SBMemoryRegionInfoList::operator*() const
{
assert (m_opaque_ap.get());
return *m_opaque_ap.get();
}

View File

@ -23,6 +23,7 @@
#include "lldb/Core/State.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SystemRuntime.h"
@ -36,6 +37,8 @@
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBMemoryRegionInfo.h"
#include "lldb/API/SBMemoryRegionInfoList.h"
#include "lldb/API/SBThread.h"
#include "lldb/API/SBThreadCollection.h"
#include "lldb/API/SBStream.h"
@ -1476,3 +1479,74 @@ SBProcess::SaveCore(const char *file_name)
error.ref() = PluginManager::SaveCore(process_sp, core_file);
return error;
}
lldb::SBError
SBProcess::GetMemoryRegionInfo (lldb::addr_t load_addr, SBMemoryRegionInfo &sb_region_info)
{
lldb::SBError sb_error;
ProcessSP process_sp(GetSP());
MemoryRegionInfoSP region_info_sp = std::make_shared<lldb_private::MemoryRegionInfo>();
if (process_sp)
{
Process::StopLocker stop_locker;
if (stop_locker.TryLock(&process_sp->GetRunLock()))
{
std::lock_guard<std::recursive_mutex> guard(process_sp->GetTarget().GetAPIMutex());
sb_error.ref() = process_sp->GetMemoryRegionInfo(load_addr, *region_info_sp);
if( sb_error.Success() ) {
sb_region_info.ref() = *region_info_sp;
}
}
else
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
log->Printf ("SBProcess(%p)::GetMemoryRegionInfo() => error: process is running",
static_cast<void*>(process_sp.get()));
sb_error.SetErrorString("process is running");
}
}
else
{
sb_error.SetErrorString ("SBProcess is invalid");
}
return sb_error;
}
lldb::SBMemoryRegionInfoList
SBProcess::GetMemoryRegions()
{
lldb::SBError sb_error;
lldb::SBMemoryRegionInfoList sb_region_list;
ProcessSP process_sp(GetSP());
if (process_sp)
{
Process::StopLocker stop_locker;
if (stop_locker.TryLock(&process_sp->GetRunLock()))
{
std::lock_guard<std::recursive_mutex> guard(process_sp->GetTarget().GetAPIMutex());
std::vector<MemoryRegionInfoSP> region_list;
sb_error.ref() = process_sp->GetMemoryRegions(region_list);
if( sb_error.Success() ) {
std::vector<MemoryRegionInfoSP>::iterator end = region_list.end();
for( std::vector<MemoryRegionInfoSP>::iterator it = region_list.begin(); it != end; it++ ) {
SBMemoryRegionInfo sb_region_info(it->get());
sb_region_list.Append(sb_region_info);
}
}
}
else
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
log->Printf ("SBProcess(%p)::GetMemoryRegionInfo() => error: process is running",
static_cast<void*>(process_sp.get()));
sb_error.SetErrorString("process is running");
}
}
else
{
sb_error.SetErrorString ("SBProcess is invalid");
}
return sb_region_list;
}