JMCInstrumenter

JMCInstrumenter Pass 会在每个有调试信息的函数入口处插入一次对 __CheckForDebuggerJustMyCode 的调用,并自动生成默认实现和标志全局变量,以支持“Just My Code”调试。

背景:当我们在 IDE(如 Visual Studio)或调试器里调试本地 C/C++ 代码时,经常只关心“自己写的业务逻辑”——而不想单步进入运行时库、编译器插桩或 STL 之类的实现细节。微软在 MSVC 下把这个功能叫作 “Just My Code” (JMC);LLVM 也支持类似的体验。为此,需要在编译产出的机器码里“打标签”,告诉调试器「这些指令是用户代码/这些不是」,于是就有了 JMCInstrumenter 这个 Pass:它在每个函数入口插入一次钩子调用,runtime/debugger 就据此区分用户与非用户代码。

  • Just My Code (JMC):调试特性,用来区分“用户自己写的代码”与运行时/库代码。

假设有个用户函数放在 src/foo.c:

; 原始函数
define i32 @foo(i32 %x) {}

该Pass 会:

  1. 生成全局变量 __D1234ABC_foo@c,放在 .data.just.my.code 段,类型 i8 初始值 1。
    2.(若无现成)创建一个空的 __JustMyCode_Default 函数,并:
    • ELF 下重命名为 __CheckForDebuggerJustMyCode、弱链接;
    • MSVC 下用 /alternatename: 绑定。
  2. 在 @foo 的入口插入:
call void @__CheckForDebuggerJustMyCode(i8* bitcast (i8* @__D1234ABC_foo@c to i8*))

调试器在运行时就能识别“从这里开始是用户代码”。


该 Pass 支持 ELF 和 MSVC,但是默认是禁用的。