mirror of
https://github.com/reswitched/Mephisto.git
synced 2024-05-11 09:14:54 -04:00
Tell GDB about the threads, allow switching between them when single stepping
This commit is contained in:
parent
99c42d1edb
commit
865528074f
49
GdbStub.cpp
49
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<void()> cb) {
|
|||
|
||||
if(cb != nullptr)
|
||||
onWake(cb);
|
||||
started = true;
|
||||
active = true;
|
||||
ctu->tm.enqueue(id);
|
||||
}
|
||||
|
@ -269,6 +270,26 @@ shared_ptr<Thread> 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<shared_ptr<Thread>> ThreadManager::thread_list() {
|
||||
vector<shared_ptr<Thread>> vals;
|
||||
transform(threads.begin(), threads.end(), back_inserter(vals), [](auto val){return val.second;} );
|
||||
return vals;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ public:
|
|||
void onWake(function<void()> cb);
|
||||
|
||||
int id;
|
||||
bool started;
|
||||
ghandle handle;
|
||||
bool active;
|
||||
ThreadRegisters regs;
|
||||
|
@ -54,9 +55,11 @@ public:
|
|||
void terminate(int id);
|
||||
shared_ptr<Thread> current();
|
||||
shared_ptr<Thread> last();
|
||||
|
||||
bool setCurrent(int id);
|
||||
bool switched;
|
||||
|
||||
vector<shared_ptr<Thread>> thread_list();
|
||||
|
||||
private:
|
||||
void tryRunNative();
|
||||
bool isNative(int id);
|
||||
|
|
Loading…
Reference in a new issue