レガシーGCCコンパイラの問題
-
13-09-2019 - |
質問
GCC 2.6.0に基づいてレガシーコンパイラを使用して、まだ使用している古い埋め込まれたプロセッサのクロスコンパイルを使用しています(はい、1994年以来まだ使用されています!)。このチップのためにGCCポートを行ったエンジニアは、それ以来ずっと進んでいます。 Web上のどこかからGCC 2.6.0のソースを回復できるかもしれませんが、このチップの変更セットは企業史のホールで消えました。コンパイラがまだ実行され、実行可能な実行可能ファイルを作成したため、最近まで混乱していましたが、Linuxカーネル2.6.25(および2.6.26)の時点では、メッセージで失敗します。 gcc: virtual memory exhausted
...パラメーターなしで、またはのみで実行された場合でも -v
. 。 2.6.24カーネルとコンパイラの動作を使用して、開発システム(2.6.26から)を再起動しました(2.6.25で再起動することはできません)。
このチップのビルドを行う目的で2.6.24に保持しているシステムが1つありますが、Linuxの世界が実行されるシステムを再構築できなくなった場合に備えて、少し露出していると感じています。コンパイラ(つまり、2.6.24システムが死亡し、いくつかのソフトウェアパーツが利用できなくなったため、2.6.24を新しいシステムにインストールして実行することはできません)。
このレガシーコンパイラを実行するために、より近代的なインストールにできることについて、誰かがアイデアを持っていますか?
編集:
いくつかのコメントに答えるために...
悲しいことに、失われたチップに固有のソースコードの変更です。この損失は、2つの主要な企業ReorgsといくつかのSysadmins(いくつかの大部分が本当に混乱を残しました)で発生しました。現在、構成制御を使用していますが、この問題には遅すぎる納屋のドアを閉めることです。
VMの使用は良いアイデアであり、私たちが最終的にやっていることかもしれません。その考えをありがとう。
最後に、Ephemientが提案したようにStraceを試してみて、最後のシステムコールはBrk()であり、新しいシステム(2.6.26カーネル)でエラーを返し、古いシステム(2.6.24カーネル)で成功を返しました。これは、TCSHの「制限」が古いシステムと新しいシステムで同じ値を返すことを除いて、私が実際に仮想メモリを使い果たしていることを示しています。 /Proc /Meminfoは、新しいシステムがわずかに多くのメモリとかなりの交換スペースを持っていることを示しています。多分それは断片化の問題ですか、それともプログラムがロードされている場所ですか?
私はさらに調査を行い、「BRKランダム化」がカーネル2.6.25に追加されましたが、 CONFIG_COMPAT_BRK
デフォルトで有効になっていると思われます(BRKランダム化を無効にします)。
編集:
わかりました、詳細:BRKランダム化は原因であるように見えます。GCCがBRK()を呼び出してデータセグメントの終了を変更し、現在失敗し、レガシーGCCが「仮想メモリが排出された」と報告します。 BRKランダム化を無効にするいくつかの文書化された方法があります。
sudo echo 0 > /proc/sys/kernel/randomize_va_space
sudo sysctl -w kernel.randomize_va_space=0
で新しいシェルを開始します
setarch i386 -R tcsh
(または "-r -l")
私はそれらを試してみましたが、Brk()戻り値がそれらのない(そして常に同じ)という点で効果があるようです(カーネル2.6.25と2.6.26の両方で試しました)が、brk()まだ失敗するので、レガシーGCCはまだ失敗します:-(。
さらに、設定しました vm.legacy_va_layout=1
と vm.overcommit_memory=2
変更なしで、私はで再起動しました vm.legacy_va_layout=1
と kernel.randomize_va_space=0
/etc/sysctl.confに保存された設定。まだ変更はありません。
編集:
使用 kernel.randomize_va_space=0
カーネル2.6.26(および2.6.25)では、次のBRK()コールが報告されています。 strace legacy-gcc
:
brk(0x80556d4) = 0x8056000
これは、brk()が失敗したことを示しますが、データセグメントがすでに要求されたものを超えて終了するため、失敗したようです。 objdumpを使用すると、データセグメントが0x805518cで終了するはずですが、故障したbrk()は、データセグメントが現在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
編集:
以下のEphemientのコメントをエコーするには、「GCCをソースなしでバイナリとして扱うのはとても奇妙です」!
したがって、Strace、Objdump、GDB、および386のアセンブラーとアーキテクチャの私の限られた理解を使用して、私はこの問題をレガシーコードで最初のマロックコールに追跡しました。レガシーGCCは、nullを返すMallocを呼び出します。これにより、Stderrで「仮想メモリが排出された」メッセージが表示されます。このマロックはlibc.so.5にあり、getenvを何度も呼び出し、brk()を呼び出すことになります...
このことから、問題はBRKランダム化以上のものであると判断することができます。または、radion_va_space = 0およびlegacy_va_layout = 1 sysctl設定にもかかわらず、BRKランダム化を完全に無効にしていません。
解決
Linux +を仮想マシンにインストールします。
他のヒント
あなたは持っていますか ソース このカスタムコンパイラ用? 2.6.0のベースラインを回復できる場合(そして、それは比較的簡単なはずです)、Diffとパッチは変更セットを回復するはずです。
その後、その変更セットを使用して、最新のGCCに対して新しいバージョンを構築することをお勧めします。そして、それを構成制御下に置きます。
申し訳ありませんが、叫ぶつもりはありません。 30年のほとんどの間、私が同じことを言ってきただけです。
あなたはできる strace
gcc-2.6.0
実行可能?それは読書のようなことをしているかもしれません /proc/$$/maps
, 、出力が取るに足らない方法で変化すると混乱します。同様の問題がありました 最近気づいた 2.6.28から2.6.29の間。
もしそうなら、あなたはハックすることができます /usr/src/linux/fs/proc/task_mmu.c
または古い出力を復元するか、いくつかをセットアップする $LD_PRELOAD
偽物に gcc
別のファイルを読むことに。
編集
あなたが言及して以来 brk
...
CONFIG_COMPAT_BRK
デフォルトを作成します kernel.randomize_va_space=1
それ以外の 2
, 、しかし、それはまだヒープ以外のすべてを無作為にします(brk
).
あなたがあなたの問題がなくなるかどうかを確認してください echo 0 > /proc/sys/kernel/randomize_va_space
また sysctl kernel.randomize_va_space=0
(同等)。
もしそうなら、追加してください kernel.randomize_va_space = 0
に /etc/sysctl.conf
または追加します norandmaps
カーネルコマンドライン(同等)に、そして再び幸せになります。
私は遭遇しました これ そしてあなたの問題について考えました。バイナリで再生してELF形式に移動する方法を見つけることができますか?または、それは無関係かもしれませんが、objdumpで遊ぶことでより多くの情報を提供できます。
プロセスメモリマップをご覧ください。
だから私は何かを解決しました...それは完全な解決策ではありませんが、レガシーGCCで私が抱えていた元の問題を乗り越えます。
.plt(手順リンケージテーブル)にすべてのlibc呼び出しにブレークポイントを置く(libc.so.5)getEnv()がget:get:
MALLOC_TRIM_THRESHOLD_ MALLOC_TOP_PAD_ MALLOC_MMAP_THRESHOLD_ MALLOC_MMAP_MAX_ MALLOC_CHECK_
だから私はこれらをウェブ検索し、見つけました これ アドバイスしました
setenv MALLOC_TOP_PAD_ 536870912
その後、レガシーGCCは機能します!!!!
しかし、家に無料ではなく、失敗する前にビルドのリンクに起きたので、私たちが持っているレガシーnldでさらに何かが起こっています:-(それは報告しています:
Virtual memory exceeded in `new'
In /etc/sysctl.conf私は持っています:
kernel.randomize_va_space=0 vm.legacy_va_layout=1
それでも同じように機能します
kernel.randomize_va_space=1 vm.legacy_va_layout=0
しかし、そうではありません
kernel.randomize_va_space=2
「LDD」を使用して共有ライブラリの依存関係を確認するための提案がありました。レガシーGCCにはLIBC5のみが必要ですが、レガシーNLDにはLIBG ++も必要です。 LIBG ++のLIBC5バージョン。
だから、私が言ったように、まだ家にいない...近づいている。おそらく、NLD問題に関する新しい質問を投稿します。
編集:
私はもともと、この答えを「受け入れる」ことを控えるつもりでした。なぜなら、私はまだ対応するレガシーリンカーに問題があるからですが、少なくともこの質問について何らかの最終性を得るために、私はその立場を再考しています。
ありがとう。
- VMを使用することを提案するためのAN0NYM0USC0ワード(最終的に受け入れられた答えになる可能性があります)
- Straceを使用することを提案し、Stackoverflowの使用を支援するためのephemient
- objdumpの使用を提案するためのshodanex
編集
以下は私が学んだ最後のことです。今では、他の方法で完全に解決できなかったので、VMソリューションを受け入れます(少なくともこれに割り当てられた時間で)。
新しいカーネルにはconfig_compat_brkビルドフラグがあり、LIBC5を使用できるようにするため、このフラグで新しいカーネルを構築すると問題が解決します(カーネルSRCを通して見ると、すべてのパスに従っているわけではありません)。また、ランタイムで(カーネルビルド時間ではなく)LIBC5の使用を許可する別の文書化された方法もあります:Sudo Sysctl -W Kernel.Randomize_va_space = 0。ただし、これは完全なジョブを行いません。また、レガシーコンパイラやリンカーなど、一部の(ほとんど?)libc5アプリはまだ壊れます。これは、新しいカーネルと古いカーネル間のアラインメントの仮定の違いによるものと思われます。 Linkerバイナリにパッチを適用して、BSSの終わりをページ境界に上げるために、より大きなBSSセクションを持っていると思わせました。これは私にとって満足のいく解決策ではありません。私は重要なバイナリ実行可能ファイルに盲目的にパッチを適用しているため、新しいカーネルでパッチ付きリンカーを実行しても、古いカーネルの元のリンカー実行に少し同一の出力を生成しましたが、それはそれを証明しません。他のいくつかのリンカー入力(つまり、リンクされているプログラムを変更します)も同じ結果を生成します。
システムが死んだ場合に再インストールできるディスク画像を作成するだけではありませんか?またはVMを作りますか?