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 eventAction(LLDBPlugin* plugin, PDReader* reader) { uint32_t action = 0; printf("LLDBPlugin; %d\n", (PDRead_find_u32(reader, &action, "action", 0) & 0xff) >> 8); printf("LLDBPlugin: got action (from event) %d\n", action); doAction(plugin, (PDAction)action); }
static void selectFrame(LLDBPlugin* plugin, PDReader* reader, PDWriter* writer) { uint32_t frameIndex; printf("selectFrame...\n"); PDRead_find_u32(reader, &frameIndex, "frame", 0); plugin->frameSelection[plugin->selectedThreadId] = frameIndex; setExceptionLocation(plugin, writer); }
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 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); } }
static bool get_disassembly(PluginData* data, PDReader* reader, PDWriter* writer) { char temp[2048]; uint64_t address_start = 0; uint32_t instruction_count = 0; PDRead_find_u64(reader, &address_start, "address_start", 0); PDRead_find_u32(reader, &instruction_count, "instruction_count", 0); // assume that one instruction is 3 bytes which is high but that gives us more data back than we need which is better than too little sprintf(temp, "disass $%04x $%04x\n", (uint16_t)address_start, (uint16_t)(address_start + instruction_count * 3)); return send_command_get_data(data, temp, parse_disassassembly_call, reader, writer, 20); }
static void on_menu(PluginData* data, PDReader* reader) { uint32_t menuId; PDRead_find_u32(reader, &menuId, "menu_id", 0); switch (menuId) { case C64_VICE_MENU_ATTACH_TO_VICE: { connect_to_local_host(data); break; } case C64_VICE_MENU_START_WITH_CONFIG: { launch_vice_with_config(data); break; } } }
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; }