Не просто, но выполнимо; обсуждается здесь и здесь .
Первый шаг заключается в размещении каждой функции в отдельном сегменте с именами, такими как .text $ a, .text $ b и т. Д. Таким образом, ассемблер не объединит их в один раздел .text, но компоновщик в конечном итоге будут; в компоновщиках Microsoft есть специальное правило, касающееся содержимого после символа $ в названии раздела. Ассемблер создаст файл .obj с несколькими разделами кода. Я попробовал это, я могу подтвердить, что это так. По крайней мере, один вкус MASM делает. :)
Затем они предлагают запустить утилиту поверх объектного файла, которая пометит ваши разделы как COMDAT. Похоже, что упомянутая утилита потеряна во времени и разложении битов, но ее действие можно приблизительно определить. Он читает и анализирует COFF-файл .obj, просматривает разделы и устанавливает флаг COMDAT для всех разделов .text. Я предполагаю, что это просто флаг; может быть больше. В качестве первого шага к его воссозданию я бы предложил скомпилировать файл C с / Gy, а затем без него, и сравнить два файла .obj с помощью низкоуровневого браузера PE / COFF. Я не зашел так далеко, так как мой сценарий был совсем другим.