/** * Do any disabling of events (including clearing breakpoints etc) * needed to no longer get the events requested by this handler node. */ static jvmtiError disableEvents(HandlerNode *node) { jvmtiError error = JVMTI_ERROR_NONE; jvmtiError error2 = JVMTI_ERROR_NONE; jthread thread; switch (NODE_EI(node)) { /* The stepping code directly enables/disables stepping as * necessary */ case EI_SINGLE_STEP: /* Internal thread event handlers are always present * (hardwired in the event hook), so we don't change the * notification mode here. */ case EI_THREAD_START: case EI_THREAD_END: case EI_VM_INIT: case EI_VM_DEATH: case EI_CLASS_PREPARE: case EI_GC_FINISH: return error; case EI_FIELD_ACCESS: case EI_FIELD_MODIFICATION: error = clearWatchpoint(node); break; case EI_BREAKPOINT: error = clearBreakpoint(node); break; default: break; } thread = requestThread(node); /* If this is the last request of it's kind on this thread * (or all threads (thread == NULL)) then disable these * events on this thread. * * Disable even if the above caused an error */ if (!eventHandlerRestricted_iterator(NODE_EI(node), matchThread, thread)) { error2 = threadControl_setEventMode(JVMTI_DISABLE, NODE_EI(node), thread); } return error != JVMTI_ERROR_NONE? error : error2; }
void remoteGdbMainLoop(Core *core, int enableFbWindow) { int listenSocket; struct sockaddr_in address; socklen_t addressLength; int got; char request[256]; uint32_t i; bool noAckMode = false; int optval; char response[256]; uint32_t currentThread = 0; gCore = core; gLastSignals = calloc(sizeof(int), getTotalThreads(core)); for (i = 0; i < getTotalThreads(core); i++) gLastSignals[i] = 0; listenSocket = socket(PF_INET, SOCK_STREAM, 0); if (listenSocket < 0) { perror("error setting up debug socket (socket)"); return; } optval = 1; if (setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) { perror("error setting up debug socket (setsockopt)"); return; } address.sin_family = AF_INET; address.sin_port = htons(8000); address.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(listenSocket, (struct sockaddr*) &address, sizeof(address)) < 0) { perror("error setting up debug socket (bind)"); return; } if (listen(listenSocket, 1) < 0) { perror("error setting up debug socket (listen)"); return; } while (true) { // Wait for a new client socket while (true) { addressLength = sizeof(address); gClientSocket = accept(listenSocket, (struct sockaddr*) &address, &addressLength); if (gClientSocket >= 0) break; } noAckMode = false; // Process commands while (true) { got = readPacket(request, sizeof(request)); if (got < 0) break; if (!noAckMode) { if (write(gClientSocket, "+", 1) != 1) { perror("Error writing to debug socket"); exit(1); } } switch (request[0]) { // Set arguments case 'A': // We don't support setting program arguments, so just silently ignore. sendResponsePacket("OK"); break; // Continue case 'c': case 'C': runUntilInterrupt(core, ALL_THREADS, enableFbWindow); gLastSignals[currentThread] = TRAP_SIGNAL; sendFormattedResponse("S%02x", gLastSignals[currentThread]); break; // Pick thread case 'H': if (request[1] == 'g' || request[1] == 'c') { // XXX hack: the request type controls which operations this // applies for. currentThread = (uint32_t)(request[2] - '1'); sendResponsePacket("OK"); } else sendResponsePacket(""); break; // Kill case 'k': return; // Read/write memory case 'm': case 'M': { char *lenPtr; char *dataPtr; unsigned int start; unsigned int length; unsigned int offset; start = (uint32_t) strtoul(request + 1, &lenPtr, 16); length = (uint32_t) strtoul(lenPtr + 1, &dataPtr, 16); if (request[0] == 'm') { // Read memory for (offset = 0; offset < length; offset++) sprintf(response + offset * 2, "%02x", readMemoryByte(core, start + offset)); sendResponsePacket(response); } else { // Write memory dataPtr += 1; // Skip colon for (offset = 0; offset < length; offset++) writeMemoryByte(core, start + offset, decodeHexByte(dataPtr + offset * 2)); sendResponsePacket("OK"); } break; } // Read register case 'p': case 'g': { uint32_t regId = (uint32_t) strtoul(request + 1, NULL, 16); uint32_t value; if (regId < 32) { value = getScalarRegister(core, currentThread, regId); sendFormattedResponse("%08x", endianSwap32(value)); } else if (regId < 64) { uint32_t lane; for (lane = 0; lane < NUM_VECTOR_LANES; lane++) { value = getVectorRegister(core, currentThread, regId, lane); sprintf(response + lane * 8, "%08x", endianSwap32(value)); } sendResponsePacket(response); } else sendResponsePacket(""); break; } // XXX need to implement write register // Query case 'q': if (strcmp(request + 1, "LaunchSuccess") == 0) sendResponsePacket("OK"); else if (strcmp(request + 1, "HostInfo") == 0) sendResponsePacket("triple:nyuzi;endian:little;ptrsize:4"); else if (strcmp(request + 1, "ProcessInfo") == 0) sendResponsePacket("pid:1"); else if (strcmp(request + 1, "fThreadInfo") == 0) sendResponsePacket("m1,2,3,4"); // XXX need to query number of threads else if (strcmp(request + 1, "sThreadInfo") == 0) sendResponsePacket("l"); else if (memcmp(request + 1, "ThreadStopInfo", 14) == 0) sprintf(response, "S%02x", gLastSignals[currentThread]); else if (memcmp(request + 1, "RegisterInfo", 12) == 0) { uint32_t regId = (uint32_t) strtoul(request + 13, NULL, 16); if (regId < 32) { sprintf(response, "name:s%d;bitsize:32;encoding:uint;format:hex;set:General Purpose Scalar Registers;gcc:%d;dwarf:%d;", regId, regId, regId); if (regId >= 28) sprintf(response + strlen(response), "generic:%s;", kGenericRegs[regId - 28]); } else if (regId < 64) { sprintf(response, "name:v%d;bitsize:512;encoding:uint;format:vector-uint32;set:General Purpose Vector Registers;gcc:%d;dwarf:%d;", regId - 32, regId, regId); } else strcpy(response, ""); sendResponsePacket(response); } else if (strcmp(request + 1, "C") == 0) sendFormattedResponse("QC%02x", currentThread + 1); else sendResponsePacket(""); // Not supported break; // Set Value case 'Q': if (strcmp(request + 1, "StartNoAckMode") == 0) { noAckMode = true; sendResponsePacket("OK"); } else sendResponsePacket(""); // Not supported break; // Single step case 's': case 'S': singleStep(core, currentThread); gLastSignals[currentThread] = TRAP_SIGNAL; sendFormattedResponse("S%02x", gLastSignals[currentThread]); break; // Multi-character command case 'v': if (strcmp(request, "vCont?") == 0) sendResponsePacket("vCont;C;c;S;s"); else if (memcmp(request, "vCont;", 6) == 0) { // XXX hack. There are two things lldb requests. One is // to step one thread while resuming the others. In this case, // I cheat and only step the one. The other is just to continue, // which I perform in the else clause. const char *sreq = strchr(request, 's'); if (sreq != NULL) { // s:0001 currentThread = (uint32_t) strtoul(sreq + 2, NULL, 16) - 1; singleStep(core, currentThread); gLastSignals[currentThread] = TRAP_SIGNAL; sendFormattedResponse("S%02x", gLastSignals[currentThread]); } else { runUntilInterrupt(core, ALL_THREADS, enableFbWindow); gLastSignals[currentThread] = TRAP_SIGNAL; sendFormattedResponse("S%02x", gLastSignals[currentThread]); } } else sendResponsePacket(""); break; // Clear breakpoint case 'z': if (clearBreakpoint(core, (uint32_t) strtoul(request + 3, NULL, 16)) < 0) sendResponsePacket(""); // Error else sendResponsePacket("OK"); break; // Set breakpoint case 'Z': if (setBreakpoint(core, (uint32_t) strtoul(request + 3, NULL, 16)) < 0) sendResponsePacket(""); // Error else sendResponsePacket("OK"); break; // Get last signal case '?': sprintf(response, "S%02x", gLastSignals[currentThread]); sendResponsePacket(response); break; // Unknown, return error default: sendResponsePacket(""); } } close(gClientSocket); } }
void remoteGdbMainLoop(Core *core, int enableFbWindow) { int listenSocket; struct sockaddr_in address; socklen_t addressLength; int got; char request[256]; int i; int noAckMode = 0; int optval; char response[256]; int currentThread = 0; gCore = core; gLastSignal = calloc(sizeof(int), getTotalThreads(core)); for (i = 0; i < getTotalThreads(core); i++) gLastSignal[i] = 0; listenSocket = socket(PF_INET, SOCK_STREAM, 0); if (listenSocket < 0) { perror("socket"); return; } optval = 1; setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval); address.sin_family = AF_INET; address.sin_port = htons(8000); address.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(listenSocket, (struct sockaddr*) &address, sizeof(address)) < 0) { perror("bind"); return; } if (listen(listenSocket, 4) < 0) { perror("bind"); return; } while (1) { // Wait for a new client socket while (1) { addressLength = sizeof(address); gClientSocket = accept(listenSocket, (struct sockaddr*) &address, &addressLength); if (gClientSocket >= 0) break; } #if DUMP_MESSAGES printf("Got connection from debugger\n"); #endif noAckMode = 0; // Process commands while (1) { got = readPacket(request, sizeof(request)); if (got < 0) break; if (!noAckMode) write(gClientSocket, "+", 1); #if DUMP_MESSAGES printf("<< %s\n", request); #endif switch (request[0]) { // Set arguments case 'A': sendResponsePacket("OK"); // Yeah, whatever break; // continue case 'c': case 'C': runUntilInterrupt(core, -1, enableFbWindow); gLastSignal[currentThread] = TRAP_SIGNAL; sendFormattedResponse("S%02x", gLastSignal[currentThread]); break; // Pick thread case 'H': if (request[1] == 'g' || request[1] == 'c') { // XXX hack: the request type controls which operations this // applies for. currentThread = request[2] - '1'; sendResponsePacket("OK"); } else { #if DUMP_MESSAGES printf("Unhandled command %s\n", request); #endif sendResponsePacket(""); } break; // Kill case 'k': #if DUMP_MESSAGES printf("Exit requested\n"); #endif exit(1); break; // Read/write memory case 'm': case 'M': { char *lenPtr; unsigned int start; unsigned int length; unsigned int offset; start = strtoul(request + 1, &lenPtr, 16); length = strtoul(lenPtr + 1, NULL, 16); if (request[0] == 'm') { // Read memory for (offset = 0; offset < length; offset++) sprintf(response + offset * 2, "%02x", readMemoryByte(core, start + offset)); sendResponsePacket(response); } else { // XXX write memory } break; } // read register case 'p': case 'g': { int regId = strtoul(request + 1, NULL, 16); int value; if (regId < 32) { value = getScalarRegister(core, currentThread, regId); sendFormattedResponse("%08x", endianSwap32(value)); } else if (regId < 64) { int lane; for (lane = 0; lane < 16; lane++) { value = getVectorRegister(core, currentThread, regId, lane); sprintf(response + lane * 8, "%08x", endianSwap32(value)); } sendResponsePacket(response); } else sendResponsePacket(""); break; } // Query case 'q': if (strcmp(request + 1, "LaunchSuccess") == 0) sendResponsePacket("OK"); else if (strcmp(request + 1, "HostInfo") == 0) sendResponsePacket("triple:nyuzi;endian:little;ptrsize:4"); else if (strcmp(request + 1, "ProcessInfo") == 0) sendResponsePacket("pid:1"); else if (strcmp(request + 1, "fThreadInfo") == 0) sendResponsePacket("m1,2,3,4"); else if (strcmp(request + 1, "sThreadInfo") == 0) sendResponsePacket("l"); else if (memcmp(request + 1, "ThreadStopInfo", 14) == 0) sprintf(response, "S%02x", gLastSignal[currentThread]); else if (memcmp(request + 1, "RegisterInfo", 12) == 0) { int regId = strtoul(request + 13, NULL, 16); if (regId < 32) { sprintf(response, "name:s%d;bitsize:32;encoding:uint;format:hex;set:General Purpose Scalar Registers;gcc:%d;dwarf:%d;", regId, regId, regId); if (regId >= 28) sprintf(response + strlen(response), "generic:%s;", kGenericRegs[regId - 28]); } else if (regId < 64) { sprintf(response, "name:v%d;bitsize:512;encoding:uint;format:vector-uint32;set:General Purpose Vector Registers;gcc:%d;dwarf:%d;", regId - 32, regId, regId); } else strcpy(response, ""); sendResponsePacket(response); } else if (strcmp(request + 1, "C") == 0) sendFormattedResponse("QC%02x", currentThread + 1); else sendResponsePacket(""); // Not supported break; // Set Value case 'Q': if (strcmp(request + 1, "StartNoAckMode") == 0) { noAckMode = 1; sendResponsePacket("OK"); } else sendResponsePacket(""); // Not supported break; // Step case 's': case 'S': singleStep(core, currentThread); gLastSignal[currentThread] = TRAP_SIGNAL; sendFormattedResponse("S%02x", gLastSignal[currentThread]); break; // Multi-character command case 'v': if (strcmp(request, "vCont?") == 0) sendResponsePacket("vCont;C;c;S;s"); else if (memcmp(request, "vCont;", 6) == 0) { // XXX hack. There are two things lldb requests. One is // to step one thread while resuming the others. In this case, // I cheat and only step the one. The other is just to continue, // which I perform in the else clause. const char *sreq = strchr(request, 's'); if (sreq != NULL) { // s:0001 currentThread = strtoul(sreq + 2, NULL, 16) - 1; singleStep(core, currentThread); gLastSignal[currentThread] = TRAP_SIGNAL; sendFormattedResponse("S%02x", gLastSignal[currentThread]); } else { runUntilInterrupt(core, -1, enableFbWindow); gLastSignal[currentThread] = TRAP_SIGNAL; sendFormattedResponse("S%02x", gLastSignal[currentThread]); } } else sendResponsePacket(""); break; // Clear breakpoint case 'z': clearBreakpoint(core, strtoul(request + 3, NULL, 16)); sendResponsePacket("OK"); break; // Set breakpoint case 'Z': setBreakpoint(core, strtoul(request + 3, NULL, 16)); sendResponsePacket("OK"); break; // Get last signal case '?': sprintf(response, "S%02x", gLastSignal[currentThread]); sendResponsePacket(response); break; // Unknown default: sendResponsePacket(""); } } #if DUMP_MESSAGES printf("Disconnected from debugger\n"); #endif close(gClientSocket); } }