int main(int argc, char *argv[]) { if (PIN_Init(argc, argv)) return Usage(); if (PIN_GetDebugStatus() == DEBUG_STATUS_DISABLED) { std::cerr << "Application level debugging must be enabled to use this tool.\n"; std::cerr << "Start Pin with either -appdebug or -appdebug_enable.\n"; std::cerr << std::flush; return 1; } if (!KnobOut.Value().empty()) Output = new std::ofstream(KnobOut.Value().c_str()); // Allocate a virtual register that each thread uses to point to its // TINFO data. Threads can use this virtual register to quickly access // their own thread-private data. // RegTinfo = PIN_ClaimToolRegister(); if (!REG_valid(RegTinfo)) { std::cerr << "Cannot allocate a scratch register.\n"; std::cerr << std::flush; return 1; } PIN_AddDebugInterpreter(DebugInterpreter, 0); PIN_AddThreadStartFunction(OnThreadStart, 0); PIN_AddThreadFiniFunction(OnThreadEnd, 0); PIN_StartProgram(); return 0; }
static void DoBreakpoint(CONTEXT *ctxt, THREADID tid) { static bool IsReplayedInstruction = false; static bool IsDebuggerLaunched = false; // When resuming from a breakpoint, we re-execute the instruction at // the breakpoint. Skip over the breakpoint in this case. // if (IsReplayedInstruction) { IsReplayedInstruction = false; return; } // If the debugger isn't launched yet, launch it now. // if (PIN_GetDebugStatus() == DEBUG_STATUS_UNCONNECTED) { // This is a sanity check to make sure PIN_GetDebugStatus() doesn't // have a bug. Once the debugger is launched, the status should // no longer be DEBUG_STATUS_UNCONNECTED. // if (IsDebuggerLaunched) { std::cerr << "Got wrong Debug Status from Pin" << std::endl; exit(1); } if (!LaunchGdb()) { std::cerr << "GDB did not connect within the timeout period." << std::endl; exit(1); } IsDebuggerLaunched = true; } IsReplayedInstruction = true; // Stop at a debugger breakpoint. // PIN_ApplicationBreakpoint(ctxt, tid, TRUE, "Tool stopped at breakpoint"); /* does not return */ }