계요
kprobe는 tracepoint와는 다르게 동적으로 커널의 거의 대부분의 주소에서 debugging과 performance분석을 가능하게 하는 툴이다. kprobe는 원하는 위치에 int3 breakpoint을 걸어서 int3이 불리면 do_iret3 handler에서 지정된 핸들러를 호출하는 것으로 구현된다. kprobe는 kprobe와 kretprobe로 구성되는데 전자는 함수가 호출될때 불리며, 후자는 함수가 끝날때 불리게 된다. kprobe는 커널에서 내부적으로 사용되거나 (eBPF구현을 위하여 등등), 혹은 kernel module의 형태로 사용자에 의해서 삽입되게 된다.
호출 방식
Kprobe가 등록되면, probed된 명령어를 따로 저장하고 그 명령어 위치에 int3과 같은 breakpoint을 걸게 된다. CPU가 breakpoint를 만나면, CPU의 레지스터가 저장되고 지정된 pre_handler를 실행시킨다. 그 후 probed된 명령어를 실행시킨후, 만약 지정된 post_handler가 있다면 이를 실행시키고 다시 probed된 영역에 int3를 걸고 호출을 종료한다. kprobe내부 에서는 CPU의 register set을 바꿀수도 있으며, 이러한 만약 IP레지스터를 바꿀 경우에는 pre_handler에서 0이 아닌 값을 호출하여 반드시 kprobe가 지정된 IP주소로 바로 jump할 수 있도록 해주어야 한다. 그렇지 않을 경우 kprobe는 다시 instruction이 바뀐다고 생각하지만, jump되는 곳은 다음 명령 시행 시점이 아닌 inconsistency가 발생한다.
Jump optimization을 이용하는 방법도 있는데, kprobe가 만약 jump optimization을 사용하게 되면 interrupt로 인한 overhead를 줄이기 위해서 breakpoint instruction이 아니라, jump instruction을 사용한다. 만약 jump optimization을 사용할 수 없는 환경이면 kprobe는 그냥 int3을 사용하여 probing을 시행시킨다.