static void processEvents(LLDBPlugin* plugin, PDReader* reader, PDWriter* writer) { uint32_t event; while ((event = PDRead_getEvent(reader))) { //printf("LLDBPlugin: %d Got event %s\n", event, eventTypes[event]); switch (event) { case PDEventType_getExceptionLocation : setExceptionLocation(plugin, writer); break; case PDEventType_getCallstack : setCallstack(plugin, writer); break; case PDEventType_setExecutable : setExecutable(plugin, reader); break; case PDEventType_selectThread : selectThread(plugin, reader, writer); break; case PDEventType_selectFrame : selectFrame(plugin, reader, writer); break; case PDEventType_getLocals : setLocals(plugin, writer); break; case PDEventType_getThreads : setThreads(plugin, writer); break; case PDEventType_getSourceFiles : setSourceFiles(plugin, writer); break; case PDEventType_setBreakpoint : setBreakpoint(plugin, reader, writer); break; case PDEventType_action : eventAction(plugin, reader); break; } } setTty(plugin, writer); }
static bool getExceptionLocation(PDReader* reader, uint64_t* address, CPUState* cpuState) { uint32_t event; bool foundException = false; while ((event = PDRead_getEvent(reader)) != 0) { switch (event) { case PDEventType_setRegisters: { if (cpuState) updateRegisters(cpuState, reader); break; } case PDEventType_setExceptionLocation: { assert_true(PDRead_findU64(reader, address, "address", 0) & PDReadStatus_ok); foundException = true; break; } } } return foundException; }
static int update(void* userData, PDUI* uiFuncs, PDReader* inEvents, PDWriter* outEvents) { uint32_t event = 0; while ((event = PDRead_getEvent(inEvents)) != 0) { switch (event) { case PDEventType_setLocals: { showInUI((LocalsData*)userData, inEvents, uiFuncs); break; } } } // Request callstack data // TODO: Dont' request locals all the time PDWrite_eventBegin(outEvents, PDEventType_getLocals); PDWrite_u8(outEvents, "dummy_remove", 0); // TODO: Remove me PDWrite_eventEnd(outEvents); return 0; }
void test_c64_vice_get_disassembly(void**) { static Assembly assembly[] = { { 0x080e, "A9 22 LDA #$22" }, { 0x0810, "A2 32 LDX #$32" }, { 0x0812, "C8 INY" }, { 0x0813, "EE 20 D0 INC $D020" }, { 0x0816, "EE 21 D0 INC $D021" }, { 0x0819, "4C 0E 08 JMP $080E" }, { 0, 0 }, }; PDWriter* writer = s_session->currentWriter; PDWrite_eventBegin(writer, PDEventType_getDisassembly); PDWrite_u64(writer, "address_start", 0x80e); PDWrite_u32(writer, "instruction_count", (uint32_t)4); PDWrite_eventEnd(writer); PDBinaryWriter_finalize(writer); Session_update(s_session); PDReader* reader = s_session->reader; PDBinaryReader_initStream(reader, PDBinaryWriter_getData(s_session->currentWriter), PDBinaryWriter_getSize(s_session->currentWriter)); uint32_t event; while ((event = PDRead_getEvent(reader)) != 0) { if (event != PDEventType_setDisassembly) continue; PDReaderIterator it; assert_false(PDRead_findArray(reader, &it, "disassembly", 0) == PDReadStatus_notFound); int i = 0; while (PDRead_getNextEntry(reader, &it)) { uint64_t address; const char* text; PDRead_findU64(reader, &address, "address", it); PDRead_findString(reader, &text, "line", it); assert_non_null(assembly[i].text); assert_int_equal((int)assembly[i].address, (int)address); assert_string_equal(assembly[i].text, text); i++; } return; } }
void test_c64_vice_callstack(void**) { uint32_t event; PDReaderIterator it; uint16_t refCallstack[] = { 0xe112 + 2, // (2) e112 0xa562 + 4, // (4) a562 0xa483 + 6, // (6) a483 0xa677 + 8, // (8) a677 0xe39a + 10, // (10) e39a }; PDWriter* writer = s_session->currentWriter; PDWrite_eventBegin(writer, PDEventType_getCallstack); PDWrite_eventEnd(writer); PDBinaryWriter_finalize(writer); Session_update(s_session); PDReader* reader = s_session->reader; PDBinaryReader_initStream(reader, PDBinaryWriter_getData(s_session->currentWriter), PDBinaryWriter_getSize(s_session->currentWriter)); while ((event = PDRead_getEvent(reader)) != 0) { switch (event) { case PDEventType_setCallstack: { if (PDRead_findArray(reader, &it, "callstack", 0) == PDReadStatus_notFound) return; int callstackSize = sizeof_array(refCallstack); int count = 0; while (PDRead_getNextEntry(reader, &it)) { uint16_t address; PDRead_findU16(reader, &address, "address", it); assert_true(count < callstackSize); assert_int_equal(refCallstack[count], address); count++; } return; } } } fail(); }
static int update(void* userData, PDUI* uiFuncs, PDReader* inEvents, PDWriter* writer) { uint32_t event; DissassemblyData* data = (DissassemblyData*)userData; data->requestDisassembly = false; while ((event = PDRead_getEvent(inEvents)) != 0) { switch (event) { case PDEventType_setDisassembly: { setDisassemblyCode(data, inEvents); break; } case PDEventType_setExceptionLocation: { uint64_t location = 0; PDRead_findU64(inEvents, &location, "address", 0); if (location != data->location) { data->location = location; data->requestDisassembly = true; } PDRead_findU8(inEvents, &data->locationSize, "address_size", 0); break; } case PDEventType_setRegisters: { updateRegisters(data, inEvents); break; } } } renderUI(data, uiFuncs); if (data->requestDisassembly) { int pc = (int)(data->pc) & ~(BlockSize - 1); PDWrite_eventBegin(writer, PDEventType_getDisassembly); PDWrite_u64(writer, "address_start", (uint64_t)pc); PDWrite_u32(writer, "instruction_count", (uint32_t)BlockSize / 3); PDWrite_eventEnd(writer); } return 0; }
bool handleEvents(CPUState* cpuState, Session* session) { uint32_t event = 0; PDReader* reader = session->reader; PDBinaryReader_initStream(reader, PDBinaryWriter_getData(session->currentWriter), PDBinaryWriter_getSize(session->currentWriter)); while ((event = PDRead_getEvent(reader)) != 0) { if (event == PDEventType_setRegisters) { updateRegisters(cpuState, reader); return true; } } return false; }
static int update(void* userData, PDUI* uiFuncs, PDReader* inEvents, PDWriter* outEvents) { uint32_t event; (void)outEvents; HexMemoryData* data = (HexMemoryData*)userData; /* PDVec2 windowSize = uiFuncs->getWindowSize(); const float fontHeight = uiFuncs->getFontHeight(); const float fontWidth = uiFuncs->getFontWidth(); int drawableLineCount = (int)(windowSize.y / fontHeight); int drawableChars = (int)(windowSize.x / fontWidth); */ // Loop over all the in events while ((event = PDRead_getEvent(inEvents)) != 0) { switch (event) { case PDEventType_setMemory: { updateMemory(data, inEvents); break; } } } drawUI(data, uiFuncs); /* PDWrite_eventBegin(outEvents, PDEventType_getMemory); PDWrite_u16(outEvents, "address", 0x6000); PDWrite_u16(outEvents, "size", (uint16_t)(drawableLineCount * drawableChars)); PDWrite_eventEnd(outEvents); */ return 0; }
static int update(void* userData, PDUI* uiFuncs, PDReader* inEvents, PDWriter* writer) { uint32_t event; DissassemblyData* data = (DissassemblyData*)userData; while ((event = PDRead_getEvent(inEvents)) != 0) { switch (event) { case PDEventType_setDisassembly: { setDisassemblyCode(data, inEvents); break; } case PDEventType_setExceptionLocation: { PDRead_findU64(inEvents, &data->location, "address", 0); PDRead_findU8(inEvents, &data->locationSize, "address_size", 0); break; } case PDEventType_setRegisters: updateRegisters(data, inEvents); break; } } renderUI(data, uiFuncs); // Temporary req PDWrite_eventBegin(writer, PDEventType_getDisassembly); PDWrite_u64(writer, "address_start", 0); PDWrite_u32(writer, "instruction_count", (uint32_t)10); PDWrite_eventEnd(writer); return 0; }
bool getMemory(void* dest, int* len, uint16_t inAddress, int readLength) { PDWriter* writer = s_session->currentWriter; PDWrite_eventBegin(writer, PDEventType_getMemory); PDWrite_u64(writer, "address_start", inAddress); PDWrite_u64(writer, "size", (uint32_t)readLength); PDWrite_eventEnd(writer); PDBinaryWriter_finalize(writer); Session_update(s_session); PDReader* reader = s_session->reader; PDBinaryReader_initStream(reader, PDBinaryWriter_getData(s_session->currentWriter), PDBinaryWriter_getSize(s_session->currentWriter)); uint32_t event; while ((event = PDRead_getEvent(reader)) != 0) { uint8_t* data; uint64_t dataSize; uint64_t address; if (event != PDEventType_setMemory) continue; assert_true(PDRead_findU64(reader, &address, "address", 0) & PDReadStatus_ok); assert_true((PDRead_findData(reader, (void**)&data, &dataSize, "data", 0) & PDReadStatus_typeMask) == PDReadType_data); memcpy(dest, data, dataSize); *len = (int)dataSize; return true; } return false; }
static int update(void* userData, PDUI* uiFuncs, PDReader* inEvents, PDWriter* writer) { uint32_t event; (void)uiFuncs; (void)writer; BreakpointsData* data = (BreakpointsData*)userData; while ((event = PDRead_getEvent(inEvents)) != 0) { switch (event) { case PDEventType_setBreakpoint: { toogleBreakpointFileLine(data, inEvents); break; } case PDEventType_replyBreakpoint: { uint64_t address = 0; uint32_t id = (uint32_t) ~0; PDRead_findU64(inEvents, &address, "address", 0); PDRead_findU32(inEvents, &id, "id", 0); for (Breakpoint* bp : data->breakpoints) { if ((uint64_t)strtol(bp->location.address, 0, 16) == address) { bp->pendingCount = 0; // breakpoint accepted printf("bp view: updated breakpoint with id %d (was %d)\n", id, bp->id); bp->id = (int)id; break; } } break; } } } uiFuncs->text(""); if (uiFuncs->button("Add Breakpoint", { 0.0f, 0.0f } )) { Breakpoint* bp = createBreakpoint(data); data->breakpoints.push_back(bp); } uiFuncs->columns(4, "", true); //uiFuncs->text(""); uiFuncs->nextColumn(); uiFuncs->text("Name/Address"); uiFuncs->nextColumn(); uiFuncs->text("Label"); uiFuncs->nextColumn(); uiFuncs->text("Condition"); uiFuncs->nextColumn(); uiFuncs->text(""); uiFuncs->nextColumn(); for (auto& i : data->breakpoints) { Breakpoint* bp = i; bool needUpdate = false; uiFuncs->pushIdPtr(bp); //if (uiFuncs->checkbox("Enabled", &bp->enabled)) // needUpdate = true; if (bp->location.filename) { uiFuncs->inputText("##filename", bp->location.filename, (int)data->maxPath, 0, 0, 0); } else { if (uiFuncs->inputText("##address", bp->location.address, (int)data->maxPath, PDUIInputTextFlags_CharsHexadecimal | PDUIInputTextFlags_EnterReturnsTrue, 0, 0)) needUpdate = true; } uiFuncs->nextColumn(); uiFuncs->text(""); uiFuncs->nextColumn(); uiFuncs->text(""); // no condition for now //if (uiFuncs->inputText("##condition", bp->condition, (int)data->maxPath, PDInputTextFlags_EnterReturnsTrue, 0, 0)) // needUpdate = true; uiFuncs->nextColumn(); if (needUpdate) { // TODO: Add support for file/line PDWrite_eventBegin(writer, PDEventType_setBreakpoint); PDWrite_u64(writer, "address", (uint64_t)strtol(bp->location.address, 0, 16)); //if (bp->condition[0] != 0) // PDWrite_string(writer, "condition", bp->condition); if (bp->id != -1) PDWrite_u32(writer, "id", (uint32_t)bp->id); PDWrite_eventEnd(writer); printf("Sending breakpint\n"); } if (uiFuncs->button("Delete", {0.0f, 0.0f})) { PDWrite_eventBegin(writer, PDEventType_deleteBreakpoint); PDWrite_u32(writer, "id", (uint32_t)bp->id); PDWrite_eventEnd(writer); bp->markDelete = true; } uiFuncs->nextColumn(); uiFuncs->popId(); } // Delete breakpoints that have been marked delete for (auto i = data->breakpoints.begin(); i != data->breakpoints.end(); ++i) { Breakpoint* bp = *i; if (bp->pendingCount > 1) bp->pendingCount++; if (bp->markDelete || bp->pendingCount >= 10) i = data->breakpoints.erase(i); } return 0; }
static void test_lldb(void** state) { (void)state; // we only do the LLDB test on Mac for now #ifdef __APPLE__ PluginData* pluginData; Session* session; int count = 0; assert_true(PluginHandler_addPlugin(OBJECT_DIR, "lldb_plugin")); assert_non_null(pluginData = PluginHandler_getPlugins(&count)[0]); session = Session_createLocal((PDBackendPlugin*)pluginData->plugin, OBJECT_DIR "/crashing_native"); assert_non_null(session); // I hate to do this but there is really no good way to deal with this otherwise (at least currently) Time_sleepMs(800); Session_update(session); Session_update(session); // Expect that we have a crash here and thus are in PDDebugState_stopException state assert_int_equal(session->state, PDDebugState_stopException); // Request locals location. PDWriter* writer = session->currentWriter; PDReader* reader = session->reader; PDBinaryWriter_reset(writer); PDWrite_eventBegin(writer, PDEventType_getCallstack); PDWrite_u8(writer, "dummy", 0); PDWrite_eventEnd(writer); PDBinaryWriter_finalize(writer); Session_update(session); PDBinaryReader_reset(reader); uint32_t event; bool foundCallstack = false; while ((event = PDRead_getEvent(reader)) != 0) { switch (event) { case PDEventType_setCallstack: { foundCallstack = true; break; } } } assert_true(foundCallstack); #endif }
static void processEvents(PluginData* data, PDReader* reader, PDWriter* writer) { uint32_t event; while ((event = PDRead_getEvent(reader))) { switch (event) { //case PDEventType_getExceptionLocation : setExceptionLocation(plugin, writer); break; //case PDEventType_getCallstack : setCallstack(plugin, writer); break; case PDEventType_getRegisters: { sendCommand(data, "registers\n"); break; } case PDEventType_getCallstack: { if (shouldSendCommand(data)) sendCommand(data, "bt\n"); break; } case PDEventType_getDisassembly: { if (shouldSendCommand(data)) getDisassembly(data, reader); break; } case PDEventType_getMemory: { if (shouldSendCommand(data)) getMemory(data, reader, writer); break; } case PDEventType_menuEvent: { onMenu(data, reader); break; } case PDEventType_setBreakpoint: { setBreakpoint(data, reader, writer); // if we add a breakpoint to VICE it will always stop but if we are already running when // adding the breakpoint we just force VICE to run again if (data->state == PDDebugState_running) sendCommand(data, "ret\n"); break; } case PDEventType_deleteBreakpoint: { delBreakpoint(data, reader, writer); break; } } } }