Search code examples
assemblyx86-64reverse-engineeringobjdump

How to interpret a dump of binary file?


Consider the following part of output from dump of a 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    $0x20,%rdi
25fd:       85 f6                   test   %esi,%esi
25ff:       74 3c                   je     263d <acm_port_dtr_rts+0x4d>
2601:       b8 03 00 00 00          mov    $0x3,%eax
2606:       b9 03 00 00 00          mov    $0x3,%ecx
260b:       f6 83 60 08 00 00 40    testb  $0x40,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    $0x22,%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  $0x2,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    $0x0,%rsi
264e:       5b                      pop    %rbx
264f:       48 83 c7 30             add    $0x30,%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
...

The following part from cdc-acm.c corresponds to above dump:

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");
}

Also, the following constants are used here:

#define ACM_CTRL_DTR            0x01
#define ACM_CTRL_RTS            0x02

How to find out which line in the dump corresponds to the following line from source code?

val = ACM_CTRL_DTR | ACM_CTRL_RTS;

EDIT

The following procedure was used to change the binary:

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

Solution

  • If you compiled with debug info, then objdump -d -S to interleave source lines with asm. gdb can use external debug symbols (like from linux-image-4.16.0-1-amd64-dbg) but I don't think that's useful for disassembling kernel modules.

    I'm not sure how to tell objdump to look for / use them. See https://www.technovelty.org/code/separate-debug-info.html for some more info about separate debug info, but it doesn't say anything about objdump -S using them, only gdb.


    Otherwise, ACM_CTRL_DTR | ACM_CTRL_RTS is 0x3, and there's a test/je that skips over a couple mov $3, %eax / mov $3, %ecx instructions when something %esi is zero, so that's if(raise) branch. The 2nd integer function arg is passed in RSI/ESI in the x86-64 System V calling convention, so that's raise unless it's been clobbered by an earlier call or some other thing you hid with ....

    The two mov instructions are probably explained by assigning val to something else, but I haven't tried to fully follow the logic.