Как получить параметр функции ядра и привести указатель void к char в SystemTap?

У меня есть системный скрипт, который проверяет функцию ядра «memcpy». Я хочу распечатать трассировку стека на основе содержимого буфера src, который является пустым указателем.

Мой код:

%{
        #include <linux/string.h>
%}
probe begin
{
        printf("Begin\n");
}
probe kernel.function("memcpy")
{
        buffer = @cast($src, "char");
        if (isinstr(buffer, "some pattern") != NULL) {
                printf("Found\n");
                print_backtrace();
        }
}

Этот скрипт выдает ошибку, когда я запускаю скрипт следующим образом: "stap -g stacktrace.stp"

неразрешенное выражение целевого символа: идентификатор '$src'

семантическая ошибка: несоответствие типа (строка): идентификатор 'buffer' в stacktrace.stp:31:14

 source:         if (isinstr(buffer, "shubham") != NULL) {
                                ^

семантическая ошибка: тип был впервые выведен здесь (длинный): идентификатор «буфер» в: 30: 2

   source:         buffer = @cast($src, "char");
                    ^

Проход 2: анализ не пройден. [человеческая ошибка :: pass2]

Я видел определение функции memcpy в коде ядра Linux, и этот параметр называется только src. Я не могу разрешить имя переменной. Я пробовал разные имена $src, $from, $s, но ничего не получалось.

Версия ядра машины: 3.10.0-514.el7.x86_64 (RHEL 7.3 (Maipo))

На нем установлены следующие пакеты ядра:

  • ядро-debuginfo-common-x86_64-3.10.0-514.el7.x86_64
  • ядро-3.10.0-514.el7.x86_64
  • заголовки ядра-3.10.0-514.el7.x86_64
  • информация об отладке ядра-3.10.0-514.el7.x86_64
  • ядро-разработка-3.10.0-514.el7.x86_64

person Shubham Pendharkar    schedule 19.02.2019    source источник
comment
Я думаю, что все, что вам нужно, это buffer = kernel_string($src);, но если бы вы могли объяснить, почему вы хотите преобразовать void* в char - может быть, вам нужен только один байт? - Мы можем с этим помочь.   -  person Mark Plotnick    schedule 21.02.2019
comment
Прежде всего, я получаю сообщение об ошибке, говорящее о том, что переменная src неразрешима. Я не знаю, почему эта ошибка генерируется, хотя memcpy имеет src в качестве параметра. Теперь, что касается вашего вопроса @MarkPlotnick, я хочу прочитать содержимое буфера, переданного в memcpy, и хочу сравнить его с предопределенным шаблоном, поэтому я хочу преобразовать его в char *.   -  person Shubham Pendharkar    schedule 21.02.2019
comment
В своем исправленном вопросе вы говорите, что systemtap не может разрешить $src. Можете ли вы отредактировать свой вопрос, указав, какой дистрибутив вы используете и какие пакеты kernel-devel, kernel-debug и kernel-debuginfo у вас установлены?   -  person Mark Plotnick    schedule 21.02.2019
comment
@MarkPlotnick добавил все детали конфигурации.   -  person Shubham Pendharkar    schedule 21.02.2019
comment
используйте stap -L 'kernel.function(memcpy)', чтобы увидеть, какие переменные доступны в этой контрольной точке.   -  person fche    schedule 01.02.2020


Ответы (2)


Обновление 2:

buffer = @cast($src, "char");

Должен ли это быть указатель char вместо char?


Обновление 1: из документации systemtap.

семантическая ошибка: неразрешенное выражение целевого символа

В обработчике зонда была ссылка на целевую переменную, которая не была разрешена. Или целевая переменная вообще недействительна в таком контексте, как функция скрипта. Эта переменная могла быть исключена оптимизирующим компилятором, или может не иметь подходящего типа, или просто где-то может быть досадная ошибка. Попробуйте еще раз с немного другой контрольной точкой (используйте оператор () вместо функции ()), чтобы найти более кооперативного соседа в той же области.


Оригинальные бредни

Понятие переменной как удобной вещи под названием src существует только в человекочитаемом исходном коде. Осмотрите свой код. Вы не объявили никаких переменных с именем src.

Я видел определение функции memcpy в коде ядра Linux, и параметр называется src.

Да, но опять же, это все на благо человека.


Часть, которую вы упускаете, заключается в том, что когда исходный код компилируется в приложение, компилятор сопоставляет все наши человеческие конструкции и превращает их в смещения стека.

Предупреждение. Я полностью игнорирую соглашения о вызовах функций для простоты.

Если вы посмотрите на скомпилированный двоичный файл для вашей платформы, вы увидите несколько более подсказок о том, что вам нужно сделать. Предполагая, что вы работаете в системе x86, вы увидите что-то вроде этого:

memcpy:
  push ebp
  mov ebp, esp
  sub esp, 8

  // The function body starts here and you will see references 
  // to what we recognize as the variable "src" with an instructions like

  mov edi, esp+0
  // That just loaded the EDI register with a reference to the location of src

Посмотреть сборку для вашей платформы можно с помощью gdb.

person Guy Hoozdis    schedule 28.02.2019
comment
Используя дизассемблирование, я все равно не смогу найти имя параметра функции memcpy. Что вы предлагаете для ее решения? Кроме того, буфер = @cast($src, char); здесь оператор приведения возвращает long как тип данных, а не указатель строки или символа, который мне нужен. - person Shubham Pendharkar; 28.02.2019

Отладочная информация gcc для ядра может быть непоследовательной в сохранении формальных параметров для встроенных копий memcpy в любом месте, где она используется.

stap -vL 'kernel.function("memcpy").*'

следует перечислить отдельные или сводку всех сайтов. Шансы что-то вроде

stap -e '
  probe kernel.function("memcpy") 
   { if (@defined($p) && @defined($q)) println($p, " ", $q) }'

может сделать трюк. Он будет запускать println только в тех местах зонда, где определены оба этих параметра. В моем более позднем ядре можно увидеть такие вариации, как ...

kernel.function("memcpy@./include/linux/string.h:347").inline /* pc=_stext+0x68c6a */ $q:void const* $p:void*
kernel.function("memcpy@./include/linux/string.h:347").inline /* pc=_stext+0x178ec */ $size:__kernel_size_t $p:void*
kernel.function("memcpy@./include/linux/string.h:347").inline /* pc=_stext+0x15a31 */ $size:__kernel_size_t $q:void const* $p:void*
kernel.function("memcpy@./include/linux/string.h:347").inline /* pc=_stext+0x13f1f */ $size:__kernel_size_t $q:void const* $p:void* $p_size:size_t $q_size:size_t
kernel.function("memcpy@./include/linux/string.h:347").inline /* pc=_stext+0xc717 */ $size:__kernel_size_t $q:void const* $p:void* $p_size:size_t $q_size:size_t

... поэтому код stap должен допускать гамму.

person fche    schedule 01.02.2020