Исторический разбор Itanium из The Old New Thing от 1 октября 2026 года. Первоисточник.
В прошлый раз мы рассмотрели механизм горячего патчинга Windows на 64-битном ARM. А как насчёт Itanium?
У Itanium также были инструкции фиксированного размера, или точнее — фиксированных по размеру бандлов (bundle), где каждый бандл кодирует три инструкции. Фиксированный размер бандлов означает, что, как и в AArch64, нет ограничения на горячий патчинг первой инструкции функции.
На самом деле для горячего патчинга вообще не было запасного места.
Во время горячего патчинга первый бандл инструкции мог быть перезаписан следующей последовательностью:
nop
brl.cond.sptk target64
Вторая инструкция brl — это «длинный переход», который принимает 64-битную цель.¹ Это «двойная» инструкция, занимающая два слота в бандле, поэтому мы видим бандл только из двух инструкций.
Исходя из моего опыта с AArch64, сначала я думал, что последовательность инструкций будет выглядеть скорее так:
movl r8 = target64
br.cond.sptk r8
Но затем я понял, что это не работает, потому что нельзя выполнить косвенный переход через регистр общего назначения. Сначала надо переместить значение в регистр ветвления, и это привело бы нас к четырём инструкциям (поскольку movl занимает два слота), что превышает вместимость бандла.
Бонусное замечание: если изучать старые бинарники для Itanium, как это делал я, можно обнаружить, что многие функции предваряются видимым запасным бандлом:
break.m 0
break.i 0
break.i 0
Этот бандл заполнен инструкциями-брейкпоинтами, и поначалу (как и я) можно ошибочно предположить, что они там для горячего патчинга. Но затем вы видите, что у некоторых функций такого запасного бандла нет, и при более тщательном изучении понимаете, что этот запасной бандл не для горячего патчинга. Это выравнивающая вставка (padding), чтобы начало каждой функции совпадало с границей в 32 байта.
¹ Формально это условная длинная ветка (long branch) с предикатом p0, статически предсказанная как выполняемая. Регистр p0 жёстко задан как true, поэтому ассемблер для удобства упрощает дизассемблировку и опускает p0.
