Всем привет! Всем известны такие удобные команды в отладчиках, как step into (вход в вызов), step out (выход из вызова в любом месте) и step over (перешагивание через вызов). Вопрос - как осущестивить сабж? Step into понятно, ставим TF флаг и по EXCEPTION_SINGLE_STEP заходим в наш вызов, а как быть с остальными?
F8 step over - просто ставится бряк поcле кола и резюмится поток. step out - х3 как оно в отладчиках мне кажется просто берется из стэка первый адрес возврата и ставится бряк по этому адресу а далее тоже самое что и с F8..
скорее запоминаеться на каждом коле, ибо не везде есть фрейм. Думаю разворачивание стека у дебугеров есть и так
step_out -- возможно трассировка без захода до первого ret, вроде бы в OllyDbg так и сделано, или я чего-то путаю?
насколько я понял step_out имелось ввиду - Debug till user code в OllyDbg пусть ТС отпишет.. врядле запоминается на каждом коле слишком сложно, этож отладчик а не эмулятор какой-то.
Хз, мы на работе писали эмуль де на любую комманду/апи можно было ставить колбек, а в колбеке на кол уже в свой мини стек фигачишь (потом забраковали ибо тукри не отличают выделение "адресного пространства" и подготовки к созданию процесса (мапинг ехе и проч.) от собсно создания процесса ыы)... В дебугере думаю не сложней сделать.
step out - это скорее всего трассировка до первого возврата. ИМХО реализуется авто-трассировка в обход: установка TF с проверкой на текущую команду: 1) если call, то снимаем TF, ставим int3 после call, запускаем и, как брякнемся, возвращаем TF на место и трассируем дальше. 2) если ret и подобные, то стопоримся на волю пользователя.
Реализация StepOut основывается на том, что зная текущее значение sp и имея возможность дизасмить начало функции, где находится инструкция sub sp, XXX (в случае, если функция использует локальные переменные), несложно получить адрес, где лежит адрес возврата из функции. Ну а тут уж дело техники.
Со step-over понятно вообщем-то. Сейчас делаю так - считываю первый байт, проверяю CALL или нет, беру длину вызова и ставлю бряк на адрес за вызовом. Думал может что-нибудь другое существует, без дополнительных бряков. Про step-out - предполагается, что мы зашли в наш вызов и, к примеру, стоим где-нибудь в середине процедуры. bers, А если мы где-то по середине функции, то раскручивать стек? как уже было упомянуто, не всегда есть фрейм стековый l_inc, Дык первый ret не обязательно будет на выходе из нашей функции, есть же другие вложенные процедуры, у которых тоже есть ret. Как быть здесь
Av0id step_out это трассировка по step_over (перепрыг через call's, rep's и прочего) до первого ret, отсюда вывод что на ret других процедур ты не попадешь ибо ты в них не заходишь.
PE_Kill А куда же ты деваешся? типа совсем эти процедуры не выполняешь? ) На самом деле заходишь но без трассировки, вот ТС и спрашивает когда её в своём отладчике опять влючить. Av0id Можно выполнить шаг с call и сразу подменить в стеке адрес возврата, а уже затем отпускать прогу на "вольное исполнение"
Y_Mur зачем к словам придираешься? Ты прекрасно понял что я имел ввиду не заходим в режиме трассировки. Если делать full step over то придется дизасмить префиксы повторения, а раз придется юзать дизасм то звучит глупо, достаточно поставить бряк после команды. Для обхода префиксов вы ведь ничего не поменяете, ну разве что условие, тогда вообще проще пропустить команду.
Av0id Вообще PE_Kill уже объяснил. Я только повторюсь. Вы невнимательно прочитали мой пост. Автотрассировка в обход. Внутрь вложенных call'ов входа с трассировкой не происходит, как описано в пункте 1 поста 7. Не знаю, как другие отладчики, но Olly делает именно так. Y_Mur Странный вопрос, учитывая, что это я ТС в седьмом посте объяснил. Очень плохой способ, потому как call далеко не всегда используется для вызова подпрограмм. Вспомним хотя бы дельта смещение. У Olly тоже проблематично с этим, но вероятность падения приложения ниже.