gcc héritage compilateur émet
-
13-09-2019 - |
Question
Nous utilisons un compilateur héritage, basé sur gcc 2.6.0, pour une compilation croisée pour un vieux processeur incrustée nous utilisons toujours (oui, il est encore en usage depuis 1994!). L'ingénieur qui a fait le port gcc pour cette puce a depuis longtemps évolué. Bien que nous pourrions être en mesure de récupérer la source gcc 2.6.0 de quelque part sur le web, le jeu de changement pour cette puce a
disparu dans les couloirs de l'histoire de l'entreprise. Nous avons embrouillé le long jusqu'à récemment que le compilateur a couru encore et produit executables réalistes, mais à partir du noyau linux 2.6.25 (et 2.6.26), il échoue avec le message gcc: virtual memory exhausted
... même lorsqu'il est exécuté sans paramètre ou avec seulement -v
. J'ai redémarré mon système de développement (à partir 2.6.26) en utilisant le noyau 2.6.24 et le compilateur fonctionne à nouveau (avec le redémarrage 2.6.25 ne fonctionne pas).
Nous avons un système que nous gardons à 2.6.24 juste pour le but de faire construit pour cette puce, mais se sentent un peu exposée au cas où le monde linux passe au point que nous ne pouvons plus longtemps reconstruire un système qui exécutera le compilateur (ie notre système 2.6.24 meurt et nous ne pouvons pas obtenir 2.6.24 pour installer et exécuter sur un nouveau système, car certaines des parties de logiciels ne sont plus disponibles).
Est-ce que quelqu'un a des idées pour ce que nous pourrions être en mesure de le faire à une installation plus moderne pour obtenir ce compilateur héritage à exécuter?
Modifier :
Pour répondre à certains des commentaires ...
Malheureusement, ce sont les changements de code source qui sont spécifiques à notre puce qui sont perdus. Cette perte a eu lieu sur deux grandes reorgs de l'entreprise et plusieurs administrateurs système (deux ou trois qui a vraiment laissé un gâchis). Nous utilisons maintenant le contrôle de configuration, mais ferme la porte de la grange trop tard pour ce problème.
L'utilisation d'une machine virtuelle est une bonne idée, et peut-être ce que nous finissons par faire. Je vous remercie de cette idée.
Enfin, j'ai essayé strace comme ephemient suggéré et a constaté que le dernier appel système a été BRK () qui a renvoyé une erreur sur le nouveau système (noyau 2.6.26) et retourné succès sur l'ancien système (noyau 2.6.24). Cela indiquerait que je suis vraiment à court de mémoire virtuelle, sauf que tcsh « limite » renvoie les mêmes valeurs sur les systèmes anciens et nouveaux, et / proc / meminfo montre les nouveaux systèmes a un peu plus de mémoire et un peu plus d'espace d'échange. Peut-être qu'il est un problème de fragmentation ou lorsque le programme est en cours de chargement?
Je l'ai fait quelques recherches et « randomization BRK » a été ajouté dans le noyau 2.6.25, mais CONFIG_COMPAT_BRK
est censé être activé par défaut (ce qui désactive randomization BRK).
Modifier :
OK, plus d'informations: Il ressemble vraiment randomization BRK est le coupable, l'héritage gcc appelle BRK () pour changer la fin du segment de données et qui ne maintenant, ce qui provoque l'gcc héritage à signaler « mémoire virtuelle épuisée ». Il existe quelques moyens documentés pour désactiver randomization BRK:
-
sudo echo 0 > /proc/sys/kernel/randomize_va_space
-
sudo sysctl -w kernel.randomize_va_space=0
-
Démarrage d'une nouvelle coque avec
setarch i386 -R tcsh
(ou "-R -L")
Je les ai essayé et ils semblent avoir un effet en ce que la valeur de retour BRK () est différent (et toujours le même) que sans eux (essayé à la fois le noyau 2.6.25 et 2.6.26), mais le BRK () échoue encore si le gcc héritage ne parvient toujours pas :-(.
En outre, j'ai mis vm.legacy_va_layout=1
et vm.overcommit_memory=2
sans changement, et je l'ai redémarré avec les paramètres de vm.legacy_va_layout=1
et kernel.randomize_va_space=0
enregistrés dans /etc/sysctl.conf. Toujours pas de changement.
Modifier :
Utilisation kernel.randomize_va_space=0
sur le noyau 2.6.26 (et 2.6.25) les résultats de l'appel étant rapporté par strace legacy-gcc
BRK () suivant:
brk(0x80556d4) = 0x8056000
Ceci indique la BRK () a échoué, mais il semble que cela a échoué car le segment de données se termine déjà au-delà de ce qui a été demandé. En utilisant objdump, je peux voir le segment de données devrait se terminer à 0x805518c alors que le BRK a échoué () indicates que le segment de données se termine actuellement à 0x8056000:
Sections: Idx Name Size VMA LMA File off Algn 0 .interp 00000013 080480d4 080480d4 000000d4 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 1 .hash 000001a0 080480e8 080480e8 000000e8 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 2 .dynsym 00000410 08048288 08048288 00000288 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 3 .dynstr 0000020e 08048698 08048698 00000698 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 4 .rel.bss 00000038 080488a8 080488a8 000008a8 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 5 .rel.plt 00000158 080488e0 080488e0 000008e0 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 6 .init 00000008 08048a40 08048a40 00000a40 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 7 .plt 000002c0 08048a48 08048a48 00000a48 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 8 .text 000086cc 08048d10 08048d10 00000d10 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 9 .fini 00000008 080513e0 080513e0 000093e0 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 10 .rodata 000027d0 080513e8 080513e8 000093e8 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 11 .data 000005d4 08054bb8 08054bb8 0000bbb8 2**2 CONTENTS, ALLOC, LOAD, DATA 12 .ctors 00000008 0805518c 0805518c 0000c18c 2**2 CONTENTS, ALLOC, LOAD, DATA 13 .dtors 00000008 08055194 08055194 0000c194 2**2 CONTENTS, ALLOC, LOAD, DATA 14 .got 000000b8 0805519c 0805519c 0000c19c 2**2 CONTENTS, ALLOC, LOAD, DATA 15 .dynamic 00000088 08055254 08055254 0000c254 2**2 CONTENTS, ALLOC, LOAD, DATA 16 .bss 000003b8 080552dc 080552dc 0000c2dc 2**3 ALLOC 17 .note 00000064 00000000 00000000 0000c2dc 2**0 CONTENTS, READONLY 18 .comment 00000062 00000000 00000000 0000c340 2**0 CONTENTS, READONLY SYMBOL TABLE: no symbols
Modifier :
Pour faire écho à la remarque de ephemient ci-dessous: « si étrange pour traiter GCC comme binaire sans source »
Ainsi, en utilisant strace, objdump, gdb et ma compréhension limitée de 386 assembleur et l'architecture que j'ai tracé le problème au 1er appel malloc dans le code existant. Les appels gcc héritage malloc, qui renvoie NULL, qui se traduit par le message « mémoire virtuelle épuisé » sur stderr. Ce malloc est en libc.so.5, et il appelle getenv un tas de fois et finit par BRK () appelle ... Je suppose que d'augmenter le tas ... qui échoue.
De cela, je ne peux que supposer que le problème est plus randomization BRK, ou je n'ai pas randomization BRK totalement invalide, malgré les randomize_va_space = 0 et legacy_va_layout = 1 paramètres sysctl.
La solution
Installer linux + l'ancien gcc sur une machine virtuelle.
Autres conseils
Avez-vous des sources pour ce compilateur personnalisé? Si vous pouvez récupérer la ligne de base 2.6.0 (et qui devrait être relativement facile), puis diff et patch devrait récupérer votre jeu de changement.
Qu'est-ce que je recommande donc utilise ce changement pour construire une mis en nouvelle version contre à jour gcc. ET PUIS METTEZ SOUS CONTRÔLE DE CONFIGURATION.
Désolé, ne signifie pas crier. Il est juste que j'ai dit la même chose pour la plupart de 30 ans.
Pouvez-vous strace
l'exécutable gcc-2.6.0
? Il peut faire quelque chose comme la lecture /proc/$$/maps
, et se confondre lorsque les changements de sortie de manière insignifiante. Un problème similaire était récemment remarqué entre 2.6.28 et 2.6.29.
Si oui, vous pouvez pirater /usr/src/linux/fs/proc/task_mmu.c
ou à peu près à restaurer l'ancienne sortie, ou mettre en place une $LD_PRELOAD
à gcc
faux dans la lecture d'un autre fichier.
Modifier
Puisque vous avez mentionné brk
...
CONFIG_COMPAT_BRK
rend le kernel.randomize_va_space=1
par défaut au lieu de 2
, mais encore tout autre randomizes que le tas (brk
).
Voyez si votre problème disparaît si vous echo 0 > /proc/sys/kernel/randomize_va_space
ou sysctl kernel.randomize_va_space=0
(équivalent).
Si, ajoutez kernel.randomize_va_space = 0
à /etc/sysctl.conf
ou ajouter norandmaps
à la ligne de commande du noyau (équivalent), et être heureux à nouveau.
Je suis tombé sur cette et pensé à votre problème . Peut-être que vous pouvez trouver un moyen de jouer avec le binaire pour le déplacer vers le format ELF? Ou peut-être il est hors de propos, mais jouer avec objdump peut vous fournir plus d'informations.
Pouvez-vous jeter un oeil à la carte mémoire du processus?
Je travaille quelque chose ... ce n'est pas une solution complète, mais il ne se passé le problème d'origine, j'ai eu avec le gcc héritage.
Mettre des points d'arrêt à chaque appel libc dans le .plt (tableau de liaison de procédure) Je vois que malloc (en libc.so.5) appelle getenv () pour obtenir:
MALLOC_TRIM_THRESHOLD_ MALLOC_TOP_PAD_ MALLOC_MMAP_THRESHOLD_ MALLOC_MMAP_MAX_ MALLOC_CHECK_
Je web et a trouvé ces cherchai cette qui a conseillé
setenv MALLOC_TOP_PAD_ 536870912
alors le gcc héritage WORKS !!!!
Mais pas à la maison libre, il se leva sur le lien dans la construction avant d'échouer, donc il y a quelque chose d'aller plus loin avec la NLD, nous avons :-( héritage Il rapporte:
Virtual memory exceeded in `new'
Dans /etc/sysctl.conf je:
kernel.randomize_va_space=0 vm.legacy_va_layout=1
Il fonctionne toujours le même si
kernel.randomize_va_space=1 vm.legacy_va_layout=0
mais pas si
kernel.randomize_va_space=2
Il a été suggéré d'utiliser « ldd » pour voir les dépendances des bibliothèques partagées:.. Gcc héritage n'a besoin que libc5, mais le NLD héritage doit également libg ++ so.27, libstdc ++ so.27, et libm.so.5 apparemment, il y a une version libc5 de libg ++. so.27 (libg ++ 27 altdev ??) Qu'en est-libc5-compat?
Alors, comme je le disais, pas encore la maison sans ... se rapprocher. Je vais probablement poster une nouvelle question sur le problème NLD.
Modifier :
J'allais d'abord à ne pas « accepter » cette réponse car il me reste encore un problème avec l'éditeur de liens existants correspondant, mais pour obtenir une finalité sur cette question au moins, je repense cette position.
Merci-toi aller vers:
- an0nym0usc0ward pour la suggestion d'utiliser une machine virtuelle (qui peut finalement devenir la réponse acceptée)
- ephemient pour suggérer en utilisant strace, et aider à l'utilisation stackoverflow
- shodanex pour suggérer à l'aide objdump
Modifier
Voici la dernière des choses que j'ai appris, et maintenant je vais accepter la solution VM puisque je ne pouvais pas résoudre pleinement d'une autre manière (au moins dans le temps imparti pour cela).
Les nouveaux noyaux ont un drapeau de construction de CONFIG_COMPAT_BRK pour permettre libc5 à utiliser, on peut donc supposer la construction d'un nouveau noyau avec ce drapeau va résoudre le problème (et en regardant à travers le src du noyau, il semble que ce sera, mais je ne peux pas être sûr puisque je ne l'ai pas suivi tous les chemins). Il y a aussi une autre façon documentée pour permettre l'utilisation libc5 lors de l'exécution (plutôt que lors de la compilation du noyau): sudo sysctl -w kernel.randomize_va_space = 0. Cela fait cependant pas faire un travail complet et certains (la plupart?) des applications libc5 vont encore se briser, par exemple notre compilateur héritage et éditeur de liens. Cela semble être dû à une différence dans les hypothèses d'alignement entre les nouveaux noyaux et plus. J'ai patché le binaire éditeur de liens pour faire croire qu'il a une plus grande section bss, afin d'amener la fin de la bss jusqu'à une limite de page, et cela fonctionne sur le nouveau noyau lorsque le sysctl var kernel.randomize_va_space = 0. Ce n'est pas une solution satisfaisante pour moi depuis que je suis ragréage à l'aveuglette un exécutable binaire critique, et même si l'exécution de l'éditeur de liens patché sur le nouveau noyau produit une sortie identique bit à la piste de liaison d'origine sur le noyau plus ancien, qui ne prouve pas que une autre entrée de liaison (autrement dit, nous changeons le programme étant lié) produira également des résultats identiques.
Pouvez-vous pas simplement faire une image de disque qui peut être réinstallé si le système meurt? ou faire une machine virtuelle?