#assembly #gdb #x86-64 #callstack
#сборка #gdb #x86-64 #callstack
Вопрос:
Есть ли какие-либо способы увидеть, какие значения помещаются в стек простым, предпочтительно визуальным способом? В настоящее время я использую gdb
для отладки, но мне было интересно, существуют ли какие-либо другие программы (или, возможно, даже gdb в другом режиме), чтобы иметь представление о том, как выглядит стек, когда я выполняю каждую инструкцию, например, в этой программе:
.globl main
main:
push %rbp
mov %rsp, %rbp
movb $8, -1(%rbp)
movw $30, -4(%rbp)
mov -1(%rbp), %rax
add -4(%rbp), %rax
Я знаю, что в gdb есть x/8xw $rbp
или их варианты, но я хотел бы рассматривать это почти как анимацию или постоянную визуализацию при пошаговом просмотре кода. Есть ли способ сделать это?
Ответ №1:
display
Нужно что-то печатать каждый раз, когда GDB останавливается, например
display /x (long [8])*(long*)$rsp
чтобы получать такой вывод после каждого шага. (Это из _start
, поэтому RSP указывает на argc
(0x1), затем argv[0]
(указатель), затем argv[1]
(NULL), затем envp[0]
и т.д.)
{0x1, 0x7fffffffea02, 0x0, 0x7fffffffea0e, 0x7fffffffea1e, 0x7fffffffea6c, 0x7fffffffea7e, 0x7fffffffea92}
Выражение приведения GDB работает путем разыменования $rsp
(указателя стека) как единого long
, затем преобразуя его в массив long
. Это, конечно, на самом деле не сработало бы на C, но выражения GDB используют только C-подобный синтаксис, они не являются правильными C. Возможно, есть более простой способ написать это, но это то, к чему я пришел методом проб и ошибок.
При этом qwords будут отображаться в порядке возрастания адреса памяти, начиная с того, на который указывает RSP, поэтому оно изменится, например, после call
или push
. Если вы хотите видеть RSP ниже, в красной зоне, используйте другую базу, например ($rsp-16)
или что-то в этом роде.
Если вы хотите просмотреть фрейм стека вашей функции ниже RBP, который не перемещается при нажатии / всплывании, вам может понадобиться база, подобная ($rbp - 16)
или что-то в этом роде.
Конечно, ваша x/8xw $rbp
команда не показывает вам никакой памяти, в которую хранятся ваши инструкции, потому что вы сохраняете ее ниже RBP = RSP. (На самом деле это гарантированно безопасно в системе x86-64 V ABI, которая имеет красную зону. Во многих других соглашениях о вызовах это может быть асинхронно выполнено обработчиком сигналов или отладчиком, оценивающим, print foo(1)
где foo
находится функция в вашей программе.)