emit_fcache_enter_common
>>> append_fcache_enter_prologue
mv a1, a5 # dont care
mv a5, a0 # 将 ARG1(dc) 赋值给 a5,因为 a5 是 REG_DCXT
...
>>>>>> insert_load_dr_tls_base
sd tp, 0(a5) # 将原始 tp 放到 dc 的 X0 slot 中保存
ld tp, -8(tp) # 拿到 dtv.private 所指向的结构体(spill_state)
tp 从这里开始指向 spill_state
>>> append_setup_fcache_target
ld a0, NEXT_TAG_OFFSET(a5) # 初始化完成后跳转到的地址,加载到 a0
sd a0, A2_SLOT(tp) # 把 a0 的值放到 A2 slot
>>> body
ld a0, 96(a5) # 把 dc->a0 加载到 a0
ld a1, 104(a5) # 把 dc->a1 加载到 a1
sd a0, 0(tp) # 把 a0 保存到 spill_state A0 slot
sd a1, 8(tp) # 把 a1 保存到 spill_state A1 slot
>>> append_restore_xflags (用了 a0)
>>> append_restore_gpr
ld a0, REG_OFFSET(tp)(a5) # 把 dc->tp 加载到 a0
sd a0, stolen_slot(tp) # 把 a0 存进 spill state stolen slot
sd tp, REG_OFFSET(tp)(a5) # 把 tp 存到到 dc->tp
... 所有寄存器(除 tp)都替换为 dc 中的值
>>> append_jmp_to_fcache_target
ld a0, A2_SLOT(tp) # 把 A2 slot 的值放回 A0(跳转地址)
jr a0
| jump
insert_fragment_prefix
ld a0, 0(tp) # 从 spill_state A0 slot 加载到 a0
ld a1, 8(tp) # 从 spill_state A1 slot 加载到 a1
到这里,除了 tp,所有的寄存器的值都是 dc 中的值了
tp 指向了 spill_state (TODO:所有读写 tp 的指令都需要 mangle!!)
actual bb
| jump to exit stub
insert_exit_stub_other_flags
sd a0, 0(tp) # 把 a0 的值存回 spill_state
sd a1, 8(tp) # 把 a1 的值存回 spill_state
li a0, link_stub # 把 link_stub 地址存入 a0
auipc a1, 0
ld a1, xxx(a1) # a1 中保存 exit_stub 最后的那个地址,也就是 fcache_return 的地址
jr a1
| jump
append_fcache_return_common
>>> append_prepare_fcache_return
sd a5, A3_SLOT(tp) # a5 存到 spill_state A3 slot
ld a5, DC_SLOT(tp) # 将 spill_state dc slot 放入 a5
此时,a5 又恢复了“正常”了!
>>> append_save_gpr
... # 将除 A0, A1 外的寄存器保存到 dc
ld a1, A3_SLOT(tp)
sd a1, REG_OFFSET(a5)(a5) # 把正确的 A5 值保存到 dc
ld a1, stolen_slot(tp)
sd a1, REG_OFFSET(tp)(a5) # 把正确的 tp 保存到 dc
ld tp, 0(a5) # 把原始 tp 加载回来
>>> body
ld sp, dstack_offs(a5) # 切换到一个干净的栈上
... # 把 fcsr 写回 dc
sd a0, last_exit(a5) # dc->last_exit = (link_stub)
>>> append_call_dispatch
>>>>>> dr_insert_call_noreturn (TODO: port to RISC-V maybe?)
call d_r_dispatch with no return.
所以问题的原因是最后一个 bb 回到
d_r_dispatch 的时候, dcontext->thread_stats 不知道怎么的被改了,这他妈也太怪了
ksco 的工作日志
emit_fcache_enter_common >>> append_fcache_enter_prologue mv a1, a5 # dont care mv a5, a0 # 将 ARG1(dc) 赋值给 a5,因为 a5 是 REG_DCXT ... >>>>>> insert_load_dr_tls_base sd tp, 0(a5) # 将原始 tp 放到 dc 的 X0 slot 中保存 ld tp, -8(tp) # 拿到 dtv.private 所指向的结构体(spill_state)…
append_save_gpr 这里需要把 tls slots 中 a0 和 a1 的值放回 dc ,不然下一个 bb 执行的时候,dc 的状态是错误的!
ksco 的工作日志
append_save_gpr 这里需要把 tls slots 中 a0 和 a1 的值放回 dc ,不然下一个 bb 执行的时候,dc 的状态是错误的!
这里不能用
a0 作为 scratch reg!!!!因为 a0 里面存着 last exit 。对于入职已经满一年的 PLCT 员工而言,6 月也是一个告别的季节:PLCT 实验室将会从 6 月底开始,鼓励和要求已经可以独当一面的青年工程师离开 PLCT 实验室,走出去,在更大的平台上做出超越过去的自己的成绩。此次团队组织调整将会涉及近一半的员工,延续到 2023Q3 结束。悲伤与痛苦都不可避免,也无需回避。让我们且歌且行,相互祝福,迈向更为广阔的世界。
(草)
(草)
fragment writes all 6 flags prior to reading any
bb ilist before mangling:
TAG 0x00000000000100c4
<raw 0x00000000000100c4-0x00000000000100c8>::
+0 L3 @0x0000003dd284dc98 ff010113 addi %sp -16 -> %sp
---- multi-instr boundary ----
<raw 0x00000000000100c8-0x00000000000100cc>::
+4 L3 @0x0000003dd284dd68 00113423 sd %ra -> +0x08(%sp)[8byte]
---- multi-instr boundary ----
<raw 0x00000000000100cc-0x00000000000100d0>::
+8 L3 @0x0000003dd284ddd8 02b00513 addi %zero 43 -> %a0
---- multi-instr boundary ----
<raw 0x00000000000100d0-0x00000000000100d4>::
<translation 0x00000000000100d0>::
+12 L3 @0x0000003dd284de90 fe1ff0ef jal $0x00000000000100b0 -> %ra
---- multi-instr boundary ----
END 0x00000000000100c4
bb ilist after mangling:
TAG 0x00000000000100c4
<raw 0x00000000000100c4-0x00000000000100c8>::
+0 L3 @0x0000003dd284dc98 ff010113 addi %sp -16 -> %sp
---- multi-instr boundary ----
<raw 0x00000000000100c8-0x00000000000100cc>::
+4 L3 @0x0000003dd284dd68 00113423 sd %ra -> +0x08(%sp)[8byte]
---- multi-instr boundary ----
<raw 0x00000000000100cc-0x00000000000100d0>::
+8 L3 @0x0000003dd284ddd8 02b00513 addi %zero 43 -> %a0
---- multi-instr boundary ----
+12 m4 @0x0000003dd284df00 000100b7 lui 0x10 -> %ra
---- multi-instr boundary ----
+16 m4 @0x0000003dd284df70 0d40809b addiw %ra 212 -> %ra
---- multi-instr boundary ----
END 0x00000000000100c4
Before mangle 的 bb 似乎不太对,after mangle 之后,jal 直接被删掉了,所以 before 应该复制一份 position dependent 的,然后标记为 meta instruction,但我好像没在 Aarch64 port 上看到这个行为 🤔️