Разница между ptrace (PTRACE_PEEKUSER) и ptrace (PTRACE_PEEKDATA)?

После публикации большого количества вопросов по ptrace (самые последние 5 вопросов - мои :() Наконец-то я получил желаемый результат, когда я заменил

reg_val[1] = ptrace(PTRACE_PEEKDATA, child, 4 * EBX, NULL);

с

reg_val[1] = ptrace(PTRACE_PEEKUSER, child, 4 * EBX, NULL);

Разница, упомянутая в man-странице, такова:

  • PTRACE_PEEKTEXT читает слово в местоположении addr в дочерней памяти
  • PTRACE_PEEKUSER считывает слово со смещением addr в дочерней области ПОЛЬЗОВАТЕЛЯ

Я не могу понять эту разницу только на странице руководства. Может ли кто-нибудь просветить меня по этому поводу?

Ответ 1

PTRACE_PEEKDATA предназначен для чтения раздела данных/кода дочернего элемента (процесс в целом - так называемый трассировка). Как вы знаете, отладчики используют ptrace много. Они могут использовать этот вызов для проверки значений переменных. Например, в GDB/DBX, если вы говорите

print count

отладчики будут внутренне вызывать ptrace с помощью PTRACE_PEEKDATA и найти его значение.

PTRACE_PEEKUSER используется для чтения содержимого дочерней области USER, которая содержит содержимое регистров и другую информацию. sys/user.h указывает, что это за другая информация.

Например, область USER содержит,

struct user_regs_struct
{
  long int ebx;
  long int ecx;
  long int edx;
  long int esi;
  long int edi;
  long int ebp;
  long int eax;
  long int xds;
  long int xes;
  long int xfs;
  long int xgs;
  long int orig_eax;
  long int eip;
  long int xcs;
  long int eflags;
  long int esp;
  long int xss;
};

Короче говоря:

  • PTRACE_PEEKDATA предназначен для данных программы (например, переменных) и кода;
  • PTRACE_PEEKUSER предназначен для таких вещей, как регистровые значения и другая информация об отладке;

Обратите внимание на эквивалентность между PTRACE_PEEKDATA и PTRACE_PEEKTEXT. От man ptrace:

В Linux нет отдельных текстовых и адресных пространств, поэтому эти два запроса в настоящее время эквивалентны.