TL;DR

  • Itanium은 함수의 첫 번들을 덮어쓰는 방식으로 핫 패칭(hot-patching)을 수행하며, 별도의 여유 공간이 필요하지 않음.
  • Itanium의 명령어는 세 개씩 고정 크기 번들(bundle)에 배치되며, 함수 첫 명령어에는 핫 패칭 제약이 없음.
  • 핫 패칭 시 첫 번들을 nop과 64비트 대상 주소를 받는 brl.cond.sptk로 덮어씀.
  • brl은 번들 슬롯 두 개를 차지하는 긴 분기(long branch) 명령어이므로, 번들에는 명령어 두 개만 들어감.
  • 함수 앞에 보이는 중단점 명령어 번들은 핫 패칭용이 아니라 함수 시작을 32바이트 경계에 맞추는 패딩임.

Itanium의 핫 패칭 방식

  • 이전에는 64비트 ARM(AArch64)의 Windows 핫 패칭을 살펴봤으며, Itanium도 고정 크기 명령어, 더 정확히는 명령어 세 개를 인코딩하는 고정 크기 번들을 사용함.
  • 고정 크기 번들이므로 AArch64와 마찬가지로 함수의 첫 명령어에는 핫 패칭 제약이 없음.
  • 실제로 Itanium에는 핫 패칭을 위한 여유 공간이 전혀 없으며, 그 공간이 필요하지도 않음.
  • 핫 패칭 중에는 명령어의 첫 번들을 nop과 brl.cond.sptk target64로 덮어씀.

긴 분기 명령어와 번들 슬롯

  • 두 번째 명령어인 brl은 64비트 대상 주소를 받는 긴 분기 명령어임.¹
  • brl은 번들 슬롯 두 개를 차지하는 더블 와이드(double-wide) 명령어이므로 해당 번들에는 명령어 두 개만 들어감.
  • 처음에는 AArch64 경험을 바탕으로 64비트 주소를 불러오는 movl r8 = target64와 br.cond.sptk r8의 조합에 가까울 것으로 생각함.
  • 하지만 범용 레지스터를 통한 간접 점프는 불가능하며, 먼저 주소를 분기 레지스터로 옮겨야 함.
  • movl이 슬롯 두 개를 차지하는 상황에서 분기 레지스터로 옮기는 명령어까지 포함하면 총 네 슬롯이 필요해 번들 용량을 초과함.

함수 앞에 보이는 번들

  • 오래된 Itanium 바이너리에서는 여러 함수 앞에 다음과 같은 여유 번들처럼 보이는 구성이 나타남.
  • break.m 0
  • break.i 0
  • break.i 0
  • 이 번들은 중단점(breakpoint) 명령어로 채워져 있어 처음에는 핫 패칭용 공간처럼 보일 수 있음.
  • 그러나 일부 함수에는 이 번들이 없으며, 자세히 살펴보면 핫 패칭 공간이 아니라 모든 함수의 시작을 32바이트 경계에 맞추는 패딩임.

각주

  • ¹ 형식상 이는 p0를 조건자로 사용하는 조건부 긴 분기 명령어이며, 정적으로 분기 실행으로 예측됨.
  • p0 레지스터는 참으로 고정되어 있으므로 어셈블러는 디스어셈블리에서 p0를 생략함.