¿Cómo hacer un buen uso del seguimiento de la pila(desde el kernel o el volcado de núcleo)?
gcc stack-trace (2)
Para los usuarios de Emacs, here hay un modo importante para saltar fácilmente dentro del seguimiento de la pila (usa addr2line
internamente).
Descargo de responsabilidad: lo escribí :)
Si tiene suerte cuando su módulo del kernel falla, obtendría un oops con un registro con mucha información, como los valores en los registros, etc. Una de esas informaciones es el seguimiento de la pila (lo mismo ocurre con los volcados de núcleos, pero originalmente había pedido esto para los módulos del kernel). Tomemos este ejemplo:
[<f97ade02>] ? skink_free_devices+0x32/0xb0 [skin_kernel]
[<f97aba45>] ? cleanup_module+0x1e5/0x550 [skin_kernel]
[<c017d0e7>] ? __stop_machine+0x57/0x70
[<c016dec0>] ? __try_stop_module+0x0/0x30
[<c016f069>] ? sys_delete_module+0x149/0x210
[<c0102f24>] ? sysenter_do_call+0x12/0x16
Mi conjetura es que el +<number1>/<number2>
tiene algo que ver con el desplazamiento desde la función en la que se produjo el error. Es decir, al inspeccionar este número, tal vez mirando la salida del ensamblaje debería poder encontrar la línea (mejor aún, las instrucciones) en las que ocurrió este error. ¿Es eso correcto?
Mi pregunta es, ¿cuáles son estos dos números exactamente? ¿Cómo los utilizas?
skink_free_devices+0x32/0xb0
Esto significa que la instrucción ofensiva es de 0x32
bytes desde el inicio de la función skink_free_devices()
que tiene 0xB0
longitud total de 0xB0
bytes.
Si compila su kernel con -g
habilitado, entonces puede obtener el número de línea dentro de las funciones donde el control saltó usando la herramienta addr2line
o nuestro buen gdb
antiguo
Algo como esto
$ addr2line -e ./vmlinux 0xc01cf0d1
/mnt/linux-2.5.26/include/asm/bitops.h:244
or
$ gdb ./vmlinux
...
(gdb) l *0xc01cf0d1
0xc01cf0d1 is in read_chan (include/asm/bitops.h:244).
(...)
244 return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
(...)
Así que simplemente proporcione la dirección que desea inspeccionar a addr2line
o gdb
y le indicarán el número de línea en el archivo fuente donde está presente la función ofensiva. Consulte this artículo para obtener todos los detalles.
EDITAR: vmlinux
es la versión sin comprimir del kernel utilizada para la depuración y generalmente se encuentra en @ /lib/modules/$(uname -r)/build/vmlinux
siempre que haya compilado su kernel a partir de las fuentes. vmlinuz
que se encuentra en /boot
es el kernel comprimido y puede que no sea tan útil en la depuración