Что делает команда gdb 'x'?

Я читаю книгу о взломе, и в ней есть глава о сборке.

Ниже приведена моя маленькая программа, написанная на C.

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int i;

    for (i = 0; i < 10; i++) {
        puts("Hello World!");
    }

    return 0;
}

И следующее: gdb test:

(gdb) break main
Breakpoint 1 at 0x40050f: file main.c, line 7.
(gdb) run
Breakpoint 1, main (argc=1, argv=0x7fffffffe708) at main.c:7
7       for (i = 0; i < 10; i++) {
(gdb) disassemble main
Dump of assembler code for function main:
   0x0000000000400500 <+0>: push   rbp
   0x0000000000400501 <+1>: mov    rbp,rsp
   0x0000000000400504 <+4>: sub    rsp,0x20
   0x0000000000400508 <+8>: mov    DWORD PTR [rbp-0x14],edi
   0x000000000040050b <+11>:    mov    QWORD PTR [rbp-0x20],rsi
=> 0x000000000040050f <+15>:    mov    DWORD PTR [rbp-0x4],0x0
   0x0000000000400516 <+22>:    jmp    0x400526 <main+38>
   0x0000000000400518 <+24>:    mov    edi,0x4005c4
   0x000000000040051d <+29>:    call   0x4003e0 <[email protected]>
   0x0000000000400522 <+34>:    add    DWORD PTR [rbp-0x4],0x1
   0x0000000000400526 <+38>:    cmp    DWORD PTR [rbp-0x4],0x9
   0x000000000040052a <+42>:    jle    0x400518 <main+24>
   0x000000000040052c <+44>:    mov    eax,0x0
---Type <return> to continue, or q <return> to quit---
   0x0000000000400531 <+49>:    leave  
   0x0000000000400532 <+50>:    ret    
End of assembler dump.

Следующая часть - это то, что я не понимаю. Обратите внимание, что $rip - это "указатель инструкции" и указывает на 0x000000000040050f <+15>

(gdb) x/x $rip
0x40050f <main+15>: 0x00fc45c7
(gdb) x/12x $rip
0x40050f <main+15>: 0x00fc45c7  0xeb000000  0x05c4bf0e  0xbee80040
0x40051f <main+31>: 0x83fffffe  0x8301fc45  0x7e09fc7d  0x0000b8ec
0x40052f <main+47>: 0xc3c90000  0x1f0f2e66  0x00000084  0x1f0f0000
(gdb) x/8xb $rip
0x40050f <main+15>: 0xc7    0x45    0xfc    0x00    0x00    0x00    0x00    0xeb
(gdb) x/8xh $rip
0x40050f <main+15>: 0x45c7  0x00fc  0x0000  0xeb00  0xbf0e  0x05c4  0x0040  0xbee8
(gdb) x/8xw $rip
0x40050f <main+15>: 0x00fc45c7  0xeb000000  0x05c4bf0e  0xbee80040
0x40051f <main+31>: 0x83fffffe  0x8301fc45  0x7e09fc7d  0x0000b8ec

Первая команда x/x $rip выводит 0x40050f <main+15>: 0x00fc45c7.

Это инструкция на 0x40050f? Является ли 0x00fc45c7 таким же, как mov DWORD PTR [rbp-0x4],0x0 (собранная инструкция на 0x40050f)?

Во-вторых, если это инструкция, каковы эти шестнадцатеричные числа из вывода команд x/12x $rip, x/8xw $rip, x/8xh $rip?

Ответ 1

Что касается (1), вы получили это правильно.

Что касается (2), команда x имеет до 3 спецификаторов: сколько объектов нужно печатать; в каком формате; и какой размер объекта. Во всех ваших примерах вы выбираете печать как hex (x). Что касается первого спецификатора, вы просите распечатать 12, 8, 8 объектов.

Что касается последнего спецификатора в ваших случаях:
x/12x не имеет, поэтому gdb по умолчанию предполагает, что вам нужны двойные слова, ака, в 4 байтовых кусках. Обратите внимание, что вы обнаружите двойное слово, которое иногда определяется по-разному, но в Intel x86 assembly/gdb оно равно 4 байтам. Как правило, я всегда указывал, что именно вы хотите, а не отказываться от настроек по умолчанию.

x/8xw делает то же самое, для 8 объектов, так как вы явно запросили теперь слова.

x/8xh запрашивает фрагменты байтов размером в половину слова, поэтому объекты печатаются в 2 байтовых кусках. В случае, если вы задаетесь вопросом, почему объединение двух соседних значений не соответствует тому, что было указано при печати в словах, это связано с тем, что x86 представляет собой малориентированную архитектуру. То, что это значит, подробно описано в книге erickson снова - если вы посмотрите на несколько страниц вперед, он сделает некоторые вычисления, которые могут оказаться полезными. В двух словах, если вы перекомпилируете их (2,1) (4,3),..., вы увидите, что они соответствуют.

Ответ 2

(gdb) help x
Examine memory: x/FMT ADDRESS.
ADDRESS is an expression for the memory address to examine.
FMT is a repeat count followed by a format letter and a size letter.
Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),
  t(binary), f(float), a(address), i(instruction), c(char) and s(string),
  T(OSType), A(floating point values in hex).
Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).
The specified number of objects of the specified size are printed
according to the format.

Defaults for format and size letters are those previously used.
Default count is 1.  Default address is following last thing printed
with this command or "print".