КС:2015:Проект:debuger — различия между версиями

Материал из Wiki - Факультет компьютерных наук
Перейти к: навигация, поиск
(Итоговая оценка)
(Что это за проект)
 
(не показано 8 промежуточных версии этого же участника)
Строка 2: Строка 2:
  
 
=== Введение ===
 
=== Введение ===
Linux предоставляет ряд средств для отладки пользователем своих процессов. Например, можно посмотреть в память или регистры другого процесса или даже поменять там что-то. При помощи этих средств реализованы, к примеру, gdb и strace.
+
Часто лучший способ понять, каким образом процесс пришёл в какое-то интересное состояние (например, в которое не должен был прийти никогда), - это проследить по шагам за его выполнением. Типичные способы, которые используются на практике:
 +
 
 +
* К процессу можно присоединиться при помощи gdb и отследить его выполнение по шагам. Неудобства: во-первых, не всегда есть возможность присоединиться gdb в интерактивном режиме. Во-вторых, проблема может быть тяжело воспроизводимой, и шагов придётся делать очень много.
 +
* В программу можно добавить отладочную печать, и процесс в процессе работы будет записывать в поток своё состояние.
 +
 
 +
Как можно добавить отладочную печать?
 +
* Например, можно модифицировать исходный код и пересобрать программу. Можно это сделать руками. Можно при помощи кодогенерации, так это делает, например, [http://ndevilla.free.fr/etrace/ etrace]. Недостаток: не всегда есть возможность пересобрать программу.
 +
* Можно воспользоваться системным вызовом [http://man7.org/linux/man-pages/man2/ptrace.2.html ptrace] и добавить [https://en.wikipedia.org/wiki/INT_%28x86_instruction%29#INT_3 software breakpoints] в интересующие места, как это делает [http://man7.org/linux/man-pages/man1/strace.1.html strace] или [http://www.gnu.org/software/gdb/ gdb]. Или даже ещё проще - написать [http://ndevilla.free.fr/etrace/ скрипт] для gdb. Недостаток этого подхода: это может быть очень медленно, если мы хотим трассировать большое количество событий.
 +
* Можно воспользоваться динамической линковкой через [http://samanbarghi.com/blog/2014/09/05/how-to-wrap-a-system-call-libc-function-in-linux/ LD_PRELOAD или ld --wrap], как это делает [http://man7.org/linux/man-pages/man1/ltrace.1.html ltrace]. Ограничение - нужна динамическая линковка.
 +
* И, наконец, мы можем на лету изменить код программы (это называется [https://en.wikipedia.org/wiki/Instrumentation_%28computer_programming%29 инструментированием]). Так делает, например, [http://valgrind.org/docs/manual/cl-manual.html callgrind].
  
 
=== Что требуется ===
 
=== Что требуется ===
Вам предлагается реализовать простой неинтерактивный дебагер, который будет выводить в файл историю вызовов функций в программе.
+
Вам предлагается написать менее функциональный, но существенно более быстрый аналог callgrind с использованием инструментирования бинарного кода, воспользовавшись библиотекой [https://ru.wikipedia.org/wiki/DynInst DynInst] или аналогичной (можно даже взять callgrind и отрезать от него всё лишнее). Ваша программа должна будет выводить в поток все вызовы функций в исследуемом процессе.
 +
 
 +
=== Слайды ===
 +
[https://yadi.sk/i/O7AslJNLjKSw6 Лежат здесь.]
  
 
== Чему вы научитесь ==
 
== Чему вы научитесь ==
Строка 24: Строка 36:
  
 
=== Требования на зачет в конце 1-го модуля ===
 
=== Требования на зачет в конце 1-го модуля ===
Нужно будет реализовать программу, которая умеет трейсить вызовы функций и выводить их имена в файл.
+
Нужно будет реализовать программу (трейсер), которая умеет логировать все события вызова функций и возврата из них.
  
 
=== Итоговая оценка ===
 
=== Итоговая оценка ===
 
* '''4 балла'''. Реализованы требования на зачёт в конце первого модуля.
 
* '''4 балла'''. Реализованы требования на зачёт в конце первого модуля.
* '''8 баллов'''. Трейсер выводит имена вызываемых функций, а также, используя отладочную информацию в отлаживаемом бинарнике, выводит значения параметров, с которыми эта функция была вызвана, номер строки и название файла исходого кода, из которых было скомпилировано место вызова.
+
* '''8 баллов'''. Трейсер, используя отладочную информацию, выводит номер строки в файле, из которого было скомпилировано место вызова, а также значения аргументов и возвращаемое значение.
* '''+2 балла'''. Трейсер умеет выводить текущий стек вызовов в человекочитаемом формате.
+
* '''+2 балла'''. Поддерживаются многопоточные приложения.
* '''+2 балла'''. Трейсер умеет выводить возвращаемое значение функции.
+
* '''+2 балла'''. Поддерживаются заинлайненные функции.
 +
* '''+N баллов'''. N = 4 * max(0, aver(1 - T<sub>tracer</sub> / T<sub>callgrind</sub>)) за обгон callgrind на предложенных тестах (постараемся выбрать максимально приближенные к реальности).

Текущая версия на 17:18, 25 сентября 2015

Что это за проект

Введение

Часто лучший способ понять, каким образом процесс пришёл в какое-то интересное состояние (например, в которое не должен был прийти никогда), - это проследить по шагам за его выполнением. Типичные способы, которые используются на практике:

  • К процессу можно присоединиться при помощи gdb и отследить его выполнение по шагам. Неудобства: во-первых, не всегда есть возможность присоединиться gdb в интерактивном режиме. Во-вторых, проблема может быть тяжело воспроизводимой, и шагов придётся делать очень много.
  • В программу можно добавить отладочную печать, и процесс в процессе работы будет записывать в поток своё состояние.

Как можно добавить отладочную печать?

  • Например, можно модифицировать исходный код и пересобрать программу. Можно это сделать руками. Можно при помощи кодогенерации, так это делает, например, etrace. Недостаток: не всегда есть возможность пересобрать программу.
  • Можно воспользоваться системным вызовом ptrace и добавить software breakpoints в интересующие места, как это делает strace или gdb. Или даже ещё проще - написать скрипт для gdb. Недостаток этого подхода: это может быть очень медленно, если мы хотим трассировать большое количество событий.
  • Можно воспользоваться динамической линковкой через LD_PRELOAD или ld --wrap, как это делает ltrace. Ограничение - нужна динамическая линковка.
  • И, наконец, мы можем на лету изменить код программы (это называется инструментированием). Так делает, например, callgrind.

Что требуется

Вам предлагается написать менее функциональный, но существенно более быстрый аналог callgrind с использованием инструментирования бинарного кода, воспользовавшись библиотекой DynInst или аналогичной (можно даже взять callgrind и отрезать от него всё лишнее). Ваша программа должна будет выводить в поток все вызовы функций в исследуемом процессе.

Слайды

Лежат здесь.

Чему вы научитесь

1. Узнаете, как устроены отладчики.

2. Узнаете, как устроена память процесса.

3. Подружитесь с эльфом и дварфом.

Начальные требования

1. Технический английский язык.

2. Знание C++.

3. Любознательность.

Критерии оценивания

Требования на зачет в конце 1-го модуля

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

Итоговая оценка

  • 4 балла. Реализованы требования на зачёт в конце первого модуля.
  • 8 баллов. Трейсер, используя отладочную информацию, выводит номер строки в файле, из которого было скомпилировано место вызова, а также значения аргументов и возвращаемое значение.
  • +2 балла. Поддерживаются многопоточные приложения.
  • +2 балла. Поддерживаются заинлайненные функции.
  • +N баллов. N = 4 * max(0, aver(1 - Ttracer / Tcallgrind)) за обгон callgrind на предложенных тестах (постараемся выбрать максимально приближенные к реальности).