Red de conocimiento informático - Material del sitio web - Cómo realizar un seguimiento dinámico en el espacio del kernel y del usuario de Linux

Cómo realizar un seguimiento dinámico en el espacio del kernel y del usuario de Linux

¿No recuerdas cómo insertar puntos de sonda en tu código? ¡ningún problema! ¡Aprenda a insertar puntos de sonda dinámicamente usando uprobe y kprobe! Básicamente, los programadores necesitan insertar puntos de sonda dinámicos en diferentes ubicaciones en las instrucciones de ensamblaje del código fuente.

Punto de sonda

Un punto de sonda es una declaración de depuración que ayuda a explorar las características de ejecución del software (es decir, el flujo de ejecución y el estado de las estructuras de datos del software cuando la declaración de sonda se ejecuta). Printk es la forma más simple de declaración de sonda y una de las herramientas básicas utilizadas por los piratas informáticos para atacar el kernel.

La inserción de Printk es un método de sondeo estático porque requiere recompilar el código fuente. Hay muchos otros puntos de seguimiento estáticos en ubicaciones estratégicas en el código del kernel que se pueden habilitar o deshabilitar dinámicamente. kprobe es uno de los métodos dinámicos para insertar puntos de sonda en el código del kernel, mientras que uprobe realiza esta operación en la aplicación del usuario.

Usar uprobe para rastrear el espacio del usuario

Los puntos de rastreo de Uprobe se pueden insertar en el código del espacio del usuario usando la interfaz sysfs o la utilidad perf.

Utilice la interfaz sysfs para insertar uprobe

Considere el siguiente código de prueba simple, que no tiene declaración impresa y queremos insertar una sonda en una determinada instrucción:

[ fuente,c\n.test.c

#include \n#include & lt;stdlib.h>\n#include

Compile el código y busque la dirección de la instrucción a detectar:

# gcc -o test test.\n# objdump -d test

Supongamos que tenemos lo siguiente código de destino en la plataforma ARM64:

0000000000400620 :400620\t90000080\tadr\tx0, 410000 <__FRAME_END__+0xf6f8>

Y queremos insertar un desplazamiento entre 0x620 y 0x644 en la sonda. Ejecute el siguiente comando:

# echo 'p:func_2_entry test:0x620' > /sys/kernel/debug/tracing/uprobe_event\n# echo 'p:func_1_entry test:0x644' >> /sys/ kernel /debug/tracing/uprobe_event\n# echo 1 > /sys/kernel/debug/tracing/events/uprobes/enable# ./test&

En la primera y segunda declaración de eco anteriores, p nos dice esta es una prueba sencilla. (func_n_entry es el nombre que vemos en la salida del seguimiento. nombre es un campo opcional; si no se proporciona, deberíamos esperar un nombre como p_test_0x644. prueba es el binario ejecutable en el que queremos insertar la sonda. Si prueba no está en el directorio actual , debe especificar path_to_test /test.

0x620 o 0x640 es el desplazamiento de la instrucción al comienzo del programa. Tenga en cuenta >> en la segunda declaración de eco porque estamos agregando otra sonda. Al insertar los puntos de sonda en las dos primeras instrucciones, habilitaremos el seguimiento de uprobe y cuando escribamos events/uprobes/enable, el programador también habilitará todos los eventos de uprobe al escribir en el directorio de eventos. Una vez que el punto de sonda esté insertado y habilitado, Podemos ver las entradas de seguimiento cada vez que ejecutamos el comando de sonda.

Lea el archivo de seguimiento para ver el resultado:

# cat /sys/kernel/debug/tracing/trac\n# tracer: no\n\n# entradas-en- buffer/ entradas escritas:8/8\n#P:\n\n# \n----- => irqs-of\n# / _----=> necesidad-resche\n# | / _ ---=> hardirq/softir\n# | / _--=> preempt-dept\n# | / dela\n# TAREA-PID FUNCIÓN# | | ||| | | |

Podemos ver qué CPU completó qué tarea y cuándo se ejecutó.

También puedes insertar sondas de retorno en las instrucciones. Cuando se devuelve la función de esta directiva, se registrará una entrada:

# echo 0 > /sys/kernel/debug/tracing/events/uprobes/enabl\n# echo 'r:func_2_exit test: 0x620' >> /sys/ kernel/debug/tracing/uprobe_event\n# echo 'r: func_1_exit test:0x644' >> /sys/kernel/debug/tracing/uprobe_event\n# echo 1 > /sys/ kernel/debug /tracing /events/uprobes/enable

Aquí usamos r en lugar de p. Todos los demás parámetros son los mismos. Tenga en cuenta que para insertar una nueva sonda, el evento uprobe debe estar deshabilitado:

test-3009 [002] ....4813.852674: func_1_entry: (0x400644)

Lo anterior El registro muestra que func_1 devuelve la dirección 0x4006b0, marca de tiempo 4813.852691.

# echo 0 > /sys/kernel/debug/tracing/ events/uprobes/enabl\n# echo 'p:func_2_entry test:0x630' > /sys/kernel/debug/tracing/uprobe_events count= %x\n# echo 1 > /sys/kernel/ debug/tracing/events/uprobes/enabl\n# echo > /sys/kernel/debug/tracing/trace# .

Instrucción de compensación de ejecución en 0x630, el valor del registro ARM64 x1 se imprimirá como count =.

El resultado es el siguiente:

test-3095 [003] ....7918.629728: func_2_entry: (0x400630) count=0x1

Utilice perf para insertar el código de la fila superior

Encontrar el desplazamiento de una instrucción o función que requiere insertar una sonda es engorroso, y necesitar saber el nombre de un registro de la CPU asignado a una variable local es aún más complicado.

Además de perf, existen otras herramientas como SystemTap, DTrace y LTTng que se pueden usar para rastrear el kernel y el espacio del usuario; sin embargo, perf funciona perfectamente con el kernel, por lo que es el preferido por el kernel; programadores.

# gcc -g -o test test.c# sonda de rendimiento -x ./test func_2_entry=func_\n# sonda de rendimiento -x ./test func_2_exit=func_2%retur\n# sonda de rendimiento -x . /test test_15=test.c:1\n# sonda de rendimiento -x ./test test_25=test.c:25 numbe\n# registro de rendimiento -e probe_test:func_2_entry -e\nprobe_test:func_2_exit -e probe_test:test_15\n-e probe_test:test _25 ./test

Como se muestra arriba, los programadores pueden insertar puntos de sonda directamente en el inicio y retorno de funciones, números de línea específicos en archivos fuente, etc. También puede obtener variables locales impresas, así como muchas otras opciones, como todas las instancias de la función de llamada. La sonda perf se puede utilizar para crear eventos de puntos de sonda que luego aparecen cuando se ejecuta .NET Framework 4.0. /testexecutable, puede utilizar el registro de rendimiento para detectar estos eventos. Al crear puntos de sondeo de rendimiento, también están disponibles otras opciones de registro, como estadísticas de rendimiento, que pueden tener muchas opciones posteriores al análisis, como scripts de rendimiento o informes de rendimiento.

Utilizando el script perf, el resultado del ejemplo anterior es el siguiente:

# script perf

Utilice kprobe para rastrear el espacio del kernel

Igual que uprobe, los puntos de seguimiento de kprobe se pueden insertar en el código del kernel utilizando la interfaz sysfs o la herramienta perf.

Insertar kprobes usando la interfaz sysfs

Los programadores pueden insertar kprobes en la mayoría de los símbolos en /proc/kallsyms; otros símbolos están en la lista negra del kernel; También hay algunos símbolos que son incompatibles con la inserción de kprobe, por ejemplo, insertar kprobe en un archivo kprobe_events provoca un error de escritura. También puede insertar una sonda en una posición de desplazamiento en la biblioteca de símbolos. Al igual que uprobe, kretprobe se puede utilizar para rastrear el retorno de una función e imprimir los valores de las variables locales en la salida del seguimiento.

A continuación se explica cómo hacerlo:

; deshabilite todos los eventos para garantizar que solo veamos la salida de kprobe en el seguimiento /n# echo 0 > /sys/kernel/debug/tracing / events/ enable; deshabilitar los eventos de kprobe hasta que se inserte el punto de sonda /n# echo 0 >

[root@pratyush ~\n# más /sys/kernel/debug/ tracing/trace# tracer: no\n\n# entradas-en-búfer/entradas-escritas :9037/9037\n #P:8\n# _-----=> irqs-of\n# / _----=> necesidad-resche\n# | _- --=> hardirq /softirq#\n| / _--=>profundidad-preempt#\n || / retardo# TAREA-PID CPU#\n |||| FUNCIÓN DE MARCA DE TIEMPO\n |||| Usando perf para insertar kprobe

Similar a uprobe, los programadores pueden usar perf para insertar kprobe en el código del kernel al inicio y retorno de la función, números de línea específicos en archivos fuente, etc. Insertar directamente en el punto de detección. Los programadores pueden proporcionar vmlinux para la opción -k, o la ruta del código fuente del kernel para la opción -s:

# perf probe -k vmlinux kfree_entry=kfre\n# perf probe -k vmlinux kfree_exit=kfree% retur \n# perf probe -s ./ kfree_mid=mm/slub.c:3408 \n# perf record -e probe:kfree_entry -e probe:kfree_exit -e probe:kfree_mid sleep 10

Usar perf script, el resultado del ejemplo anterior:

Para obtener una introducción a los comandos de Linux, consulte "Así es como se aprende Linux" y, específicamente para este capítulo, visite 3w(dot)linuxprobe/chapter-02( punto)html