Legacy-GCC-Compiler-Probleme

7

Wir verwenden einen Legacy-Compiler, der auf gcc 2.6.0 basiert, um einen alten eingebetteten Prozessor zu kompilieren, den wir immer noch benutzen (ja, er wird noch seit 1994 verwendet!). Der Ingenieur, der den gcc port für diesen Chip gemacht hat, ist schon lange weiter. Obwohl wir in der Lage sein könnten, die gcc 2.6.0 Quelle von irgendwo im Web wiederherzustellen, hat die für diesen Chip gesetzte Änderung verschwand in den Hallen der Unternehmensgeschichte. Wir haben uns bis vor kurzem durchgewühlt, da der Compiler noch lief und ausführbare ausführbare Dateien erzeugte, aber ab Linux Kernel 2.6.25 (und auch 2.6.26) schlägt er mit der Nachricht gcc: virtual memory exhausted ... fehl, auch wenn er ohne Parameter oder mit nur -v . Ich habe mein Entwicklungssystem (ab 2.6.26) mit dem Kernel 2.6.24 neu gestartet und der Compiler funktioniert wieder (Neustart mit 2.6.25 funktioniert nicht).

Wir haben ein System, das wir bei 2.6.24 behalten, nur um Builds für diesen Chip zu machen, fühlen uns aber ein wenig exponiert, falls die Linux-Welt sich so weit entwickelt, dass wir ein System nicht mehr aufbauen können das wird den Compiler laufen lassen (dh unser 2.6.24 System stirbt und wir können 2.6.24 nicht installieren und auf einem neuen System laufen lassen, weil einige der Softwareteile nicht mehr verfügbar sind).

Hat jemand irgendwelche Ideen, was wir mit einer moderneren Installation machen könnten, um diesen Legacy-Compiler zu starten?

Bearbeiten :

Um einige der Kommentare zu beantworten ...

Leider sind es die Quellcodeänderungen, die spezifisch für unseren Chip sind, die verloren gegangen sind. Dieser Verlust ereignete sich über zwei große Unternehmen Reorgs und mehrere Systemadministratoren (von denen einige wirklich ein Durcheinander hinterlassen). Wir benutzen jetzt die Konfigurationskontrolle, aber das schließt das Scheunentor zu spät für dieses Problem.

Die Verwendung einer virtuellen Maschine ist eine gute Idee und möglicherweise das, was wir letztendlich tun. Danke für diese Idee.

Schließlich habe ich strace wie vorgeschlagen vorgeschlagen und festgestellt, dass der letzte Systemaufruf war brk (), der einen Fehler auf dem neuen System (2.6.26 Kernel) zurückgegeben und Erfolg auf dem alten System (2.6.24 Kernel) zurückgegeben. Dies würde bedeuten, dass mir wirklich der virtuelle Speicher ausgeht, außer dass tcsh "limit" die gleichen Werte auf alten und neuen Systemen zurückgibt und / proc / meminfo zeigt, dass das neue System etwas mehr Speicher und etwas mehr Auslagerungsspeicher hat. Vielleicht ist es ein Problem der Fragmentierung oder wo wird das Programm geladen?

Ich habe etwas weiter geforscht und "brk randomization" wurde im Kernel 2.6.25 hinzugefügt, allerdings ist CONFIG_COMPAT_BRK standardmäßig aktiviert (was brk randomization deaktiviert).

Bearbeiten :

OK, weitere Informationen: Es sieht wirklich so aus, als ob die Randomisierung von brk der Übeltäter ist, das alte gcc ruft brk () auf, um das Ende des Datensegments zu ändern, und das scheitert nun, was dazu führt, dass der alte gcc "virtual memory exhausted" meldet. Es gibt einige dokumentierte Möglichkeiten, die Randomisierung von brk zu deaktivieren:

  • sudo echo 0 > /proc/sys/kernel/randomize_va_space

  • sudo sysctl -w kernel.randomize_va_space=0

  • startet eine neue Shell mit setarch i386 -R tcsh (oder "-R -L")

Ich habe sie ausprobiert und sie scheinen einen Effekt darin zu haben, dass der brk () Rückgabewert verschieden ist (und immer derselbe) als ohne sie (probiert sowohl Kernel 2.6.25 als auch 2.6.26 aus), aber der brk () schlägt immer noch fehl, so dass das alte gcc immer noch fehlschlägt :-(.

Zusätzlich habe ich vm.legacy_va_layout=1 und vm.overcommit_memory=2 ohne Änderung eingestellt, und ich habe mit den Einstellungen vm.legacy_va_layout=1 und kernel.randomize_va_space=0 , die in /etc/sysctl.conf gespeichert sind, neu gestartet. Immer noch keine Veränderung.

Bearbeiten :

Die Verwendung von kernel.randomize_va_space=0 im Kernel 2.6.26 (und 2.6.25) führt dazu, dass der folgende Aufruf von brk () von strace legacy-gcc :

gemeldet wird

brk(0x80556d4) = 0x8056000

Dies zeigt an, dass brk () fehlgeschlagen ist, aber es sieht so aus, als ob es fehlgeschlagen ist, da das Datensegment bereits über die angeforderte Datenmenge hinaus endet. Mit objdump kann ich sehen, dass das Datensegment bei 0x805518c enden soll, während das fehlgeschlagene brk () anzeigt, dass das Datensegment derzeit bei 0x8056000 endet:

%Vor%

Bearbeiten :

Um den Kommentar von ephemient unten zu wiederholen: "So seltsam, GCC als eine binäre Quelle ohne Quelle zu behandeln!"!

Also, unter Verwendung von strace, objdump, gdb und meinem begrenzten Verständnis von Assembler und Architektur von 386 habe ich das Problem auf den ersten malloc-Aufruf im Legacy-Code zurückgeführt. Das veraltete gcc ruft malloc auf, was NULL zurückgibt, was zu der Meldung "virtual memory exhausted" in stderr führt. Dieses malloc befindet sich in libc.so.5 und ruft getenv auf ein paar mal und am Ende ruft brk () ... ich denke, um den Haufen zu erhöhen ... was fehlschlägt.

Daraus kann ich nur vermuten, dass das Problem mehr als brk Randomisierung ist, oder ich habe die Randomisierung von brk nicht vollständig deaktiviert, trotz der Einstellungen randomize_va_space = 0 und legacy_va_layout = 1 sysctl.

    
JimKleck 23.04.2009, 01:30
quelle

6 Antworten

12

Installieren Sie linux + den alten gcc auf einer virtuellen Maschine.

    
an0nym0usc0ward 23.04.2009, 01:34
quelle
5

Haben Sie die Quellen für diesen benutzerdefinierten Compiler? Wenn Sie die Basis 2.6.0 wiederherstellen können (und das sollte relativ einfach sein), sollten diff und patch Ihre Änderungsmenge wiederherstellen.

Was würde ich dann empfehlen, diesen Änderungssatz zu verwenden, um eine neue Version gegen den aktuellen gcc zu erstellen? UND DANN UNTER KONFIGURATIONSKONTROLLE STECKEN.

Sorry, ich will nicht schreien. Es ist nur, dass ich seit fast 30 Jahren dasselbe gesagt habe.

    
Charlie Martin 23.04.2009 01:36
quelle
2

Können Sie strace the gcc-2.6.0 ausführbar machen? Es kann etwas wie das Lesen von /proc/$$/maps sein, und verwirrt werden, wenn sich die Ausgabe auf unbedeutende Weise ändert. Ein ähnliches Problem wurde kürzlich zwischen 2.6.28 und 2.6.29 festgestellt

Wenn das so ist, können Sie /usr/src/linux/fs/proc/task_mmu.c oder ähnliches hacken, um die alte Ausgabe wiederherzustellen, oder eine $LD_PRELOAD einrichten, um gcc zum Lesen einer anderen Datei vorzutäuschen.

Bearbeiten

Da du brk ...

erwähnt hast

CONFIG_COMPAT_BRK macht den Standardwert kernel.randomize_va_space=1 anstelle von 2 , aber das sortiert immer noch alles andere als den Heap ( brk ).

Sehen Sie, ob Ihr Problem verschwindet, wenn Sie echo 0 > /proc/sys/kernel/randomize_va_space oder sysctl kernel.randomize_va_space=0 (gleichwertig).

Wenn ja, füge kernel.randomize_va_space = 0 zu /etc/sysctl.conf hinzu oder füge norandmaps zur Kernel-Befehlszeile (äquivalent) hinzu und sei wieder glücklich.

    
ephemient 23.04.2009 15:57
quelle
1

Ich bin auf dieses gestoßen und habe über Ihr Problem nachgedacht. Vielleicht können Sie eine Möglichkeit finden, mit der Binärdatei zu spielen, um sie in das ELF-Format zu verschieben? Oder vielleicht ist es irrelevant, aber das Spielen mit objdump kann Ihnen mehr Informationen liefern.

Können Sie sich die Prozessspeicherkarte ansehen?

    
shodanex 24.04.2009 15:03
quelle
1

Ich habe also etwas herausgearbeitet ... es ist keine vollständige Lösung, aber es geht über das ursprüngliche Problem hinaus, das ich mit dem alten gcc hatte.

Haltepunkte für jeden libc-Aufruf in der .plt (Prozedur-Verbindungstabelle) setzen Ich sehe, dass malloc (in libc.so.5) getenv () aufruft, um zu erhalten:

%Vor%

Also habe ich diese im Internet durchsucht und dieses gefunden, das

empfohlen hat %Vor%

dann das Erbe gcc arbeitet !!!!

Aber nicht zu Hause frei, es hat sich auf den Link in der Build vor dem Scheitern, so ist noch etwas weiter mit der alten nld wir haben :-( Es berichtet:

%Vor%

In /etc/sysctl.conf habe ich:

%Vor%

Es funktioniert immer noch genauso, wenn

%Vor%

aber nicht wenn

%Vor%

Es gab einen Vorschlag, "ldd" zu verwenden, um die Abhängigkeiten der gemeinsam genutzten Bibliotheken zu sehen: Das veraltete gcc benötigt nur libc5, aber das ältere nld benötigt auch libg ++. so.27, libstdc ++. so.27, libm.so.5 und anscheinend gibt es eine libc5-Version von libg ++. so.27 (libg ++ 27-altdev ??) und was ist mit libc5-compat?

Also, wie gesagt, noch nicht frei nach Hause ... näher kommen. Ich werde wahrscheinlich eine neue Frage über das NTL-Problem stellen.

Bearbeiten :

Ich habe ursprünglich darauf verzichtet, diese Antwort zu "akzeptieren", da ich immer noch ein Problem mit dem entsprechenden Legacy-Linker habe, aber um diese Frage zumindest endgültig zu beantworten, überdenke ich diese Position.

>

Danke, gehen Sie zu:

  • an0nym0usc0ward für den Vorschlag, eine vm zu verwenden (die möglicherweise zur akzeptierten Antwort wird)
  • Beispiel für die Verwendung von strace und Hilfe bei der Verwendung von stackoverflow
  • shodanex für die Verwendung von objdump
  • vorgeschlagen

Bearbeiten

Unten sind die letzten Dinge, die ich gelernt habe, und jetzt werde ich die VM-Lösung akzeptieren, da ich sie auf andere Weise nicht vollständig lösen konnte (zumindest in der dafür vorgesehenen Zeit).

Die neueren Kernel haben ein CONFIG_COMPAT_BRK Build-Flag, um libc5 verwenden zu können, also wird vermutlich das Bauen eines neuen Kernels mit diesem Flag das Problem beheben (und durch den Kernel src sieht es aus, aber ich kann nicht sicher sein da ich nicht alle Wege verfolgt habe). Es gibt auch eine andere dokumentierte Möglichkeit, libc5 zur Laufzeit (und nicht zum Zeitpunkt der Kernel-Erstellung) zu verwenden: sudo sysctl -w kernel.randomize_va_space = 0. Dies tut jedoch nicht einen vollständigen Job und einige (die meisten?) libc5-Anwendungen werden immer noch brechen, z. unser älterer Compiler und Linker. Dies scheint auf einen Unterschied in den Alignment-Annahmen zwischen den neueren und älteren Kernen zurückzuführen zu sein. Ich habe das Linker-Binary gepatcht, damit es denkt, es habe einen größeren bss-Abschnitt, um das Ende des bss auf eine Seitengrenze zu bringen, und das funktioniert auf dem neueren Kernel, wenn sysctl var kernel.randomize_va_space = 0 ist. Dies ist KEINE befriedigende Lösung für mich, da ich eine kritische binäre ausführbare Datei blind patche, und obwohl das Ausführen des gepatchten Linkers auf dem neueren Kernel eine bit-identische Ausgabe zu dem ursprünglichen Linker-Lauf auf dem älteren Kernel erzeugte, beweist dies nicht Einige andere Linker-Eingaben (dh wir ändern das zu verknüpfende Programm) werden ebenfalls identische Ergebnisse liefern.

    
JimKleck 27.04.2009 17:03
quelle
0

Können Sie nicht einfach ein Disk-Image erstellen, das bei einem Systemausfall erneut installiert werden kann? oder eine VM machen?

    
nzpcmad 23.04.2009 01:36
quelle