2010-08-01 24 views
2

Dans un programme C, j'ai besoin de réinitialiser toutes les variables globales telles qu'elles étaient lorsque le programme démarre à des fins de test. Je souhaite reproduire la copie de données de Load Memory Address, LMA à VMA (adresse d'exécution) effectuée par les bibliothèques GCC avec une fonction de réinitialisation. Par exemple, si les variables foo sont déclarées comme globales et initialisées. Et si ma fonction de réinitialisation est re_init():Experts - GCC et ld linker: réinitialisation des variables contenues dans la section .data?

#include <stdio.h> 
int foo1 = 42; 
int foo2 = 777; 

int main(){ 
    foo1 = 0; 
    foo2 = 0; 
    re_init(); 
    printf("foo1:%d and foo2:%d",foo1,foo2); 
    return 0; 
} 

alors je veux avoir en sortie:

foo1:42 and foo2:777 

Je crois que la bonne façon de le faire est le fichier de liaison par défaut et peut-être le code de démarrage qui copie les valeurs d'initiation à la RAM. Donc, avec GCC (cygwin), que dois-je faire pour y parvenir?

Edit: Cette page semble o avoir plus de précision sur elle: http://sources.redhat.com/binutils/docs-2.12/ld.info/Output-Section-LMA.html#Output%20Section%20LMA

Répondre

3

Je ne sais pas exactement comment Cygwin fait cela, mais en général, la section de données ne sont pas copiées de son LMA à sa VMA; au lieu de cela, le fragment pertinent du fichier exécutable est mappé en mémoire dans la RAM au niveau du VMA souhaité par le noyau, puis le lieur dynamique exécute toutes les relocalisations qui pointent sur la section de données.

Pour réinitialiser la section de données à partir du contenu de l'exécutable, par conséquent, vous devrez dupliquer assez de l'éditeur de liens dynamique et du chargeur exécutable côté noyau pour: trouver le fichier exécutable (ce n'est pas forcément argv [ 0]); analyser ses en-têtes et localiser la section de données; détruire l'ancienne cartographie et la recréer au VMA approprié; effectuer à nouveau toutes les délocalisations; et ensuite gérer toutes les retombées causées par le fait d'avoir arraché l'état d'exécution de la bibliothèque C (ce n'est pas seulement vos propres variables globales dans la section données, les choses comme les tables d'allocation maître stdout et malloc sont également présentes).

Faites des recherches sur "unexec" et "undump", qui résolvent un problème similaire (mais pas le même), qui pourrait vous donner du code que vous pouvez recycler.

+0

Zack avait plus de voix: réponse acceptée. J'apprécierais une réponse aussi claire que Steven Schlansker cependant. – djondal

2

Le chemin que vous empruntez est rempli de problèmes de portabilité, de bugs et de tristesse.

La meilleure façon de résoudre ce problème: les globales sont mauvaises! Je factoriserais tout mon code pour stocker l'état dans une structure "context", qui est transmise. Ainsi, la réinitialisation de l '"état" ne fait que fabriquer une nouvelle structure "contextuelle".

+0

Et la tristesse ... Intéressant! – djondal

+0

Je deviens triste juste à y penser! :-p –

0

Voici une autre idée de solution, même si je pense toujours que l'élimination de l'état global est meilleure.

Définir vos globals dans un fichier d'en-tête via des macros:

globals.h:

DEFINE_GLOBAL(int, foo, 5); 
DEFINE_GLOBAL(char, bar, 'x'); 

main.c:

#include <stdio.h> 

#define DEFINE_GLOBAL(type, name, initialvalue) type name = initialvalue 
#include "globals.h" 
#undef DEFINE_GLOBAL 

void resetState() { 
    #define DEFINE_GLOBAL(type, name, initialvalue) name = initialvalue 
    #include "globals.h" 
    #undef DEFINE_GLOBAL 
} 

Je n'ai pas testé, il peut-être besoin d'une correction de la syntaxe - mais je pense que le concept est solide.

+0

Je suis d'accord que l'état global est un autre nom pour la douleur et la souffrance au niveau de la qualité du code. C'est le concept anti-encapsulation. Mais je ne traite pas de la conception de quelqu'un d'autre ici ... Malheureusement, j'ai des centaines de variables globales à ré-initialiser. – djondal

+0

Peut-être que vous pourriez écrire un script rapide pour lire dans les fichiers et cracher les commandes de réinitialisation appropriées? c'est-à-dire, rechercher toutes les variables globales et générer une fonction pour toutes les réinitialiser? –