SlideShare ist ein Scribd-Unternehmen logo
1 von 13
Utilisation des core dump
Thierry GAYET
Lorsque l'on développe, il peut parfois être utile de récupérer le
contexte mémoire qui a été à l'origine de la terminaison anormale
d'un programme. Il est donc possible de demander la génération
d'un core dump qui pourra être chargé dans un débugger comme gdb
pour analyse.
1. Définition
Avec un débogueur post-mortem comme gdb, il est possible d'analyser l'état d'exécution d'un
logiciel après un crash. L'analyse se fait sur la base d'un fichier core qui est une copie du contenu
de la mémoire du programme au moment de son crash. Ce fichier est aussi appelé « core
dump ».
L'action par défaut de certains signaux est de forcer un processus à se terminer et de produire un
fichier core dump, un fichier disque contenant une image de la mémoire du processus au moment
où de sa terminaison.
Dans la liste des signaux possible, les suivants ont pour action de générer des core dump :
Signal Valeur Commentaire
SIGQUIT 3 Demande « Quitter » depuis le clavier
SIGILL 4 Instruction illégale
SIGABRT 6 Signal d'arrêt depuis abort
SIGFPE 8 Erreur mathématique virgule flottante.
SIGSEGV 11 Référence mémoire invalide
SIGSYS 12,-,12 Mauvais argument de fonction (SVr4)
SIGTRAP 5 Point d'arrêt rencontré
SIGXCPU 24,24,30 Limite de temps CPU dépassée (4.2BSD).
SIGXFSZ 25,25,31 Taille de fichier excessive (4.2BSD)
Jusqu'au Linux 2.2 inclus, l'action par défaut pour SIGSYS, SIGXCPU, SIGXFSZ, et (sur les
architectures autres que Sparc ou Mips) SIGBUS était de terminer simplement le processus, sans
fichier core. (Sur certains Unix, l'action par défaut pour SIGXCPU et SIGXFSZ est de finir le
processus sans fichier core). Linux 2.4 se conforme à POSIX.1-2001 pour ces signaux, et termine
le processus avec un fichier core.
SIGEMT n'est pas spécifié par POSIX.1-2001 mais apparaît néanmoins sur la plupart des Unix,
avec une action par défaut typique correspondant à une fin du processus avec fichier core.
2. Vérifications de la config. système
Au préalable, il faut vérifier si les capacités du système permette la génération de fichier core
dump. Pour ce faire, la commande ulimit permet de connaître les limites associées aux
utilisateurs :
$ ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 31477
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 31477
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
La première valeur est la plus importante concernant la génération de fichier core dump.
Si cette valeur est déjà positionnée à unlimited, il n'y a rien à faire. Dans le cas contraire il faut
modifier cette limite de façon à éviter la création de core dump tronqués. Le modification de cette
valeur peut être soit spécifique aux core dump ou bien globale à toutes les valeurs :
$ ulimit -c unlimited
On peut aussi contrôler les limites soft et hard :
$ ulimit -Sc
# ulimit -Hc
ou plus globalement :
$ ulimit unlimited
3. Configuration
Le noyau pouvant inclure ou non la fonctionnalité de générer des core dump, il faudra vérifier dans
les sources du noyau GNU/Linux
General setup --->
Configure standard kernel features (for small systems) --->
Enable ELF core dumps
Pour les systèmes orienté linux embarqué, il faudra également vérifier la configuration d'autres
briques logicielles :
• uClibc : activer le mode debug
La librairie uClibc doit être configuré différemment dans le but de supporter les backtrace. Si les
applications sont multi-threadés vous aurez besoin d'activer la configuration suivante :
General Library Settings --->
Build pthreads debugging support
Il faudra également configurer uClibc pour désactiver le stripping de la librairie de façon à garder
ses symboles :
uClibc development/debugging options --->
Strip libraries and executables
Enable Core Dump support in Busybox
• Busybox :
La busybox fournit le processus d'init du système qui est le père de tous les processus. La busybox
peut aussi être configurer pour supporter les core dump pour tous fils (par héritage).
Acivez premièrement la configuration suivante :
Init Utilities --->
Support dumping core for child processes (debugging only)
Ensuite, creez un fichier vide à la racine du système de fichier du device avec le nom suivant :
“.init_enable_core“.
4. Modification à chaud des limites
Malgré ces limites systèmes, un processus peut connaître et redéfinir ses limites associé à ses
ressources logicielle RLIMIT_CORE pour établir une limite haute sur la taille du fichier core dump
qu'il produirait s'il recevait un signal qui aurait comme action de générer un fichier core dump.
RLIMIT_CORE définit donc la taille maximum du fichier core. Lorsqu'elle vaut zéro, aucun fichier
d'image noyau (Ndt : core dump) n'est créé. Lorsqu'elle ne vaut pas zéro, les fichiers d'image
noyau plus grands sont tronqués à cette taille.
La première étape consiste à activer la fonctionnalité par l'appel système prctl(). Le premier flag
signifie si on lit ou modifie l'état et le second indique si le processus courant est « dumpable » (1-
oui, 0-non).
Exemple d'usage :
#include <sys/prctl.h>
int ret;
/* Vérifie l'état associé à la fonctionnalité des core dump */
ret = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
printf("PR_GET_DUMPABLE returned %d", ret);
/* Active la fionctionnalité des core dump */
ret = prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
printf("PR_SET_DUMPABLE returned %d", ret);
/* Vérifie l'état associé à la fonctionnalité des core dump après modification */
ret = prctl( PR_GET_DUMPABLE, 0, 0, 0, 0 );
printf( "PR_GET_DUMPABLE returned %d", ret );
La seconde étape de l'utilisation manuelle (via programmation) d'un core dump est de mofifier ses
limites via l'appel système setrlimit() via la flag RLIMIT_CORE. Cette fonction prend en entrée
une structure de données comportant deux champs. Le premier défini la limitation courante et le
second la limitation maximale autorisé. Pour une limite non-limitée, il faut définir les deux valeurs
de la structure à « RLIM_INFINITY ».
Exemple d'usage :
#include <sys/time.h>
#include <sys/resource.h>
int ret;
struct rlimit rlim;
/* Vérifie la limitation associé aux core dump */
ret = getrlimit(RLIMIT_CORE, &rlim);
printf("RLIMIT_CORE returned %d (%d, %d)", ret, rlim.rlim_cur, rlim.rlim_max);
/* Positionne les limitations associés aux core dump à unlimited */
rlim.rlim_cur = RLIM_INFINITY;
rlim.rlim_max = RLIM_INFINITY;
ret = setrlimit(RLIMIT_CORE, &rlim);
printf("RLIMIT_CORE returned %d", ret);
/* Revérifie la limitation associé aux core dump après modification des limites */
ret = getrlimit(RLIMIT_CORE, &rlim);
printf("RLIMIT_CORE returned %d (%d, %d)", ret, rlim.rlim_cur, rlim.rlim_max);
5. Personnalisation
Le noyau Linux propose plusieurs paramètres pour les core dump :
 /proc/sys/kernel/core_pattern :
Par défaut, un fichier core dump est nommé core, mais le fichier /proc/sys/kernel/core_pattern
(Depuis Linux 2.6 et 2.4.21) peut être configuré pour définir un modèle qui sera utilisé pour
nommer les fichiers core dump.
Le modèle peut contenir des spécificateurs qui seront substitués par les valeurs suivantes lors de
la création d'un fichier core dump :
%% Le caractère % si nécessaire
%p PID du processus « dumpé »
%u UID réel du processus « dumpé »
%g GID réel du processus « dumpé »
%s Numéro du signal ayant provoqué le « dump »
%t Heure du « dump » (secondes depuis le 1er janvier 1970, 00H00)
%h Nom d'hôte (pareil que 'nodename' renvoyé par uname(2))
%e Nom du fichier exécutable
Un seul % à la fin du modèle est rejeté du nom du fichier core comme si c'était la combinaison
d'un % suivi par n'importe quel caractère autre que ceux listés ci-dessus. Tous les autres
caractères dans le modèle deviennent une partie littérale du nom de fichier core.
Le modèle peut comporter des caractères « / » qui seront interprétés comme des délimiteurs de
noms de répertoires. La taille maximum du nom de fichier core résultant est 64 octets. La valeur
par défaut dans ce fichier est « core ». Pour rétrocompatibilité, si /proc/sys/kernel/core_pattern
n'inclut pas « %p » et si /proc/sys/kernel/core_uses_pid (voir plus loin) n'est pas nul, .PID sera
ajouté au nom du fichier core.
Depuis la version 2.4, Linux fournit également /proc/sys/kernel/core_pattern, une méthode plus
primitive de contrôle du nom du fichier core dump. Si le fichier /proc/sys/kernel/core_uses_pid
contient la valeur 0, le fichier core dump est simplement nommé core. Si ce fichier contient une
valeur non nulle, le fichier core dump inclura le PID dans un nom de la forme core.PID.
Ce paramètre permet de personnaliser un traitement lors de la traitement d'un core dump. Cela
peut soit aboutir à la génération d'un fichier core ou core.PID, ou bien lancer un programme. Si le
premier caractère est un pipe « | », le ligne est vu comme un programme a exécuter plutôt qu'une
ligne à écrire.
Contraintes :
• Le programme doit avoir spécifier un chemin absolu depuis la racine du système de
fichiers ;
• Le processus à exécuter, doit pouvoir être lancé sur les droits « utilisateur » et avec un
groupe « root » ;
• Les arguments spécifiés au programmes sur la ligne de commandes (depuis 2.6.24)
doivent être délimités par des espaces. La ligne ne doit pas excéder 128 octets ;
• Les arguments de la ligne de commande peut inclure les specificateurs à base de « % ».
Par exemple, pour passer le PID au processus, il faut spécifier %p en argument.
Quelques exemple d'usages :
• |/usr/share/apport/apport %p %s %c : envoie le dump mémoire au programme append
• core : génère simplement un fichier core
Autre exemple pratique :
$ sudo mkdir -p /tmp/cores
$ sudo chmod a+rwx /tmp/cores
$ sudo echo "/tmp/cores/core.%e.%p.%h.%t" > /proc/sys/kernel/core_pattern
Pour que cela soit permanent, il suffit d'ajouter la ligne suivant au fichier de configuration
« /etc/sysctl.conf » :
kernel.core_pattern=/tmp/cores/core.%e.%p.%h.%t
Pour réaliser un programme gérant les core dump, nous allons mettre en place un exemple
pratique.
Partons du code source suivant « core_test.c » :
#define _GNU_SOURCE
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUF_SIZE 1024
int
main(int argc, char *argv[])
{
int tot, j;
ssize_t nread;
char buf[BUF_SIZE];
FILE *fp;
char cwd[PATH_MAX];
/* Change our current working directory to that of the
crashing process */
snprintf(cwd, PATH_MAX, "/proc/%s/cwd", argv[1]);
chdir(cwd);
/* Write output to file "core.info" in that directory */
fp = fopen("core.info", "w+");
if (fp == NULL)
exit(EXIT_FAILURE);
/* Display command-line arguments given to core_pattern
pipe program */
fprintf(fp, "argc=%dn", argc);
for (j = 0; j < argc; j++)
fprintf(fp, "argc[%d]=<%s>n", j, argv[j]);
/* Count bytes in standard input (the core dump) */
tot = 0;
while ((nread = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)
tot += nread;
fprintf(fp, "Total bytes in core dump: %dn", tot);
exit(EXIT_SUCCESS);
}
Buildons le et incluons le dans la chaine lors de la génération d'un fichier core :
$ gcc core_test.c -o core_test
$ su
# echo "|$PWD/core_test %p UID=%u GID=%g sig=%s" > /proc/sys/kernel/core_pattern
# exit
Rejouons le core dump de façon à obtenir un fichier texte core.info en plus du fichier core :
$ ./coredump
Erreur de segmentation (core dumped)
Le core dump est bien présent :
$ ls -al core.1282
-rw-rw-r-- 1 tgayet tgayet 2046480 août 6 16:20 core.1282
$ file core.1282
core.1282: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from 'coredump'
Tout comme le fichier texte :
$ ls -al core.info
-rw-rw---- 1 root root 166 août 6 16:45 core.info
$ sudo file core.info
core.info: ASCII text
$ sudo cat core.info
[sudo] password for tgayet:
argc=5
argc[0]=</home/tgayet/workspace/core_pattern_pipe_test>
argc[1]=<2134>
argc[2]=<UID=1000>
argc[3]=<GID=1000>
argc[4]=<sig=11>
Total bytes in core dump: 204800
 /proc/sys/kernel/core_uses_pid
Depuis la version 2.4, Linux fourni une méthode permettant de contrôler le nom du fichier core
dump. Si le fichier /proc/sys/kernel/core_uses_pid contient la valeur 0, les fichiers core dump
seront simplement nommé « core ». Dans le cas contraire, pour toute autre valeur non nulle, le
fichier core dump comprendra l'ID du processus dans un nom généré comme core.PID.
 /proc/sys/fs/suid_dumpable
Depuis Linux 2.6.13, la valeur de ce fichier détermine si les fichiers core dump sont produit pour
set-user-ID ou autrement binaires protégés. Trois valeurs entières peuvent être spécifiées:
• 0 (par défaut) Ceci fournit le comportement traditionnel (pré-Linux 2.6.13). Un core dump
ne sera pas produit d'un processus qui a changé ses droits (en appelant seteuid (2), setgid
(2), ou similaire, ou en exécutant un set-user-ID ou le programme set-group-ID) ou dont le
binaire n'a pas l'autorisation en lecture.
• 1 ("debug") tous les processus peuvent générer des core dump si possible. Le core dump
aura les droits du processus ayant généré le dump. La sécurité n'est pas appliquée. Ce
système est destiné aux siuations de debug.
• 2 ("suidsafe") Tout binaire ne génèrons pas de core dump (voir «0» ci-dessus). S'il est
généré, le code dump sera en lecture seule par root. Cela permet à l'utilisateur de le
supprimer mais pas de le lire pour des raisons de sécurité des vidages de la mémoire.
 /proc/<pid>/coredump_filter
Quand la mémoire d'un processus est dumpé, toute la mémoire anonyme est écrite dans le fichier
core tant que le fichier n'a pas atteint sa limite. Parfois, il peut être utile que certain segment de
mémoire ne soient pas dumpés, par exemple avec de grosses zones de mémoires partagés.
D'un autre coté, on peut vouloir sauvegarder des segments de mémoire spécifique dans le fichier
core.
/proc/<pid>/coredump_filter nous permet de personnaliser quel segment de mémoire doit être
sauvegardé au moment de la génération d'un core dump. coredump_filter est un masque de bits
des types de mémoires en charge. Si un des bits du masque est activé, le segment de mémoire
correspondant est dumpé.
Les 7 types de mémoires suivantes sont supportés :
bit n°0 : mémoire anonyme privée
bit n°1 : mémoire anonyme partagée
bit n°2 : mémoire file-backed privée
bit n°3 : mémoire file-backed partagée
bit n°4: pages du header ELF dans la zone de mémoire file-backed privée (effectif
seulement si le bit 2 n'est pas positionné)
bit n°5 : mémoire hugetlb privée
bit n°6 : mémoire hugetlb partagée
A noter que les pages MMIO tel qu'un framebuffer ne sont jamais dumpés alors que le pages
VDSO le sont toujours indépendamment du status du masques de bits.
Les bits de 0 à 4 du masque n'ont aucun effet sur lé mémoire hugetlb qui sont plus affecté avec
les bits 5 et 6.
La valeur par défaut pour un core dump est 0x23 ce qui signifie que tous les segments de
mémoire partagée (privée et partagé) ainsi que la mémoire hugetlb privée.
Pour tout activer, il suffit de mettre tous les bits à 1 ce qui donne 0xFF :
$ echo 0xF > /proc/<pid>/coredump_filter
Si vous ne voulez pas dumper toute la mémoire partagée pour un processus donné dont le pid est
1234, vous pouvez changer les propriétés du processus directement :
$ echo 0x21 > /proc/1234/coredump_filter
Quand un nouveau processus est crée, il hérite son masque du processus parent. Il peut donc
être utille de positionner coredump_filter avant de lancer un binaire :
$ echo 0x7 > /proc/self/coredump_filter
$ ./my_bin
Pour que cette option soit présente, il faut que le noyau ait été compilé avec l'option
CONFIG_ELF_CORE.
6. Tests du support des core dump
Testons maintenant le bon fonctionnement de la génération d'un core dump :
$ sudo mkdir -p `pwd`/cores
$ sudo chmod a+rwx `pwd`/cores
$ sudo echo "`pwd`/cores/core.%e.%p.%h.%t" > /proc/sys/kernel/core_pattern
Écrivons un petit code de test « $ gcc -Wall -g -o coredump coredump.c » :
#include <stdio.h>
int main(void)
{
char *foo = (char*)0x12345;
*foo = 'a';
return 0;
}
Générons le binaire à partir du code source :
$ gcc -Wall -g coredump.c -o coredump
Exécutons le :
$ ./coredump
Segmentation fault (core dumped)
On remarque la mention entre parenthèse (core dumped) qui spécifie que le handle de signal par
défaut à été activé suite à la réception d'un signal d'erreur ce qui a entraîne la génération d'un
fichier core dump.
Ce test est trivial, mais pour simuler la réception d'un signal d'erreur au processus ayant le PID
1234, nous aurions pu envoyer un signal à ce dernier de deux façon possible :
$ kill -11 1234
ou
$ kill -s SIGEGV 1234
On vérifie en effet que le fichier a bien été crée suivant le nommage et le path demandé :
$ tree cores/
cores/
└── core.coredump.31788.tgayet-desktop.1375796915
0 directories, 1 file
$ ls -al cores/core.coredump.31788.tgayet-desktop.1375796915
-rw------- 1 tgayet tgayet 204800 août 6 15:48 cores/core.coredump.31788.tgayet-desktop.1375796915
$ file cores/core.coredump.31788.tgayet-desktop.1375796915
cores/core.coredump.31788.tgayet-desktop.1375796915: ELF 32-bit LSB core file Intel 80386, version 1
(SYSV), SVR4-style, from './coredump'
On peut même tester de le charger dans gdb :
$ gdb ./coredump cores/core.coredump.31788.tgayet-desktop.1375796915
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/tgayet/workspace/coredump...done.
[New LWP 31788]
warning: Can't read pathname for load map: Erreur d'entrée/sortie.
Core was generated by `./coredump'.
Program terminated with signal 11, Segmentation fault.
#0 0x080483c4 in main () at coredump.c:6
6 *foo = 'a';
(gdb)
Le debugueur gdb, nous positionne bien sur la ligne ayant généré le problème.
La commande readelf nous donne quelques informations intéressantes :
$ readelf --all cores/core.coredump.31788.tgayet-desktop.1375796915
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: CORE (Core file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 52 (bytes into file)
Start of section headers: 0 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 15
Size of section headers: 0 (bytes)
Number of section headers: 0
Section header string table index: 0
There are no sections in this file.
There are no sections to group in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
NOTE 0x000214 0x00000000 0x00000000 0x0022c 0x00000 0
LOAD 0x001000 0x08048000 0x00000000 0x00000 0x01000 R E 0x1000
LOAD 0x001000 0x08049000 0x00000000 0x01000 0x01000 R 0x1000
LOAD 0x002000 0x0804a000 0x00000000 0x01000 0x01000 RW 0x1000
LOAD 0x003000 0xb75d6000 0x00000000 0x01000 0x01000 RW 0x1000
LOAD 0x004000 0xb75d7000 0x00000000 0x00000 0x1a3000 R E 0x1000
LOAD 0x004000 0xb777a000 0x00000000 0x02000 0x02000 R 0x1000
LOAD 0x006000 0xb777c000 0x00000000 0x01000 0x01000 RW 0x1000
LOAD 0x007000 0xb777d000 0x00000000 0x03000 0x03000 RW 0x1000
LOAD 0x00a000 0xb77a1000 0x00000000 0x02000 0x02000 RW 0x1000
LOAD 0x00c000 0xb77a3000 0x00000000 0x01000 0x01000 R E 0x1000
LOAD 0x00d000 0xb77a4000 0x00000000 0x00000 0x20000 R E 0x1000
LOAD 0x00d000 0xb77c4000 0x00000000 0x01000 0x01000 R 0x1000
LOAD 0x00e000 0xb77c5000 0x00000000 0x01000 0x01000 RW 0x1000
LOAD 0x00f000 0xbf99e000 0x00000000 0x23000 0x23000 RW 0x1000
There is no dynamic section in this file.
There are no relocations in this file.
There are no unwind sections in this file.
No version information found in this file.
Notes at offset 0x00000214 with length 0x0000022c:
Owner Data size Description
CORE 0x00000090 NT_PRSTATUS (prstatus structure)
CORE 0x0000007c NT_PRPSINFO (prpsinfo structure)
CORE 0x000000a0 NT_AUXV (auxiliary vector)
LINUX 0x00000030 Unknown note type: (0x00000200)
7. Génération d'un core dump depuis GDB
Depuis la console de gdb, il est possible de charger en dynamique un core dump.
Chargeons gdb avec le binaire non strippé, c'est à dire avec ses symboles de débug et ses infos
associées. Ensuite chargeons le core dump préalablement crée. Nous en générerons un autre
juste après :
$ gdb ./coredump
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/tgayet/workspace/coredump...done.
(gdb) core cores/core.coredump.31788.tgayet-desktop.1375796915
[New LWP 31788]
warning: Can't read pathname for load map: Erreur d'entrée/sortie.
Core was generated by `./coredump'.
Program terminated with signal 11, Segmentation fault.
#0 0x080483c4 in main () at coredump.c:6
6 *foo = 'a';
(gdb) bt
#0 0x080483c4 in main () at coredump.c:6
Pour demander la génération d'un core dump, il suffit de saisir la commande « generate-core-
file » :
(gdb) generate-core-file
Saved corefile core.1282
gdb donne l'info suivante :
(gdb) help generate-core-file
Save a core file with the current state of the debugged process.
Argument is optional filename. Default filename is 'core.<process_id>'
8. Accès à la RAM de Linux
L'accès à la mémoire sous linux peut être utile dans certain cas. Le noyau GNU/Linux
propose le device /dev/core qui est un lien symbolique vers /proc/kcore. En réalité, c'est
une sorte d'alias vers la mémoire de l'ordinateur.
Le fichier à la taille de la RAM physique donc peut être assez important, auquel il faut
ajouter 4 ko.
Le format est un fichier ELF core standard.
Avec le dump mémoire globale et un noyau GNULinux non-strippé (avec ses symboles),
gdb est en mesure de donner l'état du noyau incluant ses structures de données :
$ sudo gdb vmlinux /proc/kcore
... snip ...
(gdb) p jiffies_64
$1 = 4326692196
(gdb)
9. Problème de génération possible
Il y a diverses circonstances dans lesquelles un fichier core dump peut ne pas être produit :
• Le processus n'a pas la permission d'écrire le fichier core. (Par défaut, le fichier core est
appelé core et est créé dans le répertoire de travail courant. Voir plus loin pour les détails
de nommage du fichier.) L'écriture du fichier core échouera si le répertoire dans lequel il
doit être créé n'est pas accessible en écriture, ou si un fichier du même nom existe déjà et
n'est pas accessible en écriture ou si ce n'est pas un fichier régulier (par exemple, c'est un
répertoire ou un lien symbolique) ;
• Un fichier (régulier, accessible en écriture) avec le même nom qui serait utilisé pour le
fichier core existe déjà, mais il y a plus d'un lien matériel vers ce fichier ;
• Le système de fichiers où le fichier core devrait être créé est plein ; ou n'a plus d'i-noeud ;
ou est monté en lecture seule ; ou l'utilisateur a atteint son quota dans le système de
fichiers ;
• Le répertoire dans lequel le fichier core dump doit être créé n'existe pas ;
• Le fichier core_pattern nomme un répertoire ou un fichier existant sur lequel on n'a pas la
permission d'écriture ;
• Les limites de ressources RLIMIT_CORE ou RLIMIT_FSIZE pour un processus valent
zéro ;
• Le binaire devant être exécuté par le processus n'a pas la permission de lecture ;
• Le processus exécute un programme Set-UID (Set-GID) qui appartient à un utilisateur
/dev/core
/proc/core
(groupe) autre que l'UID (GID) réel du processus. Il faut voir la description
PR_SET_DUMPABLE de prctl(2) ainsi que /proc/sys/fs/suid_dumpable dans proc(5).
10. Remarques
Si un processus multithread ou, plus précisément, un processus qui partage sa mémoire avec un
autre processus qui a été créé avec l'attribut CLONE_VM de clone(2) créé un fichier core dump, le
PID est toujours ajouté au nom du fichier core, à moins que le PID ne soit déjà inclus quelque part
dans le nom de fichier via une spécification %p dans /proc/sys/kernel/core_pattern.
Malheureusement, si votre application est équipé d'un gestionnaire de signaux personnalisée,
aucun core dump ne sera généré, car ils sont générés uniquement par les gestionnaires de
signaux par défaut.
L'appel au gestionnaire par défaut peut être sollicité à la fin du handle de signal, mais sans que
cela soit puisse suffire. Il vaut mieux en effet restaurer le gestionnaire personnalisé en phase de
débug.
11. Conclusion
Avec les core dump, nous voilà muni d'un outil de choix, permettant d'investiguer en cas de crash.
12. Liens
• http://man7.org/linux/man-pages/man5/core.5.html
• http://www.bottomupcs.com/elf.html#coredump_gdb
• http://linux.die.net/man/5/proc
• http://www.linuxcertif.com/man/7/signal/
• http://www.linuxcertif.com/man/5/core/
• http://www.linuxcertif.com/man/1/gdb/
• http://www.linuxcertif.com/man/2/getrlimit/
• http://web.cecs.pdx.edu/~jrb/ui/linux/driver4.txt
• https://www.kernel.org/doc/Documentation/filesystems/proc.txt

Weitere ähnliche Inhalte

Was ist angesagt?

nl80211 and libnl
nl80211 and libnlnl80211 and libnl
nl80211 and libnlawkman
 
Mise en place de service FTP kalinux.pdf
Mise en place de service FTP kalinux.pdfMise en place de service FTP kalinux.pdf
Mise en place de service FTP kalinux.pdfImnaTech
 
Build your own embedded linux distributions by yocto project
Build your own embedded linux distributions by yocto projectBuild your own embedded linux distributions by yocto project
Build your own embedded linux distributions by yocto projectYen-Chin Lee
 
Linux MMAP & Ioremap introduction
Linux MMAP & Ioremap introductionLinux MMAP & Ioremap introduction
Linux MMAP & Ioremap introductionGene Chang
 
6 stages of linux boot process
6 stages of linux boot process6 stages of linux boot process
6 stages of linux boot processTeja Bheemanapally
 
Process Address Space: The way to create virtual address (page table) of user...
Process Address Space: The way to create virtual address (page table) of user...Process Address Space: The way to create virtual address (page table) of user...
Process Address Space: The way to create virtual address (page table) of user...Adrian Huang
 
Profiling your Applications using the Linux Perf Tools
Profiling your Applications using the Linux Perf ToolsProfiling your Applications using the Linux Perf Tools
Profiling your Applications using the Linux Perf ToolsemBO_Conference
 
Comprendre les scripts shell auto-extractible
Comprendre les scripts shell auto-extractibleComprendre les scripts shell auto-extractible
Comprendre les scripts shell auto-extractibleThierry Gayet
 
Marco Cavallini @ LinuxLab 2018 : Workshop Yocto Project, an automatic genera...
Marco Cavallini @ LinuxLab 2018 : Workshop Yocto Project, an automatic genera...Marco Cavallini @ LinuxLab 2018 : Workshop Yocto Project, an automatic genera...
Marco Cavallini @ LinuxLab 2018 : Workshop Yocto Project, an automatic genera...Marco Cavallini
 
Linux Interrupts
Linux InterruptsLinux Interrupts
Linux InterruptsKernel TLV
 
Android Boot Time Optimization
Android Boot Time OptimizationAndroid Boot Time Optimization
Android Boot Time OptimizationKan-Ru Chen
 
Fiche TD sur les systèmes informatiques
Fiche TD sur les systèmes informatiquesFiche TD sur les systèmes informatiques
Fiche TD sur les systèmes informatiquesATPENSC-Group
 
Vmlinux: anatomy of bzimage and how x86 64 processor is booted
Vmlinux: anatomy of bzimage and how x86 64 processor is bootedVmlinux: anatomy of bzimage and how x86 64 processor is booted
Vmlinux: anatomy of bzimage and how x86 64 processor is bootedAdrian Huang
 
Linux booting procedure
Linux booting procedureLinux booting procedure
Linux booting procedureDhaval Kaneria
 
Launch the First Process in Linux System
Launch the First Process in Linux SystemLaunch the First Process in Linux System
Launch the First Process in Linux SystemJian-Hong Pan
 

Was ist angesagt? (20)

nl80211 and libnl
nl80211 and libnlnl80211 and libnl
nl80211 and libnl
 
Mise en place de service FTP kalinux.pdf
Mise en place de service FTP kalinux.pdfMise en place de service FTP kalinux.pdf
Mise en place de service FTP kalinux.pdf
 
Build your own embedded linux distributions by yocto project
Build your own embedded linux distributions by yocto projectBuild your own embedded linux distributions by yocto project
Build your own embedded linux distributions by yocto project
 
Linux MMAP & Ioremap introduction
Linux MMAP & Ioremap introductionLinux MMAP & Ioremap introduction
Linux MMAP & Ioremap introduction
 
Introduction to Modern U-Boot
Introduction to Modern U-BootIntroduction to Modern U-Boot
Introduction to Modern U-Boot
 
6 stages of linux boot process
6 stages of linux boot process6 stages of linux boot process
6 stages of linux boot process
 
Linux Network Stack
Linux Network StackLinux Network Stack
Linux Network Stack
 
Linux Booting Process
Linux Booting ProcessLinux Booting Process
Linux Booting Process
 
Process Address Space: The way to create virtual address (page table) of user...
Process Address Space: The way to create virtual address (page table) of user...Process Address Space: The way to create virtual address (page table) of user...
Process Address Space: The way to create virtual address (page table) of user...
 
Kernel crashdump
Kernel crashdumpKernel crashdump
Kernel crashdump
 
Profiling your Applications using the Linux Perf Tools
Profiling your Applications using the Linux Perf ToolsProfiling your Applications using the Linux Perf Tools
Profiling your Applications using the Linux Perf Tools
 
Comprendre les scripts shell auto-extractible
Comprendre les scripts shell auto-extractibleComprendre les scripts shell auto-extractible
Comprendre les scripts shell auto-extractible
 
Basics of-linux
Basics of-linuxBasics of-linux
Basics of-linux
 
Marco Cavallini @ LinuxLab 2018 : Workshop Yocto Project, an automatic genera...
Marco Cavallini @ LinuxLab 2018 : Workshop Yocto Project, an automatic genera...Marco Cavallini @ LinuxLab 2018 : Workshop Yocto Project, an automatic genera...
Marco Cavallini @ LinuxLab 2018 : Workshop Yocto Project, an automatic genera...
 
Linux Interrupts
Linux InterruptsLinux Interrupts
Linux Interrupts
 
Android Boot Time Optimization
Android Boot Time OptimizationAndroid Boot Time Optimization
Android Boot Time Optimization
 
Fiche TD sur les systèmes informatiques
Fiche TD sur les systèmes informatiquesFiche TD sur les systèmes informatiques
Fiche TD sur les systèmes informatiques
 
Vmlinux: anatomy of bzimage and how x86 64 processor is booted
Vmlinux: anatomy of bzimage and how x86 64 processor is bootedVmlinux: anatomy of bzimage and how x86 64 processor is booted
Vmlinux: anatomy of bzimage and how x86 64 processor is booted
 
Linux booting procedure
Linux booting procedureLinux booting procedure
Linux booting procedure
 
Launch the First Process in Linux System
Launch the First Process in Linux SystemLaunch the First Process in Linux System
Launch the First Process in Linux System
 

Andere mochten auch

Module 2 Formation des doctorants
Module 2 Formation des doctorantsModule 2 Formation des doctorants
Module 2 Formation des doctorantsMagalie Le Gall
 
Shopping mission impossible
Shopping mission impossibleShopping mission impossible
Shopping mission impossiblecatavrio
 
Pauvres petits-vieux
Pauvres petits-vieuxPauvres petits-vieux
Pauvres petits-vieuxcatavrio
 
Philo du poulet
Philo du pouletPhilo du poulet
Philo du pouletcatavrio
 
Proyecto de Vida de Julieth
Proyecto de Vida de Julieth Proyecto de Vida de Julieth
Proyecto de Vida de Julieth lorenarodriguez08
 
011 xxx streapteasemasculin-ip-all
011 xxx streapteasemasculin-ip-all011 xxx streapteasemasculin-ip-all
011 xxx streapteasemasculin-ip-allcatavrio
 
Open Source et Agilité
Open Source et AgilitéOpen Source et Agilité
Open Source et AgilitéChristophe NEY
 
Beezbox: développez votre activité en exploitant les facebook, twitter et Li...
Beezbox:  développez votre activité en exploitant les facebook, twitter et Li...Beezbox:  développez votre activité en exploitant les facebook, twitter et Li...
Beezbox: développez votre activité en exploitant les facebook, twitter et Li...Solofo RAFENO
 
Beaujolaisnouveau
BeaujolaisnouveauBeaujolaisnouveau
Beaujolaisnouveaucatavrio
 
Vivelaretraite
VivelaretraiteVivelaretraite
Vivelaretraitecatavrio
 
Vente maison récente Lamorlaye
Vente maison récente LamorlayeVente maison récente Lamorlaye
Vente maison récente LamorlayeMarc Foujols
 

Andere mochten auch (20)

Illusion4
Illusion4Illusion4
Illusion4
 
3
33
3
 
Module 2 Formation des doctorants
Module 2 Formation des doctorantsModule 2 Formation des doctorants
Module 2 Formation des doctorants
 
Shopping mission impossible
Shopping mission impossibleShopping mission impossible
Shopping mission impossible
 
Pauvres petits-vieux
Pauvres petits-vieuxPauvres petits-vieux
Pauvres petits-vieux
 
Importancia de las teorías acerca de los colaboradores
Importancia de las  teorías acerca de los colaboradoresImportancia de las  teorías acerca de los colaboradores
Importancia de las teorías acerca de los colaboradores
 
Comenzar
ComenzarComenzar
Comenzar
 
Dominique Palombo - Movement
Dominique Palombo - MovementDominique Palombo - Movement
Dominique Palombo - Movement
 
Philo du poulet
Philo du pouletPhilo du poulet
Philo du poulet
 
Proyecto de Vida de Julieth
Proyecto de Vida de Julieth Proyecto de Vida de Julieth
Proyecto de Vida de Julieth
 
011 xxx streapteasemasculin-ip-all
011 xxx streapteasemasculin-ip-all011 xxx streapteasemasculin-ip-all
011 xxx streapteasemasculin-ip-all
 
Los dientes saludables
Los dientes saludablesLos dientes saludables
Los dientes saludables
 
Open Source et Agilité
Open Source et AgilitéOpen Source et Agilité
Open Source et Agilité
 
Illusion4
Illusion4Illusion4
Illusion4
 
Beezbox: développez votre activité en exploitant les facebook, twitter et Li...
Beezbox:  développez votre activité en exploitant les facebook, twitter et Li...Beezbox:  développez votre activité en exploitant les facebook, twitter et Li...
Beezbox: développez votre activité en exploitant les facebook, twitter et Li...
 
Beaujolaisnouveau
BeaujolaisnouveauBeaujolaisnouveau
Beaujolaisnouveau
 
Hypnose j
Hypnose jHypnose j
Hypnose j
 
Vivelaretraite
VivelaretraiteVivelaretraite
Vivelaretraite
 
Vente maison récente Lamorlaye
Vente maison récente LamorlayeVente maison récente Lamorlaye
Vente maison récente Lamorlaye
 
WEB 2.0
WEB 2.0WEB 2.0
WEB 2.0
 

Ähnlich wie utilisation des core dump sous linux

Analyse d'un kernel (crash, core) dump
Analyse d'un kernel (crash, core) dumpAnalyse d'un kernel (crash, core) dump
Analyse d'un kernel (crash, core) dumpGaëtan Trellu
 
Rapport systéme embarqué busybox
Rapport systéme embarqué busyboxRapport systéme embarqué busybox
Rapport systéme embarqué busyboxAyoub Rouzi
 
Maintenance du système Linux
Maintenance du système LinuxMaintenance du système Linux
Maintenance du système LinuxEL AMRI El Hassan
 
PostgreSQL sous linux
PostgreSQL sous linuxPostgreSQL sous linux
PostgreSQL sous linuxKhalid ALLILI
 
systemd red hat linux examen Ex200 rh124
systemd red hat linux examen Ex200 rh124systemd red hat linux examen Ex200 rh124
systemd red hat linux examen Ex200 rh124loffyhacker
 
A la découverte de redo
A la découverte de redoA la découverte de redo
A la découverte de redoThierry Gayet
 
Principes de fonctionnement unix
Principes de fonctionnement unixPrincipes de fonctionnement unix
Principes de fonctionnement unixwebreaker
 
Etude DéTailléé de la pile réseau sous GNU Linux
Etude DéTailléé de la pile réseau sous GNU LinuxEtude DéTailléé de la pile réseau sous GNU Linux
Etude DéTailléé de la pile réseau sous GNU LinuxThierry Gayet
 
PostgreSQL sous linux
PostgreSQL sous linuxPostgreSQL sous linux
PostgreSQL sous linuxKhalid ALLILI
 
Cours SE Gestion des périphériques - IG IPSET
Cours SE Gestion des périphériques - IG IPSETCours SE Gestion des périphériques - IG IPSET
Cours SE Gestion des périphériques - IG IPSETMedBechir
 
Chargez un noyau linux sans reboot avec kexec
Chargez un noyau linux sans reboot avec kexecChargez un noyau linux sans reboot avec kexec
Chargez un noyau linux sans reboot avec kexecThierry Gayet
 
Install arch ultrabook full luks ssd
Install arch ultrabook full luks ssdInstall arch ultrabook full luks ssd
Install arch ultrabook full luks ssdAnthony Le Goff
 
Solution d'OTA
Solution d'OTASolution d'OTA
Solution d'OTASidereo
 
C2 - Langage C - ISIMA 1 - Deuxieme partie
C2 - Langage C - ISIMA 1 - Deuxieme partieC2 - Langage C - ISIMA 1 - Deuxieme partie
C2 - Langage C - ISIMA 1 - Deuxieme partieLoic Yon
 
Rapport Kernel Linux - Configuration – Compilation & installation
Rapport Kernel Linux - Configuration –  Compilation & installationRapport Kernel Linux - Configuration –  Compilation & installation
Rapport Kernel Linux - Configuration – Compilation & installationAyoub Rouzi
 
Virtualiastion des systèmes d'exploitations
Virtualiastion des systèmes d'exploitationsVirtualiastion des systèmes d'exploitations
Virtualiastion des systèmes d'exploitationsSGHIOUAR abdelfettah
 

Ähnlich wie utilisation des core dump sous linux (20)

Analyse d'un kernel (crash, core) dump
Analyse d'un kernel (crash, core) dumpAnalyse d'un kernel (crash, core) dump
Analyse d'un kernel (crash, core) dump
 
Boot
BootBoot
Boot
 
Rapport systéme embarqué busybox
Rapport systéme embarqué busyboxRapport systéme embarqué busybox
Rapport systéme embarqué busybox
 
Maintenance du système Linux
Maintenance du système LinuxMaintenance du système Linux
Maintenance du système Linux
 
PostgreSQL sous linux
PostgreSQL sous linuxPostgreSQL sous linux
PostgreSQL sous linux
 
systemd red hat linux examen Ex200 rh124
systemd red hat linux examen Ex200 rh124systemd red hat linux examen Ex200 rh124
systemd red hat linux examen Ex200 rh124
 
A la découverte de redo
A la découverte de redoA la découverte de redo
A la découverte de redo
 
Principes de fonctionnement unix
Principes de fonctionnement unixPrincipes de fonctionnement unix
Principes de fonctionnement unix
 
Etude DéTailléé de la pile réseau sous GNU Linux
Etude DéTailléé de la pile réseau sous GNU LinuxEtude DéTailléé de la pile réseau sous GNU Linux
Etude DéTailléé de la pile réseau sous GNU Linux
 
PostgreSQL sous linux
PostgreSQL sous linuxPostgreSQL sous linux
PostgreSQL sous linux
 
Noyau
NoyauNoyau
Noyau
 
Cours SE Gestion des périphériques - IG IPSET
Cours SE Gestion des périphériques - IG IPSETCours SE Gestion des périphériques - IG IPSET
Cours SE Gestion des périphériques - IG IPSET
 
Chargez un noyau linux sans reboot avec kexec
Chargez un noyau linux sans reboot avec kexecChargez un noyau linux sans reboot avec kexec
Chargez un noyau linux sans reboot avec kexec
 
Utilisation de dkms
Utilisation de dkmsUtilisation de dkms
Utilisation de dkms
 
Install arch ultrabook full luks ssd
Install arch ultrabook full luks ssdInstall arch ultrabook full luks ssd
Install arch ultrabook full luks ssd
 
Solution d'OTA
Solution d'OTASolution d'OTA
Solution d'OTA
 
OpenNMS
OpenNMSOpenNMS
OpenNMS
 
C2 - Langage C - ISIMA 1 - Deuxieme partie
C2 - Langage C - ISIMA 1 - Deuxieme partieC2 - Langage C - ISIMA 1 - Deuxieme partie
C2 - Langage C - ISIMA 1 - Deuxieme partie
 
Rapport Kernel Linux - Configuration – Compilation & installation
Rapport Kernel Linux - Configuration –  Compilation & installationRapport Kernel Linux - Configuration –  Compilation & installation
Rapport Kernel Linux - Configuration – Compilation & installation
 
Virtualiastion des systèmes d'exploitations
Virtualiastion des systèmes d'exploitationsVirtualiastion des systèmes d'exploitations
Virtualiastion des systèmes d'exploitations
 

utilisation des core dump sous linux

  • 1. Utilisation des core dump Thierry GAYET Lorsque l'on développe, il peut parfois être utile de récupérer le contexte mémoire qui a été à l'origine de la terminaison anormale d'un programme. Il est donc possible de demander la génération d'un core dump qui pourra être chargé dans un débugger comme gdb pour analyse. 1. Définition Avec un débogueur post-mortem comme gdb, il est possible d'analyser l'état d'exécution d'un logiciel après un crash. L'analyse se fait sur la base d'un fichier core qui est une copie du contenu de la mémoire du programme au moment de son crash. Ce fichier est aussi appelé « core dump ». L'action par défaut de certains signaux est de forcer un processus à se terminer et de produire un fichier core dump, un fichier disque contenant une image de la mémoire du processus au moment où de sa terminaison. Dans la liste des signaux possible, les suivants ont pour action de générer des core dump : Signal Valeur Commentaire SIGQUIT 3 Demande « Quitter » depuis le clavier SIGILL 4 Instruction illégale SIGABRT 6 Signal d'arrêt depuis abort SIGFPE 8 Erreur mathématique virgule flottante. SIGSEGV 11 Référence mémoire invalide SIGSYS 12,-,12 Mauvais argument de fonction (SVr4) SIGTRAP 5 Point d'arrêt rencontré SIGXCPU 24,24,30 Limite de temps CPU dépassée (4.2BSD). SIGXFSZ 25,25,31 Taille de fichier excessive (4.2BSD) Jusqu'au Linux 2.2 inclus, l'action par défaut pour SIGSYS, SIGXCPU, SIGXFSZ, et (sur les architectures autres que Sparc ou Mips) SIGBUS était de terminer simplement le processus, sans fichier core. (Sur certains Unix, l'action par défaut pour SIGXCPU et SIGXFSZ est de finir le processus sans fichier core). Linux 2.4 se conforme à POSIX.1-2001 pour ces signaux, et termine le processus avec un fichier core. SIGEMT n'est pas spécifié par POSIX.1-2001 mais apparaît néanmoins sur la plupart des Unix, avec une action par défaut typique correspondant à une fin du processus avec fichier core. 2. Vérifications de la config. système Au préalable, il faut vérifier si les capacités du système permette la génération de fichier core dump. Pour ce faire, la commande ulimit permet de connaître les limites associées aux utilisateurs : $ ulimit -a core file size (blocks, -c) unlimited
  • 2. data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 31477 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 31477 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited La première valeur est la plus importante concernant la génération de fichier core dump. Si cette valeur est déjà positionnée à unlimited, il n'y a rien à faire. Dans le cas contraire il faut modifier cette limite de façon à éviter la création de core dump tronqués. Le modification de cette valeur peut être soit spécifique aux core dump ou bien globale à toutes les valeurs : $ ulimit -c unlimited On peut aussi contrôler les limites soft et hard : $ ulimit -Sc # ulimit -Hc ou plus globalement : $ ulimit unlimited 3. Configuration Le noyau pouvant inclure ou non la fonctionnalité de générer des core dump, il faudra vérifier dans les sources du noyau GNU/Linux General setup ---> Configure standard kernel features (for small systems) ---> Enable ELF core dumps Pour les systèmes orienté linux embarqué, il faudra également vérifier la configuration d'autres briques logicielles : • uClibc : activer le mode debug La librairie uClibc doit être configuré différemment dans le but de supporter les backtrace. Si les applications sont multi-threadés vous aurez besoin d'activer la configuration suivante : General Library Settings --->
  • 3. Build pthreads debugging support Il faudra également configurer uClibc pour désactiver le stripping de la librairie de façon à garder ses symboles : uClibc development/debugging options ---> Strip libraries and executables Enable Core Dump support in Busybox • Busybox : La busybox fournit le processus d'init du système qui est le père de tous les processus. La busybox peut aussi être configurer pour supporter les core dump pour tous fils (par héritage). Acivez premièrement la configuration suivante : Init Utilities ---> Support dumping core for child processes (debugging only) Ensuite, creez un fichier vide à la racine du système de fichier du device avec le nom suivant : “.init_enable_core“. 4. Modification à chaud des limites Malgré ces limites systèmes, un processus peut connaître et redéfinir ses limites associé à ses ressources logicielle RLIMIT_CORE pour établir une limite haute sur la taille du fichier core dump qu'il produirait s'il recevait un signal qui aurait comme action de générer un fichier core dump. RLIMIT_CORE définit donc la taille maximum du fichier core. Lorsqu'elle vaut zéro, aucun fichier d'image noyau (Ndt : core dump) n'est créé. Lorsqu'elle ne vaut pas zéro, les fichiers d'image noyau plus grands sont tronqués à cette taille. La première étape consiste à activer la fonctionnalité par l'appel système prctl(). Le premier flag signifie si on lit ou modifie l'état et le second indique si le processus courant est « dumpable » (1- oui, 0-non). Exemple d'usage : #include <sys/prctl.h> int ret; /* Vérifie l'état associé à la fonctionnalité des core dump */ ret = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0); printf("PR_GET_DUMPABLE returned %d", ret); /* Active la fionctionnalité des core dump */ ret = prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); printf("PR_SET_DUMPABLE returned %d", ret); /* Vérifie l'état associé à la fonctionnalité des core dump après modification */ ret = prctl( PR_GET_DUMPABLE, 0, 0, 0, 0 ); printf( "PR_GET_DUMPABLE returned %d", ret );
  • 4. La seconde étape de l'utilisation manuelle (via programmation) d'un core dump est de mofifier ses limites via l'appel système setrlimit() via la flag RLIMIT_CORE. Cette fonction prend en entrée une structure de données comportant deux champs. Le premier défini la limitation courante et le second la limitation maximale autorisé. Pour une limite non-limitée, il faut définir les deux valeurs de la structure à « RLIM_INFINITY ». Exemple d'usage : #include <sys/time.h> #include <sys/resource.h> int ret; struct rlimit rlim; /* Vérifie la limitation associé aux core dump */ ret = getrlimit(RLIMIT_CORE, &rlim); printf("RLIMIT_CORE returned %d (%d, %d)", ret, rlim.rlim_cur, rlim.rlim_max); /* Positionne les limitations associés aux core dump à unlimited */ rlim.rlim_cur = RLIM_INFINITY; rlim.rlim_max = RLIM_INFINITY; ret = setrlimit(RLIMIT_CORE, &rlim); printf("RLIMIT_CORE returned %d", ret); /* Revérifie la limitation associé aux core dump après modification des limites */ ret = getrlimit(RLIMIT_CORE, &rlim); printf("RLIMIT_CORE returned %d (%d, %d)", ret, rlim.rlim_cur, rlim.rlim_max); 5. Personnalisation Le noyau Linux propose plusieurs paramètres pour les core dump :  /proc/sys/kernel/core_pattern : Par défaut, un fichier core dump est nommé core, mais le fichier /proc/sys/kernel/core_pattern (Depuis Linux 2.6 et 2.4.21) peut être configuré pour définir un modèle qui sera utilisé pour nommer les fichiers core dump. Le modèle peut contenir des spécificateurs qui seront substitués par les valeurs suivantes lors de la création d'un fichier core dump : %% Le caractère % si nécessaire %p PID du processus « dumpé » %u UID réel du processus « dumpé » %g GID réel du processus « dumpé » %s Numéro du signal ayant provoqué le « dump » %t Heure du « dump » (secondes depuis le 1er janvier 1970, 00H00) %h Nom d'hôte (pareil que 'nodename' renvoyé par uname(2)) %e Nom du fichier exécutable Un seul % à la fin du modèle est rejeté du nom du fichier core comme si c'était la combinaison d'un % suivi par n'importe quel caractère autre que ceux listés ci-dessus. Tous les autres
  • 5. caractères dans le modèle deviennent une partie littérale du nom de fichier core. Le modèle peut comporter des caractères « / » qui seront interprétés comme des délimiteurs de noms de répertoires. La taille maximum du nom de fichier core résultant est 64 octets. La valeur par défaut dans ce fichier est « core ». Pour rétrocompatibilité, si /proc/sys/kernel/core_pattern n'inclut pas « %p » et si /proc/sys/kernel/core_uses_pid (voir plus loin) n'est pas nul, .PID sera ajouté au nom du fichier core. Depuis la version 2.4, Linux fournit également /proc/sys/kernel/core_pattern, une méthode plus primitive de contrôle du nom du fichier core dump. Si le fichier /proc/sys/kernel/core_uses_pid contient la valeur 0, le fichier core dump est simplement nommé core. Si ce fichier contient une valeur non nulle, le fichier core dump inclura le PID dans un nom de la forme core.PID. Ce paramètre permet de personnaliser un traitement lors de la traitement d'un core dump. Cela peut soit aboutir à la génération d'un fichier core ou core.PID, ou bien lancer un programme. Si le premier caractère est un pipe « | », le ligne est vu comme un programme a exécuter plutôt qu'une ligne à écrire. Contraintes : • Le programme doit avoir spécifier un chemin absolu depuis la racine du système de fichiers ; • Le processus à exécuter, doit pouvoir être lancé sur les droits « utilisateur » et avec un groupe « root » ; • Les arguments spécifiés au programmes sur la ligne de commandes (depuis 2.6.24) doivent être délimités par des espaces. La ligne ne doit pas excéder 128 octets ; • Les arguments de la ligne de commande peut inclure les specificateurs à base de « % ». Par exemple, pour passer le PID au processus, il faut spécifier %p en argument. Quelques exemple d'usages : • |/usr/share/apport/apport %p %s %c : envoie le dump mémoire au programme append • core : génère simplement un fichier core Autre exemple pratique : $ sudo mkdir -p /tmp/cores $ sudo chmod a+rwx /tmp/cores $ sudo echo "/tmp/cores/core.%e.%p.%h.%t" > /proc/sys/kernel/core_pattern Pour que cela soit permanent, il suffit d'ajouter la ligne suivant au fichier de configuration « /etc/sysctl.conf » : kernel.core_pattern=/tmp/cores/core.%e.%p.%h.%t Pour réaliser un programme gérant les core dump, nous allons mettre en place un exemple pratique. Partons du code source suivant « core_test.c » : #define _GNU_SOURCE #include <sys/stat.h> #include <fcntl.h> #include <limits.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define BUF_SIZE 1024
  • 6. int main(int argc, char *argv[]) { int tot, j; ssize_t nread; char buf[BUF_SIZE]; FILE *fp; char cwd[PATH_MAX]; /* Change our current working directory to that of the crashing process */ snprintf(cwd, PATH_MAX, "/proc/%s/cwd", argv[1]); chdir(cwd); /* Write output to file "core.info" in that directory */ fp = fopen("core.info", "w+"); if (fp == NULL) exit(EXIT_FAILURE); /* Display command-line arguments given to core_pattern pipe program */ fprintf(fp, "argc=%dn", argc); for (j = 0; j < argc; j++) fprintf(fp, "argc[%d]=<%s>n", j, argv[j]); /* Count bytes in standard input (the core dump) */ tot = 0; while ((nread = read(STDIN_FILENO, buf, BUF_SIZE)) > 0) tot += nread; fprintf(fp, "Total bytes in core dump: %dn", tot); exit(EXIT_SUCCESS); } Buildons le et incluons le dans la chaine lors de la génération d'un fichier core : $ gcc core_test.c -o core_test $ su # echo "|$PWD/core_test %p UID=%u GID=%g sig=%s" > /proc/sys/kernel/core_pattern # exit Rejouons le core dump de façon à obtenir un fichier texte core.info en plus du fichier core : $ ./coredump Erreur de segmentation (core dumped) Le core dump est bien présent : $ ls -al core.1282 -rw-rw-r-- 1 tgayet tgayet 2046480 août 6 16:20 core.1282 $ file core.1282 core.1282: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from 'coredump' Tout comme le fichier texte : $ ls -al core.info -rw-rw---- 1 root root 166 août 6 16:45 core.info
  • 7. $ sudo file core.info core.info: ASCII text $ sudo cat core.info [sudo] password for tgayet: argc=5 argc[0]=</home/tgayet/workspace/core_pattern_pipe_test> argc[1]=<2134> argc[2]=<UID=1000> argc[3]=<GID=1000> argc[4]=<sig=11> Total bytes in core dump: 204800  /proc/sys/kernel/core_uses_pid Depuis la version 2.4, Linux fourni une méthode permettant de contrôler le nom du fichier core dump. Si le fichier /proc/sys/kernel/core_uses_pid contient la valeur 0, les fichiers core dump seront simplement nommé « core ». Dans le cas contraire, pour toute autre valeur non nulle, le fichier core dump comprendra l'ID du processus dans un nom généré comme core.PID.  /proc/sys/fs/suid_dumpable Depuis Linux 2.6.13, la valeur de ce fichier détermine si les fichiers core dump sont produit pour set-user-ID ou autrement binaires protégés. Trois valeurs entières peuvent être spécifiées: • 0 (par défaut) Ceci fournit le comportement traditionnel (pré-Linux 2.6.13). Un core dump ne sera pas produit d'un processus qui a changé ses droits (en appelant seteuid (2), setgid (2), ou similaire, ou en exécutant un set-user-ID ou le programme set-group-ID) ou dont le binaire n'a pas l'autorisation en lecture. • 1 ("debug") tous les processus peuvent générer des core dump si possible. Le core dump aura les droits du processus ayant généré le dump. La sécurité n'est pas appliquée. Ce système est destiné aux siuations de debug. • 2 ("suidsafe") Tout binaire ne génèrons pas de core dump (voir «0» ci-dessus). S'il est généré, le code dump sera en lecture seule par root. Cela permet à l'utilisateur de le supprimer mais pas de le lire pour des raisons de sécurité des vidages de la mémoire.  /proc/<pid>/coredump_filter Quand la mémoire d'un processus est dumpé, toute la mémoire anonyme est écrite dans le fichier core tant que le fichier n'a pas atteint sa limite. Parfois, il peut être utile que certain segment de mémoire ne soient pas dumpés, par exemple avec de grosses zones de mémoires partagés. D'un autre coté, on peut vouloir sauvegarder des segments de mémoire spécifique dans le fichier core. /proc/<pid>/coredump_filter nous permet de personnaliser quel segment de mémoire doit être sauvegardé au moment de la génération d'un core dump. coredump_filter est un masque de bits des types de mémoires en charge. Si un des bits du masque est activé, le segment de mémoire correspondant est dumpé. Les 7 types de mémoires suivantes sont supportés :
  • 8. bit n°0 : mémoire anonyme privée bit n°1 : mémoire anonyme partagée bit n°2 : mémoire file-backed privée bit n°3 : mémoire file-backed partagée bit n°4: pages du header ELF dans la zone de mémoire file-backed privée (effectif seulement si le bit 2 n'est pas positionné) bit n°5 : mémoire hugetlb privée bit n°6 : mémoire hugetlb partagée A noter que les pages MMIO tel qu'un framebuffer ne sont jamais dumpés alors que le pages VDSO le sont toujours indépendamment du status du masques de bits. Les bits de 0 à 4 du masque n'ont aucun effet sur lé mémoire hugetlb qui sont plus affecté avec les bits 5 et 6. La valeur par défaut pour un core dump est 0x23 ce qui signifie que tous les segments de mémoire partagée (privée et partagé) ainsi que la mémoire hugetlb privée. Pour tout activer, il suffit de mettre tous les bits à 1 ce qui donne 0xFF : $ echo 0xF > /proc/<pid>/coredump_filter Si vous ne voulez pas dumper toute la mémoire partagée pour un processus donné dont le pid est 1234, vous pouvez changer les propriétés du processus directement : $ echo 0x21 > /proc/1234/coredump_filter Quand un nouveau processus est crée, il hérite son masque du processus parent. Il peut donc être utille de positionner coredump_filter avant de lancer un binaire : $ echo 0x7 > /proc/self/coredump_filter $ ./my_bin Pour que cette option soit présente, il faut que le noyau ait été compilé avec l'option CONFIG_ELF_CORE. 6. Tests du support des core dump Testons maintenant le bon fonctionnement de la génération d'un core dump : $ sudo mkdir -p `pwd`/cores $ sudo chmod a+rwx `pwd`/cores $ sudo echo "`pwd`/cores/core.%e.%p.%h.%t" > /proc/sys/kernel/core_pattern Écrivons un petit code de test « $ gcc -Wall -g -o coredump coredump.c » : #include <stdio.h> int main(void) { char *foo = (char*)0x12345; *foo = 'a'; return 0; } Générons le binaire à partir du code source : $ gcc -Wall -g coredump.c -o coredump Exécutons le : $ ./coredump
  • 9. Segmentation fault (core dumped) On remarque la mention entre parenthèse (core dumped) qui spécifie que le handle de signal par défaut à été activé suite à la réception d'un signal d'erreur ce qui a entraîne la génération d'un fichier core dump. Ce test est trivial, mais pour simuler la réception d'un signal d'erreur au processus ayant le PID 1234, nous aurions pu envoyer un signal à ce dernier de deux façon possible : $ kill -11 1234 ou $ kill -s SIGEGV 1234 On vérifie en effet que le fichier a bien été crée suivant le nommage et le path demandé : $ tree cores/ cores/ └── core.coredump.31788.tgayet-desktop.1375796915 0 directories, 1 file $ ls -al cores/core.coredump.31788.tgayet-desktop.1375796915 -rw------- 1 tgayet tgayet 204800 août 6 15:48 cores/core.coredump.31788.tgayet-desktop.1375796915 $ file cores/core.coredump.31788.tgayet-desktop.1375796915 cores/core.coredump.31788.tgayet-desktop.1375796915: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from './coredump' On peut même tester de le charger dans gdb : $ gdb ./coredump cores/core.coredump.31788.tgayet-desktop.1375796915 GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04 Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i686-linux-gnu". For bug reporting instructions, please see: <http://bugs.launchpad.net/gdb-linaro/>... Reading symbols from /home/tgayet/workspace/coredump...done. [New LWP 31788] warning: Can't read pathname for load map: Erreur d'entrée/sortie. Core was generated by `./coredump'. Program terminated with signal 11, Segmentation fault. #0 0x080483c4 in main () at coredump.c:6 6 *foo = 'a'; (gdb) Le debugueur gdb, nous positionne bien sur la ligne ayant généré le problème. La commande readelf nous donne quelques informations intéressantes : $ readelf --all cores/core.coredump.31788.tgayet-desktop.1375796915 ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  • 10. Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: CORE (Core file) Machine: Intel 80386 Version: 0x1 Entry point address: 0x0 Start of program headers: 52 (bytes into file) Start of section headers: 0 (bytes into file) Flags: 0x0 Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 15 Size of section headers: 0 (bytes) Number of section headers: 0 Section header string table index: 0 There are no sections in this file. There are no sections to group in this file. Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align NOTE 0x000214 0x00000000 0x00000000 0x0022c 0x00000 0 LOAD 0x001000 0x08048000 0x00000000 0x00000 0x01000 R E 0x1000 LOAD 0x001000 0x08049000 0x00000000 0x01000 0x01000 R 0x1000 LOAD 0x002000 0x0804a000 0x00000000 0x01000 0x01000 RW 0x1000 LOAD 0x003000 0xb75d6000 0x00000000 0x01000 0x01000 RW 0x1000 LOAD 0x004000 0xb75d7000 0x00000000 0x00000 0x1a3000 R E 0x1000 LOAD 0x004000 0xb777a000 0x00000000 0x02000 0x02000 R 0x1000 LOAD 0x006000 0xb777c000 0x00000000 0x01000 0x01000 RW 0x1000 LOAD 0x007000 0xb777d000 0x00000000 0x03000 0x03000 RW 0x1000 LOAD 0x00a000 0xb77a1000 0x00000000 0x02000 0x02000 RW 0x1000 LOAD 0x00c000 0xb77a3000 0x00000000 0x01000 0x01000 R E 0x1000 LOAD 0x00d000 0xb77a4000 0x00000000 0x00000 0x20000 R E 0x1000 LOAD 0x00d000 0xb77c4000 0x00000000 0x01000 0x01000 R 0x1000 LOAD 0x00e000 0xb77c5000 0x00000000 0x01000 0x01000 RW 0x1000 LOAD 0x00f000 0xbf99e000 0x00000000 0x23000 0x23000 RW 0x1000 There is no dynamic section in this file.
  • 11. There are no relocations in this file. There are no unwind sections in this file. No version information found in this file. Notes at offset 0x00000214 with length 0x0000022c: Owner Data size Description CORE 0x00000090 NT_PRSTATUS (prstatus structure) CORE 0x0000007c NT_PRPSINFO (prpsinfo structure) CORE 0x000000a0 NT_AUXV (auxiliary vector) LINUX 0x00000030 Unknown note type: (0x00000200) 7. Génération d'un core dump depuis GDB Depuis la console de gdb, il est possible de charger en dynamique un core dump. Chargeons gdb avec le binaire non strippé, c'est à dire avec ses symboles de débug et ses infos associées. Ensuite chargeons le core dump préalablement crée. Nous en générerons un autre juste après : $ gdb ./coredump GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04 Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i686-linux-gnu". For bug reporting instructions, please see: <http://bugs.launchpad.net/gdb-linaro/>... Reading symbols from /home/tgayet/workspace/coredump...done. (gdb) core cores/core.coredump.31788.tgayet-desktop.1375796915 [New LWP 31788] warning: Can't read pathname for load map: Erreur d'entrée/sortie. Core was generated by `./coredump'. Program terminated with signal 11, Segmentation fault. #0 0x080483c4 in main () at coredump.c:6 6 *foo = 'a'; (gdb) bt #0 0x080483c4 in main () at coredump.c:6 Pour demander la génération d'un core dump, il suffit de saisir la commande « generate-core- file » : (gdb) generate-core-file Saved corefile core.1282 gdb donne l'info suivante :
  • 12. (gdb) help generate-core-file Save a core file with the current state of the debugged process. Argument is optional filename. Default filename is 'core.<process_id>' 8. Accès à la RAM de Linux L'accès à la mémoire sous linux peut être utile dans certain cas. Le noyau GNU/Linux propose le device /dev/core qui est un lien symbolique vers /proc/kcore. En réalité, c'est une sorte d'alias vers la mémoire de l'ordinateur. Le fichier à la taille de la RAM physique donc peut être assez important, auquel il faut ajouter 4 ko. Le format est un fichier ELF core standard. Avec le dump mémoire globale et un noyau GNULinux non-strippé (avec ses symboles), gdb est en mesure de donner l'état du noyau incluant ses structures de données : $ sudo gdb vmlinux /proc/kcore ... snip ... (gdb) p jiffies_64 $1 = 4326692196 (gdb) 9. Problème de génération possible Il y a diverses circonstances dans lesquelles un fichier core dump peut ne pas être produit : • Le processus n'a pas la permission d'écrire le fichier core. (Par défaut, le fichier core est appelé core et est créé dans le répertoire de travail courant. Voir plus loin pour les détails de nommage du fichier.) L'écriture du fichier core échouera si le répertoire dans lequel il doit être créé n'est pas accessible en écriture, ou si un fichier du même nom existe déjà et n'est pas accessible en écriture ou si ce n'est pas un fichier régulier (par exemple, c'est un répertoire ou un lien symbolique) ; • Un fichier (régulier, accessible en écriture) avec le même nom qui serait utilisé pour le fichier core existe déjà, mais il y a plus d'un lien matériel vers ce fichier ; • Le système de fichiers où le fichier core devrait être créé est plein ; ou n'a plus d'i-noeud ; ou est monté en lecture seule ; ou l'utilisateur a atteint son quota dans le système de fichiers ; • Le répertoire dans lequel le fichier core dump doit être créé n'existe pas ; • Le fichier core_pattern nomme un répertoire ou un fichier existant sur lequel on n'a pas la permission d'écriture ; • Les limites de ressources RLIMIT_CORE ou RLIMIT_FSIZE pour un processus valent zéro ; • Le binaire devant être exécuté par le processus n'a pas la permission de lecture ; • Le processus exécute un programme Set-UID (Set-GID) qui appartient à un utilisateur /dev/core /proc/core
  • 13. (groupe) autre que l'UID (GID) réel du processus. Il faut voir la description PR_SET_DUMPABLE de prctl(2) ainsi que /proc/sys/fs/suid_dumpable dans proc(5). 10. Remarques Si un processus multithread ou, plus précisément, un processus qui partage sa mémoire avec un autre processus qui a été créé avec l'attribut CLONE_VM de clone(2) créé un fichier core dump, le PID est toujours ajouté au nom du fichier core, à moins que le PID ne soit déjà inclus quelque part dans le nom de fichier via une spécification %p dans /proc/sys/kernel/core_pattern. Malheureusement, si votre application est équipé d'un gestionnaire de signaux personnalisée, aucun core dump ne sera généré, car ils sont générés uniquement par les gestionnaires de signaux par défaut. L'appel au gestionnaire par défaut peut être sollicité à la fin du handle de signal, mais sans que cela soit puisse suffire. Il vaut mieux en effet restaurer le gestionnaire personnalisé en phase de débug. 11. Conclusion Avec les core dump, nous voilà muni d'un outil de choix, permettant d'investiguer en cas de crash. 12. Liens • http://man7.org/linux/man-pages/man5/core.5.html • http://www.bottomupcs.com/elf.html#coredump_gdb • http://linux.die.net/man/5/proc • http://www.linuxcertif.com/man/7/signal/ • http://www.linuxcertif.com/man/5/core/ • http://www.linuxcertif.com/man/1/gdb/ • http://www.linuxcertif.com/man/2/getrlimit/ • http://web.cecs.pdx.edu/~jrb/ui/linux/driver4.txt • https://www.kernel.org/doc/Documentation/filesystems/proc.txt