Действительно структурированный вывод в strace (Эльвира Хабирова, OSSDEVCONF-2016) — различия между версиями
Материал из 0x1.tv
StasFomin (обсуждение | вклад) (→Видео) |
StasFomin (обсуждение | вклад) (→Расширенные тезисы) |
||
== Расширенные тезисы == <latex> \subsection{=== Обзор проблемы} === <latex> В \EN{\emph{strace}} на входе и выходе из системного вызова вызывается ассоциированный с ним обработчик (декодер), которому передаются полученные из \EN{tracee} аргументы. Ранее, \EN{\emph{strace}} кроме того, что обрабатывал эти аргументы, еще и немедленно печатал их. На входе могла печататься только часть аргументов (до первого \EN{out}\footnote{ \EN{out} аргумент~--- аргумент, который указывает на участок памяти, в котором находятся данные, являющиеся выходными для вызываемой функции. Также существует понятие \EN{in-out} аргумента: такой аргумент указывает на место в памяти с данными, являющимися входными и выходными} аргумента). В случае, если это имеет смысл и если указан достаточный уровень подробности вывода, \EN{\emph{strace}} копирует из \EN{tracee} данные, находящиеся по указателям, переданным в аргументах, и печатает их. Этот процесс может быть весьма многоуровневым~--- в случае передачи массивов указателей на структуры, например. Дополнительно \EN{\emph{strace}} может собирать и печатать статистику по времени выполнения, печатать содержимое \EN{iovec} и проч. \EN{\emph{strace}} не содержал унифицированных средств по печати информации о системном вызове; каждый декодер самостоятельно обеспечивал тот формат вывода, который считал нужным (за исключением некоторых базовых вещей, таких как вывод строки, флагов, массивов, дескрипторов... Хотя и здесь есть исключения в случае отдельных декодеров, которым требуется нестандартный вывод). Далее рассмотрим несколько примеров существующих декодеров системных вызовов. Рассмотрим иллюстрацию: \begin{figure}[h!] \centering \begin{scriptsize} \begin{verbatim}accept4(3, {sa_family=AF_UNIX, sun_path="accept4.socket.connect"}, [110->25], SOCK_NONBLOCK|SOCK_CLOEXEC) = 5\end{verbatim} \end{scriptsize} \squeeze \caption{Пример отображения информации о системном вызове \EN{\emph{accept4}}}\label{fig:accept4} \squeeze \end{figure} ~\ref{fig:accept4}. \EN{\emph{accept4}} принимает в качестве второго аргумента указатель на структуру \EN{\emph{struct sockaddr}}, в качестве третьего~--- размер структуры аргумента, и в качестве четвертого набор фагов. В данном случае \EN{\emph{strace}} скопировал из \EN{tracee} структуру \EN{\emph{struct sockaddr}} и декодировал её согласно значению поля \EN{\emph{sa\_family}} (т.~е. интерпретировал последующие данные как поле \EN{\emph{sun\_path}}); также \EN{\emph{strace}} прочитал значение по указателю, переданному в аргументе \EN{\emph{addrlen}}, причём и на входе, и на выходе, так как это \EN{in-out} аргумент. Четвёртый аргумент декодирован как набор флагов. Перейдем к иллюстрации: \begin{figure}[h!] \centering \begin{scriptsize}\begin{verbatim}setitimer(ITIMER_REAL, {it_interval={0, 222222}, it_value={0, 111111}}, NULL) = 0\end{verbatim} \end{scriptsize} \squeeze \caption{Пример отображения информации о системном вызове \EN{\emph{setitimer}}}\label{fig:setitimer} \squeeze \end{figure} ~\ref{fig:setitimer}. В качестве второго и третьего аргументов \EN{\emph{setitimer}} принимает указатель на \EN{\emph{struct itimerval}}, который, в свою очередь, являет собой пару структур \EN{\emph{struct timeval}}. Заметим, что декодер системного вызова выводит имена полей \EN{\emph{struct itimerval}}, но не \EN{\emph{struct timeval}}. На иллюстрации~\ref{fig:pwritev} можно отметить сразу несколько особенностей вывода: \begin{figure}[h!] \centering \begin{scriptsize} \begin{verbatim} $ strace -etrace=pwritev -ewrite=1 -s2 ./preadv-pwritev ... pwritev(1, [{iov_base="01"..., iov_len=3}, {iov_base="34"..., iov_len=5}, ...], 3, 0) = 15 * 3 bytes in buffer 0 | 00000 30 31 32 012 | * 5 bytes in buffer 1 | 00000 33 34 35 36 37 34567 | * 7 bytes in buffer 2 | 00000 38 39 61 62 63 64 65 89abcde |\end{verbatim} \end{scriptsize} \squeeze \caption{Пример отображения информации о системном вызове \EN{\emph{pwritev}} с печатью содержимого \EN{iovec}}\label{fig:pwritev} \squeeze \end{figure} \begin{itemize} \item[--] Строки и массивы, если их размер превышает указанный в параметре \texttt{-s} (32 по умолчанию), сокращаются и терминируются многоточиями. \item[--] Для I/O вызовов существует возможность, посредством задания опции \texttt{-ewrite=1}/\texttt{-eread=1}, вывода содержимого данных, передаваемых в этих вызовах, в формате шестнадцатеричного дампа. \end{itemize} На следующей иллюстрации заметим нестандартный способ аббревиирования вывода массива переменных, который отличается от используемого в большинстве других системных вызовов многоточия. \begin{figure}[h!] \centering \begin{small} \begin{verbatim}execve("./execve", ["./execve"], [/* 41 vars */]) = 0\end{verbatim} \end{small} \squeeze \caption{Пример отображения информации о системном вызове \EN{\emph{execve}}}\label{fig:execve} \squeeze \end{figure} На иллюстрации~\ref{fig:execve} На следующей иллюстрации показан пример системного вызова \EN{\emph{prctl}}. \begin{figure}[h!] \centering \begin{small} \begin{verbatim}prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, {len=3, filter=[BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 0), BPF_JUMP(BPF_JMP|BPF_K|BPF_JEQ, 0x3, 0, 0x1), BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW)]}) = 0\end{verbatim} \end{small} \squeeze \caption{Пример отображения информации о системном вызове \EN{\emph{prctl}} с \EN{\emph{PR\_SET\_SECCOMP}} в качестве аргумента \EN{\emph{option}}}\label{fig:prctl} \squeeze \end{figure} ~\ref{fig:prctl} То, какие из аргументов \EN{\emph{arg2}}, \EN{\emph{arg3}}, \EN{\emph{arg4}}, \EN{\emph{arg5}} выведет \EN{\emph{strace}} и в каком формате, определяется значением первого аргумента \EN{\emph{option}}. В данном случае это команда установки \EN{BPF}-фильтра \EN{\emph{seccomp}}. Другой особенностью данного примера является формат вывода команд \EN{BPF}, которые являют собой структуры, но для которых в \EN{\texttt{<linux/filter.h>}} определены макрокоманды для их определения в коде на языке Си; декодер системного вызова определяет по содержимому структур подходяющую макрокоманду и печатает соответствующую макрокоманду. На следующей иллюстрации отметим формат вывода третьего аргумента, \EN{\emph{vec}}, который представляет собой массив байт, из каждого из которых значащий только один бит. На иллюстрации~\ref{fig:listen} интересен формат вывода, используемый для файловых дескрипторов (первый аргумент). \begin{figure}[h!] \centering \begin{small} \begin{verbatim}mincore(0x2ba1f6293000, 131073, [11111111111111111111...]) = 0\end{verbatim} \end{small} \squeeze \caption{Пример отображения информации о системном вызове \EN{\emph{mincore}}}\label{fig:mincore} \squeeze \end{figure} \begin{figure}[h!] \centering \begin{small} \begin{verbatim}listen(3<TCP:[4490622]>, 1) = 0\end{verbatim} \end{small} \squeeze \caption{Пример отображения информации о системном вызове \EN{\emph{listen}}}\label{fig:listen} \squeeze \end{figure} А в примере на следующем рисунке~\ref{fig:rt_setsigprocmask}, можно отметить специфический формат, используемый для вывода маски сигналов. \begin{figure}[h!] \centering \begin{small} \begin{verbatim}rt_sigprocmask(SIG_SETMASK, NULL, [HUP INT QUIT ALRM TERM], 8) = 0\end{verbatim} \end{small} \squeeze \caption{Пример отображения информации о системном вызове \EN{\emph{rt\_setsigprocmask}}}\label{fig:rt_setsigprocmask} \squeeze \end{figure} На иллюстрации~\ref{fig:mincore} В </latex> === \subsection{Идея структурированного вывода} === <latex> Итак, количество техник вывода, применяемых в \EN{\emph{strace}}, с одной стороны, велико и разнообразно (вывод битовых масок, масок сигналов, различные варианты аббревиирования структур), с другой, всё же поддаётся классификации (есть некие общие правила вывода структур, указателей, массивов). В основе структурированного вывода лежит идея, что все особенности формата вывода можно оформить в виде \EN{reusable} примитивов и использовать для вывода только их. Пример преобразования декодера показан на иллюстрации: |
Версия 14:56, 9 октября 2016
Содержание
Аннотация
- Докладчик
- Эльвира Хабирова
strace --- утилита для отладки программ. Она отображает сделанные отлаживаемым процессом tracee системные вызовы, пришедшие ему сигналы, изменения его состояния и пр.
Вывод strace на данный момент нацелен на человекочитаемость и по этой причине тяжело поддается автоматической обработке.
Кроме того, из-за отсутствия единой системы вывода в выводе могут присутствовать неточности, что еще сильнее усложняет задачу.
Поэтому в рамках GSoC~2016 проблема автоматической обработки была решена разработкой такой единой системы.
Как результат, стало возможным легко встраивать не только подсистемы любого формата вывода, но и дополнительные слои логики.
Видео
Слайды
Расширенные тезисы
Обзор проблемы
Идея структурированного вывода
Второй важной особенностью является введение промежуточного представления системного вызова: