diff --git a/GdbStub.cpp b/GdbStub.cpp index 7a01c84..9f679e6 100644 --- a/GdbStub.cpp +++ b/GdbStub.cpp @@ -331,16 +331,37 @@ void GdbStub::handleQuery() { else if(strncmp(query, "Xfer:features:read:target.xml:", strlen("Xfer:features:read:target.xml:")) == 0) sendReply(target_xml); + else if (strncmp(query, "fThreadInfo", strlen("fThreadInfo")) == 0) { + auto list = ctu->tm.thread_list(); + char tmp[17] = {0}; + string val = "m"; + for (auto it = list.begin(); it != list.end(); it++) { + if (!(*it)->started) + continue; + memset(tmp, 0, sizeof(tmp)); + sprintf(tmp, "%x", (*it)->id); + val += (char*)tmp; + val += ","; + } + val.pop_back(); + sendReply(val.c_str()); + } else if (strncmp(query, "sThreadInfo", strlen("sThreadInfo")) == 0) + sendReply("l"); else sendReply(""); } void GdbStub::handleSetThread() { - if(memcmp(commandBuffer, "Hg0", 3) == 0 || memcmp(commandBuffer, "Hc-1", 4) == 0 || - memcmp(commandBuffer, "Hc0", 4) == 0 || memcmp(commandBuffer, "Hc1", 4) == 0) - return sendReply("OK"); - - sendReply("E01"); + // TODO: allow actually changing threads now :| + if(memcmp(commandBuffer, "Hg", 2) == 0 || memcmp(commandBuffer, "Hc", 2) == 0) { + // Get thread id + if (commandBuffer[2] != '-') { + int threadid = (int)hexToInt(commandBuffer + 2, strlen((char*)commandBuffer + 2)); + ctu->tm.setCurrent(threadid); + } + sendReply("OK"); + } else + sendReply("E01"); } auto stringFromFormat(const char* format, ...) { @@ -364,7 +385,10 @@ void GdbStub::sendSignal(uint32_t signal) { intToGdbHex(sp, reg(31)); intToGdbHex(pc, reg(32)); + auto curthread = ctu->tm.current(); string buffer = stringFromFormat("T%02x%02x:%.16s;%02x:%.16s;", latestSignal, 32, pc, 31, sp); + if (curthread != nullptr) + buffer += stringFromFormat("thread:%x;", curthread->id); LOG_DEBUG(GdbStub, "Response: %s", buffer.c_str()); sendReply(buffer.c_str()); } @@ -669,6 +693,18 @@ void GdbStub::removeBreakpoint() { sendReply("OK"); } +void GdbStub::isThreadAlive() { + int threadid = (int)hexToInt(commandBuffer + 1, strlen((char*)commandBuffer + 1)); + auto threads = ctu->tm.thread_list(); + for (auto it = threads.begin(); it != threads.end(); it++) { + if ((*it)->id == threadid) { + sendReply("OK"); + return; + } + } + sendReply("E01"); +} + void GdbStub::handlePacket() { if(!isDataAvailable()) return; @@ -719,6 +755,9 @@ void GdbStub::handlePacket() { case 'z': removeBreakpoint(); break; + case 'T': + isThreadAlive(); + break; case 'Z': addBreakpoint(); break; diff --git a/GdbStub.h b/GdbStub.h index 59b1a03..daa8d29 100644 --- a/GdbStub.h +++ b/GdbStub.h @@ -52,6 +52,7 @@ private: void writeRegisters(); void readMemory(); void writeMemory(); + void isThreadAlive(); void step(); void _continue(); bool commitBreakpoint(BreakpointType type, gptr addr, uint32_t len); diff --git a/ThreadManager.cpp b/ThreadManager.cpp index 55cc055..01af9f4 100644 --- a/ThreadManager.cpp +++ b/ThreadManager.cpp @@ -2,7 +2,7 @@ #define INSN_PER_SLICE 1000000 -Thread::Thread(Ctu *_ctu, int _id) : ctu(_ctu), id(_id) { +Thread::Thread(Ctu *_ctu, int _id) : ctu(_ctu), id(_id), started(false) { active = false; memset(®s, 0, sizeof(ThreadRegisters)); @@ -42,6 +42,7 @@ void Thread::resume(function cb) { if(cb != nullptr) onWake(cb); + started = true; active = true; ctu->tm.enqueue(id); } @@ -269,6 +270,26 @@ shared_ptr ThreadManager::last() { return _last; } +bool ThreadManager::setCurrent(int id) { + auto thread = threads.find(id); + if (thread == threads.end()) + return false; + if(_current != nullptr) { + _current->freeze(); + _last = _current; + } + _current = thread->second; + _current->thaw(); + return true; +} + + bool ThreadManager::isNative(int id) { return nativeThreads.find(id) != nativeThreads.end(); } + +vector> ThreadManager::thread_list() { + vector> vals; + transform(threads.begin(), threads.end(), back_inserter(vals), [](auto val){return val.second;} ); + return vals; +} diff --git a/ThreadManager.h b/ThreadManager.h index 23c48e6..82e2d62 100644 --- a/ThreadManager.h +++ b/ThreadManager.h @@ -14,6 +14,7 @@ public: void onWake(function cb); int id; + bool started; ghandle handle; bool active; ThreadRegisters regs; @@ -54,9 +55,11 @@ public: void terminate(int id); shared_ptr current(); shared_ptr last(); - + bool setCurrent(int id); bool switched; + vector> thread_list(); + private: void tryRunNative(); bool isNative(int id);