Вопрос

Мы используем устаревший компилятор, основанный на gcc 2.6.0, для перекрестной компиляции для старого встроенного процессора, который мы все еще используем (да, он все еще используется с 1994 года!).Инженер, который создавал порт gcc для этого чипа, уже давно ушел.Хотя мы могли бы восстановить исходный код gcc 2.6.0 откуда-нибудь в Интернете, набор изменений для этого чипа исчез в залах корпоративной истории.До недавнего времени мы путались, поскольку компилятор все еще запускался и создавал работоспособные исполняемые файлы, но начиная с ядра 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 показывает, что в новых системах немного больше памяти и совсем немного больше места подкачки.Может быть, это проблема фрагментации или того, куда загружается программа?

Я провел некоторые дальнейшие исследования, и, однако, "рандомизация 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

Редактировать:

Чтобы повторить комментарий эфемера ниже:"Так странно рассматривать GCC как двоичный файл без исходного кода"!

Итак, используя strace, objdump, gdb и мое ограниченное понимание ассемблера и архитектуры 386, я проследил проблему до 1-го вызова malloc в устаревшем коде.Устаревший gcc вызывает malloc, который возвращает NULL, что приводит к сообщению "виртуальная память исчерпана" в stderr.Этот malloc находится в libc.so.5, и он вызывает getenv кучу раз и в конечном итоге вызывает brk()...Я думаю, чтобы увеличить кучу...который терпит неудачу.

Исходя из этого, я могу только предположить, что проблема заключается не только в рандомизации brk, или я не полностью отключил рандомизацию brk, несмотря на настройки sysctl randomize_va_space=0 и legacy_va_layout= 1.

Это было полезно?

Решение

Установите linux + старый gcc на виртуальную машину.

Другие советы

У вас есть необходимые источники для этого пользовательского компилятора?Если вы сможете восстановить базовую версию 2.6.0 (а это должно быть относительно легко), то diff и patch должны восстановить ваш набор изменений.

Тогда я бы порекомендовал использовать этот набор изменений для создания новой версии на основе обновленного 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.

Установка точек останова при каждом вызове libc в .plt (таблица привязки процедур) Я вижу, что malloc (в libc.so.5) вызывает getenv(), чтобы получить:

    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'

В /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 ++.so.27, libstdc ++.so.27, libm.so.5 и, по-видимому, существует libc5-версия libg ++.so.27 (libg ++ 27-altdev ??) а как насчет libc5-compat?

Так что, как я уже сказал, я еще не свободен от дома...становлюсь все ближе.Вероятно, я опубликую новый вопрос о проблеме nld.

Редактировать:

Изначально я собирался воздержаться от "Принятия" этого ответа, поскольку у меня все еще есть проблема с соответствующим устаревшим компоновщиком, но для того, чтобы получить хотя бы некоторую окончательность в этом вопросе, я переосмысливаю эту позицию.

Спасибо, что вышли на улицу, чтобы:

  • an0nym0usc0ward за предложение использовать виртуальную машину (которое в конечном итоге может стать принятым ответом)
  • эфемерно для того, чтобы предложить использовать strace, и помочь с использованием stackoverflow
  • shodanex за предложение использовать objdump

Редактировать

Ниже приведен последний материал, который я выучил, и теперь я приму решение виртуальной машины, поскольку я не мог полностью решить его каким-либо другим способом (по крайней мере, за отведенное для этого время).

Более новые ядра имеют флаг сборки CONFIG_COMPAT_BRK, позволяющий использовать libc5, поэтому, предположительно, создание нового ядра с этим флагом устранит проблему (и, просматривая src ядра, похоже, что так и будет, но я не могу быть уверен, поскольку я не следовал всем путям).Существует также другой документированный способ разрешить использование libc5 во время выполнения (а не во время сборки ядра).:sudo sysctl -w ядро.randomize_va_space=0.Это, однако, не выполняет полную работу, и некоторые (большинство?) приложения libc5 все равно будут ломаться, напримернаш устаревший компилятор и компоновщик.По-видимому, это связано с различием в предположениях о выравнивании между более новым и старым ядрами.Я исправил двоичный файл компоновщика, чтобы заставить его думать, что у него есть раздел bss большего размера, чтобы довести конец bss до границы страницы, и это работает на более новом ядре, когда sysctl var kernel.randomize_va_space=0.Это НЕ является удовлетворительным решением для меня, поскольку я слепо исправляю критический двоичный исполняемый файл, и даже несмотря на то, что запуск исправленного компоновщика на более новом ядре выдал результат, немного идентичный исходному компоновщику, запущенному на более старом ядре, это не доказывает, что какой-то другой ввод компоновщика (т. Е.мы меняем программу, на которую ссылаемся), также приведет к идентичным результатам.

Не могли бы вы просто создать образ диска, который можно будет переустановить, если система выйдет из строя?или создать виртуальную машину?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top