mirror of
https://github.com/reswitched/Mephisto.git
synced 2024-06-15 19:06:53 -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:",
|
else if(strncmp(query, "Xfer:features:read:target.xml:",
|
||||||
strlen("Xfer:features:read:target.xml:")) == 0)
|
strlen("Xfer:features:read:target.xml:")) == 0)
|
||||||
sendReply(target_xml);
|
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
|
else
|
||||||
sendReply("");
|
sendReply("");
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbStub::handleSetThread() {
|
void GdbStub::handleSetThread() {
|
||||||
if(memcmp(commandBuffer, "Hg0", 3) == 0 || memcmp(commandBuffer, "Hc-1", 4) == 0 ||
|
// TODO: allow actually changing threads now :|
|
||||||
memcmp(commandBuffer, "Hc0", 4) == 0 || memcmp(commandBuffer, "Hc1", 4) == 0)
|
if(memcmp(commandBuffer, "Hg", 2) == 0 || memcmp(commandBuffer, "Hc", 2) == 0) {
|
||||||
return sendReply("OK");
|
// Get thread id
|
||||||
|
if (commandBuffer[2] != '-') {
|
||||||
sendReply("E01");
|
int threadid = (int)hexToInt(commandBuffer + 2, strlen((char*)commandBuffer + 2));
|
||||||
|
ctu->tm.setCurrent(threadid);
|
||||||
|
}
|
||||||
|
sendReply("OK");
|
||||||
|
} else
|
||||||
|
sendReply("E01");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto stringFromFormat(const char* format, ...) {
|
auto stringFromFormat(const char* format, ...) {
|
||||||
|
@ -364,7 +385,10 @@ void GdbStub::sendSignal(uint32_t signal) {
|
||||||
intToGdbHex(sp, reg(31));
|
intToGdbHex(sp, reg(31));
|
||||||
intToGdbHex(pc, reg(32));
|
intToGdbHex(pc, reg(32));
|
||||||
|
|
||||||
|
auto curthread = ctu->tm.current();
|
||||||
string buffer = stringFromFormat("T%02x%02x:%.16s;%02x:%.16s;", latestSignal, 32, pc, 31, sp);
|
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());
|
LOG_DEBUG(GdbStub, "Response: %s", buffer.c_str());
|
||||||
sendReply(buffer.c_str());
|
sendReply(buffer.c_str());
|
||||||
}
|
}
|
||||||
|
@ -669,6 +693,18 @@ void GdbStub::removeBreakpoint() {
|
||||||
sendReply("OK");
|
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() {
|
void GdbStub::handlePacket() {
|
||||||
if(!isDataAvailable())
|
if(!isDataAvailable())
|
||||||
return;
|
return;
|
||||||
|
@ -719,6 +755,9 @@ void GdbStub::handlePacket() {
|
||||||
case 'z':
|
case 'z':
|
||||||
removeBreakpoint();
|
removeBreakpoint();
|
||||||
break;
|
break;
|
||||||
|
case 'T':
|
||||||
|
isThreadAlive();
|
||||||
|
break;
|
||||||
case 'Z':
|
case 'Z':
|
||||||
addBreakpoint();
|
addBreakpoint();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -52,6 +52,7 @@ private:
|
||||||
void writeRegisters();
|
void writeRegisters();
|
||||||
void readMemory();
|
void readMemory();
|
||||||
void writeMemory();
|
void writeMemory();
|
||||||
|
void isThreadAlive();
|
||||||
void step();
|
void step();
|
||||||
void _continue();
|
void _continue();
|
||||||
bool commitBreakpoint(BreakpointType type, gptr addr, uint32_t len);
|
bool commitBreakpoint(BreakpointType type, gptr addr, uint32_t len);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#define INSN_PER_SLICE 1000000
|
#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;
|
active = false;
|
||||||
memset(®s, 0, sizeof(ThreadRegisters));
|
memset(®s, 0, sizeof(ThreadRegisters));
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ void Thread::resume(function<void()> cb) {
|
||||||
|
|
||||||
if(cb != nullptr)
|
if(cb != nullptr)
|
||||||
onWake(cb);
|
onWake(cb);
|
||||||
|
started = true;
|
||||||
active = true;
|
active = true;
|
||||||
ctu->tm.enqueue(id);
|
ctu->tm.enqueue(id);
|
||||||
}
|
}
|
||||||
|
@ -269,6 +270,26 @@ shared_ptr<Thread> ThreadManager::last() {
|
||||||
return _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) {
|
bool ThreadManager::isNative(int id) {
|
||||||
return nativeThreads.find(id) != nativeThreads.end();
|
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);
|
void onWake(function<void()> cb);
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
|
bool started;
|
||||||
ghandle handle;
|
ghandle handle;
|
||||||
bool active;
|
bool active;
|
||||||
ThreadRegisters regs;
|
ThreadRegisters regs;
|
||||||
|
@ -54,9 +55,11 @@ public:
|
||||||
void terminate(int id);
|
void terminate(int id);
|
||||||
shared_ptr<Thread> current();
|
shared_ptr<Thread> current();
|
||||||
shared_ptr<Thread> last();
|
shared_ptr<Thread> last();
|
||||||
|
bool setCurrent(int id);
|
||||||
bool switched;
|
bool switched;
|
||||||
|
|
||||||
|
vector<shared_ptr<Thread>> thread_list();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void tryRunNative();
|
void tryRunNative();
|
||||||
bool isNative(int id);
|
bool isNative(int id);
|
||||||
|
|
Loading…
Reference in a new issue