ptrace - трассирует процесс
НАЗВАНИЕptrace - трассирует процесс
СИНТАКСИС
#include
long ptrace(enum __ptrace_request request, pid_t pid, void
* addr, void * data);
ОПИСАНИЕ
ptrace - это средство, позволяющее родительскому процессу
наблюдать и контролировать протекание другого процесса,
просматривать и изменять его данные и регистры. Обычно
эта функция используется для создания точек прерывания в
программе отладки и отслеживания системных вызовов.
Родительский процесс может начать трассировку, сначала
вызвав функцию fork(2), а затем получившийся дочерний
процесс может выполнить PTRACE_TRACEME, за которым
(обычно) следует выполнение exec(3). С другой стороны,
родительский процесс может начать отладку существующего
процесса при помощи PTRACE_ATTACH.
При трассировке дочерний процесс останавливается каждый
раз при получении сигнала, даже если этот сигнал
игнорируется. (Исключением является SIGKILL, работающий
обычным образом.) Родительский процесс будет уведомлен об
этом при вызове wait(2), после которого он может
просматривать и изменять содержимое дочернего процесса до
его запуска. После этого родительский процесс разрешает
дочернему продолжать работу, в некоторых случаях игнорируя
посылаемый ему сигнал или отправляя вместо этого другой
сигнал).
По окончании трассировки родительский процесс может
прекратить работу дочернего при помощи функции PTRACE_KILL
или дать ему возможность работать в обычном,
нетрассируемом, режиме, используя PTRACE_DETACH.
Значение аргумента request определяет действие,
выполняемое функцией:
PTRACE_TRACEME
Означает, что этот процесс должен быть трассирован
его родительским процессом. Любой сигнал (кроме
SIGKILL), получаемый этим процессом, приведет к его
приостановке, и родительский процесс будет
уведомлен об этом с помощью функции wait. Кроме
того, если этот процесс вызовет exec, то к нему
придет сигнал SIGTRAP, в результате чего
родительский процесс получит управление до того,
как запустится новая программа. Скорее всего,
процессу не следует посылать этот вызов, если
родительский процесс не готов к трассировке
дочернего. (Параметры pid, addr и data
игнорируются).
Вышеописанный запрос посылается только дочерним процессом;
все остальные отправляются родительским. В запросах,
описанных ниже, параметр pid задает номер процесса, над
которым будут производиться действия. При вызове всех
запросов (кроме PTRACE_KILL) дочерний процесс должен быть
остановлен.
PTRACE_PEEKTEXT, PTRACE_PEEKDATA
Читает слово с адресом addr, находящееся в памяти
дочернего процесса, возвращая это слово как
результат функции ptrace . Linux не разделяет
понятий адресных пространств текста и данных,
поэтому оба вызова абсолютно идентичны. (Аргумент
data игнорируется.)
PTRACE_PEEKUSR
Читает слово с адресом addr в области USER
дочернего процесса, которая содержит информацию о
регистрах и процессе (см. файлы и
). Слово возвращается в качестве
результата функции ptrace . Обычно смещение должно
быть выровнено по границе слова, хотя это может
зависеть от архитектуры системы (параметр data
игнорируется).
PTRACE_POKETEXT, PTRACE_POKEDATA
Копирует слово data в память дочернего процесса с
адресом addr. Как описано выше, эти два запроса в
данное время аналогичны.
PTRACE_POKEUSR
Копирует слово data по смещению addr в области USER
дочернего процесса. Обычно смещение должно быть
выровнено по границе слова. Для того, чтобы
сохранить упорядоченность данных в системе,
некоторые изменения в процесс вносить запрещено.
PTRACE_GETREGS, PTRACE_GETFPREGS
Копирует общие регистры или, соответственно,
регистры сопроцессора, дочернего процесса в
переменную data родительского. Формат передаваемой
структуры описан в файле . (Параметр
addr игнорируется).
PTRACE_SETREGS, PTRACE_SETFPREGS
Изменяет содержимое общих (или, соответственно,
математических) регистров дочернего процесса на
основании структуры, находящейся в переменной data
родительского процесса. Как и в случае c
PTRACE_POKEUSER, изменение некоторых общих
регистров запрещено (параметр addr игнорируется).
PTRACE_CONT
Возобновляет работу остановленного дочернего
процесса. Если параметр data не равен нулю или
SIGSTOP, то он считается сигналом, который надо
передать дочернему процессу; в противном случае
сигнал не передается. Таким образом родительский
процесс сможет контролировать передачу сигнала
дочернему процессу (параметр addr игнорируется).
PTRACE_SYSCALL, PTRACE_SINGLESTEP
Аналогично PTRACE_CONT они возобновляют работу
остановленного дочернего процесса, но указывают,
что процесс должен быть остановлен при следующем
входе в систему или выходе из нее при вызове или
после исполнения одной из команд. (Дочерний
процесс будет также остановлен при получении
сигнала). С точки зрения родительского процесса,
дочерний будет остановлен при получении сигнала
SIGTRAP. Таким образом, PTRACE_SYSCALL позволяет
изучить содержимое аргументов при первой остановке
процесса, возникшей при вызове системной функции; а
затем просмотреть результат исполнения системного
вызова при второй остановке. (Параметр addr
игнорируется.)
PTRACE_KILL
Посылает дочернему процессу сигнал SIGKILL, для
того чтобы процесс прекратил свою работу (параметры
addr и data игнорируются).
PTRACE_ATTACH
Подключается к процессу, заданному в pid, делая его
трассируемым дочерним процессом; после этого
дочерний процесс работает так, как будто он вызвал
PTRACE_TRACEME. Текущий процесс, на самом деле,
становится родительским для дочернего по многим
критериям (например, он будет получать сообщения об
операциях дочернего процесса и будет становиться
родительским при работе команды ps(1)), но функция
getppid(2), вызванная дочерним процессом, будет
возвращать pid предыдущего родителя. Дочерний
процесс получит сигнал SIGSTOP, но это
необязательно вызовет его остановку; используйте
для этого функцию wait. (Параметры addr и data
игнорируются.)
PTRACE_DETACH
Возобновляет работу остановленного дочернего
процесса аналогично PTRACE_CONT, но сначала
отключается от него, аннулируя эффект PTRACE_ATTACH
и эффект PTRACE_TRACEME. Хотя этого не было
предусмотрено, в Linux при помощи этого вызова
трассируемый дочерний процесс может возобновить
свою нормальную работу (с отключением трассировки)
независимо от того, как эта трассировка была
запущена. (Поле addr игнорируется).
ЗАМЕЧАНИЯ
Несмотря на то, что параметры ptrace обрабатываются в
соответствии с описанным выше прототипом, в GNU libc в
данное время функция ptrace определена как вариативная
функция с одним обязательным параметром request. Это
означает, что ненужные параметры могут быть
проигнорированы, что приведет в действие неописанный здесь
механизм gcc(1).
init(8), процесс с pid 1, не может быть трассирован.
Структура памяти и области USER дочернего процесса зависят
от ОС и архитектуры системы.
Размер "слова" определяется вариантом ОС (например, для
32-битного варианта Linux слово будет 32-битным и т.п.).
Трассировка вызывает небольшие изменения в поведении
трассируемых процессов. Например, если трассировка
процесса запущена при помощи PTRACE_ATTACH, то его
предыдущий родительский процесс не сможет при помощи wait
получить сообщение о событиях в дочернем процессе, а для
нового родительского процесса эффективного способа
передать это сообщение старому процессу не существует.
Эта страница описывает работу системного вызова ptrace в
Linux. Его работа может быть иной в других системах Unix.
Man-страница ptrace в SunOS описывает этот вызов как
"уникальный и заумный", каким он на самом деле и является.
Интерфейс отладки процессов, основанный на proc и
представленный в Solaris 2, содержит дополнительные вызовы
ptrace, обеспечивающие большую гибкость и функциональность
отладки.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При удачном завершении работы функции запросы PTRACE_PEEK*
возвращают данные памяти, а остальные запросы возвращают
нулевое значение. При ошибке все запросы возвращают -1, а
переменной errno присваивается номер ошибки. Значение,
возвращаемое при удачном завершении PTRACE_PEEK*, может
равняться -1, поэтому после вызова данной функции
необходимо проверить содержимое errno, чтобы узнать,
вернула ли функция ошибку или запрос был удовлетворен.
КОДЫ ОШИБОК
EPERM Заданный процесс не может быть трассирован. Это
может произойти потому, что родительский процесс не
имеет достаточного количества прав на
трассирование: не-root процессы не могут по
очевидным причинам трассировать процессы, которым
невозможно послать сигналы или которые работают в
режиме setuid/setgid. С другой стороны, процесс
может уже быть трассируемым или называться init
(pid 1).
ESRCH Заданный процесс не существует, не трассируется
вызывающим процессом или не остановлен (согласно
запросам).
EIO Задано неверное значение request, или была попытка
записи информации в неподходящую область памяти
дочернего или родительского процесса; было нарушено
выравнивание слов по границе, или при возобновлении
работы дочернего процесса номер сигнала был задан
неверно.
EFAULT Была сделана попытка записи информации в область
памяти дочернего или родительского процесса, но,
скорее всего, эта память не существует или
недоступна. К сожалению, в Linux в разных ситуациях
в результате этой ошибки возвращаются значения EIO
или EFAULT, что не всегда поддается объяснению.
СООТВЕТСТВИЕ СТАНДАРТАМ
SVr4, SVID EXT, AT&T, X/OPEN, BSD 4.3