Подтвердить что ты не робот

Как работает обратная отладка?

У GDB есть новая версия, которая поддерживает обратную отладку (см. http://www.gnu.org/software/gdb/news/reversible.html). Мне интересно, как это работает.

Чтобы получить обратную отладочную работу, мне кажется, что вам нужно сохранить все состояние машины, включая память для каждого шага. Это сделало бы производительность невероятно медленной, не говоря уже об использовании большого количества памяти. Как решаются эти проблемы?

4b9b3361

Ответ 1

Я поддерживаю gdb и один из авторов новой обратной отладки. Я был бы рад поговорить о том, как это работает. Как предположили несколько человек, вам нужно сохранить достаточно состояние машины, которое вы можете восстановить позже. Существует несколько схем, одним из которых является просто сохранение регистров или мест памяти, которые изменяются каждой машинной инструкцией. Затем, чтобы "отменить" эту инструкцию, вы просто возвращаете данные в эти регистры или ячейки памяти.

Да, это дорого, но современный cpus настолько быстр, что когда вы все равно интерактивны (делаете степпинг или точки останова), вы на самом деле этого не замечаете.

Ответ 3

Обратите внимание, что вы не должны забывать использовать симуляторы, виртуальные машины и аппаратные устройства для реализации обратного выполнения.

Еще одно решение для его реализации - отслеживать выполнение на физическом оборудовании, например, GreenHills и Lauterbach в их аппаратных отладчиках. Исходя из этого фиксированного следа действия каждой команды, вы можете перейти в любую точку трассы, удалив последствия каждой команды по очереди. Обратите внимание, что это предполагает, что вы можете отслеживать все, что влияет на состояние, видимое в отладчике.

Другим способом является использование метода контрольной точки + повторного выполнения, который используется VmWare Workstation 6.5 и Virtutech Simics 3.0 (и более поздних версий) и который, кажется, подходит к Visual Studio 2010. Здесь вы используете виртуальную машину или симулятор, чтобы получить уровень косвенности при выполнении системы. Вы регулярно выгружаете все состояние на диск или в память, а затем полагаетесь на то, что симулятор может детерминировать повторный запуск одного и того же пути программы.

Упрощенный, он работает следующим образом: скажите, что вы находитесь в момент времени T при выполнении системы. Чтобы перейти ко времени T-1, вы берете контрольную точку из точки t < T, а затем выполните (T-t-1) циклы, чтобы закончить один цикл раньше, чем вы были. Это можно сделать очень хорошо работать и применять даже для рабочих нагрузок, которые делают дисковый ввод-вывод, состоят из кода на уровне ядра и выполняет работу драйвера устройства. Ключ должен иметь симулятор, который содержит всю целевую систему, со всеми ее процессорами, устройствами, памятью и IO. Подробнее см. почтовый список gdb и обсуждение, следующее в списке рассылки gdb. Я использую этот подход довольно регулярно, чтобы отлаживать хитрый код, особенно в драйверах устройств и ранних загрузках ОС.

Другим источником информации является белая бумага Virtutech по контрольной точке (которую я написал в полном разглашении).

Ответ 4

Во время сеанса EclipseCon мы также спросили, как они это делают с

Ответ 5

Хотя этот вопрос старый, большинство ответов тоже, и как остается интересной темой, я отправляю ответ 2015 года. В главах 1 и 2 моей магистерской диссертации Объединение обратной отладки и живого программирования в направлении визуального мышления в компьютерном программировании охватывает некоторые из исторических подходов к обратному отладке (особенно сфокусирован на методе моментального снимка (или контрольной точки) и повтора), и объясняет разницу между ним и всезнающей отладкой:

Компьютер, предварительно выполнив программу до некоторой точки, должен действительно предоставить нам информацию об этом. Такое улучшение возможно и встречается в так называемых всезначительных отладчиках. Они обычно классифицируются как обратные отладчики, хотя их можно более точно описать как "отладчики журнала истории", поскольку они просто записывают информацию во время выполнения для просмотра или запроса позже, вместо того, чтобы позволить программисту фактически шаг назад во времени в исполняющей программе, "Omniscient" исходит из того факта, что вся история состояния программы, записанная, доступна отладчику после выполнения. Тогда нет необходимости повторно запускать программу, и нет необходимости в ручном кодовом контроле.

Всеобъемлющая отладка, основанная на программном обеспечении, началась с системы EXDAMS 1969 года, где она называлась "история-время отладки". Отладчик GNU, GDB, поддерживал всезначительную отладку с 2009 года, используя функцию "запись процесса и воспроизведение". TotalView, UndoDB и Chronon, по-видимому, являются лучшими всеведущими отладчиками, доступными в настоящее время, но являются коммерческими системами. TOD для Java, по-видимому, является лучшей альтернативой с открытым исходным кодом, которая использует частичный детерминированный повтор, а также частичный захват трассировки и распределенную базу данных, позволяющую записывать большие объемы информации.

Отладочные устройства, которые не просто позволяют осуществлять навигацию по записи, но на самом деле способны отступить назад во время выполнения, также существуют. Их можно более точно описать как временные, временные, двунаправленные или обратные отладчики.

Первой такой системой был прототип COPE 1981 года...

Ответ 6

Натан Феллман писал:

Но обратная отладка позволяет только отменить следующие команды и команды ввода, которые вы набрали, или позволяет вам отменить любое количество инструкций?

Вы можете отменить любое количество инструкций. Вы не ограничены, например, только останавливаясь в тех точках, где вы остановились, когда вы шли вперед. Ты можешь установить новую точку останова и вернуться к ней назад.

Например, если я устанавливаю точку останова в команде и позволяю ей работать до тех пор, могу ли я снова вернуться к предыдущей инструкции, даже если я пропустил ее?

Да. Пока вы включили режим записи, прежде чем вы перейдете к точке останова.

Ответ 7

Здесь показано, как работает другой обратный отладчик, называемый ODB. Выдержка:

Omniscient Debugging - это идея сбор "временных марок" на каждом "достопримечательность" (установка значения, делая вызов метода, бросать/ловить исключение) в программы, а затем программист использовать эти метки времени для изучить историю этой программы работать.

ODB... вставки кода в классы программы как они загружаются и когда программа выполняется, события записываются.

Я предполагаю, что gdb работает одинаково.

Ответ 8

Обратная отладка означает, что вы можете запустить программу назад, что очень полезно для отслеживания причины проблемы.

Вам не нужно сохранять полное состояние машины для каждого шага, только изменения. Это, вероятно, все еще довольно дорого.

Ответ 9

Mozilla rr - более надежная альтернатива обратной отладке GDB

https://github.com/mozilla/rr

Встроенная запись и воспроизведение GDB имеет серьезные ограничения, например, нет поддержки инструкций AVX: Сбой обратной отладки gdb с " Запись процесса не поддерживает инструкцию 0xf0d по адресу "

Перевернутая сторона рр:

  • гораздо надежнее в настоящее время
  • также предлагает интерфейс GDB с протоколом gdbserver, что делает его отличной заменой
  • небольшое падение производительности для многих программ

В следующем примере демонстрируются некоторые из его функций, в частности команды reverse-next, reverse-step и reverse-continue.

Установите Ubuntu 16.04:

sudo apt-get install rr linux-tools-common linux-tools-generic linux-cloud-tools-generic
sudo cpupower frequency-set -g performance
# Overcome "rr needs /proc/sys/kernel/perf_event_paranoid <= 1, but it is 3."
echo 'kernel.perf_event_paranoid=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Но также рассмотрите возможность компиляции из исходного кода, чтобы получить последние обновления, это было несложно.

Тестовая программа:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int f() {
    int i;
    i = 0;
    i = 1;
    i = 2;
    return i;
}

int main(void) {
    int i;

    i = 0;
    i = 1;
    i = 2;

    /* Local call. */
    f();

    printf("i = %d\n", i);

    /* Is randomness completely removed?
     * Recently fixed: https://github.com/mozilla/rr/issues/2088 */
    i = time(NULL);
    printf("time(NULL) = %d\n", i);

    return EXIT_SUCCESS;
}

скомпилируйте и запустите:

gcc -O0 -ggdb3 -o reverse.out -std=c89 -Wextra reverse.c
rr record ./reverse.out
rr replay

Теперь вы остались внутри сеанса GDB, и вы можете правильно отменить отладку:

(rr) break main
Breakpoint 1 at 0x55da250e96b0: file a.c, line 16.
(rr) continue
Continuing.

Breakpoint 1, main () at a.c:16
16          i = 0;
(rr) next
17          i = 1;
(rr) print i
$1 = 0
(rr) next
18          i = 2;
(rr) print i
$2 = 1
(rr) reverse-next
17          i = 1;
(rr) print i
$3 = 0
(rr) next
18          i = 2;
(rr) print i
$4 = 1
(rr) next
21          f();
(rr) step
f () at a.c:7
7           i = 0;
(rr) reverse-step
main () at a.c:21
21          f();
(rr) next
23          printf("i = %d\n", i);
(rr) next
i = 2
27          i = time(NULL);
(rr) reverse-next
23          printf("i = %d\n", i);
(rr) next
i = 2
27          i = time(NULL);
(rr) next
28          printf("time(NULL) = %d\n", i);
(rr) print i
$5 = 1509245372
(rr) reverse-next
27          i = time(NULL);
(rr) next
28          printf("time(NULL) = %d\n", i);
(rr) print i
$6 = 1509245372
(rr) reverse-continue
Continuing.

Breakpoint 1, main () at a.c:16
16          i = 0;

При отладке сложного программного обеспечения вы, вероятно, дойдете до точки сбоя, а затем попадете в глубокую рамку. В этом случае, не забывайте, что для reverse-next в старших кадрах вы должны сначала:

reverse-finish

до этого кадра, просто сделать обычный up недостаточно.