Дочерний процесс не продолжает выполнение при ptrace'ing

Я сделал следующий простой пример для чтения памяти из дочернего процесса с помощью ptrace.

Я хочу видеть значение по определенному адресу, 0x601050, каждую секунду во время выполнения небольшой программы умножения матриц. Для этого я использую PTRACE_PEEKDATA, за которым следует PTRACE_CONT, и засыпаю на 1 секунду в бесконечном цикле.

Однако программа умножения матриц никогда не выполняется — она должна вывести на стандартный вывод в первой инструкции, но, похоже, никогда не выполняется. Я понял, что ptrace(PTRACE_CONT,pid) будет сигнализировать дочернему процессу о возобновлении выполнения, а sleep(1) позволит ему выполняться в течение секунды (до следующего вызова ptrace), но это не так.

#include <string.h>
#include <errno.h>
#include <inttypes.h>

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/user.h>
#include <sys/reg.h>

int read_mem(long *out, pid_t pid, long addr, size_t sz)
{
    long tmp;
    size_t copied = 0;

    while(copied < sz)
    {
        tmp = ptrace(PTRACE_PEEKDATA, pid, addr+copied);

        if(errno)
        { 
            fprintf(stderr,"ptrace: error : %s\n",strerror(errno));
            return copied;
        }

        memcpy(out,&tmp,sizeof(long));

        copied += sizeof(long);
        out++;

        printf("ptrace: copied %d bytes\n",copied);
    }

    return copied;
}

int main()
{   
    pid_t child;
    long result;
    struct user_regs_struct regs;
    int status;

    long addr = 0x601050;
    size_t sz = sizeof(double);
    long *buf = (long*)malloc(sz);

    child = fork();

    if(child == 0) 
    {
        ptrace(PTRACE_TRACEME);
        execl("./matmul", "matmul", NULL);
    }
    else 
    {
        ptrace(PTRACE_GETREGS, child, &regs);
        printf("ptrace: regs.rip : 0x%lx\n", regs.rip);

        while(1)
        {
            read_mem(buf, child, addr, sz);
            printf("ptrace: read(0x%lx) : %f\n", addr, (double)(*buf));

            ptrace(PTRACE_CONT, child);

            sleep(1);
        }
    }
    return 0;
}

person Alfredo Gimenez    schedule 25.10.2014    source источник
comment
Как вы можете вызывать ptrace с переменным количеством параметров?   -  person ooga    schedule 26.10.2014
comment
Он компилируется/работает нормально, я полагал, что ptrace по умолчанию установил остальные значения в 0 или NULL.   -  person Alfredo Gimenez    schedule 26.10.2014
comment
Я должен был опубликовать это раньше, но @ooga была именно в этом. По какой-то причине он позволяет мне компилировать и запускать ptrace с переменным числом параметров, но он не выполняется должным образом. Добавление аргументов 0/NULL исправило это.   -  person Alfredo Gimenez    schedule 02.04.2015


Ответы (1)


Кажется, вы не установили параметр PTRACE_O_TRACEEXEC. Если этого не сделать, SIGTRAP будет отправлен в tracee при вызове exec; если он не подготовлен, действие по умолчанию — завершение с созданием дампа ядра.

person user58697    schedule 25.10.2014
comment
Я понимаю, что использование ptrace(PTRACE_TRACEME) перехватывает трассировку при следующем вызове exec, но не должна ли ptrace(PTRACE_CONT,child) возобновить выполнение? - person Alfredo Gimenez; 26.10.2014