diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 4bb3e3f02d65..a01bed40f0dc 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -400,13 +400,28 @@ public: bool GetTargetTriple (ConstString &target_triple); + size_t + ReadMemoryFromFileCache (const Address& addr, + void *dst, + size_t dst_len, + Error &error); + + // Reading memory through the target allows us to skip going to the process + // for reading memory if possible and it allows us to try and read from + // any constant sections in our object files on disk. If you always want + // live program memory, read straight from the process. If you possibly + // want to read from const sections in object files, read from the target. + // This version of ReadMemory will try and read memory from the process + // if the process is alive. The order is: + // 1 - if (prefer_file_cache == true) then read from object file cache + // 2 - if there is a valid process, try and read from its memory + // 3 - if (prefer_file_cache == false) then read from object file cache size_t ReadMemory (const Address& addr, + bool prefer_file_cache, void *dst, size_t dst_len, Error &error); - - SectionLoadList& GetSectionLoadList() diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp index a038dd83edc4..c87814fa1f64 100644 --- a/lldb/source/Core/Address.cpp +++ b/lldb/source/Core/Address.cpp @@ -68,7 +68,8 @@ ReadBytes (ExecutionContextScope *exe_scope, const Address &address, void *dst, if (target) { Error error; - return target->ReadMemory (address, dst, dst_len, error); + bool prefer_file_cache = false; + return target->ReadMemory (address, prefer_file_cache, dst, dst_len, error); } return 0; } diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp index 653804930828..e6fe1b018a5e 100644 --- a/lldb/source/Core/Disassembler.cpp +++ b/lldb/source/Core/Disassembler.cpp @@ -422,7 +422,8 @@ Disassembler::ParseInstructions DataBufferSP data_sp(heap_buffer); Error error; - const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(), heap_buffer->GetBytes(), heap_buffer->GetByteSize(), error); + bool prefer_file_cache = true; + const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(), prefer_file_cache, heap_buffer->GetBytes(), heap_buffer->GetByteSize(), error); if (bytes_read > 0) { diff --git a/lldb/source/Plugins/Process/Utility/UnwindAssemblyProfiler-x86.cpp b/lldb/source/Plugins/Process/Utility/UnwindAssemblyProfiler-x86.cpp index d6463e22474f..fd42948d5db7 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindAssemblyProfiler-x86.cpp +++ b/lldb/source/Plugins/Process/Utility/UnwindAssemblyProfiler-x86.cpp @@ -470,7 +470,8 @@ read_byte_for_edis (uint8_t *buf, uint64_t offset_address, void *arg) uint8_t onebyte_buf[1]; Error error; - if (target->ReadMemory (read_addr, onebyte_buf, 1, error) != -1) + const bool prefer_file_cache = true; + if (target->ReadMemory (read_addr, prefer_file_cache, onebyte_buf, 1, error) != -1) { *buf = onebyte_buf[0]; return 0; @@ -550,6 +551,7 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan) row.SetRegisterInfo (m_lldb_ip_regnum, initial_regloc); unwind_plan.AppendRow (row); + const bool prefer_file_cache = true; while (m_func_bounds.ContainsFileAddress (m_cur_insn) && non_prologue_insn_count < 10) { @@ -562,7 +564,7 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan) // An unrecognized/junk instruction break; } - if (m_target.ReadMemory (m_cur_insn, m_cur_insn_bytes, insn_len, error) == -1) + if (m_target.ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes, insn_len, error) == -1) { // Error reading the instruction out of the file, stop scanning break; @@ -672,7 +674,7 @@ loopnext: Address last_insn (m_func_bounds.GetBaseAddress()); last_insn.SetOffset (last_insn.GetOffset() + m_func_bounds.GetByteSize() - 1); uint8_t bytebuf[1]; - if (m_target.ReadMemory (last_insn, bytebuf, 1, error) != -1) + if (m_target.ReadMemory (last_insn, prefer_file_cache, bytebuf, 1, error) != -1) { if (bytebuf[0] == 0xc3) // ret aka retq { @@ -723,7 +725,8 @@ AssemblyParse_x86::get_fast_unwind_plan (AddressRange& func, UnwindPlan &unwind_ uint8_t bytebuf[4]; Error error; - if (m_target.ReadMemory (func.GetBaseAddress(), bytebuf, sizeof (bytebuf), error) == -1) + const bool prefer_file_cache = true; + if (m_target.ReadMemory (func.GetBaseAddress(), prefer_file_cache, bytebuf, sizeof (bytebuf), error) == -1) return false; uint8_t i386_prologue[] = {0x55, 0x89, 0xe5}; @@ -781,6 +784,7 @@ AssemblyParse_x86::find_first_non_prologue_insn (Address &address) return false; } + const bool prefer_file_cache = true; while (m_func_bounds.ContainsFileAddress (m_cur_insn)) { Error error; @@ -790,7 +794,7 @@ AssemblyParse_x86::find_first_non_prologue_insn (Address &address) // An error parsing the instruction, i.e. probably data/garbage - stop scanning break; } - if (m_target.ReadMemory (m_cur_insn, m_cur_insn_bytes, insn_len, error) == -1) + if (m_target.ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes, insn_len, error) == -1) { // Error reading the instruction out of the file, stop scanning break; diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 36058e9cc5f0..6f5858a8accc 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -589,12 +589,43 @@ Target::ModulesDidUnload (ModuleList &module_list) } size_t -Target::ReadMemory (const Address& addr, void *dst, size_t dst_len, Error &error) +Target::ReadMemoryFromFileCache (const Address& addr, void *dst, size_t dst_len, Error &error) +{ + const Section *section = addr.GetSection(); + if (section && section->GetModule()) + { + ObjectFile *objfile = section->GetModule()->GetObjectFile(); + if (objfile) + { + size_t bytes_read = section->ReadSectionDataFromObjectFile (objfile, + addr.GetOffset(), + dst, + dst_len); + if (bytes_read > 0) + return bytes_read; + else + error.SetErrorStringWithFormat("error reading data from section %s", section->GetName().GetCString()); + } + else + { + error.SetErrorString("address isn't from a object file"); + } + } + else + { + error.SetErrorString("address doesn't contain a section that points to a section in a object file"); + } + return 0; +} + +size_t +Target::ReadMemory (const Address& addr, bool prefer_file_cache, void *dst, size_t dst_len, Error &error) { error.Clear(); - + bool process_is_valid = m_process_sp && m_process_sp->IsAlive(); + size_t bytes_read = 0; Address resolved_addr(addr); if (!resolved_addr.IsSectionOffset()) { @@ -608,6 +639,12 @@ Target::ReadMemory (const Address& addr, void *dst, size_t dst_len, Error &error } } + if (prefer_file_cache) + { + bytes_read = ReadMemoryFromFileCache (resolved_addr, dst, dst_len, error); + if (bytes_read > 0) + return bytes_read; + } if (process_is_valid) { @@ -623,7 +660,7 @@ Target::ReadMemory (const Address& addr, void *dst, size_t dst_len, Error &error } else { - size_t bytes_read = m_process_sp->ReadMemory(load_addr, dst, dst_len, error); + bytes_read = m_process_sp->ReadMemory(load_addr, dst, dst_len, error); if (bytes_read != dst_len) { if (error.Success()) @@ -646,14 +683,11 @@ Target::ReadMemory (const Address& addr, void *dst, size_t dst_len, Error &error } } - const Section *section = resolved_addr.GetSection(); - if (section && section->GetModule()) + if (!prefer_file_cache) { - ObjectFile *objfile = section->GetModule()->GetObjectFile(); - return section->ReadSectionDataFromObjectFile (objfile, - resolved_addr.GetOffset(), - dst, - dst_len); + // If we didn't already try and read from the object file cache, then + // try it after failing to read from the process. + return ReadMemoryFromFileCache (resolved_addr, dst, dst_len, error); } return 0; }