static void waitForBreak(uint64_t breakAddress, const CPUState* cpuState, uint64_t checkMask) { CPUState outState; //printf("wait for break $%llx\n", breakAddress); for (int i = 0; i < 12; ++i) { uint64_t address = 0; PDReader* reader = s_session->reader; PDBinaryReader_initStream(reader, PDBinaryWriter_getData(s_session->currentWriter), PDBinaryWriter_getSize(s_session->currentWriter)); if (getExceptionLocation(reader, &address, &outState)) { if (checkMask & CPUState_maskA) assert_true(cpuState->a == outState.a); if (checkMask & CPUState_maskX) assert_true(cpuState->x == outState.x); if (checkMask & CPUState_maskY) assert_int_equal(cpuState->y, outState.y); assert_int_equal((int)address, (int)breakAddress); return; } Time_sleepMs(1); Session_update(s_session); } fail(); }
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; } }
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_getBackendPlugins(&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; PDWrite_event_begin(writer, PDEventType_GetCallstack); PDWrite_u8(writer, "dummy", 0); PDWrite_event_end(writer); Session_update(session); PDBinaryWriter_finalize(session->currentWriter); PDBinaryReader_initStream(reader, PDBinaryWriter_getData(session->currentWriter), PDBinaryWriter_getSize(session->currentWriter)); uint32_t event; bool foundCallstack = false; while ((event = PDRead_get_event(reader)) != 0) { switch (event) { case PDEventType_SetCallstack: { foundCallstack = true; break; } } } assert_true(foundCallstack); #endif }
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(); }
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; }
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; }