Код (Text): int _tmain(int argc, _TCHAR* argv[]) { STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); DEBUG_EVENT de; CreateProcess(target,0,0,0,FALSE,NORMAL_PRIORITY_CLASS,0,0,&si,&pi); printf("Started\n"); DebugActiveProcess(pi.dwProcessId); for(;;) { ZeroMemory(&de,sizeof(DEBUG_EVENT)); WaitForDebugEvent(&de,INFINITE); if(de.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT) { break; } if(de.dwDebugEventCode==EXCEPTION_DEBUG_EVENT) { /// ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE); } } DebugActiveProcessStop(pi.dwProcessId); printf("Finished\n"); getch(); return 0; } Ничего непонимаю(((
DebugActiveProcess,WaitForDebugEvent что возвращает? CREATE_PROCESS_DEBUG_EVENT , CREATE_THREAD_DEBUG_EVENT , EXCEPTION_DEBUG_EVENT и прочее тоже обрабатывать надо. Сделайте отладочный вывод, сразу всё понятно станет.
Да точно нада для каждого ивента вызывать ContinueDebugEvent. ЗЫ:а где находиться адрес по которому была ошибка?В EXCEPTION_RECORD::ExceptionAddress пурга какая то.В отлаживаемом приложение делаеться деление на ноль,секции релоков в нем нет,база 0х400000.А в поле EXCEPTION_RECORD::ExceptionAddress 0х77F5E6E6 О_о
Да, всё у тебя верно, он же не на EntryPoint останавливается. Трассировка раньше начинается. Вот куски кода, может помогут. А вообще в интернете тьма примеров, Bing в помощь. Код (Text): else if ( DebugEvent.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT ) { DM( "Process created.(ImageBase=0x%08X,lpStartAddress=0x%08X)" , DebugEvent.u.CreateProcessInfo.lpBaseOfImage , DebugEvent.u.CreateProcessInfo.lpStartAddress ); hMainFile = DebugEvent.u.CreateProcessInfo.hFile; lpProcessStartAddress = DebugEvent.u.CreateProcessInfo.lpStartAddress; if ( !DebugEvent.u.CreateProcessInfo.lpStartAddress ) { DME( "lpStartAddress = 0." ); bError = TRUE; break; } } потом ловишь EXCEPTION_DEBUG_EVENT Код (Text): else if ( DebugEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT ) { if ( (DWORD)DebugEvent.u.Exception.ExceptionRecord.ExceptionCode == 0x80000003L ) //EXCEPTION_BREAKPOINT { if ( !lpMainProcessModule ) { DM( "Initial breakpoint." ); lpMainProcessModule = GetAddressOfMainModuleInProcessW( pi.dwProcessId , lpFilePath , &dwSizeOfMainProcessModule ); if ( !lpMainProcessModule ) { DME( "Cant find main module of process(%ls)." , lpFilePath ); bError = TRUE; break; } bError = !Tracer_SetBreakpoint( pi.hProcess , lpProcessStartAddress , &bOrignalByte );//0xCC(int3) at EntryPoint if ( bError ) { DME( "Tracer_SetBreakpoint fails." ); break; } bEntryPointBreakpoint = TRUE; } else { if ( bEntryPointBreakpoint ) { bEntryPointBreakpoint = FALSE; DM( "EntryPoint catched. Start tracing..." ); bError = !Tracer_RemoveBreakpoint( pi.hProcess , lpProcessStartAddress , &bOrignalByte ); if ( bError ) { DME( "Tracer_RemoveBreakpoint fails." ); break; } bError = !Tracer_ChangeThreadEIP( pi.hThread , -1 , bIsProcessx64 ); if ( bError ) { DME( "Tracer_ChangeThreadEIP fails." ); break; } } bError = !Tracer_SetTF( &pi , bIsProcessx64 ); if ( bError ) { DME( "Tracer_SetTF fails." ); break; } } bError = !ContinueDebugEvent( DebugEvent.dwProcessId , DebugEvent.dwThreadId , ((DWORD)0x00010002L) ); //DBG_CONTINUE if ( bError ) { DME( "ContinueDebugEvent fails." ); break; } continue; } else if ( (DWORD)DebugEvent.u.Exception.ExceptionRecord.ExceptionCode == 0x80000004L )//EXCEPTION_SINGLE_STEP { //do what u need bError = !Tracer_SetTF( &pi , bIsProcessx64 ); if ( bError ) { DME( "Tracer_SetTF fails." ); break; } bError = !ContinueDebugEvent( DebugEvent.dwProcessId , DebugEvent.dwThreadId , ((DWORD)0x00010002L) ); //DBG_CONTINUE if ( bError ) { DME( "ContinueDebugEvent fails." ); break; } continue; } }
Не думал что отладка начинаеться еще до инициализации... А тлс ф-ции то же под неё значит попадают? ЗЫ:а почему собственно при инициализации в дебаг моде, возникают исключения которые не возникают в обычном режиме?
_nic Попадают. Указав опцию FLG_SHOW_LDR_SNAPS в реестре для приложения вы получие большое число сообщений на порт. Из них вас будет интересовать сепшен DBG_PRINTEXCEPTION_C. Далее вы получите его параметры из инфы про фолт и будите искать в этой строке текст(может быть не сначала и без учёта регистра): "Calling Tls Callback" После чего извлекаете вектор и базу модуля из аргументов принта.
http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/Process/PEB.html - PEB::BeingDebugged Вот эта что ли?
_nic Не думал, что код инициализации тоже можно\нужно отлаживать?! Для того, чтобы информировать отладчик. Например, системный DbgBreakPoint при инициализации сигнализирует о том, что все стандартные дебаг-эвенты закончились, все потоки процесса пора отпускать "на волю", и соотв-но, чтобы отладчик не потерял управление ему дается последний шанс расставить свои брикпойнты. Все это дело расписано в ремарках к DebugActiveProcess. При создании процесса делается то же самое, и перед передачей управления на энтрипойнт процесса вызывается DbgBreakPoint
_nic Да. Усталъ обьяснять сей баян. Действительно - есть механизм передачи управления на еп баянный. Нам, точнее вам нужно его изучить. Ссыль на EP в стартап контексте. Вы в апк процедуре брейк получаете. Стартап контекст в конце SFC. Собственно вот и всё.
А как можно обьяснить такое ? Запускаю блокнот в отладочном режиме,жму "сохранить как" - куча исключений, в обычном режиме конечно же все ОК.И коды части эксептов почему то не описанны в мсдн Код (Text): int _tmain(int argc, _TCHAR* argv[]) { STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); DEBUG_EVENT de; CreateProcess(target,0,0,0,FALSE,NORMAL_PRIORITY_CLASS,0,0,&si,&pi); printf("Started\n"); DebugActiveProcess(pi.dwProcessId); int i=0; while(i!=1) { ZeroMemory(&de,sizeof(DEBUG_EVENT)); WaitForDebugEvent(&de,INFINITE); switch(de.dwDebugEventCode) { case EXIT_PROCESS_DEBUG_EVENT: ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE); i=1; printf("EXIT_PROCESS_DEBUG_EVENT\n"); break; case EXCEPTION_DEBUG_EVENT: printf("EXCEPTION_DEBUG_EVENT\n"); printf("Adr:%X\n",de.u.Exception.ExceptionRecord.ExceptionAddress); PrintExpt(de.u.Exception.ExceptionRecord.ExceptionCode); getch(); ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE); break; case CREATE_THREAD_DEBUG_EVENT: ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE); printf("CREATE_THREAD_DEBUG_EVENT\n"); break; case CREATE_PROCESS_DEBUG_EVENT: printf("CREATE_PROCESS_DEBUG_EVENT\n"); printf("Base: %X\n",de.u.CreateProcessInfo.lpBaseOfImage); ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE); break; case EXIT_THREAD_DEBUG_EVENT: ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE); printf("EXIT_THREAD_DEBUG_EVENT\n"); break; case LOAD_DLL_DEBUG_EVENT: ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE); printf("LOAD_DLL_DEBUG_EVENT\n"); break; case UNLOAD_DLL_DEBUG_EVENT: ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE); printf("UNLOAD_DLL_DEBUG_EVENT\n"); break; case OUTPUT_DEBUG_STRING_EVENT: ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE); printf("OUTPUT_DEBUG_STRING_EVENT\n"); break; case RIP_EVENT: ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE); printf("RIP_EVENT\n"); break; } } DebugActiveProcessStop(pi.dwProcessId); printf("Finished\n"); getch(); return 0; } Выглядит это примерно так и ACCESS_VIOLATION идет дальше до бесконечности... Это что, то же получаеться какая то отладочная фича?