Как стать автором
Обновить

Комментарии 17

А какие современные компиляторы в нативный код используют OMF ?

Очевидно, никакие

Считаю что объектный формат хранения и линковка вообще устаревшие концепции, т.к. они не позволяют хранить метапрограммы (например шаблоны C++), в результате в том же C++ шаблоны могут существовать только в *.h-файлах. Хранить нужно частично скомпилированные синтаксические деревья, а вместо линковки применять процесс «окончательной компиляции».
… в результате в том же C++ шаблоны могут существовать только в *.h-файлах. Хранить нужно частично скомпилированные синтаксические деревья...

Поясните пожалуйста, возможно я заблуждаюсь, но ведь к моменту обработки AST и последующей оптимизации/кодогенерации шаблоны уже будут развёрнуты к подходящему для используемых типов аргументов виду, разве нет? Т.е. в AST шаблоны уже должны быть последовательностью инструкций используемого компилятором IR.
Это если шаблон построен по старинке — и объявления, и реализации в *.h-файлах. Но если оставить в хедерах только объявления, а реализации положить в отдельные файлы *.cpp, то в момент обработки AST шаблоны в последовательность инструкций развернуть не получится. Этим придется заниматься линкеру.
Понятно, что не всякий линкер для этого подойдет. Помнится, солярисовский Sun PRO компилятор именно поэтому использовал свой, интеллектуальный линкер ldi (или ild? Склероз проклятый). Можно было и gcc-шный ld подсунуть, и он даже работал — но ровно до тех пор, пока дело не доходило до линковки с «внешним» шаблонным кодом.

Это очень похоже на модули из C++20

А в TinyC пошли наоборот, сделали ELF и для Windows. Исторически, видимо сложилось.

А что происходит с поддержкой отладчиков и всяких исключений SEH, которые разные для 32 и 64-бит ?

Они не разные

суммарный объем кодов и статических данных в образе EXE-файла не должен превышать 2 в 32 степени

Несущественно, но на самом деле в два раза меньше:
docs.microsoft.com/en-us/cpp/build/x64-software-conventions

Ничто не мешает Windows загружать каждую программу именно в начало ее виртуального адресного пространства

ASLR

Данное ограничение позволяет не только использовать «внутри» образа EXE-файла четырехбайтовую адресацию, но и вообще использовать 32-х разрядные формы инструкций

Ровно до того момента, пока Вы не захотите иметь дело например с сиплюсплюсным RTTI под виндой — там, увы, придётся писать addr64 в некоторых структурах.

А вообще очень, очень жаль, что в подобных отраслях тулчейн из 16битных времён тянут в 64битные кучей костылей и велосипедов. Раз уж Вам так нравится PL/1 — почему бы не превратить Ваш компилятор например во фронтэнд к LLVM?

Так речь идет об адресации в пределах EXE-файла. Да, там есть команды типа mov rax,<переменная>, т.е. адресация в 8 байтном поле.

И в структурах самой программы полно указателей и прочего. Но в этих случаях старшие 4 байта просто остаются нулевыми, а младшие - нормально настраиваются через имеющийся OMF.

Так речь идет об адресации в пределах EXE-файла

Именно! И старшие 4 байта Вы принимаете нулевыми только потому, что выбрали ImageBase не 0x140000000, как делает по умолчанию майкрософтовский компоновщик для 64битных PE, а 0x400000.
Причина стала следствием и наоборот :)
mingw'шный компоновщик например тоже так делает, но, думаю, ровно по тем же причинам — желание всеми способами удержать на плаву явно устаревающий/неподходящий, но такой тёплый и ламповый формат.

А какое преимущество дает загрузка по такому странному адресу 140000000 ? Если оставлять загрузку из IA-32, по крайней мере, можно код короче записать и, да, маленьким прицепом-бонусом можно по-прежнему использовать OMF после пустяшной доделки.

А здесь в чем плюсы? Например, при тестировании я загружал в RSP большое значение и если в недрах системных подпрограмм случайно был оставлен ESP вместо RSP, то в этом месте старшая половина RSP обнулялась и сразу все падало. Удачный тест, но зачем в обычных задачах такое значение стека? Наверное, есть задачи, где свой код требуется отодвинуть в памяти подальше, но большинство задач этого не требует. И, кстати, LLVM и OMF ортогональные вещи. Зачем же отказываться от OMF, который еще 40 лет назад прекрасно позволял собирать выполняемый модуль, не тащя в него библиотеки целиком?

А какое преимущество дает загрузка по такому странному адресу 140000000 ?

На явное преимущество не тянет… Преследуемая цель та же, что и переход от 0x10000 к 0x400000 30-35 лет назад: разделить 16бит и 32бит. Только теперь жёсткого требования нет, лишь рекомендация, и то, сходу не смог нагуглить где же она была, но точно где-то в доках или блогах MS.
Но цель та же — гарантированно отделить в АП 32битные образы от 64битных.
Странный? Нисколько. Любой PE из x64-винды или созданный родным компоновщиком из VS будет иметь такой ImageBase по умолчанию (для DLL 0x180000000).

Зачем же отказываться от OMF

Затем, что на очередной итерации это придётся сделать.
Конечно, можно и дальше кастомизировать его для себя, just for fun, потому что интересно.
Но однажды всем этим придётся заниматься кому-то кроме/вместо Вас и вероятно случится так, что написать весь Ваш набор инструментов по-новой или взять готовый общеиспользуемый окажется проще, дешевле и надёжнее, чем разбираться что и как было.

А что с вызовами функций из разделяемых библиотек? Ведь нету гарантии, что они будут загружены в нижние 4Гб адресного пространства, а значит нужно будет делать вызовы через восьмибайтные указатели.

Наверное, плохо объяснил. Адрес в 4 байта - это только для адресов-констант, которые известны во время компиляции и действуют "внутри" Exe-файла. А всякие DLL и ALLOCATE - разумеется через адрес в 8 байт, но их настраивать через OMF не нужно.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории