Valgrind 中的内联汇编代码片段是什么意思?

问题描述 投票:0回答:1

这在 Valgrind 的

VALGRIND_DO_CLIENT_REQUEST_EXPR
中意味着什么?

__asm__ volatile (
  __SPECIAL_INSTRUCTION_PREAMBLE
  /* %RDX = client_request ( %RAX ) */        
  "xchgq %rbx, %rbx"
  : "=d" (_zzq_result)
  : "a" (&_zzq_args[0]), "0" (_zzq_default)
  : "cc", "memory"
)

其中

__SPECIAL_INSTRUCTION_PREAMBLE
定义为:

#define __SPECIAL_INSTRUCTION_PREAMBLE    \
  "rolq $3,  %%rdi ; rolq $13, %%rdi\n\t" \
  "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"

似乎有些黑魔法。

c assembly x86-64 valgrind inline-assembly
1个回答
3
投票

“客户端”可执行文件无法直接与 Valgrind 主机交互。客户端和主机有独立的内存空间。与 Purify 和 Sanitizers 等工具不同,Valgrind 无法为客户端提供任何 C 函数来自省来自 Valgrind 主机的任何信息。

客户端请求机制使用短的 asm 前导码作为 Valgrind 主机的标记。这是一个没有副作用的指令序列,也是任何编译器都不会发出的序列。如果编译器生成的代码被 Valgrind 错误地视为客户端请求,那将是一个大问题。您提供的 amd64 示例使用 RDI 的 4 次左循环,总共 128 位,保持不变。接下来是 RBX 与自身的交换。其他 CPU 架构使用类似的“无操作”序列来发出客户端请求信号。

由于这些指令不执行任何操作,因此它们可以编译成发布版本,并且只有非常小的大小和运行时开销。

这里是 Valgrind 源代码中的注释,解释了这些特殊指令(在 VEX/priv/guest_amd64_toIR.c 中 - 在 Valgrind 中我们可以互换使用“guest”和“client”)。


/* "Special" instructions.

   This instruction decoder can decode three special instructions
   which mean nothing natively (are no-ops as far as regs/mem are
   concerned) but have meaning for supporting Valgrind.  A special
   instruction is flagged by the 16-byte preamble 48C1C703 48C1C70D
   48C1C73D 48C1C733 (in the standard interpretation, that means: rolq
   $3, %rdi; rolq $13, %rdi; rolq $61, %rdi; rolq $51, %rdi).
   Following that, one of the following 3 are allowed (standard
   interpretation in parentheses):

      4887DB (xchgq %rbx,%rbx)   %RDX = client_request ( %RAX )
      4887C9 (xchgq %rcx,%rcx)   %RAX = guest_NRADDR
      4887D2 (xchgq %rdx,%rdx)   call-noredir *%RAX
      4887F6 (xchgq %rdi,%rdi)   IR injection

   Any other bytes following the 16-byte preamble are illegal and
   constitute a failure in instruction decoding.  This all assumes
   that the preamble will never occur except in specific code
   fragments designed for Valgrind to catch.

   No prefixes may precede a "Special" instruction.
*/

以及相应的代码

   /* Spot "Special" instructions (see comment at top of file). */
   {
      const UChar* code = guest_code + delta;
      /* Spot the 16-byte preamble:
         48C1C703   rolq $3,  %rdi
         48C1C70D   rolq $13, %rdi
         48C1C73D   rolq $61, %rdi
         48C1C733   rolq $51, %rdi
      */
      if (code[ 0] == 0x48 && code[ 1] == 0xC1 && code[ 2] == 0xC7 
                                               && code[ 3] == 0x03 &&
          code[ 4] == 0x48 && code[ 5] == 0xC1 && code[ 6] == 0xC7 
                                               && code[ 7] == 0x0D &&
          code[ 8] == 0x48 && code[ 9] == 0xC1 && code[10] == 0xC7 
                                               && code[11] == 0x3D &&
          code[12] == 0x48 && code[13] == 0xC1 && code[14] == 0xC7 
                                               && code[15] == 0x33) {
         /* Got a "Special" instruction preamble.  Which one is it? */
         if (code[16] == 0x48 && code[17] == 0x87 
                              && code[18] == 0xDB /* xchgq %rbx,%rbx */) {
            /* %RDX = client_request ( %RAX ) */
            DIP("%%rdx = client_request ( %%rax )\n");
            delta += 19;
            jmp_lit(&dres, Ijk_ClientReq, guest_RIP_bbstart+delta);
            vassert(dres.whatNext == Dis_StopHere);
            goto decode_success;
         }
         else
© www.soinside.com 2019 - 2024. All rights reserved.