Мы используем устаревший компилятор, основанный на gcc 2.6.0, для кросс-компиляции для старого встроенного процессора, который мы все еще используем (да, он все еще используется с 1994 года!). Инженер, который сделал gcc-порт для этого чипа, давно ушел. Хотя мы можем восстановить исходный код gcc 2.6.0 из Интернета, набор изменений для этого чипа имеет
исчез в залах корпоративной истории. До недавнего времени мы путались, поскольку компилятор все еще выполнял и создавал работоспособные исполняемые файлы, но начиная с ядра Linux Linux 2.6.25 (и также 2.6.26) он завершается с сообщением gcc: virtual memory exhausted
... даже при запуске без параметров или с только -v
. Я перезагрузил свою систему разработки (из 2.6.26) с использованием ядра 2.6.24, и компилятор снова работает (перезагрузка с 2.6.25 не работает).
У нас есть одна система, которую мы держим на уровне 2.6.24 только для того, чтобы делать сборки для этого чипа, но чувствуем себя немного уязвимыми в случае, если мир Linux переходит к такой точке, что мы больше не можем перестраивать систему который запустит компилятор (то есть наша система 2.6.24 умрет, и мы не сможем установить 2.6.24 для установки и запуска в новой системе, поскольку некоторые программные части больше не доступны).
У кого-нибудь есть идеи относительно того, что мы могли бы сделать для более современной установки, чтобы запустить этот устаревший компилятор?
Редактировать
Чтобы ответить на некоторые комментарии ...
К сожалению, именно изменения исходного кода, характерные для нашего чипа, потеряны. Эта потеря произошла из-за двух главных реорганизаций компании и нескольких сисадминов (пара из которых действительно оставила беспорядок). Теперь мы используем управление конфигурацией, но это закрывает дверь сарая слишком поздно для этой проблемы.
Использование ВМ - хорошая идея, и, возможно, это то, что мы в итоге делаем. Спасибо за эту идею.
Наконец, я попробовал strace, как предложил ephemient, и обнаружил, что последним системным вызовом был brk (), который возвращал ошибку в новой системе (ядро 2.6.26) и возвращал успех в старой системе (ядро 2.6.24). Это указывает на то, что у меня действительно заканчивается виртуальная память, за исключением того, что tcsh "limit" возвращает одинаковые значения на старых и новых системах, а / proc / meminfo показывает, что в новых системах немного больше памяти и немного больше места подкачки. Может быть, это проблема фрагментации или куда загружается программа?
Я провел дальнейшие исследования, и в ядре 2.6.25 была добавлена «рандомизация brk», однако 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
Редактировать
Повторяя комментарий Эфимента ниже: «Странно считать GCC двоичным файлом без источника»!
Итак, используя strace, objdump, gdb и мое ограниченное понимание ассемблера и архитектуры 386, я отследил проблему до первого вызова malloc в устаревшем коде. Устаревший gcc вызывает malloc, который возвращает NULL, что приводит к сообщению «исчерпана виртуальная память» на stderr. Этот malloc находится в libc.so.5 и вызывает getenv
несколько раз и в конечном итоге вызывает brk () ... я думаю, чтобы увеличить кучу ... который не удается.
Из этого я могу только предположить, что проблема заключается не только в рандомизации brk, либо я не полностью отключил рандомизацию brk, несмотря на то, что параметры sysctl randomize_va_space = 0 и legacy_va_layout = 1.