python-ptrace icon indicating copy to clipboard operation
python-ptrace copied to clipboard

Is there a way to capture 'stderr' / 'stdout' from the ptraced program?

Open nrathaus opened this issue 2 years ago • 2 comments

Let assume I have this code (it is incomplete):

pid = createChild(arguments, False, env)
dbg = PtraceDebugger()
process = dbg.addProcess(pid, is_attached)
process.cont()

There seems to be no way to handle the stderr and stdout, there are something called pass_fd in the createChild function, but there is no documentation (that I can find) how to do it, trying to use os.pipe() on it seems to not work os.read(..) seems to be blocked

Can you provide an example? or direct me in the right way?

nrathaus avatar Mar 15 '23 09:03 nrathaus

The pass_fds argument compliments the close_fds and allows control over the file descriptors to have the child inherit, however stdout/err are not accessible this way. Glancing at the code there is no way to control the value of those streams, however this might not be too hard to implement.

What is your use case ? Are you looking for a Popen style stdout/stderr ?

spoutn1k avatar Mar 15 '23 16:03 spoutn1k

The idea was to trace a program/debug it and capture its stdout/stderr so that you can see what is going on

At the moment the output is seen "locally" where python runs, but if you are trying to automate the debugging process - and don't have terminal visibility where the program runs, this is lost

Think of it like this: [My Python] -> [python-trace] -> [App run]

The output of stdout/stderr from [App Run] cannot be piped back to [My Python]

If I would have run GDB I could do this:

    args = [
        "/bin/gdb",
        "-q",
        "-ex",
        "set debuginfod enabled off",
        "-ex",
        "catch throw",
        "-ex",
        "run",
        "-ex",
        "continue",
        "-ex",
        "backtrace",
        "-ex",
        "detach",
        "-ex",
        "quit",
        "--args",
    ] + sys.argv[1:]
    
    process = subprocess.Popen(
        args=args, stdout=subprocess.PIPE, stderr=subprocess.PIPE
    )

    stdout, stderr = process.communicate()
    if isinstance(stdout, bytes):
        stdout = stdout.decode()

    if isinstance(stderr, bytes):
        stderr = stderr.decode()

    print(f"stdout:\n{stdout}")
    print(f"stderr:\n{stderr}")

This would use gdb to capture exceptions (both 'throws' as well as code crashes) as well as using Popen capture the stdout/stderr

Though unfortunately I do not have distinction here what is program output and what is gdb output

Let me know if you need more insight into the idea I am trying to achieve

nrathaus avatar Mar 15 '23 17:03 nrathaus