Tell GDB about the threads, allow switching between them when single stepping

This commit is contained in:
roblabla 2017-12-06 00:53:14 +01:00
parent 99c42d1edb
commit 865528074f
4 changed files with 71 additions and 7 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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(&regs, 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;
}

View file

@ -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);