Reading memory while inferior is running

Hi,

i know this has been asked before [1], but i just wanted to explore whether it’s a waste of time to patch this into our LLDB fork. I talked about our architecture in [2]. It boils down to having to suspend/resume the inferior to quickly read a tiny bit of memory. This causes us quite a bit of problems as outlined in the other thread.

Our memory reads would be just that: fetch a block of memory from a known, non-stack address. We can resolve atomicity issues on our end. Do you think this would be feasible?

Thanks,
Mario

[1] http://lists.cs.uiuc.edu/pipermail/lldb-dev/2014-June/004139.html
[2] http://lists.cs.uiuc.edu/pipermail/lldb-dev/2014-December/006138.html

It is fine to not require that a process be stopped in order to read memory. Are you still doing your python based approach? We are currently enforcing that a process must be stopped in order to read memory in SBProcess::ReadMemory() where we acquire the run lock and make sure the process stays stopped. This can be changed, but we will probably need to add code the lldb_private::Process that asks the current process if it can handle reading memory while running.

So the code would need to go from this:

    if (process_sp)
    {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&process_sp->GetRunLock()))
        {
            Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
            bytes_read = process_sp->ReadMemory (addr, dst, dst_len, sb_error.ref());
        }
        else
        {
            if (log)
                log->Printf ("SBProcess(%p)::ReadMemory() => error: process is running",
                             static_cast<void*>(process_sp.get()));
            sb_error.SetErrorString("process is running");
        }
    }

to something like:

    if (process_sp)
    {
        Process::StopLocker stop_locker;
        if (process_sp->CanReadMemoryWhileRunning() || stop_locker.TryLock(&process_sp->GetRunLock()))
        {
            Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
            bytes_read = process_sp->ReadMemory (addr, dst, dst_len, sb_error.ref());
        }
        else
        {
            if (log)
                log->Printf ("SBProcess(%p)::ReadMemory() => error: process is running",
                             static_cast<void*>(process_sp.get()));
            sb_error.SetErrorString("process is running");
        }
    }

The lldb_private::Process::CanReadMemoryWhileRunning() would need to be a virtual function that is added to lldb_private::Process which defaults to return false. Then any process plug-ins that do allow this can override this function and return true.

Greg

This is excellent news. I assume your refer to the Python script i posted in [1]. That was a port of our production code to illustrate issues with high frequency process suspends/resumes in conjunction with tracing steps/breakpoints.

If reading from the inferiors memory while the process is running works, then that issues will vanish.

We are targeting Mac OS X and iOS, both of which use debugserver and hence GDBProcess afaik. Does GDBProcess support reading memory while the process is running?

Thanks,
Mario

[1] http://lists.cs.uiuc.edu/pipermail/lldb-dev/2014-December/006138.html

This is excellent news. I assume your refer to the Python script i posted in [1]. That was a port of our production code to illustrate issues with high frequency process suspends/resumes in conjunction with tracing steps/breakpoints.

If reading from the inferiors memory while the process is running works, then that issues will vanish.

We are targeting Mac OS X and iOS, both of which use debugserver and hence GDBProcess afaik. Does GDBProcess support reading memory while the process is running?

Unfortunately no, not as it is currently coded. There is a "non-stop mode" that the GDB remote protocol allows, but we don't currently support that in our ProcessGDBRemote.cpp. I am not sure how much work it would be to convert over to using this but this would allow for memory to be read while things are running. Currently the GDB remote protocol can only send one packet at a time, including when running the process, so you send a continue packet and the response will be a stop reply packet, so the only way to currently send a memory read is to interrupt the packet by sending a CTRL+C (0x03 byte) which stops the target, then you can send the memory read, and then resume the target. That probably won't improve things.

So feel free to look into supporting the non-stop mode if you want. One thing to note is that any existing iOS devices out there with previously released developer support have a fixed developer disk image that has the "debugserver" binary hard coded on it and they will never change, so we have no hopes of adding non-stop mode to any previously released Xcode tools.

Oh well, you win some, you lose some :slight_smile: I was expecting that to be the case. At least i don’t have to go down that rabbit hole with this info in hand.

Thanks!
Mario