Шаг GDB с задержками

Есть проект, который работает с несколькими входными файлами: split2flac

Из описания проекта:

split2flac разбивает одну большую APE / Аудио изображение FLAC / TTA / WV / WAV (или набор таких файлов, рекурсивно) с листом CUE в треки FLAC / M4A / MP3 / OGG_VORBIS / WAV с тегами, переименованием, кодировкой { {1}} преобразование cue Sheet, изображений обложек альбомов. Он также использует файл конфигурации , поэтому нет необходимости каждый раз передавать много аргументов, только входной файл. Должен работать в любой POSIX-совместимой оболочке.

5
09.02.2018, 12:27
4 ответа

La CLI de Gdb admite un bucle while. No hay un comando integrado sleep, pero puede llamar al shell para ejecutar el programa sleep, o usar el intérprete de python integrado de gdb, si lo tiene. Es interrumpible con Control -C.

Método 1:

(gdb) while (1)
 >step
 >shell sleep 1
 >end

Método 2:

(gdb) python import time
(gdb) while (1)
 >step
 >python time.sleep(1)
 >end

Método 3 (definir una macro):

(gdb) define runslowly
Type commands for definition of "runslowly".
End with a line saying just "end".
>python import time
>while (1)
 >step
 >python time.sleep(1)
 >end
>end
(gdb) document runslowly
Type documentation for "runslowly".
End with a line saying just "end".
>step a line at a time, every 1 second
>end

(gdb) runslowly
11
27.01.2020, 20:31

Podrías tener el shell pipe en los comandos; aquí está la idea:

while :; do echo step; sleep 1; done | gdb arm-program

gdb lee los comandos de la tubería; ve un comando de "paso" cada segundo ad infinitum.

Es posible que desee configurar algunos puntos de interrupción -y ejecutar el programa; ajustar al gusto:

(echo br 1; echo run; while :; do echo step; sleep 1; done ) | gdb arm-program
4
27.01.2020, 20:31

expectможно автоматизировать это

#!/usr/bin/env expect
spawn -noecho gdb -q ls
expect -ex {(gdb)}
send -- "break main\r"
expect -ex {(gdb)}
send -- "run\r"
while {1} {
    expect -ex {(gdb)}
    send -- "s\r"
    sleep 1
}

или если есть риск того, что программа закончится s, вы можете повторить gdbэто с небольшими осложнениями

#!/usr/bin/env expect

while {1} {
    spawn -noecho gdb -q ls
    expect -ex {(gdb)}
    send -- "break main\r"
    expect -ex {(gdb)}
    send -- "run\r"
    expect {
        -ex {The program is not being run} {}
        eof {}
        -ex {(gdb)} {
            send -- "s\r"
            sleep 1
            exp_continue
        }
    }
}
7
27.01.2020, 20:31

Принятый в настоящее время ответ делает всегда step, после запуска и, следовательно, также «пропускает» точки останова, сигналы и даже конец программы (в последнем случае вызывает единственную ошибку «Программа не выполняется». run" до того, как gdb внутренне прервет while, где это произошло ).
В качестве дополнительной причины он останавливается, если разбиение на страницы установлено на (, что является значением по умолчанию ), как только вывод GDB становится "полным".

С помощью Python API это можно легко решить:

  • определите пользовательскую команду (с дополнительным аргументом, чтобы сказать, как быстро автоматически -шаг)
  • необязательный :определить параметр по умолчанию (замененный здесь для простоты фиксированным значением)
  • выполнить цикл while в python,обрабатывать «ожидаемое» прерывание клавиатуры CTRL -C
  • зарегистрировать stopобработчик событий, который проверяет причину остановки и сохраняет там тип шага
  • настроить цикл while на остановку для "не простой" остановки (точка останова/точка наблюдения/сигнал/...)

Следующий код можно поместить в файл gdb -auto -step.py, который можно сделать активным с помощью source gdb-auto-step.pyв любое время (или включить в файл.gdbinit, чтобы сделать его всегда доступным.):

import gdb
import time

class CmdAutoStep (gdb.Command):
    """Auto-Step through the code until something happens or manually interrupted.
An argument says how fast auto stepping is done (1-19, default 5)."""
    def __init__(self):
        print('Registering command auto-step')
        super(CmdAutoStep, self).__init__("auto-step", gdb.COMMAND_RUNNING)
        gdb.events.stop.connect(stop_handler_auto_step)

    def invoke(self, argument, from_tty):

        try:
            frame = gdb.newest_frame()
        except gdb.error:
            raise gdb.GdbError("The program is not being run.")

        number = 5 # optional: use a parameter for the default
        if argument:
            if not argument.isdigit():
                raise gdb.GdbError("argument must be a digit, not " + argument)
            number = int(argument)
            if number == 0 or number > 19:
                raise gdb.GdbError("argument must be a digit between 1 and 19")

        sleep_time = 3.0 / (number * 1.4)

        global last_stop_was_simple
        last_stop_was_simple = True

        pagination = gdb.execute("show pagination", False, True).find("on")
        if pagination:
            gdb.execute("set pagination off", False, False)
        
        try:
            while (last_stop_was_simple):
                gdb.execute ("step")
                time.sleep(sleep_time)
        except KeyboardInterrupt as ki:
            if pagination:
                gdb.execute("set pagination on", False, False)
        except gdb.GdbError as user_error:
            if pagination:
                gdb.execute("set pagination on", False, False)
            # pass user errors unchanged
            raise user_error
        except:
            if pagination:
                gdb.execute("set pagination on", False, False)
            traceback.print_exc()

def stop_handler_auto_step(event):
    # check the type of stop, the following is the common one after step/next,
    # a more complex one would be a subclass (for example breakpoint or signal)
    global last_stop_was_simple
    last_stop_was_simple = type(event) is gdb.StopEvent

CmdAutoStep()

0
10.05.2021, 11:22

Теги

Похожие вопросы