Erreur de bus lors de la recompilation du fichier binary

Parfois, sur différentes architectures Unix, la recompilation d’un programme en cours d’exécution provoque le blocage du programme avec une “erreur de bus”. Quelqu’un peut-il expliquer dans quelles conditions cela se produit? Tout d’abord, comment la mise à jour du fichier binary sur le disque peut-elle modifier le code en mémoire? La seule chose que je peux imaginer est que certains systèmes mappent le code en mémoire et que, lorsque le compilateur réécrit l’image du disque, cela entraîne la non-validité de mmap. Quels seraient les avantages d’une telle méthode? Il semble très déconseillé de pouvoir planter des codes en cours d’exécution en modifiant l’exécutable.

Sur les systèmes de fichiers locaux, tous les principaux systèmes Unix-like prennent en charge la résolution de ce problème en supprimant le fichier. L’ancien vnode rest ouvert et, même après la disparition de l’entrée de répertoire et sa réutilisation pour la nouvelle image, l’ancien fichier est toujours là, inchangé, et maintenant sans nom, jusqu’à ce que la dernière référence (dans ce cas le kernel) disparaisse .

Mais si vous commencez à le réécrire, alors oui, c’est mmap (3) ‘ed. Lorsque le bloc est réécrit, deux choses peuvent se produire selon les options mmap (3) utilisées par l’éditeur de liens dynamics:

  1. le kernel invalidera la page correspondante, ou
  2. l’image disque changera mais les pages mémoire existantes ne

De toute façon, le programme en cours d’exécution est peut-être en difficulté. Dans le premier cas, il est garanti de faire sauter, et dans le second cas, il sera détruit à moins que toutes les pages aient été référencées, insérées dans la page et ne soient jamais supprimées.

Il y avait deux drapeaux mmap destinés à résoudre ce problème. L’une était MAP_DENYWRITE (empêcher les écritures) et l’autre était MAP_COPY, qui conservait une version pure de l’original et empêchait les auteurs de modifier l’image mappée.

Mais DENYWRITE a été désactivé pour des raisons de sécurité et COPY n’est pas implémenté dans les principaux systèmes Unix.

Eh bien, c’est un scénario un peu complexe qui pourrait se produire dans votre cas. La raison de cette erreur est normalement le problème d’alignement de la mémoire. L’erreur de bus est plus commune au système basé sur FreeBSD. Considérez un scénario que vous avez une structure quelque chose comme,

struct MyStruct {char ch [29]; // 29 octets int32 i; // 4 octets }

La taille totale de cette structure serait donc de 33 octets. Considérons maintenant un système où vous avez des lignes de cache de 32 octets. Cette structure ne peut pas être chargée dans une seule ligne de cache. Considérons maintenant les déclarations suivantes

Struct MyStruct abc; char * cptr = & abc; // charte les points au début de la structure int32 * iptr = (cptr + 1) // les points iptr au deuxième octet de la structure.

Maintenant, la taille totale de la structure est de 33 octets, car votre pointeur int pointe sur le deuxième octet. Vous pouvez donc lire les données à 32 octets depuis le pointeur int (car la taille totale de la mémoire allouée est de 33 octets). Mais lorsque vous essayez de le lire et si la structure est allouée à la limite d’une ligne de cache, il n’est pas possible pour le système d’exploitation de lire 32 octets en un seul appel. La ligne de cache actuelle ne contenant que 31 octets de données et les 1 octets restants se trouvant sur la ligne de cache suivante. Cela se traduira par une adresse invalide et donnera “erreur de bus”. La plupart des systèmes d’exploitation gèrent ce scénario en générant deux appels de lecture en mémoire en interne, mais certains systèmes Unix ne gèrent pas ce scénario. Pour éviter cela, il est recommandé de prendre soin de l’alignement de la mémoire. La plupart du temps, ce scénario se produit lorsque vous essayez de taper une structure dans un autre type de données et d’essayer de lire la mémoire de cette structure.

Le scénario est un peu complexe, donc je ne suis pas sûr de pouvoir l’expliquer plus simplement. J’espère que vous comprenez le scénario.