устаревшие проблемы компилятора gcc

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

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 ассемблера и архитектуры, я проследил проблему до первого вызова malloc в устаревшем коде. Устаревший gcc вызывает malloc, который возвращает NULL, что приводит к сообщению «виртуальная память исчерпана» на stderr. Этот malloc находится в libc.so.5, он несколько раз вызывает getenv и в конечном итоге вызывает brk () ... Я думаю, чтобы увеличить кучу ... что не удается.

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


person JimKleck    schedule 23.04.2009    source источник
comment
Уточните насчет исчезновения набора изменений --- потеряли ли вы исходный код (часть) вашего компилятора?   -  person Norman Ramsey    schedule 23.04.2009
comment
Я чувствую вашу боль, но я бы действительно больше беспокоился о ... ну, почти о любом другом риске, чем о риске невозможности получить доступ к исходному коду Linux для конкретной версии ядра 2.6 в будущем.   -  person unwind    schedule 23.04.2009
comment
Хм, так это динамически связано с libc.so.5, где проблема? Ужасный взлом, но glibc должна быть достаточно совместимой, чтобы, если вы сделаете ln -s libc.so.6 libc.so.5, ваш код, вероятно, все равно будет работать.   -  person ephemient    schedule 27.04.2009
comment
Это уродливый хакер, но, как сказал мой друг: «Если работает, значит, красиво». К сожалению, это не работает (устаревшие отчеты gcc не могут обрабатывать тип reloc ‹NULL›) ... так что он остается некрасивым :-) На самом деле это не удивительно, поскольку libc5- ›libc6 была большой проблемой.   -  person JimKleck    schedule 27.04.2009
comment
Я видел недавнюю фиксацию ядра Linux, которая, кажется, связана с этой проблемой: git.kernel.org/linus/ 4471a675dfc7ca676c165079e91c712b09dc9ce4   -  person CesarB    schedule 20.04.2011


Ответы (6)


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

person an0nym0usc0ward    schedule 23.04.2009
comment
+1. Поместите его в VMWare Player (или другой, но VMWare был бы моим выбором), а затем вы можете взять его и перенести с машины на машину по своему желанию. А резервное копирование так же просто, как сохранение всего каталога виртуальной машины. - person paxdiablo; 23.04.2009

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

Тогда я бы порекомендовал использовать этот набор изменений для создания новой версии на основе актуального gcc. А ЗАТЕМ ПОСТАВИТЬ ЕГО ПОД КОНФИГУРАЦИОННЫЙ КОНТРОЛЬ.

Извини, я не хочу кричать. Просто я говорю одно и то же больше 30 лет.

person Charlie Martin    schedule 23.04.2009
comment
Не сдерживай Чарли, расскажи нам, что ты на самом деле чувствуешь. - person dmckee --- ex-moderator kitten; 23.04.2009
comment
Если по прошествии 30 лет они все еще не слушают вас, возможно, пора подумать о том, чтобы сдаться :-) - person paxdiablo; 23.04.2009
comment
Коварство в этом заключается в том, что время от времени кто-то получает это. Достаточно часто, чтобы держать вас на крючке, но не достаточно часто, чтобы снизить кровяное давление. - person dmckee --- ex-moderator kitten; 23.04.2009
comment
Потерянные источники встречаются чаще, чем вы думаете. В Атланте есть компания, которая только декомпилирует двоичные файлы для идиотов, потерявших свои исходники. Вы бы не хотели лишать работы этих хороших людей, не так ли? - person Norman Ramsey; 23.04.2009
comment
@norman Я думаю, они не могут быть более обычными, цивилизация остановится. И да, собственно говоря. - person Charlie Martin; 23.04.2009
comment
@Pax, если бы я не был действительно упрям, разве я бы 40 лет программировал вместо того, чтобы найти настоящую работу? - person Charlie Martin; 23.04.2009
comment
Проблема в том, что компетентные люди попадают в ситуации, создаваемые некомпетентными людьми. Никто из нас не потеряет исходный код, потому что мы бы его зарегистрировали и сделали резервную копию, верно? Однако я думаю, мы можем согласиться с тем, что не вся отрасль так хороша, как мы. :-) - person David Thornley; 27.04.2009
comment
Ну, нет, на самом деле, если это приводит меня к заглавным буквам, обычно это то, что я узнал на собственном горьком опыте. - person Charlie Martin; 27.04.2009
comment
Что касается предложения создать новую версию на основе актуального GCC, то обновление цели GCC с 2.6.0 до текущей версии будет таким же объемом работы, как и выполнение этого с нуля. - person Laurynas Biveinis; 02.05.2009
comment
Что ж, тогда ты мог бы начать, не так ли? Послушайте, эта проблема никуда не денется. Если это не мертвый продукт, отказ от мусора означает, что исходный код GCC будет еще больше отклоняться. - person Charlie Martin; 03.05.2009

Можете ли вы strace исполнять gcc-2.6.0 исполняемый файл? Он может делать что-то вроде чтения /proc/$$/maps и сбиваться с толку, когда вывод изменяется незначительно. Похожая проблема была недавно замечена между 2.6.28 и 2.6.29.

Если это так, вы можете взломать /usr/src/linux/fs/proc/task_mmu.c или около того, чтобы восстановить старый вывод, или настроить какой-нибудь $LD_PRELOAD для подделки gcc чтения другого файла.

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

Поскольку вы упомянули _7 _...

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 в командную строку ядра (эквивалент) и снова будьте счастливы.

person ephemient    schedule 23.04.2009
comment
Так странно рассматривать GCC как двоичный файл без исходного кода ... Я бы определенно пошел по пути Чарли, если это вообще возможно. - person ephemient; 23.04.2009
comment
В ответ на вашу правку, приведенную выше, я попробовал это ... без радости. Я добавил в вопрос больше примечаний по этому поводу. На самом деле похоже, что устаревший gcc пытается изменить конец сегмента данных, но система уже считает, что конец находится за, до которого старый gcc пытается его расширить. - person JimKleck; 24.04.2009

Я наткнулся на это и подумал о вашей проблеме. Может быть, ты найдешь способ поиграться с двоичным файлом, чтобы перевести его в формат ELF? Или, может быть, это не имеет значения, но игра с objdump может предоставить вам больше информации.

Можете ли вы взглянуть на карту памяти процесса?

person shodanex    schedule 24.04.2009
comment
Ссылка, которую вы предложили, кажется более направленной на запуск программы во встроенном Linux, я запускаю устаревший gcc на ПК. Но я пробовал objdump, унаследованный gcc - elf32-i386. - person JimKleck; 24.04.2009

Итак, я кое-что придумал ... это не полное решение, но оно решает исходную проблему, которая у меня была с устаревшим 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

тогда РАБОТАЕТ legacy 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 и, очевидно, есть версия libg ++. so.27 для libc5 (libg ++ 27-altdev ??), а как насчет libc5-compat?

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

Изменить:

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

Благодарю за:

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

Изменить

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

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

person JimKleck    schedule 27.04.2009

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

person rbrayb    schedule 23.04.2009