static void showInUI(ThreadsData* user_data, PDReader* reader, PDUI* uiFuncs) { PDReaderIterator it; ThreadsData* data = (ThreadsData*)user_data; if (PDRead_find_array(reader, &it, "threads", 0) == PDReadStatus_NotFound) return; uiFuncs->text(""); uiFuncs->columns(3, "threads", true); uiFuncs->text("Id"); uiFuncs->next_column(); uiFuncs->text("Name"); uiFuncs->next_column(); uiFuncs->text("Function"); uiFuncs->next_column(); int i = 0; PDVec2 size = { 0.0f, 0.0f }; data->setSelectedThread = false; int oldSelectedThread = data->selectedThread; while (PDRead_get_next_entry(reader, &it)) { uint64_t id; const char* name = ""; const char* function = ""; PDRead_find_u64(reader, &id, "id", it); PDRead_find_string(reader, &name, "name", it); PDRead_find_string(reader, &function, "function", it); char label[32]; sprintf(label, "%llx", id); if (uiFuncs->selectable(label, data->selectedThread == i, 1 << 1, size)) { data->selectedThread = i; data->threadId = (int)id; } uiFuncs->next_column(); uiFuncs->text(name); uiFuncs->next_column(); uiFuncs->text(function); uiFuncs->next_column(); i++; } if (oldSelectedThread != data->selectedThread) { data->setSelectedThread = true; } }
static void updateCallstack(CallstackData* data, PDReader* reader) { PDReaderIterator it; if (PDRead_find_array(reader, &it, "callstack", 0) == PDReadStatus_NotFound) return; for (CallstackEntry& entry : data->callstack) { free((void*)entry.address); free((void*)entry.module); free((void*)entry.filename); } data->callstack.clear(); // TODO: Have a "spec" for the callstack to be used while (PDRead_get_next_entry(reader, &it)) { const char* filename = ""; const char* module = ""; char address[64] = { 0 }; uint32_t line = (uint32_t) ~0; CallstackEntry entry = { 0 }; getAddressString(address, reader, it); PDRead_find_string(reader, &filename, "filename", it); PDRead_find_string(reader, &module, "module_name", it); PDRead_find_u32(reader, &line, "line", it); entry.address = strdup(address); entry.line = -1; if (filename) { int fSep = findSeparator(filename); entry.filename = strdup(&filename[fSep]); } if (module) { int mSep = findSeparator(module); entry.module = strdup(&module[mSep]); } if (line != (uint32_t) ~0) entry.line = (int)line; data->callstack.push_back(entry); } }
void getRegisterString(char* value, PDReader* reader, PDReaderIterator it) { uint64_t regValue = 0; const char* regString = 0; // Support that backend can write down value in custom format if (PDRead_find_string(reader, ®String, "register_string", it) & PDReadStatus_Ok) { strncpy(value, regString, ValueSize); return; } uint32_t type = PDRead_find_u64(reader, ®Value, "register", it); switch (type & PDReadStatus_TypeMask) { case PDReadType_U8: sprintf(value, "0x%02x", (uint8_t)regValue); break; case PDReadType_S8: sprintf(value, "0x%02x", (int8_t)regValue); break; case PDReadType_U16: sprintf(value, "0x%04x", (uint16_t)regValue); break; case PDReadType_S16: sprintf(value, "0x%04x", (int16_t)regValue); break; case PDReadType_U32: sprintf(value, "0x%08x", (uint32_t)regValue); break; case PDReadType_S32: sprintf(value, "0x%08x", (int32_t)regValue); break; } }
static bool set_executable(PluginData* data, PDReader* reader) { const char* filename = 0; PDRead_find_string(reader, &filename, "filename", 0); if (!filename) { log_debug("Unable to find filename %s\n", filename); return false; } log_debug("set_executable %s\n", filename); int start_address = parse_prg(filename); if (start_address == -1) { return false; } log_debug("loading %s and running from $%x\n", filename, start_address); char temp[2048]; sprintf(temp, "load \"%s\" 0\n", filename); if (!send_command_get_data(data, temp, parse_set_executable, reader, 0, 20)) { return false; } send_command(data, "g $%x\n", start_address); return true; }
static void setBreakpoint(LLDBPlugin* plugin, PDReader* reader, PDWriter* writer) { const char* filename; uint32_t line; PDRead_find_string(reader, &filename, "filename", 0); PDRead_find_u32(reader, &line, "line", 0); // TODO: Handle failure here lldb::SBBreakpoint breakpoint = plugin->target.BreakpointCreateByLocation(filename, line); if (!breakpoint.IsValid()) { printf("adding breakpoints to breakpoint list %s:%d\n", filename, line); // Unable to set breakpoint as the target doesn't seem to be valid. This is the usual case // if we haven't actually started an executable yet. So we save them here for later and // then set them before launching the executable Breakpoint bp = { strdup(filename), (int)line }; plugin->breakpoints.push_back(bp); return; } printf("Set breakpoint at %s:%d\n", filename, line); }
static void setExceptionLocation(PDUI* uiFuncs, PDUISCInterface* sourceFuncs, SourceCodeData* data, PDReader* inEvents) { const char* filename; uint32_t line; // TODO: How to show this? Tell user to switch to disassembly view? if (PDRead_find_string(inEvents, &filename, "filename", 0) == PDReadStatus_NotFound) return; if (PDRead_find_u32(inEvents, &line, "line", 0) == PDReadStatus_NotFound) return; setSourceCodeFile(uiFuncs, sourceFuncs, data, filename, line); }
static void updateRegisters(RegistersData* data, PDReader* reader) { PDReaderIterator it; if (PDRead_find_array(reader, &it, "registers", 0) == PDReadStatus_NotFound) return; while (PDRead_get_next_entry(reader, &it)) { const char* name = ""; char registerValue[ValueSize]; PDRead_find_string(reader, &name, "name", it); getRegisterString(registerValue, reader, it); addOrUpdate(data, name, registerValue); } }
static void setExecutable(DbgEngPlugin* plugin, PDReader* reader) { printf("DbgEngPlugin: setExecutable\n"); const char* filename = 0; PDRead_find_string(reader, &filename, "filename", 0); if (!filename) { printf("Unable to find filename which is required when starting a LLDB debug session\n"); return; } printf("found filename \"%s\"\n", filename); plugin->targetName = filename; }
static void updateRegisters(DissassemblyData* data, PDReader* reader) { PDReaderIterator it; if (PDRead_find_array(reader, &it, "registers", 0) == PDReadStatus_NotFound) return; while (PDRead_get_next_entry(reader, &it)) { const char* name = ""; PDRead_find_string(reader, &name, "name", it); if (!strcmp(name, "pc")) { PDRead_find_u64(reader, &data->pc, "register", it); } } }
static void setDisassemblyCode(DissassemblyData* data, PDReader* reader) { PDReaderIterator it; if (PDRead_find_array(reader, &it, "disassembly", 0) == PDReadStatus_NotFound) return; while (PDRead_get_next_entry(reader, &it)) { uint64_t address; const char* text; PDRead_find_u64(reader, &address, "address", it); PDRead_find_string(reader, &text, "line", it); insertLine(data, address, text); } }
static bool set_breakpoint(PluginData* data, PDReader* reader, PDWriter* writer) { uint64_t address = 0; int32_t id = -1; const char* condition = 0; PDRead_find_s32(reader, &id, "id", 0); PDRead_find_u64(reader, &address, "address", 0); PDRead_find_string(reader, &condition, "condition", 0); log_debug("got breakpoint %d %llu %s\n", id, address, condition); if (id != -1) del_breakpoint_by_id(data, id); char temp[1024]; if (condition) { sprintf(temp, "break $%04x if %s\n", (uint16_t)address, condition); } else { sprintf(temp, "break $%04x\n", (uint16_t)address); } return send_command_get_data(data, temp, parse_breakpoint_call, reader, writer, 20); }
static void setExecutable(LLDBPlugin* plugin, PDReader* reader) { const char* filename = 0; PDRead_find_string(reader, &filename, "filename", 0); if (!filename) { printf("Unable to find filename which is required when starting a LLDB debug session\n"); return; } printf("found filename \"%s\"\n", filename); plugin->target = plugin->debugger.CreateTarget(filename); if (!plugin->target.IsValid()) { printf("Unable to create valid target (%s)\n", filename); } for (Breakpoint& bp : plugin->breakpoints) { lldb::SBBreakpoint breakpoint = plugin->target.BreakpointCreateByLocation(bp.filename, (uint32_t)bp.line); if (!breakpoint.IsValid()) { // TODO: Send message back that this breakpoint could't be set printf("Unable to set breakpoint %s:%d\n", bp.filename, bp.line); } } printf("Valid target %s\n", filename); onRun(plugin); }
static int update(void* user_data, PDUI* uiFuncs, PDReader* inEvents, PDWriter* writer) { uint32_t event; (void)uiFuncs; SourceCodeData* data = (SourceCodeData*)user_data; PDUISCInterface* sourceFuncs = uiFuncs->sc_input_text("test", 800, 700, 0, 0); while ((event = PDRead_get_event(inEvents)) != 0) { switch (event) { case PDEventType_SetExceptionLocation: { setExceptionLocation(uiFuncs, sourceFuncs, data, inEvents); data->requestFiles = true; break; } case PDEventType_SetSourceCodeFile: { const char* filename; if (PDRead_find_string(inEvents, &filename, "filename", 0) == PDReadStatus_NotFound) break; setSourceCodeFile(uiFuncs, sourceFuncs, data, filename, 0); break; } case PDEventType_ToggleBreakpointCurrentLine: { toggleBreakpointCurrentLine(sourceFuncs, data, writer); break; } case PDEventType_SetSourceFiles: { // TODO: Store the files data->hasFiles = true; break; } } } updateKeyboard(data, sourceFuncs, uiFuncs); PDUI_sc_update(sourceFuncs); PDUI_sc_draw(sourceFuncs); //showInUI(data, uiFuncs); PDWrite_event_begin(writer, PDEventType_GetExceptionLocation); PDWrite_event_end(writer); if (!data->hasFiles && data->requestFiles) { PDWrite_event_begin(writer, PDEventType_GetSourceFiles); PDWrite_event_end(writer); } return 0; }
static int update(void* user_data, PDUI* uiFuncs, PDReader* reader, PDWriter* writer) { uint32_t event; CallstackData* data = (CallstackData*)user_data; data->request = false; data->setSelectedFrame = false; while ((event = PDRead_get_event(reader)) != 0) { switch (event) { case PDEventType_SetCallstack: { updateCallstack(data, reader); break; } case PDEventType_SelectFrame: { PDRead_find_u32(reader, &data->selectedFrame, "frame", 0); break; } case PDEventType_SetExceptionLocation: { const char* filename = 0; uint32_t line = 0; uint64_t location = 0; PDRead_find_u64(reader, &location, "address", 0); if (location != data->location) { data->location = location; data->request = true; } PDRead_find_string(reader, &filename, "filename", 0); PDRead_find_u32(reader, &line, "line", 0); if (!filename || line == 0) break; if (strcmp(data->filename, filename)) { strcpy(data->filename, filename); data->line = (int)line; data->request = true; } } } } showUI(uiFuncs, data); if (data->setSelectedFrame) { PDWrite_event_begin(writer, PDEventType_SelectFrame); PDWrite_u32(writer, "frame", (uint32_t)data->selectedFrame); PDWrite_event_end(writer); } if (data->request) { PDWrite_event_begin(writer, PDEventType_GetCallstack); PDWrite_event_end(writer); } return 0; }