clayborg added a comment.

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. Does PTRACE_SINGLESTEP cause _only_ the current thread to single 
step and keep all other threads paused? We can't allow any other threads making 
any progress when the process is briefly resumed in a multi-threaded process.

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. 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.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D87868

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to