[Lldb-commits] [PATCH] D87868: [RFC] When calling the process mmap try to call all found instead of just the first one

Pavel Labath via Phabricator via lldb-commits lldb-commits at lists.llvm.org
Tue Oct 6 05:44:41 PDT 2020


labath added a comment.

In D87868#2309260 <https://reviews.llvm.org/D87868#2309260>, @clayborg wrote:

> In D87868#2308515 <https://reviews.llvm.org/D87868#2308515>, @labath wrote:
>
>> That sounds like a plan. FWIW, here's the implementation I hacked up today:
>>
>>   Status NativeProcessLinux::AllocateMemory(size_t size, uint32_t permissions,
>>                                             lldb::addr_t &addr) {
>>     PopulateMemoryRegionCache();
>>     auto region_it = llvm::find_if(m_mem_region_cache, [](const auto &pair) {
>>       return pair.first.GetExecutable() == MemoryRegionInfo::eYes;
>>     });
>>     if (region_it == m_mem_region_cache.end())
>>       return Status("No executable memory region found!");
>>     addr_t exe_addr = region_it->first.GetRange().GetRangeBase();
>>   
>>     NativeThreadLinux &thread = *GetThreadByID(GetID());
>>     assert(thread.GetState() == eStateStopped);
>>   
>>     int prot = PROT_NONE;
>>     if (permissions & ePermissionsReadable)
>>       prot |= PROT_READ;
>>     if (permissions & ePermissionsWritable)
>>       prot |= PROT_WRITE;
>>     if (permissions & ePermissionsExecutable)
>>       prot |= PROT_EXEC;
>>   
>>     NativeRegisterContextLinux &reg_ctx = thread.GetRegisterContext();
>>     DataBufferSP registers_sp;
>>     reg_ctx.ReadAllRegisterValues(registers_sp);
>>     uint8_t memory[2];
>>     size_t bytes_read;
>>     ReadMemory(exe_addr, memory, 2, bytes_read);
>>   
>>     reg_ctx.SetPC(exe_addr);
>>     reg_ctx.WriteRegisterFromUnsigned(lldb_rax_x86_64, SYS_mmap);
>>     reg_ctx.WriteRegisterFromUnsigned(lldb_rdi_x86_64, 0);
>>     reg_ctx.WriteRegisterFromUnsigned(lldb_rsi_x86_64, size);
>>     reg_ctx.WriteRegisterFromUnsigned(lldb_rdx_x86_64, prot);
>>     reg_ctx.WriteRegisterFromUnsigned(lldb_r10_x86_64,
>>                                       MAP_ANONYMOUS | MAP_PRIVATE);
>>     reg_ctx.WriteRegisterFromUnsigned(lldb_r8_x86_64, -1);
>>     reg_ctx.WriteRegisterFromUnsigned(lldb_r9_x86_64, 0);
>>     WriteMemory(exe_addr, "\x0f\x05", 2, bytes_read);
>>     PtraceWrapper(PTRACE_SINGLESTEP, thread.GetID(), nullptr, nullptr);
>>     int status;
>>     ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, thread.GetID(),
>>                                                    &status, __WALL);
>>     assert((unsigned)wait_pid == thread.GetID());
>>     addr = reg_ctx.ReadRegisterAsUnsigned(lldb_rax_x86_64, -ESRCH);
>>   
>>     WriteMemory(exe_addr, memory, 2, bytes_read);
>>     reg_ctx.WriteAllRegisterValues(registers_sp);
>>   
>>     if (addr > -4096)
>>       return Status(-addr, eErrorTypePOSIX);
>>     return Status();
>>   }
>>
>> It needs more error handling, and generalization to non-x86 architectures, but it actually works, and is enough to make all but one test pass (TestBitfields.py seems to fail due to some data corruption -- quite puzzling).
>
> Very cool. That seems simple enough to allow us to try this out, at least on unix variants.

Ok, I'll to find some time to implement that properly.

> Does PTRACE_SINGLESTEP cause _only_ the current thread to single step and keep all other threads paused?

Affirmative.

> This nice thing is lldb-server _is_ compiled natively for each system so we can rely on system headers for the sys call numbers if they are available.

Unfortunately things are not as rosy as that. On linux, the syscall numbers can differ between 32- and 64-bit variants (on x86_64, SYS_mmap is 9, i386  it's 90). Since 64-bit lldb-server can debug a 32-bit inferior, it still needs to hardcode the syscall number for it. I believe the other mmap constants (`PROT_***`, `MAP_***`) are the same on all variants, though they could theoretically be different...

> So looks like this could be made to work. Did you also do the deallocate memory? I ran a few expressions and I am not sure that we ever use the deallocate memory packets to debugserver on mac, so it might not be needed.

For my prototype. I did not, but the code for that would be fairly similar (and could be factored into a common function, etc..).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D87868/new/

https://reviews.llvm.org/D87868



More information about the lldb-commits mailing list