如何解释二进制文件的转储?

How to interpret a dump of binary file?

考虑二进制文件 (amd64) 的转储输出的以下部分:

$ objdump -D /lib/modules/4.16.0-1-amd64/kernel/drivers/usb/class/cdc-acm.ko
...
25f0:       e8 00 00 00 00          callq  25f5 <acm_port_dtr_rts+0x5>
25f5:       53                      push   %rbx
25f6:       48 89 fb                mov    %rdi,%rbx
25f9:       48 83 ef 20             sub    [=10=]x20,%rdi
25fd:       85 f6                   test   %esi,%esi
25ff:       74 3c                   je     263d <acm_port_dtr_rts+0x4d>
2601:       b8 03 00 00 00          mov    [=10=]x3,%eax
2606:       b9 03 00 00 00          mov    [=10=]x3,%ecx
260b:       f6 83 60 08 00 00 40    testb  [=10=]x40,0x860(%rbx)
2612:       89 83 94 07 00 00       mov    %eax,0x794(%rbx)
2618:       75 18                   jne    2632 <acm_port_dtr_rts+0x42>
261a:       48 8d 73 e8             lea    -0x18(%rbx),%rsi
261e:       45 31 c9                xor    %r9d,%r9d
2621:       45 31 c0                xor    %r8d,%r8d
2624:       ba 22 00 00 00          mov    [=10=]x22,%edx
2629:       e8 32 eb ff ff          callq  1160 <acm_ctrl_msg.isra.10>
262e:       85 c0                   test   %eax,%eax
2630:       74 09                   je     263b <acm_port_dtr_rts+0x4b>
2632:       f6 83 1c 08 00 00 02    testb  [=10=]x2,0x81c(%rbx)
2639:       75 08                   jne    2643 <acm_port_dtr_rts+0x53>
263b:       5b                      pop    %rbx
263c:       c3                      retq
263d:       89 f1                   mov    %esi,%ecx
263f:       31 c0                   xor    %eax,%eax
2641:       eb c8                   jmp    260b <acm_port_dtr_rts+0x1b>
2643:       48 8b 7b e8             mov    -0x18(%rbx),%rdi
2647:       48 c7 c6 00 00 00 00    mov    [=10=]x0,%rsi
264e:       5b                      pop    %rbx
264f:       48 83 c7 30             add    [=10=]x30,%rdi
2653:       e9 00 00 00 00          jmpq   2658 <acm_port_dtr_rts+0x68>
2658:       0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
265f:       00
...

cdc-acm.c 中的以下部分对应于上面的转储:

static void acm_port_dtr_rts(struct tty_port *port, int raise)
{
  struct acm *acm = container_of(port, struct acm, port);
  int val;
  int res;

  if (raise)
        val = ACM_CTRL_DTR | ACM_CTRL_RTS;
  else
        val = 0;

  acm->ctrlout = val;

  res = acm_set_control(acm, val);
  if (res && (acm->ctrl_caps & USB_CDC_CAP_LINE))
        dev_err(&acm->control->dev, "failed to set dtr/rts\n");
}

此外,这里使用了以下常量:

#define ACM_CTRL_DTR            0x01
#define ACM_CTRL_RTS            0x02

如何从源代码中找出转储中的哪一行对应于以下行?

val = ACM_CTRL_DTR | ACM_CTRL_RTS;

编辑

以下过程用于更改二进制文件:

hexdump -v -e "1/1 \" %02x\n\"" cdc-acm.ko.orig >text_file
<edit text_file>
xxd -r -p text_file cdc-acm.ko

如果使用调试信息进行编译,则 objdump -d -S 将源代码行与 asm 交错。 gdb 可以使用外部调试符号(比如来自 linux-image-4.16.0-1-amd64-dbg),但我认为这对反汇编内核模块没有用。

我不确定如何告诉 objdump 查找/使用它们。有关单独调试信息的更多信息,请参阅 https://www.technovelty.org/code/separate-debug-info.html,但它没有说明 objdump -S 使用它们,仅说明 gdb。


否则,ACM_CTRL_DTR | ACM_CTRL_RTS0x3,并且有一个 test/je 在 %esi 时跳过几个 mov , %eax / mov , %ecx 指令] 为零,所以这是 if(raise) 分支。在 x86-64 System V 调用约定中,第二个整数函数 arg 在 RSI/ESI 中传递,所以它是 raise 除非它被较早的 call 或您用 [ 隐藏的其他东西破坏=23=].

这两个mov指令可能是通过将val分配给其他东西来解释的,但我还没有尝试完全遵循逻辑。