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 writeRegister(PDWriter* writer, const char* name, uint8_t size, uint16_t reg, uint8_t readOnly) { PDWrite_arrayEntryBegin(writer); PDWrite_string(writer, "name", name); PDWrite_u8(writer, "size", size); if (readOnly) PDWrite_u8(writer, "read_only", 1); if (size == 2) PDWrite_u16(writer, "register", reg); else PDWrite_u8(writer, "register", (uint8_t)reg); PDWrite_arrayEntryEnd(writer); }
static void writeStatusRegister(PDWriter* writer, const char* name, uint16_t reg) { PDWrite_arrayEntryBegin(writer); PDWrite_string(writer, "name", name); PDWrite_u8(writer, "read_only", 1); char statusString[128] = { 0 }; sprintf(statusString, "0x$%2x N:%d V:%d -:%d B:%d D:%d I:%d Z:%d C:%d", reg, (reg >> 7) & 1, (reg >> 6) & 1, (reg >> 5) & 1, (reg >> 4) & 1, (reg >> 3) & 1, (reg >> 2) & 1, (reg >> 1) & 1, (reg >> 0) & 1); PDWrite_string(writer, "register_string", statusString); PDWrite_arrayEntryEnd(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 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); }