Since our expression parser needs to locate areas of memory that are not in use when you have a process that can't JIT code, like core file debugging, the core file process plug-ins should be able to override the Process::GetMemoryRegionInfo(...) function.

In order to make this happen, I have added permissions to sections so that we can know what the permissions are for a given section, and modified both core file plug-ins to override Process::GetMemoryRegionInfo() and answer things correctly.

llvm-svn: 272276
This commit is contained in:
Greg Clayton 2016-06-09 16:34:06 +00:00
parent ecdbb765fa
commit 3385fa08bf
11 changed files with 387 additions and 94 deletions

View File

@ -1340,7 +1340,27 @@ namespace lldb_private {
}
return nullptr;
}
const Entry *
FindEntryThatContainsOrFollows(B addr) const
{
#ifdef ASSERT_RANGEMAP_ARE_SORTED
assert(IsSorted());
#endif
if (!m_entries.empty())
{
typename Collection::const_iterator end = m_entries.end();
typename Collection::const_iterator pos =
std::lower_bound(m_entries.begin(), end, addr, [](const Entry &lhs, B rhs_base) -> bool {
return lhs.GetRangeBase() < rhs_base;
});
if (pos != end)
return &(*pos);
}
return nullptr;
}
Entry *
Back()
{

View File

@ -273,7 +273,19 @@ public:
{
m_thread_specific = b;
}
//------------------------------------------------------------------
/// Get the permissions as OR'ed bits from lldb::Permissions
//------------------------------------------------------------------
uint32_t
GetPermissions() const;
//------------------------------------------------------------------
/// Set the permissions using bits OR'ed from lldb::Permissions
//------------------------------------------------------------------
void
SetPermissions(uint32_t permissions);
ObjectFile *
GetObjectFile ()
{
@ -356,12 +368,15 @@ protected:
lldb::offset_t m_file_size; // Object file size (can be smaller than m_byte_size for zero filled sections...)
uint32_t m_log2align; // log_2(align) of the section (i.e. section has to be aligned to 2^m_log2align)
SectionList m_children; // Child sections
bool m_fake:1, // If true, then this section only can contain the address if one of its
bool m_fake : 1, // If true, then this section only can contain the address if one of its
// children contains an address. This allows for gaps between the children
// that are contained in the address range for this section, but do not produce
// hits unless the children contain the address.
m_encrypted:1, // Set to true if the contents are encrypted
m_thread_specific:1;// This section is thread specific
m_encrypted : 1, // Set to true if the contents are encrypted
m_thread_specific : 1, // This section is thread specific
m_readable : 1, // If this section has read permissions
m_writable : 1, // If this section has write permissions
m_executable : 1; // If this section has executable permissions
uint32_t m_target_byte_size; // Some architectures have non-8-bit byte size. This is specified as
// as a multiple number of a host bytes
private:

View File

@ -92,7 +92,36 @@ namespace lldb_private
{
m_execute = val;
}
//----------------------------------------------------------------------
// Get permissions as a uint32_t that is a mask of one or more bits from
// the lldb::Permissions
//----------------------------------------------------------------------
uint32_t
GetLLDBPermissions() const
{
uint32_t permissions = 0;
if (m_read)
permissions |= lldb::ePermissionsReadable;
if (m_write)
permissions |= lldb::ePermissionsWritable;
if (m_execute)
permissions |= lldb::ePermissionsExecutable;
return permissions;
}
//----------------------------------------------------------------------
// Set permissions from a uint32_t that contains one or more bits from
// the lldb::Permissions
//----------------------------------------------------------------------
void
SetLLDBPermissions(uint32_t permissions)
{
m_read = (permissions & lldb::ePermissionsReadable) ? eYes : eNo;
m_write = (permissions & lldb::ePermissionsWritable) ? eYes : eNo;
m_execute = (permissions & lldb::ePermissionsExecutable) ? eYes : eNo;
}
protected:
RangeType m_range;
OptionalBool m_read;

View File

@ -16,27 +16,29 @@
// Project includes
#include "CommandObjectMemory.h"
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionGroupOutputFile.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Target/MemoryHistory.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Thread.h"
@ -1766,6 +1768,109 @@ protected:
}
};
//-------------------------------------------------------------------------
// CommandObjectMemoryRegion
//-------------------------------------------------------------------------
#pragma mark CommandObjectMemoryRegion
class CommandObjectMemoryRegion : public CommandObjectParsed
{
public:
CommandObjectMemoryRegion(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "memory region",
"Get information on a memory region that contains an address in the current process.",
"memory region ADDR",
eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched),
m_prev_end_addr(LLDB_INVALID_ADDRESS)
{
}
~CommandObjectMemoryRegion() override = default;
protected:
bool
DoExecute(Args &command, CommandReturnObject &result) override
{
ProcessSP process_sp = m_exe_ctx.GetProcessSP();
if (process_sp)
{
Error error;
lldb::addr_t load_addr = m_prev_end_addr;
m_prev_end_addr = LLDB_INVALID_ADDRESS;
const size_t argc = command.GetArgumentCount();
if (argc > 1 || (argc == 0 && load_addr == LLDB_INVALID_ADDRESS))
{
result.AppendErrorWithFormat("'%s' takes one argument:\nUsage: %s\n", m_cmd_name.c_str(),
m_cmd_syntax.c_str());
result.SetStatus(eReturnStatusFailed);
}
else
{
const char *load_addr_cstr = command.GetArgumentAtIndex(0);
if (command.GetArgumentCount() == 1)
{
load_addr = Args::StringToAddress(&m_exe_ctx, load_addr_cstr, LLDB_INVALID_ADDRESS, &error);
if (error.Fail() || load_addr == LLDB_INVALID_ADDRESS)
{
result.AppendErrorWithFormat("invalid address argument \"%s\": %s\n", load_addr_cstr,
error.AsCString());
result.SetStatus(eReturnStatusFailed);
}
}
lldb_private::MemoryRegionInfo range_info;
error = process_sp->GetMemoryRegionInfo(load_addr, range_info);
if (error.Success())
{
lldb_private::Address addr;
ConstString section_name;
if (process_sp->GetTarget().ResolveLoadAddress(load_addr, addr))
{
SectionSP section_sp(addr.GetSection());
if (section_sp)
{
// Got the top most section, not the deepest section
while (section_sp->GetParent())
section_sp = section_sp->GetParent();
section_name = section_sp->GetName();
}
}
result.AppendMessageWithFormat(
"[0x%16.16" PRIx64 "-0x%16.16" PRIx64 ") %c%c%c%s%s\n", range_info.GetRange().GetRangeBase(),
range_info.GetRange().GetRangeEnd(), range_info.GetReadable() ? 'r' : '-',
range_info.GetWritable() ? 'w' : '-', range_info.GetExecutable() ? 'x' : '-',
section_name ? " " : "", section_name ? section_name.AsCString() : "");
m_prev_end_addr = range_info.GetRange().GetRangeEnd();
result.SetStatus(eReturnStatusSuccessFinishResult);
}
else
{
result.SetStatus(eReturnStatusFailed);
result.AppendErrorWithFormat("%s\n", error.AsCString());
}
}
}
else
{
m_prev_end_addr = LLDB_INVALID_ADDRESS;
result.AppendError("invalid process");
result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
const char *
GetRepeatCommand(Args &current_command_args, uint32_t index) override
{
// If we repeat this command, repeat it without any arguments so we can
// show the next memory range
return m_cmd_name.c_str();
}
lldb::addr_t m_prev_end_addr;
};
//-------------------------------------------------------------------------
// CommandObjectMemory
//-------------------------------------------------------------------------
@ -1776,10 +1881,11 @@ CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
"A set of commands for operating on memory.",
"memory <subcommand> [<subcommand-options>]")
{
LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter)));
LoadSubCommand("find", CommandObjectSP(new CommandObjectMemoryFind(interpreter)));
LoadSubCommand("read", CommandObjectSP(new CommandObjectMemoryRead(interpreter)));
LoadSubCommand("write", CommandObjectSP(new CommandObjectMemoryWrite(interpreter)));
LoadSubCommand("history", CommandObjectSP(new CommandObjectMemoryHistory(interpreter)));
LoadSubCommand("region", CommandObjectSP(new CommandObjectMemoryRegion(interpreter)));
}
CommandObjectMemory::~CommandObjectMemory() = default;

View File

@ -17,70 +17,58 @@
using namespace lldb;
using namespace lldb_private;
Section::Section (const ModuleSP &module_sp,
ObjectFile *obj_file,
user_id_t sect_id,
const ConstString &name,
SectionType sect_type,
addr_t file_addr,
addr_t byte_size,
lldb::offset_t file_offset,
lldb::offset_t file_size,
uint32_t log2align,
uint32_t flags,
uint32_t target_byte_size/*=1*/) :
ModuleChild (module_sp),
UserID (sect_id),
Flags (flags),
m_obj_file (obj_file),
m_type (sect_type),
m_parent_wp (),
m_name (name),
m_file_addr (file_addr),
m_byte_size (byte_size),
m_file_offset (file_offset),
m_file_size (file_size),
m_log2align (log2align),
m_children (),
m_fake (false),
m_encrypted (false),
m_thread_specific (false),
m_target_byte_size(target_byte_size)
Section::Section(const ModuleSP &module_sp, ObjectFile *obj_file, user_id_t sect_id, const ConstString &name,
SectionType sect_type, addr_t file_addr, addr_t byte_size, lldb::offset_t file_offset,
lldb::offset_t file_size, uint32_t log2align, uint32_t flags, uint32_t target_byte_size /*=1*/)
: ModuleChild(module_sp),
UserID(sect_id),
Flags(flags),
m_obj_file(obj_file),
m_type(sect_type),
m_parent_wp(),
m_name(name),
m_file_addr(file_addr),
m_byte_size(byte_size),
m_file_offset(file_offset),
m_file_size(file_size),
m_log2align(log2align),
m_children(),
m_fake(false),
m_encrypted(false),
m_thread_specific(false),
m_readable(false),
m_writable(false),
m_executable(false),
m_target_byte_size(target_byte_size)
{
// printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s\n",
// this, module_sp.get(), sect_id, file_addr, file_addr + byte_size, file_offset, file_offset + file_size, flags, name.GetCString());
}
Section::Section (const lldb::SectionSP &parent_section_sp,
const ModuleSP &module_sp,
ObjectFile *obj_file,
user_id_t sect_id,
const ConstString &name,
SectionType sect_type,
addr_t file_addr,
addr_t byte_size,
lldb::offset_t file_offset,
lldb::offset_t file_size,
uint32_t log2align,
uint32_t flags,
uint32_t target_byte_size/*=1*/) :
ModuleChild (module_sp),
UserID (sect_id),
Flags (flags),
m_obj_file (obj_file),
m_type (sect_type),
m_parent_wp (),
m_name (name),
m_file_addr (file_addr),
m_byte_size (byte_size),
m_file_offset (file_offset),
m_file_size (file_size),
m_log2align (log2align),
m_children (),
m_fake (false),
m_encrypted (false),
m_thread_specific (false),
m_target_byte_size(target_byte_size)
Section::Section(const lldb::SectionSP &parent_section_sp, const ModuleSP &module_sp, ObjectFile *obj_file,
user_id_t sect_id, const ConstString &name, SectionType sect_type, addr_t file_addr, addr_t byte_size,
lldb::offset_t file_offset, lldb::offset_t file_size, uint32_t log2align, uint32_t flags,
uint32_t target_byte_size /*=1*/)
: ModuleChild(module_sp),
UserID(sect_id),
Flags(flags),
m_obj_file(obj_file),
m_type(sect_type),
m_parent_wp(),
m_name(name),
m_file_addr(file_addr),
m_byte_size(byte_size),
m_file_offset(file_offset),
m_file_size(file_size),
m_log2align(log2align),
m_children(),
m_fake(false),
m_encrypted(false),
m_thread_specific(false),
m_readable(false),
m_writable(false),
m_executable(false),
m_target_byte_size(target_byte_size)
{
// printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s.%s\n",
// this, module_sp.get(), sect_id, file_addr, file_addr + byte_size, file_offset, file_offset + file_size, flags, parent_section_sp->GetName().GetCString(), name.GetCString());
@ -252,7 +240,8 @@ Section::Dump (Stream *s, Target *target, uint32_t depth) const
range.Dump (s, 0);
}
s->Printf("%c 0x%8.8" PRIx64 " 0x%8.8" PRIx64 " 0x%8.8x ", resolved ? ' ' : '*', m_file_offset, m_file_size, Get());
s->Printf("%c %c%c%c 0x%8.8" PRIx64 " 0x%8.8" PRIx64 " 0x%8.8x ", resolved ? ' ' : '*', m_readable ? 'r' : '-',
m_writable ? 'w' : '-', m_executable ? 'x' : '-', m_file_offset, m_file_size, Get());
DumpName (s);
@ -317,6 +306,33 @@ Section::Slide (addr_t slide_amount, bool slide_children)
return false;
}
//------------------------------------------------------------------
/// Get the permissions as OR'ed bits from lldb::Permissions
//------------------------------------------------------------------
uint32_t
Section::GetPermissions() const
{
uint32_t permissions = 0;
if (m_readable)
permissions |= ePermissionsReadable;
if (m_writable)
permissions |= ePermissionsWritable;
if (m_executable)
permissions |= ePermissionsExecutable;
return permissions;
}
//------------------------------------------------------------------
/// Set the permissions using bits OR'ed from lldb::Permissions
//------------------------------------------------------------------
void
Section::SetPermissions(uint32_t permissions)
{
m_readable = (permissions & ePermissionsReadable) != 0;
m_writable = (permissions & ePermissionsWritable) != 0;
m_executable = (permissions & ePermissionsExecutable) != 0;
}
lldb::offset_t
Section::GetSectionData (void *dst, lldb::offset_t dst_len, lldb::offset_t offset)
{
@ -565,9 +581,12 @@ SectionList::Dump (Stream *s, Target *target, bool show_header, uint32_t depth)
if (show_header && !m_sections.empty())
{
s->Indent();
s->Printf( "SectID Type %s Address File Off. File Size Flags Section Name\n", target_has_loaded_sections ? "Load" : "File");
s->Printf("SectID Type %s Address Perm File Off. File Size Flags "
" Section Name\n",
target_has_loaded_sections ? "Load" : "File");
s->Indent();
s->PutCString("---------- ---------------- --------------------------------------- ---------- ---------- ---------- ----------------------------\n");
s->PutCString("---------- ---------------- --------------------------------------- ---- ---------- ---------- "
"---------- ----------------------------\n");
}

View File

@ -2032,6 +2032,9 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
else if (name == g_sect_name_arm_extab) sect_type = eSectionTypeARMextab;
else if (name == g_sect_name_go_symtab) sect_type = eSectionTypeGoSymtab;
const uint32_t permissions = ((header.sh_flags & SHF_ALLOC) ? ePermissionsReadable : 0) |
((header.sh_flags & SHF_WRITE) ? ePermissionsWritable : 0) |
((header.sh_flags & SHF_EXECINSTR) ? ePermissionsExecutable : 0);
switch (header.sh_type)
{
case SHT_SYMTAB:
@ -2083,6 +2086,7 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
header.sh_flags, // Flags for this section.
target_bytes_size));// Number of host bytes per target byte
section_sp->SetPermissions(permissions);
if (is_thread_specific)
section_sp->SetIsThreadSpecific (is_thread_specific);
m_sections_ap->AddSection(section_sp);

View File

@ -1625,6 +1625,10 @@ ObjectFileMachO::CreateSections (SectionList &unified_section_list)
}
if (m_data.GetU32(&offset, &load_cmd.maxprot, 4))
{
const uint32_t segment_permissions =
((load_cmd.initprot & VM_PROT_READ) ? ePermissionsReadable : 0) |
((load_cmd.initprot & VM_PROT_WRITE) ? ePermissionsWritable : 0) |
((load_cmd.initprot & VM_PROT_EXECUTE) ? ePermissionsExecutable : 0);
const bool segment_is_encrypted = (load_cmd.flags & SG_PROTECTED_VERSION_1) != 0;
@ -1651,6 +1655,7 @@ ObjectFileMachO::CreateSections (SectionList &unified_section_list)
segment_sp->SetIsEncrypted (segment_is_encrypted);
m_sections_ap->AddSection(segment_sp);
segment_sp->SetPermissions(segment_permissions);
if (add_to_unified)
unified_section_list.AddSection(segment_sp);
}
@ -1782,7 +1787,7 @@ ObjectFileMachO::CreateSections (SectionList &unified_section_list)
sect64.align,
load_cmd.flags)); // Flags for this section
segment_sp->SetIsFake(true);
segment_sp->SetPermissions(segment_permissions);
m_sections_ap->AddSection(segment_sp);
if (add_to_unified)
unified_section_list.AddSection(segment_sp);
@ -1932,6 +1937,7 @@ ObjectFileMachO::CreateSections (SectionList &unified_section_list)
section_is_encrypted = encrypted_file_ranges.FindEntryThatContains(sect64.offset) != NULL;
section_sp->SetIsEncrypted (segment_is_encrypted || section_is_encrypted);
section_sp->SetPermissions(segment_permissions);
segment_sp->GetChildren().AddSection(section_sp);
if (segment_sp->IsFake())

View File

@ -14,15 +14,16 @@
#include <mutex>
// Other libraries and framework includes
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/State.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Log.h"
#include "lldb/Target/Target.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/State.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/UnixSignals.h"
#include "llvm/Support/ELF.h"
@ -148,7 +149,7 @@ ProcessElfCore::GetPluginVersion()
lldb::addr_t
ProcessElfCore::AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header)
{
lldb::addr_t addr = header->p_vaddr;
const lldb::addr_t addr = header->p_vaddr;
FileRange file_range (header->p_offset, header->p_filesz);
VMRangeToFileOffset::Entry range_entry(addr, header->p_memsz, file_range);
@ -166,6 +167,14 @@ ProcessElfCore::AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *head
m_core_aranges.Append(range_entry);
}
// Keep a separate map of permissions that that isn't coalesced so all ranges
// are maintained.
const uint32_t permissions = ((header->p_flags & llvm::ELF::PF_R) ? lldb::ePermissionsReadable : 0) |
((header->p_flags & llvm::ELF::PF_W) ? lldb::ePermissionsWritable : 0) |
((header->p_flags & llvm::ELF::PF_X) ? lldb::ePermissionsExecutable : 0);
m_core_range_infos.Append(VMRangeToPermissions::Entry(addr, header->p_memsz, permissions));
return addr;
}
@ -227,7 +236,10 @@ ProcessElfCore::DoLoadCore ()
}
if (!ranges_are_sorted)
{
m_core_aranges.Sort();
m_core_range_infos.Sort();
}
// Even if the architecture is set in the target, we need to override
// it to match the core file which is always single arch.
@ -315,6 +327,38 @@ ProcessElfCore::ReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &er
return DoReadMemory (addr, buf, size, error);
}
Error
ProcessElfCore::GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &region_info)
{
region_info.Clear();
const VMRangeToPermissions::Entry *permission_entry = m_core_range_infos.FindEntryThatContainsOrFollows(load_addr);
if (permission_entry)
{
if (permission_entry->Contains(load_addr))
{
region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase());
region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd());
const Flags permissions(permission_entry->data);
region_info.SetReadable(permissions.Test(lldb::ePermissionsReadable) ? MemoryRegionInfo::eYes
: MemoryRegionInfo::eNo);
region_info.SetWritable(permissions.Test(lldb::ePermissionsWritable) ? MemoryRegionInfo::eYes
: MemoryRegionInfo::eNo);
region_info.SetExecutable(permissions.Test(lldb::ePermissionsExecutable) ? MemoryRegionInfo::eYes
: MemoryRegionInfo::eNo);
}
else if (load_addr < permission_entry->GetRangeBase())
{
region_info.GetRange().SetRangeBase(load_addr);
region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase());
region_info.SetReadable(MemoryRegionInfo::eNo);
region_info.SetWritable(MemoryRegionInfo::eNo);
region_info.SetExecutable(MemoryRegionInfo::eNo);
}
return Error();
}
return Error("invalid address");
}
size_t
ProcessElfCore::DoReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &error)
{

View File

@ -102,6 +102,9 @@ public:
size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override;
lldb_private::Error
GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &region_info) override;
lldb::addr_t GetImageInfoAddress() override;
lldb_private::ArchSpec
@ -135,6 +138,7 @@ private:
//------------------------------------------------------------------
typedef lldb_private::Range<lldb::addr_t, lldb::addr_t> FileRange;
typedef lldb_private::RangeDataArray<lldb::addr_t, lldb::addr_t, FileRange, 1> VMRangeToFileOffset;
typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t> VMRangeToPermissions;
lldb::ModuleSP m_core_module_sp;
lldb_private::FileSpec m_core_file;
@ -155,6 +159,9 @@ private:
// Address ranges found in the core
VMRangeToFileOffset m_core_aranges;
// Permissions for all ranges
VMRangeToPermissions m_core_range_infos;
// NT_FILE entries found from the NOTE segment
std::vector<NT_FILE_Entry> m_nt_file_entries;

View File

@ -18,14 +18,15 @@
// Other libraries and framework includes
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@ -122,14 +123,15 @@ ProcessMachCore::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_nam
//----------------------------------------------------------------------
// ProcessMachCore constructor
//----------------------------------------------------------------------
ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec &core_file) :
Process (target_sp, listener_sp),
m_core_aranges (),
m_core_module_sp (),
m_core_file (core_file),
m_dyld_addr (LLDB_INVALID_ADDRESS),
m_mach_kernel_addr (LLDB_INVALID_ADDRESS),
m_dyld_plugin_name ()
ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec &core_file)
: Process(target_sp, listener_sp),
m_core_aranges(),
m_core_range_infos(),
m_core_module_sp(),
m_core_file(core_file),
m_dyld_addr(LLDB_INVALID_ADDRESS),
m_mach_kernel_addr(LLDB_INVALID_ADDRESS),
m_dyld_plugin_name()
{
}
@ -304,11 +306,14 @@ ProcessMachCore::DoLoadCore ()
{
m_core_aranges.Append(range_entry);
}
m_core_range_infos.Append(
VMRangeToPermissions::Entry(section_vm_addr, section->GetByteSize(), section->GetPermissions()));
}
}
if (!ranges_are_sorted)
{
m_core_aranges.Sort();
m_core_range_infos.Sort();
}
if (m_dyld_addr == LLDB_INVALID_ADDRESS || m_mach_kernel_addr == LLDB_INVALID_ADDRESS)
@ -522,6 +527,39 @@ ProcessMachCore::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error
return 0;
}
Error
ProcessMachCore::GetMemoryRegionInfo(addr_t load_addr, MemoryRegionInfo &region_info)
{
region_info.Clear();
const VMRangeToPermissions::Entry *permission_entry = m_core_range_infos.FindEntryThatContainsOrFollows(load_addr);
if (permission_entry)
{
if (permission_entry->Contains(load_addr))
{
region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase());
region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd());
const Flags permissions(permission_entry->data);
region_info.SetReadable(permissions.Test(ePermissionsReadable) ? MemoryRegionInfo::eYes
: MemoryRegionInfo::eNo);
region_info.SetWritable(permissions.Test(ePermissionsWritable) ? MemoryRegionInfo::eYes
: MemoryRegionInfo::eNo);
region_info.SetExecutable(permissions.Test(ePermissionsExecutable) ? MemoryRegionInfo::eYes
: MemoryRegionInfo::eNo);
}
else if (load_addr < permission_entry->GetRangeBase())
{
region_info.GetRange().SetRangeBase(load_addr);
region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase());
region_info.SetReadable(MemoryRegionInfo::eNo);
region_info.SetWritable(MemoryRegionInfo::eNo);
region_info.SetExecutable(MemoryRegionInfo::eNo);
}
return Error();
}
return Error("invalid address");
}
void
ProcessMachCore::Clear()
{

View File

@ -103,7 +103,10 @@ public:
size_t
DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override;
lldb_private::Error
GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &region_info) override;
lldb::addr_t
GetImageInfoAddress () override;
@ -150,8 +153,10 @@ private:
//------------------------------------------------------------------
typedef lldb_private::Range<lldb::addr_t, lldb::addr_t> FileRange;
typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, FileRange> VMRangeToFileOffset;
typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t> VMRangeToPermissions;
VMRangeToFileOffset m_core_aranges;
VMRangeToPermissions m_core_range_infos;
lldb::ModuleSP m_core_module_sp;
lldb_private::FileSpec m_core_file;
lldb::addr_t m_dyld_addr;