segmentation raspberry que dumped c++ c unix segmentation-fault syslog

c++ - raspberry - ¿Cómo se lee un mensaje de registro de kernel segfault?



segmentation fault raspberry pi (3)

Si es una biblioteca compartida

Estás sucio, desafortunadamente; no es posible saber dónde colocaron las bibliotecas en memoria el enlazador dinámico después de los hechos .

Bueno, todavía hay una posibilidad de recuperar la información, no del binario, sino del objeto. Pero necesitas la dirección base del objeto. Y esta información aún está dentro del núcleo, en la estructura link_map.

Entonces primero quieres importar la estructura link_map en GDB. Entonces, compilemos un programa con el símbolo de depuración y lo agreguemos al GDB.

link.c

#include <link.h> toto(){struct link_map * s = 0x400;}

get_baseaddr_from_coredump.sh

#!/bin/bash BINARY=$(which myapplication) IsBinPIE () { readelf -h $1|grep ''Type'' |grep "EXEC">/dev/null || return 0 return 1 } Hex2Decimal () { export number="`echo "$1" | sed -e ''s:^0[xX]::'' | tr ''[a-f]'' ''[A-F]''`" export number=`echo "ibase=16; $number" | bc` } GetBinaryLength () { if [ $# != 1 ]; then echo "Error, no argument provided" fi IsBinPIE $1 || (echo "ET_EXEC file, need a base_address"; exit 0) export totalsize=0 # Get PT_LOAD''s size segment out of Program Header Table (ELF format) export sizes="$(readelf -l $1 |grep LOAD |awk ''{print $6}''|tr ''/n'' '' '')" for size in $sizes do Hex2Decimal "$size"; export totalsize=$(expr $number + $totalsize); export totalsize=$(expr $number + $totalsize) done return $totalsize } if [ $# = 1 ]; then echo "Using binary $1" IsBinPIE $1 && (echo "NOT ET_EXEC, need a base_address..."; exit 0) BINARY=$1 fi gcc -g3 -fPIC -shared link.c -o link.so GOTADDR=$(readelf -S $BINARY|grep -E ''/.got.plt[ /t]''|awk ''{print $4}'') echo "First do the following command :" echo file $BINARY echo add-symbol-file ./link.so 0x0 read echo "Now copy/paste the following into your gdb session with attached coredump" cat <<EOF set /$linkmapaddr = *(0x$GOTADDR + 4) set /$mylinkmap = (struct link_map *) /$linkmapaddr while (/$mylinkmap != 0) if (/$mylinkmap->l_addr) printf "add-symbol-file .%s %#.08x/n", /$mylinkmap->l_name, /$mylinkmap->l_addr end set /$mylinkmap = /$mylinkmap->l_next end

le imprimirá todo el contenido link_map, dentro de un conjunto de comandos GDB.

En sí mismo, puede parecer que no se escanea, pero con el base_addr del objeto compartido que tratamos, puede obtener más información de una dirección depurando directamente el objeto compartido involucrado en otra instancia de GDB. Guarde el primer gdb para tener una idea del símbolo.

NOTA: la secuencia de comandos es bastante incompleta, sospecho que puede agregar al segundo parámetro de agregar-símbolo-archivo impreso la suma con este valor:

readelf -S $SO_PATH|grep -E ''/.text[ /t]''|awk ''{print $5}''

donde $ SO_PATH es el primer argumento del add-symbol-file

Espero eso ayude

Esta puede ser una pregunta muy simple, estoy intentando depurar una aplicación que genera el siguiente error segfault en kern.log

kernel: myapp[15514]: segfault at 794ef0 ip 080513b sp 794ef0 error 6 in myapp[8048000+24000]

Aquí están mis preguntas:

  1. ¿Hay alguna documentación sobre cuáles son los números de error de diferencia en segfault, en este caso es el error 6, pero he visto el error 4, 5?

  2. ¿Cuál es el significado de la información at bf794ef0 ip 0805130b sp bf794ef0 and myapp[8048000+24000] ?

Hasta ahora pude compilar con símbolos, y cuando hago un x 0x8048000+24000 , devuelve un símbolo, ¿es esa la forma correcta de hacerlo? Mis suposiciones hasta ahora son las siguientes:

  • sp = puntero de pila?
  • ip = puntero de instrucción
  • at = ????
  • myapp [8048000 + 24000] = dirección del símbolo?

Cuando el informe apunta a un programa, no a una biblioteca compartida

Ejecute addr2line -e myapp 080513b (y repita para los otros valores de puntero de instrucción proporcionados) para ver dónde está ocurriendo el error. Mejor, obtenga una compilación instrumentada de depuración y reproduzca el problema bajo un depurador como gdb.

Si es una biblioteca compartida

En la parte libfoo.so[NNNNNN+YYYY] , el NNNNNN es donde se cargó la biblioteca. Reste esto del puntero de instrucción ( ip ) y obtendrá el desplazamiento en el .so de la instrucción ofensiva. Luego puede usar objdump -DCgl libfoo.so y buscar las instrucciones en ese desplazamiento. Debería ser capaz de averiguar fácilmente qué función es de las etiquetas asm. Si .so no tiene optimizaciones, también puede intentar usar addr2line -e libfoo.so <offset> .

Lo que significa el error

Aquí está el desglose de los campos:

  • address : la ubicación en la memoria a la que intenta acceder el código (es probable que 10 y 11 sean desplazamientos desde un puntero que esperamos que se establezca en un valor válido pero que apunta a 0 )
  • ip - puntero de instrucción, es decir. donde el código que está tratando de hacer esto vive
  • puntero sp - stack
  • error - Indicadores específicos de la arquitectura; ver arch/*/mm/fault.c para su plataforma.

En base a mi conocimiento limitado, sus suposiciones son correctas.

  • sp = puntero de pila
  • ip = puntero de instrucción
  • myapp[8048000+24000] = dirección

Si estuviera depurando el problema, modificaría el código para producir un volcado de núcleo o registrar una traza inversa en el bloqueo. También puede ejecutar el programa debajo (o adjuntar) GDB.

El código de error es solo el código de error arquitectónico para fallas de página y parece ser específico de la arquitectura. A menudo están documentados en arch/*/mm/fault.c en la fuente del kernel. Mi copia de Linux/arch/i386/mm/fault.c tiene la siguiente definición para error_code:

  • bit 0 == 0 significa que no se encontró la página, 1 significa falla de protección
  • bit 1 == 0 significa leer, 1 significa escribir
  • bit 2 == 0 significa kernel, 1 significa modo de usuario

Mi copia de Linux/arch/x86_64/mm/fault.c agrega lo siguiente:

  • bit 3 == 1 significa que la falla fue una instrucción de búsqueda