problemi di compilatore gcc legacy
-
13-09-2019 - |
Domanda
Stiamo usando un compilatore eredità, sulla base di gcc 2.6.0, per attraversare compilare per un vecchio processore di piani integrati stiamo ancora usando (sì, è ancora in uso dal 1994!). L'ingegnere che ha fatto la porta gcc per questo chip è da tempo andato avanti. Anche se potremmo essere in grado di recuperare l'origine gcc 2.6.0 da qualche parte sul web, il set di cambiamento per questo chip ha
scomparso nelle sale di storia aziendale. Abbiamo confuso insieme fino a poco tempo come il compilatore ancora correva e prodotto eseguibili praticabili, ma a partire dal kernel Linux 2.6.25 (e anche 2.6.26) non riesce con il messaggio gcc: virtual memory exhausted
... anche quando eseguito senza parametri o solo con -v
. Ho ripartito il mio sistema di sviluppo (dal 2.6.26) usando il kernel 2.6.24 e il compilatore funziona di nuovo (riavvio con 2.6.25 non fa).
Abbiamo un sistema che stiamo mantenendo al 2.6.24 solo per lo scopo di fare costruisce per questo chip, ma si sentono un po 'esposto nel caso in cui il mondo Linux si muove al punto che non possiamo più ricostruire un sistema che verrà eseguito il compilatore (ad esempio il nostro sistema 2.6.24 muore e non possiamo ottenere 2.6.24 per installare ed eseguire su un nuovo sistema, perché alcune delle parti del software non sono più disponibili).
Qualcuno ha qualche idea per quello che potremmo essere in grado di fare per un impianto più moderno per ottenere questo compilatore eredità di correre?
Modifica :
Per rispondere ad alcune delle commenti ...
Purtroppo sono le modifiche al codice sorgente che sono specifici per il nostro chip che si perdono. Questa perdita si è verificato più di due importanti reorgs aziendali e diversi amministratori di sistema (un paio di che in realtà lasciato un pasticcio). Ora usiamo controllo della configurazione, ma che sta chiudendo la porta della stalla troppo tardi per questo problema.
L'uso di una VM è una buona idea, e può essere ciò che si finisce per fare. Grazie per questa idea.
Infine, ho provato strace come ephemient suggerito e ha scoperto che l'ultima chiamata di sistema è stato BRK (), che ha restituito un errore sul nuovo sistema (2.6.26 del kernel) e restituito il successo sul vecchio sistema (2.6.24 del kernel). Ciò indicherebbe che io davvero sono a corto di memoria virtuale, se non che tcsh "limite" restituisce gli stessi valori sui sistemi vecchi e nuovi, e / proc / meminfo mostra i nuovi sistemi ha un po 'più di memoria e un bel spazio di swap' di più. Forse è un problema di frammentazione o dove il programma viene caricata?
Ho fatto qualche ulteriore ricerca e "brk randomizzazione" è stato aggiunto nel kernel 2.6.25, tuttavia CONFIG_COMPAT_BRK
è presumibilmente attivata per impostazione predefinita (che disabilita BRK randomizzazione).
Modifica :
OK, ulteriori informazioni: Sembra veramente BRK randomizzazione è il colpevole, il gcc legacy sta chiamando BRK () per modificare la fine del segmento di dati e che ora non riesce, causando il gcc legacy a riferire "memoria virtuale esaurita". Ci sono alcuni modi per disabilitare documentati BRK randomizzazione:
-
sudo echo 0 > /proc/sys/kernel/randomize_va_space
-
sudo sysctl -w kernel.randomize_va_space=0
-
iniziare una nuova shell con
setarch i386 -R tcsh
(o "-R -L")
li ho provato e che sembrano avere un effetto in quanto il valore di ritorno brk () è diverso (e sempre lo stesso) che senza di loro (provato sia su kernel 2.6.25 e 2.6.26), ma il brk () non riesce ancora così l'eredità gcc non riesce ancora :-(.
Inoltre ho impostato vm.legacy_va_layout=1
e vm.overcommit_memory=2
senza alcun cambiamento, e ho riavviato con le impostazioni vm.legacy_va_layout=1
e kernel.randomize_va_space=0
salvati in /etc/sysctl.conf. Ancora nessun cambiamento.
Modifica :
Utilizzando kernel.randomize_va_space=0
sul kernel 2.6.26 (e 2.6.25) genera il seguente brk () chiamata viene riportato da strace legacy-gcc
:
brk(0x80556d4) = 0x8056000
Indica il brk () fallito, ma sembra che non è riuscito perché il segmento dei dati si conclude già al di là di ciò che è stato richiesto. Utilizzando objdump, posso vedere il segmento di dati dovrebbe finire al 0x805518c mentre il BRK fallito () indicates che il segmento dati attualmente termina a 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
Modifica :
Per eco il commento di ephemient di seguito: "così strano per il trattamento di GCC come un binario senza fonte"
Quindi, usando strace, objdump, gdb e la mia comprensione limitata di 386 assembler e architettura ho tracciato il problema alla chiamata malloc prima nel codice legacy. Le chiamate eredità gcc malloc, che restituisce NULL, che si traduce nel messaggio "memoria virtuale esaurito" su stderr. Questo malloc è in libc.so.5, e chiama getenv un mucchio di volte e finisce brk chiamando il numero () ... Credo che per aumentare l'heap ... che non riesce.
Da questo posso solo supporre che il problema è più di brk randomizzazione, o non ho completamente disabilitata brk randomizzazione, nonostante le randomize_va_space = 0 e legacy_va_layout = 1 sysctl impostazioni.
Soluzione
Installa linux + il vecchio gcc su una macchina virtuale.
Altri suggerimenti
Avete fonti di questo compilatore personalizzato? Se è possibile ripristinare il 2.6.0 della linea di base (e che dovrebbe essere relativamente facile), quindi diff e patch dovrebbe recuperare il set di cambiamento.
Da allora mi piacerebbe consiglio è che il cambiamento utilizzando set di costruire una nuova versione contro aggiornata gcc. E poi metterlo SOTTO CONTROLLO CONFIGURAZIONE.
Siamo spiacenti, non intendo gridare. E 'solo che ho detto la stessa cosa per la maggior parte dei 30 anni.
Si può strace
l'eseguibile gcc-2.6.0
? Si può fare qualcosa di simile lettura /proc/$$/maps
, e ottenere confusi quando le variazioni di uscita in modo insignificante. Un problema simile è stato recentemente notato tra 2.6.28 e 2.6.29.
Se è così, è possibile hack /usr/src/linux/fs/proc/task_mmu.c
o giù di lì per ripristinare la vecchia uscita, o impostare alcune $LD_PRELOAD
a gcc
falso nella lettura un altro file.
Modifica
Dal momento che lei ha citato brk
...
CONFIG_COMPAT_BRK
rende il kernel.randomize_va_space=1
di default al posto di 2
, ma che rende casuale ancora tutto diverso dal mucchio (brk
).
vedere se il problema va via se echo 0 > /proc/sys/kernel/randomize_va_space
o sysctl kernel.randomize_va_space=0
(equivalente).
Se è così, aggiungi kernel.randomize_va_space = 0
a /etc/sysctl.conf
o aggiungere norandmaps
alla linea di comando del kernel (equivalente), ed essere di nuovo felice.
Mi sono imbattuto in questo e pensato circa il tuo problema . Può essere che si può trovare un modo per giocare con il binario per spostarlo in formato ELF? O può essere è irrilevante, ma giocare con objdump in grado di fornire ulteriori informazioni.
Si può avere uno sguardo alla mappa di memoria processo?
Così ho lavorato qualcosa ... non è una soluzione completa, ma non andare oltre il problema originale che ho avuto con il gcc legacy.
Mettere punti di interruzione su ogni chiamata libc nella .plt (tabella di linkage procedura) Vedo che malloc (in libc.so.5) chiama getenv () per ottenere:
MALLOC_TRIM_THRESHOLD_ MALLOC_TOP_PAD_ MALLOC_MMAP_THRESHOLD_ MALLOC_MMAP_MAX_ MALLOC_CHECK_
Così ho cercato sul web questi e trovato questo che ha consigliato
setenv MALLOC_TOP_PAD_ 536870912
poi il gcc eredità FUNZIONA !!!!
Ma non a casa gratuitamente, si alzò per il collegamento nella build prima di guastarsi, quindi c'è qualcosa ulteriormente andando avanti con la NLD eredità che abbiamo :-( Si riporta:
Virtual memory exceeded in `new'
In /etc/sysctl.conf ho:
kernel.randomize_va_space=0 vm.legacy_va_layout=1
Ancora funziona lo stesso se
kernel.randomize_va_space=1 vm.legacy_va_layout=0
, ma non se
kernel.randomize_va_space=2
C'è stato un suggerimento di usare "ldd" per vedere le dipendenze delle librerie condivise:.. Il gcc eredità bisogno solo libc5, ma la NLD eredità ha bisogno anche libg ++ so.27, libstdc ++ so.27, libm.so.5 e a quanto pare c'è una versione libc5 di libg ++. so.27 (lIBG ++ 27-altdev ??) e che dire di libc5-compat?
Quindi, come ho detto, non ancora a casa gratis ... essere sempre più vicino. Io probabilmente pubblicare una nuova domanda sul problema NLD.
Modifica :
Mi è stato originariamente intenzione di astenersi dal "Accettare" questa risposta dal momento che ho ancora un problema con il corrispondente linker eredità, ma al fine di ottenere qualche definitivo su questa questione, almeno, sto ripensare quella posizione.
ringraziamento di uscire a:
- an0nym0usc0ward per il suggerimento di utilizzare una macchina virtuale (che può in ultima analisi, diventare la risposta accettata)
- ephemient per suggerire usando strace, e aiutare con l'utilizzo StackOverflow
- shodanex per suggerire utilizzando objdump
Modifica
Di seguito è riportato l'ultima roba che ho imparato, e ora mi accetterà la soluzione VM perché non ho potuto pienamente risolverlo qualsiasi altro modo (almeno nel tempo previsto per questo).
I kernel più recenti hanno una bandiera CONFIG_COMPAT_BRK build per consentire libc5 da utilizzare, quindi presumibilmente la costruzione di un nuovo kernel con questo flag risolverà il problema (e guardando attraverso lo src kernel, sembra che lo farà, ma non posso essere sicuro dal momento che non ho seguito tutti i percorsi). C'è anche un altro modo documentato per permettere l'uso libc5 in fase di esecuzione (piuttosto che al kernel tempo di costruzione): sudo sysctl -w kernel.randomize_va_space = 0. Questo, però fa Non fare un lavoro completo e alcuni (la maggior parte?) app libc5 saranno ancora rompere, per esempio il nostro compilatore e linker legacy. Questo sembra essere dovuto a una differenza di ipotesi di allineamento tra i kernel più recenti e meno recenti. Ho patchato il binario linker per farlo pensare che ha una sezione BSS più grande, al fine di portare alla fine del BSS fino a un limite di pagina, e questo funziona sul più recente kernel quando lo sysctl var kernel.randomize_va_space = 0. Questa non è una soluzione soddisfacente per me dal momento che sto ciecamente patching un binario eseguibile critica, e anche se l'esecuzione del linker patch sul kernel più recenti ha prodotto un'uscita bit-identico alla corsa linker originale sul kernel più vecchie, che non prova che qualche altro ingresso linker (cioè si cambia il programma essendo legato) produrrà anche risultati identici.
Potrebbe non semplicemente fare un'immagine disco che può essere re-installato se il sistema muore? o fare una VM?