Author: gclayton Date: Thu Jun 9 11:34:06 2016 New Revision: 272276 URL: http://llvm.org/viewvc/llvm-project?rev=272276&view=rev Log: 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. Modified: lldb/trunk/include/lldb/Core/RangeMap.h lldb/trunk/include/lldb/Core/Section.h lldb/trunk/include/lldb/Target/MemoryRegionInfo.h lldb/trunk/source/Commands/CommandObjectMemory.cpp lldb/trunk/source/Core/Section.cpp lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.h lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.cpp lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.h Modified: lldb/trunk/include/lldb/Core/RangeMap.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/RangeMap.h?rev=272276&r1=272275&r2=272276&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/RangeMap.h (original) +++ lldb/trunk/include/lldb/Core/RangeMap.h Thu Jun 9 11:34:06 2016 @@ -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() { Modified: lldb/trunk/include/lldb/Core/Section.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Section.h?rev=272276&r1=272275&r2=272276&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/Section.h (original) +++ lldb/trunk/include/lldb/Core/Section.h Thu Jun 9 11:34:06 2016 @@ -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: Modified: lldb/trunk/include/lldb/Target/MemoryRegionInfo.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/MemoryRegionInfo.h?rev=272276&r1=272275&r2=272276&view=diff ============================================================================== --- lldb/trunk/include/lldb/Target/MemoryRegionInfo.h (original) +++ lldb/trunk/include/lldb/Target/MemoryRegionInfo.h Thu Jun 9 11:34:06 2016 @@ -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; Modified: lldb/trunk/source/Commands/CommandObjectMemory.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectMemory.cpp?rev=272276&r1=272275&r2=272276&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectMemory.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectMemory.cpp Thu Jun 9 11:34:06 2016 @@ -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" @@ -1767,6 +1769,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 ¤t_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 "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; Modified: lldb/trunk/source/Core/Section.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Section.cpp?rev=272276&r1=272275&r2=272276&view=diff ============================================================================== --- lldb/trunk/source/Core/Section.cpp (original) +++ lldb/trunk/source/Core/Section.cpp Thu Jun 9 11:34:06 2016 @@ -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 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, boo 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 *ta 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"); } Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=272276&r1=272275&r2=272276&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original) +++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Thu Jun 9 11:34:06 2016 @@ -2032,6 +2032,9 @@ ObjectFileELF::CreateSections(SectionLis 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(SectionLis 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); Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp?rev=272276&r1=272275&r2=272276&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (original) +++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Thu Jun 9 11:34:06 2016 @@ -1625,6 +1625,10 @@ ObjectFileMachO::CreateSections (Section } 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 (Section 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 (Section 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 (Section 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()) Modified: lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp?rev=272276&r1=272275&r2=272276&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp (original) +++ lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp Thu Jun 9 11:34:06 2016 @@ -14,15 +14,16 @@ #include <mutex> // Other libraries and framework includes -#include "lldb/Core/PluginManager.h" +#include "lldb/Core/DataBufferHeap.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/Core/DataBufferHeap.h" -#include "lldb/Core/Log.h" -#include "lldb/Target/Target.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::AddAddressRangeFromLoadS 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 return DoReadMemory (addr, buf, size, error); } +Error +ProcessElfCore::GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo ®ion_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) { Modified: lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.h?rev=272276&r1=272275&r2=272276&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.h (original) +++ lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.h Thu Jun 9 11:34:06 2016 @@ -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 ®ion_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; Modified: lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.cpp?rev=272276&r1=272275&r2=272276&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.cpp (original) +++ lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.cpp Thu Jun 9 11:34:06 2016 @@ -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 //---------------------------------------------------------------------- // 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 ad return 0; } +Error +ProcessMachCore::GetMemoryRegionInfo(addr_t load_addr, MemoryRegionInfo ®ion_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() { Modified: lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.h?rev=272276&r1=272275&r2=272276&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.h (original) +++ lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.h Thu Jun 9 11:34:06 2016 @@ -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 ®ion_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; _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits