static void setCallstack(LLDBPlugin* plugin, PDWriter* writer) { lldb::SBThread thread(plugin->process.GetThreadByID(plugin->selectedThreadId)); printf("set callstack\n"); int frameCount = (int)thread.GetNumFrames(); if (frameCount == 0) return; // TODO: Write type of callstack PDWrite_eventBegin(writer, PDEventType_setCallstack); PDWrite_arrayBegin(writer, "callstack"); for (int i = 0; i < frameCount; ++i) { char fileLine[2048]; char moduleName[2048]; lldb::SBFrame frame = thread.GetFrameAtIndex((uint32_t)i); lldb::SBModule module = frame.GetModule(); lldb::SBCompileUnit compileUnit = frame.GetCompileUnit(); lldb::SBSymbolContext context(frame.GetSymbolContext(0x0000006e)); lldb::SBLineEntry entry(context.GetLineEntry()); uint64_t address = (uint64_t)frame.GetPC(); module.GetFileSpec().GetPath(moduleName, sizeof(moduleName)); PDWrite_arrayEntryBegin(writer); if (compileUnit.GetNumSupportFiles() > 0) { char filename[2048]; lldb::SBFileSpec fileSpec = compileUnit.GetSupportFileAtIndex(0); fileSpec.GetPath(filename, sizeof(filename)); sprintf(fileLine, "%s:%d", filename, entry.GetLine()); printf("callstack %s:%d\n", fileLine, entry.GetLine()); PDWrite_string(writer, "filename", filename); PDWrite_u32(writer, "line", entry.GetLine()); } PDWrite_string(writer, "module_name", moduleName); PDWrite_u64(writer, "address", address); PDWrite_arrayEntryEnd(writer); } PDWrite_arrayEnd(writer); PDWrite_eventEnd(writer); }
static void parseForCallstack(PDWriter* writer, const char* data, int length) { uint16_t callStackEntries[256 * 2]; int callStackCount = 0; memcpy(s_tempBuffer, data, length); s_tempBuffer[length] = 0; char* pch = strtok(s_tempBuffer, "\n"); while (pch) { // expected format of each line: // xxx.. .C:080e A9 22 LDA #$22 if (pch[0] == '(' && pch[1] != 'C') { uint32_t offset = (uint32_t)atoi(&pch[2]); char* endOffset = strstr(&pch[2], ") "); if (endOffset) { endOffset += 2; uint16_t address = (uint16_t)strtol(endOffset, 0, 16); callStackEntries[(callStackCount * 2) + 0] = address; callStackEntries[(callStackCount * 2) + 1] = (uint16_t)offset; callStackCount++; } } pch = strtok(0, "\n"); } if (callStackCount == 0) return; PDWrite_eventBegin(writer, PDEventType_setCallstack); PDWrite_arrayBegin(writer, "callstack"); for (int i = 0; i < callStackCount; ++i) { PDWrite_arrayEntryBegin(writer); PDWrite_u16(writer, "address", callStackEntries[(i * 2) + 0] + callStackEntries[(i * 2) + 1]); PDWrite_arrayEntryEnd(writer); } PDWrite_arrayEnd(writer); PDWrite_eventEnd(writer); }
static void setRegisters(PDWriter* writer) { PDWrite_eventBegin(writer, PDEventType_setRegisters); PDWrite_arrayBegin(writer, "registers"); writeRegister(writer, "pc", 2, pc, 1); writeRegister(writer, "sp", 1, sp, 0); writeRegister(writer, "a", 1, a, 0); writeRegister(writer, "x", 1, x, 0); writeRegister(writer, "y", 1, y, 0); writeRegister(writer, "status", 1, status, 1); PDWrite_arrayEnd(writer); PDWrite_eventEnd(writer); }
static void setSourceFiles(LLDBPlugin* plugin, PDWriter* writer) { if (!plugin->hasValidTarget) return; PDWrite_eventBegin(writer, PDEventType_setSourceFiles); PDWrite_arrayBegin(writer, "files"); const uint32_t moduleCount = plugin->target.GetNumModules(); for (uint32_t im = 0; im < moduleCount; ++im) { lldb::SBModule module(plugin->target.GetModuleAtIndex(im)); const uint32_t compileUnitCount = module.GetNumCompileUnits(); for (uint32_t ic = 0; ic < compileUnitCount; ++ic) { lldb::SBCompileUnit compileUnit(module.GetCompileUnitAtIndex(ic)); const uint32_t supportFileCount = compileUnit.GetNumSupportFiles(); for (uint32_t is = 0; is < supportFileCount; ++is) { char filename[4096]; lldb::SBFileSpec fileSpec(compileUnit.GetSupportFileAtIndex(is)); filename[0] = 0; fileSpec.GetPath(filename, sizeof(filename)); if (filename[0] == 0) continue; PDWrite_arrayEntryBegin(writer); PDWrite_string(writer, "file", filename); PDWrite_arrayEntryEnd(writer); } } } PDWrite_arrayEnd(writer); PDWrite_eventEnd(writer); }
static void setThreads(LLDBPlugin* plugin, PDWriter* writer) { uint32_t threadCount = plugin->process.GetNumThreads(); if (threadCount == 0) return; PDWrite_eventBegin(writer, PDEventType_setThreads); PDWrite_arrayBegin(writer, "threads"); for (uint32_t i = 0; i < threadCount; ++i) { lldb::SBThread thread = plugin->process.GetThreadAtIndex(i); lldb::SBFrame frame = thread.GetFrameAtIndex(0); uint64_t threadId = thread.GetThreadID(); const char* threadName = thread.GetName(); const char* queueName = thread.GetQueueName(); const char* functionName = frame.GetFunctionName(); PDWrite_arrayEntryBegin(writer); PDWrite_u64(writer, "id", threadId); if (threadName) PDWrite_string(writer, "name", threadName); else if (queueName) PDWrite_string(writer, "name", queueName); else PDWrite_string(writer, "name", "unknown_thread"); if (functionName) PDWrite_string(writer, "function", functionName); else PDWrite_string(writer, "function", "unknown_function"); PDWrite_arrayEntryEnd(writer); } PDWrite_arrayEnd(writer); PDWrite_eventEnd(writer); }
static PDDebugState update(void* userData, PDAction action, PDReader* reader, PDWriter* writer) { PluginData* plugin = (PluginData*)userData; plugin->hasUpdatedRegistes = false; plugin->hasUpdatedExceptionLocation = false; onAction(plugin, action); processEvents(plugin, reader, writer); updateEvents(plugin, writer); if (plugin->hasUpdatedRegistes) { PDWrite_eventBegin(writer, PDEventType_setRegisters); PDWrite_arrayBegin(writer, "registers"); writeStatusRegister(writer, "flags", plugin->regs.flags); writeRegister(writer, "pc", 2, plugin->regs.pc, 1); writeRegister(writer, "sp", 1, plugin->regs.sp, 0); writeRegister(writer, "a", 1, plugin->regs.a, 0); writeRegister(writer, "x", 1, plugin->regs.x, 0); writeRegister(writer, "y", 1, plugin->regs.y, 0); PDWrite_arrayEnd(writer); PDWrite_eventEnd(writer); } if (plugin->hasUpdatedExceptionLocation) { PDWrite_eventBegin(writer, PDEventType_setExceptionLocation); PDWrite_u64(writer, "address", plugin->regs.pc); PDWrite_u8(writer, "address_size", 2); PDWrite_eventEnd(writer); } return plugin->state; }
static void setLocals(LLDBPlugin* plugin, PDWriter* writer) { lldb::SBThread thread(plugin->process.GetThreadByID(plugin->selectedThreadId)); lldb::SBFrame frame = thread.GetSelectedFrame(); lldb::SBValueList variables = frame.GetVariables(true, true, true, false); uint32_t count = variables.GetSize(); if (count <= 0) return; PDWrite_eventBegin(writer, PDEventType_setLocals); PDWrite_arrayBegin(writer, "locals"); for (uint32_t i = 0; i < count; ++i) { lldb::SBValue value = variables.GetValueAtIndex(i); PDWrite_arrayEntryBegin(writer); PDWrite_u64(writer, "address", value.GetAddress().GetFileAddress()); if (value.GetValue()) PDWrite_string(writer, "value", value.GetValue()); if (value.GetTypeName()) PDWrite_string(writer, "type", value.GetTypeName()); if (value.GetName()) PDWrite_string(writer, "name", value.GetName()); PDWrite_arrayEntryEnd(writer); } PDWrite_arrayEnd(writer); PDWrite_eventEnd(writer); }
static void parseDisassembly(PDWriter* writer, const char* data, int length) { memcpy(s_tempBuffer, data, length); s_tempBuffer[length] = 0; // parse the buffer char* pch = strtok(s_tempBuffer, "\n"); PDWrite_eventBegin(writer, PDEventType_setDisassembly); PDWrite_arrayBegin(writer, "disassembly"); while (pch) { // expected format of each line: // xxx.. .C:080e A9 22 LDA #$22 char* line = strstr(pch, ".C"); if (!line) break; uint16_t address = (uint16_t)strtol(&line[3], 0, 16); PDWrite_arrayEntryBegin(writer); PDWrite_u16(writer, "address", address); PDWrite_string(writer, "line", parseDisassemblyLine(&line[9])); PDWrite_arrayEntryEnd(writer); pch = strtok(0, "\n"); } PDWrite_arrayEnd(writer); PDWrite_eventEnd(writer); }