2020-03-25 01:00:18 +00:00
|
|
|
#include <QF/keys.h>
|
2020-03-26 09:19:25 +00:00
|
|
|
#include <Array.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <types.h>
|
2020-03-24 16:07:58 +00:00
|
|
|
|
2020-03-24 16:32:52 +00:00
|
|
|
#include "qwaq-app.h"
|
2020-03-24 16:07:58 +00:00
|
|
|
#include "qwaq-curses.h"
|
|
|
|
#include "qwaq-debugger.h"
|
|
|
|
#include "qwaq-editor.h"
|
2020-03-25 01:00:18 +00:00
|
|
|
#include "qwaq-listener.h"
|
2020-03-24 16:07:58 +00:00
|
|
|
#include "qwaq-proxyview.h"
|
|
|
|
#include "qwaq-window.h"
|
|
|
|
|
|
|
|
@implementation Debugger
|
2020-03-24 16:32:52 +00:00
|
|
|
-(qdb_target_t)debug_target
|
|
|
|
{
|
|
|
|
return debug_target;
|
|
|
|
}
|
2020-03-24 16:07:58 +00:00
|
|
|
|
|
|
|
-initWithTarget:(qdb_target_t) target
|
|
|
|
{
|
|
|
|
if (!(self = [super init])) {
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
debug_target = target;
|
|
|
|
|
|
|
|
files = [[Array array] retain];
|
2020-03-24 16:32:52 +00:00
|
|
|
source_window = [[Window alloc] initWithRect: {nil, [application size]}];
|
|
|
|
[application addView:source_window];
|
2020-03-24 16:07:58 +00:00
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
-(Editor *) find_file:(string) filename
|
|
|
|
{
|
|
|
|
Editor *file;
|
|
|
|
for (int i = [files count]; i-- > 0; ) {
|
|
|
|
file = [files objectAtIndex: i];
|
|
|
|
if ([file filename] == filename) {
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Rect rect = {{1, 1}, [source_window size]};
|
|
|
|
rect.extent.width -= 2;
|
|
|
|
rect.extent.height -= 2;
|
|
|
|
file = [[Editor alloc] initWithRect: rect file: filename];
|
|
|
|
[files addObject: file];
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
|
|
|
|
-(void) setup
|
|
|
|
{
|
|
|
|
qdb_state_t state = qdb_get_state (debug_target);
|
|
|
|
|
|
|
|
current_file = [self find_file: state.file];
|
|
|
|
file_proxy = [[ProxyView alloc] initWithView: current_file];
|
2020-03-24 23:28:12 +00:00
|
|
|
[[current_file gotoLine:state.line - 1] highlightLine];
|
2020-03-26 09:22:40 +00:00
|
|
|
[[current_file onEvent] addListener: self :@selector(proxy_event::)];
|
2020-03-24 16:07:58 +00:00
|
|
|
//FIXME id<View>?
|
|
|
|
[source_window insertSelected: (View *) file_proxy];
|
2020-03-24 16:39:56 +00:00
|
|
|
[source_window setTitle: [current_file filename]];
|
2020-03-24 16:32:52 +00:00
|
|
|
[source_window redraw];
|
2020-03-26 00:04:31 +00:00
|
|
|
|
|
|
|
locals_window = [[Window alloc] initWithRect: {{0, 0}, {40, 10}}];
|
|
|
|
[locals_window setBackground: color_palette[064]];
|
|
|
|
[locals_window setTitle: "Locals"];
|
2020-03-26 09:22:40 +00:00
|
|
|
locals_view = [[View alloc] initWithRect: {{1, 1}, {38, 8}}
|
|
|
|
options: ofCanFocus];
|
2020-03-26 00:04:31 +00:00
|
|
|
[locals_window insertSelected: locals_view];
|
|
|
|
[application addView: locals_window];
|
2020-03-26 09:22:40 +00:00
|
|
|
|
|
|
|
[[locals_view onEvent] addListener:self :@selector(proxy_event::)];
|
2020-03-24 16:07:58 +00:00
|
|
|
}
|
|
|
|
|
2020-03-25 01:00:18 +00:00
|
|
|
-(void) show_line
|
|
|
|
{
|
|
|
|
qdb_state_t state = qdb_get_state (debug_target);
|
|
|
|
Editor *file = [self find_file: state.file];
|
|
|
|
|
|
|
|
printf ("%s:%d\n", state.file, state.line);
|
|
|
|
if (current_file != file) {
|
2020-03-26 09:22:40 +00:00
|
|
|
[[current_file onEvent] removeListener:self :@selector(proxy_event::)];
|
2020-03-25 01:00:18 +00:00
|
|
|
[file_proxy setView:file];
|
2020-03-26 09:22:40 +00:00
|
|
|
[[file onEvent] addListener:self :@selector(proxy_event::)];
|
2020-03-25 01:00:18 +00:00
|
|
|
[source_window setTitle: [file filename]];
|
|
|
|
current_file = file;
|
|
|
|
}
|
|
|
|
[[current_file gotoLine:state.line - 1] highlightLine];
|
|
|
|
[source_window redraw];
|
|
|
|
}
|
|
|
|
|
2020-03-26 00:04:31 +00:00
|
|
|
static void
|
|
|
|
update_current_func (Debugger *self, unsigned fnum)
|
|
|
|
{
|
|
|
|
self.current_fnum = fnum;
|
|
|
|
if (self.aux_func) {
|
|
|
|
obj_free (self.aux_func);
|
|
|
|
self.aux_func = nil;
|
|
|
|
}
|
|
|
|
if (self.local_defs) {
|
|
|
|
obj_free (self.local_defs);
|
|
|
|
}
|
|
|
|
if (self.local_data) {
|
|
|
|
obj_free (self.local_data);
|
|
|
|
}
|
|
|
|
self.func = qdb_get_function (self.debug_target, fnum);
|
|
|
|
self.aux_func = qdb_get_auxfunction (self.debug_target, fnum);
|
|
|
|
if (self.aux_func) {
|
|
|
|
self.local_defs = qdb_get_local_defs (self.debug_target, fnum);
|
|
|
|
}
|
|
|
|
if (self.func) {
|
|
|
|
self.local_data = obj_malloc (self.func.local_size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
-(void)update_watchvars
|
|
|
|
{
|
|
|
|
qdb_state_t state = qdb_get_state (debug_target);
|
|
|
|
if (state.func != current_fnum) {
|
|
|
|
update_current_func (self, state.func);
|
|
|
|
}
|
|
|
|
if (!local_data) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
qdb_get_data (debug_target, func.local_data, func.local_size, local_data);
|
2020-03-26 09:19:25 +00:00
|
|
|
if (!local_defs) {
|
|
|
|
[locals_view mvprintf:{0,0}, "%d", func.local_size];
|
|
|
|
for (int y = 1; y < [locals_view size].height; y++) {
|
|
|
|
unsigned ind = (y - 1) * 4;
|
|
|
|
if (ind < func.local_size) {
|
|
|
|
[locals_view mvprintf:{0, y}, "%02x", ind];
|
|
|
|
for (int x = 0; x < 4 && ind < func.local_size; x++, ind++) {
|
|
|
|
[locals_view mvprintf:{x * 9 + 3, y}, "%08x",
|
|
|
|
local_data[ind]];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (int y = 0; y < [locals_view size].height; y++) {
|
|
|
|
if (y >= aux_func.num_locals) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
qdb_def_t *def = local_defs + y;
|
|
|
|
[locals_view mvprintf:{0, y}, "%s",
|
|
|
|
qdb_get_string (debug_target, def.name)];
|
2020-03-26 12:01:39 +00:00
|
|
|
@param value = nil;
|
2020-03-26 09:19:25 +00:00
|
|
|
string valstr = "--";
|
2020-03-26 12:01:39 +00:00
|
|
|
unsigned offset = func.local_data + def.offset;
|
|
|
|
printf ("%d %d %s %d\n", def.type_size, offset,
|
|
|
|
qdb_get_string (debug_target, def.name),
|
|
|
|
def.type_encoding);
|
|
|
|
qdb_get_data (debug_target, offset, def.type_size >> 16,
|
|
|
|
&value);
|
2020-03-26 09:19:25 +00:00
|
|
|
switch (def.type_size & 0xffff) {
|
|
|
|
case ev_void:
|
|
|
|
case ev_invalid:
|
|
|
|
case ev_type_count:
|
|
|
|
break;
|
|
|
|
case ev_string:
|
2020-03-26 12:01:39 +00:00
|
|
|
valstr = qdb_get_string (debug_target, value.integer_val);
|
|
|
|
break;
|
2020-03-26 09:19:25 +00:00
|
|
|
case ev_float:
|
2020-03-26 12:01:39 +00:00
|
|
|
valstr = sprintf ("%.9g", value.float_val);
|
|
|
|
break;
|
2020-03-26 09:19:25 +00:00
|
|
|
case ev_vector:
|
2020-03-26 12:01:39 +00:00
|
|
|
valstr = sprintf ("%.9v", value.vector_val);
|
|
|
|
break;
|
2020-03-26 09:19:25 +00:00
|
|
|
case ev_entity:
|
2020-03-26 12:01:39 +00:00
|
|
|
valstr = sprintf ("%e", value.entity_val);
|
|
|
|
break;
|
2020-03-26 09:19:25 +00:00
|
|
|
case ev_field:
|
2020-03-26 12:01:39 +00:00
|
|
|
valstr = sprintf ("[%x]", value.field_val);
|
|
|
|
break;
|
2020-03-26 09:19:25 +00:00
|
|
|
case ev_func:
|
2020-03-26 12:01:39 +00:00
|
|
|
valstr = sprintf ("[%x]", value.func_val);
|
|
|
|
break;
|
2020-03-26 09:19:25 +00:00
|
|
|
case ev_pointer:
|
2020-03-26 12:01:39 +00:00
|
|
|
valstr = sprintf ("[%x]", value.pointer_val);
|
|
|
|
break;
|
2020-03-26 09:19:25 +00:00
|
|
|
case ev_quat:
|
2020-03-26 12:01:39 +00:00
|
|
|
valstr = sprintf ("[%q]", value.quaternion_val);
|
|
|
|
break;
|
2020-03-26 09:19:25 +00:00
|
|
|
case ev_integer:
|
2020-03-26 12:01:39 +00:00
|
|
|
valstr = sprintf ("%d", value.integer_val);
|
|
|
|
break;
|
2020-03-26 09:19:25 +00:00
|
|
|
case ev_uinteger:
|
2020-03-26 12:01:39 +00:00
|
|
|
valstr = sprintf ("%d", value.integer_val);
|
|
|
|
break;
|
2020-03-26 09:19:25 +00:00
|
|
|
case ev_short:
|
2020-03-26 12:01:39 +00:00
|
|
|
valstr = sprintf ("%d", value.integer_val);
|
|
|
|
break;
|
2020-03-26 09:19:25 +00:00
|
|
|
case ev_double:
|
2020-03-26 12:01:39 +00:00
|
|
|
valstr = sprintf ("%.17g", value.double_val);
|
2020-03-26 09:19:25 +00:00
|
|
|
break;
|
2020-03-26 00:04:31 +00:00
|
|
|
}
|
2020-03-26 12:01:39 +00:00
|
|
|
int x = [locals_view size].width - strlen (valstr);
|
2020-03-26 09:19:25 +00:00
|
|
|
[locals_view mvaddstr:{x, y}, valstr];
|
2020-03-26 00:04:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
[TextContext refresh];
|
|
|
|
}
|
|
|
|
|
2020-03-26 00:19:22 +00:00
|
|
|
static int
|
2020-03-26 09:22:40 +00:00
|
|
|
proxy_event (Debugger *self, id proxy, qwaq_event_t *event)
|
2020-03-25 01:00:18 +00:00
|
|
|
{
|
2020-03-26 00:19:22 +00:00
|
|
|
if (event.what == qe_mouseclick && !(event.mouse.buttons & 0x78)) {
|
2020-03-26 09:22:40 +00:00
|
|
|
if (proxy == self.current_file) {
|
|
|
|
printf ("%s\n", [proxy getWordAt: {event.mouse.x, event.mouse.y}]);
|
|
|
|
[self.source_window redraw];
|
|
|
|
return 1;
|
|
|
|
}
|
2020-03-25 08:29:08 +00:00
|
|
|
} else if (event.what == qe_keydown) {
|
2020-03-25 01:00:18 +00:00
|
|
|
switch (event.key.code) {
|
|
|
|
case QFK_F7:
|
2020-03-26 00:19:22 +00:00
|
|
|
qdb_set_trace (self.debug_target, 1);
|
|
|
|
qdb_continue (self.debug_target);
|
|
|
|
return 1;
|
2020-03-25 01:00:18 +00:00
|
|
|
}
|
|
|
|
}
|
2020-03-26 00:19:22 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-03-26 09:22:40 +00:00
|
|
|
-(void)proxy_event:(id)proxy :(qwaq_event_t *)event
|
2020-03-26 00:19:22 +00:00
|
|
|
{
|
2020-03-26 09:22:40 +00:00
|
|
|
if (proxy_event (self, proxy, event)) {
|
2020-03-26 05:16:58 +00:00
|
|
|
event.what = qe_none;
|
2020-03-26 00:19:22 +00:00
|
|
|
}
|
2020-03-25 01:00:18 +00:00
|
|
|
}
|
|
|
|
|
2020-03-24 16:07:58 +00:00
|
|
|
-handleDebugEvent
|
|
|
|
{
|
|
|
|
if (!file_proxy) {
|
|
|
|
[self setup];
|
|
|
|
}
|
2020-03-25 01:00:18 +00:00
|
|
|
[self show_line];
|
2020-03-26 00:04:31 +00:00
|
|
|
[self update_watchvars];
|
2020-03-24 16:07:58 +00:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
2020-03-26 04:27:53 +00:00
|
|
|
void traceon() = #0;
|
|
|
|
void traceoff() = #0;
|
|
|
|
|
2020-03-24 16:07:58 +00:00
|
|
|
void qdb_set_trace (qdb_target_t target, int state) = #0;
|
|
|
|
int qdb_set_breakpoint (qdb_target_t target, unsigned staddr) = #0;
|
|
|
|
int qdb_clear_breakpoint (qdb_target_t target, unsigned staddr) = #0;
|
|
|
|
int qdb_set_watchpoint (qdb_target_t target, unsigned offset) = #0;
|
|
|
|
int qdb_clear_watchpoint (qdb_target_t target) = #0;
|
|
|
|
int qdb_continue (qdb_target_t target) = #0;
|
|
|
|
qdb_state_t qdb_get_state (qdb_target_t target) = #0;
|
2020-03-25 13:39:17 +00:00
|
|
|
int qdb_get_data (qdb_target_t target, unsigned src, unsigned len,
|
|
|
|
void *dst) = #0;
|
2020-03-26 09:14:20 +00:00
|
|
|
string qdb_get_string (qdb_target_t target, unsigned str) = #0;
|
2020-03-25 13:39:17 +00:00
|
|
|
qdb_def_t qdb_find_global (qdb_target_t target, string name) = #0;
|
|
|
|
qdb_def_t qdb_find_field (qdb_target_t target, string name) = #0;
|
|
|
|
qdb_function_t *qdb_find_function (qdb_target_t target, string name) = #0;
|
2020-03-26 00:03:44 +00:00
|
|
|
qdb_function_t *qdb_get_function (qdb_target_t target, unsigned fnum) = #0;
|
2020-03-25 13:39:17 +00:00
|
|
|
qdb_auxfunction_t *qdb_find_auxfunction (qdb_target_t target,
|
|
|
|
string name) = #0;
|
2020-03-26 00:03:44 +00:00
|
|
|
qdb_auxfunction_t *qdb_get_auxfunction (qdb_target_t target,
|
|
|
|
unsigned fnum) = #0;
|
2020-03-25 13:39:17 +00:00
|
|
|
qdb_def_t *qdb_get_local_defs (qdb_target_t target, unsigned fnum) = #0;
|