[qwaq] Create a type encoding class

For now it just manages type encodings via their encoding string,
ensuring types are fetched from the target only once, if at all (may
already have the type due to it being common).
This commit is contained in:
Bill Currie 2020-03-30 12:43:02 +09:00
parent ddec80edc1
commit 1c13339bbe
11 changed files with 199 additions and 23 deletions

View file

@ -82,6 +82,9 @@ typedef struct qfot_type_s {
};
} qfot_type_t;
// the minimum size of a type encoding
#define TYPESIZE 4
typedef struct qfot_type_encodings_s {
qfot_type_t *types;
int size;

View file

@ -29,6 +29,7 @@ qwaq_app_dat_src= \
qwaq-app.r \
debugger/debug.r \
debugger/debugger.r \
debugger/typeencodings.r \
editor/editbuffer.r \
editor/editor.r \
ui/button.r \

View file

@ -618,7 +618,7 @@ cmd_mvwhline (qwaq_resources_t *res)
static void
dump_command (qwaq_resources_t *res, int len)
{
if (1) {
if (0) {
qwaq_commands cmd = RB_PEEK_DATA (res->command_queue, 0);
Sys_Printf ("%s[%d]", qwaq_command_names[cmd], len);
for (int i = 2; i < len; i++) {

View file

@ -506,7 +506,8 @@ static builtin_t builtins[] = {
{"qdb_continue", qdb_continue, -1},
{"qdb_get_state", qdb_get_state, -1},
{"qdb_get_data", qdb_get_data, -1},
{"qdb_get_string", qdb_get_string, -1},
{"qdb_get_string|{tag qdb_target_s=}i", qdb_get_string, -1},
{"qdb_get_string|{tag qdb_target_s=}*", qdb_get_string, -1},
{"qdb_find_global", qdb_find_global, -1},
{"qdb_find_field", qdb_find_field, -1},
{"qdb_find_function", qdb_find_function, -1},

View file

@ -63,7 +63,10 @@ int qdb_clear_watchpoint (qdb_target_t target);
int qdb_continue (qdb_target_t target);
qdb_state_t qdb_get_state (qdb_target_t target);
int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, void *dst);
string qdb_get_string (qdb_target_t target, unsigned str);
@overload string qdb_get_string (qdb_target_t target, unsigned str);
// note: str is likely not valid in the host progs, it's just a convinience to
// avoid cast shenanigans when getting type encoding strings
@overload string qdb_get_string (qdb_target_t target, string str);
qdb_def_t qdb_find_global (qdb_target_t target, string name);
qdb_def_t qdb_find_field (qdb_target_t target, string name);
qdb_function_t *qdb_find_function (qdb_target_t target, string name);

View file

@ -13,6 +13,7 @@ qdb_state_t qdb_get_state (qdb_target_t target) = #0;
int qdb_get_data (qdb_target_t target, unsigned src, unsigned len,
void *dst) = #0;
string qdb_get_string (qdb_target_t target, unsigned str) = #0;
string qdb_get_string (qdb_target_t target, string str) = #0;
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;

View file

@ -1,6 +1,7 @@
#ifndef __qwaq_debugger_debugger_h
#define __qwaq_debugger_debugger_h
#include <types.h>
#include <Object.h>
#include "debugger/debug.h"
@ -12,7 +13,8 @@
@interface Debugger : Object
{
qdb_target_t debug_target;
qdb_target_t target;
qfot_type_encodings_t target_encodings;
Window *source_window;
ProxyView *file_proxy;
@ -28,7 +30,7 @@
qdb_def_t *local_defs;
void *local_data;
}
-(qdb_target_t)debug_target;
-(qdb_target_t)target;
-initWithTarget:(qdb_target_t) target;
-handleDebugEvent;
@end

View file

@ -8,13 +8,14 @@
#include "ui/proxyview.h"
#include "ui/window.h"
#include "debugger/debugger.h"
#include "debugger/typeencodings.h"
#include "editor/editor.h"
#include "qwaq-app.h"
@implementation Debugger
-(qdb_target_t)debug_target
-(qdb_target_t)target
{
return debug_target;
return target;
}
-initWithTarget:(qdb_target_t) target
@ -22,12 +23,15 @@
if (!(self = [super init])) {
return nil;
}
debug_target = target;
self.target = target;
files = [[Array array] retain];
source_window = [[Window alloc] initWithRect: {nil, [application size]}];
[application addView:source_window];
qdb_def_t encodings_def = qdb_find_global (target, ".type_encodings");
qdb_get_data (target, encodings_def.offset, sizeof(target_encodings),
&target_encodings);
return self;
}
@ -50,7 +54,7 @@
-(void) setup
{
qdb_state_t state = qdb_get_state (debug_target);
qdb_state_t state = qdb_get_state (target);
current_file = [self find_file: state.file];
file_proxy = [[ProxyView alloc] initWithView: current_file];
@ -75,7 +79,7 @@
-(void) show_line
{
qdb_state_t state = qdb_get_state (debug_target);
qdb_state_t state = qdb_get_state (target);
Editor *file = [self find_file: state.file];
printf ("%s:%d\n", state.file, state.line);
@ -104,10 +108,10 @@ update_current_func (Debugger *self, unsigned fnum)
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);
self.func = qdb_get_function (self.target, fnum);
self.aux_func = qdb_get_auxfunction (self.target, fnum);
if (self.aux_func) {
self.local_defs = qdb_get_local_defs (self.debug_target, fnum);
self.local_defs = qdb_get_local_defs (self.target, fnum);
}
if (self.func) {
self.local_data = obj_malloc (self.func.local_size);
@ -116,14 +120,14 @@ update_current_func (Debugger *self, unsigned fnum)
-(void)update_watchvars
{
qdb_state_t state = qdb_get_state (debug_target);
qdb_state_t state = qdb_get_state (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);
qdb_get_data (target, func.local_data, func.local_size, local_data);
[locals_view clear];
if (!local_defs) {
[locals_view mvprintf:{0,0}, "%d", func.local_size];
@ -145,23 +149,25 @@ update_current_func (Debugger *self, unsigned fnum)
break;
}
qdb_def_t *def = local_defs + y;
unsigned te = def.type_encoding + (int) target_encodings.types;
qfot_type_t *type;
type = [TypeEncodings getType:te fromTarget:target];
[locals_view mvprintf:{0, y}, "%s",
qdb_get_string (debug_target, def.name)];
qdb_get_string (target, def.name)];
@param value = nil;
string valstr = "--";
unsigned offset = func.local_data + def.offset;
printf ("%d %d %s %d\n", def.type_size, offset,
qdb_get_string (debug_target, def.name),
qdb_get_string (target, def.name),
def.type_encoding);
qdb_get_data (debug_target, offset, def.type_size >> 16,
&value);
qdb_get_data (target, offset, def.type_size >> 16, &value);
switch (def.type_size & 0xffff) {
case ev_void:
case ev_invalid:
case ev_type_count:
break;
case ev_string:
valstr = qdb_get_string (debug_target, value.integer_val);
valstr = qdb_get_string (target, value.integer_val);
break;
case ev_float:
valstr = sprintf ("%.9g", value.float_val);
@ -216,8 +222,8 @@ proxy_event (Debugger *self, id proxy, qwaq_event_t *event)
} else if (event.what == qe_keydown) {
switch (event.key.code) {
case QFK_F7:
qdb_set_trace (self.debug_target, 1);
qdb_continue (self.debug_target);
qdb_set_trace (self.target, 1);
qdb_continue (self.target);
return 1;
}
}

View file

@ -0,0 +1,13 @@
#ifndef __qwaq_debugger_typeencodings_h
#define __qwaq_debugger_typeencodings_h
#include <types.h>
#include <Object.h>
#include "debugger/debug.h"
@interface TypeEncodings : Object
+(qfot_type_t *)getType:(unsigned)typeAddr fromTarget:(qdb_target_t)target;
@end
#endif//__qwaq_debugger_typeencodings_h

View file

@ -0,0 +1,146 @@
#include <runtime.h>
#include <hash.h>
#include <string.h>
#include <ui/curses.h> // printf FIXME
#include "debugger/typeencodings.h"
@implementation TypeEncodings
// these are encodings that we already have so don't need to copy them from
// the target
static hashtab_t *static_encodings;
// these are condings that had to be copied from the target
static hashtab_t *dynamic_encodings;
static qfot_type_t *
next_type (qfot_type_t *type)
{
int size = type.size;
if (!size) { // null type
size = TYPESIZE;
}
return (qfot_type_t *) ((int *) type + size);
}
static string
type_get_key (void *t, void *unusded)
{
qfot_type_t *type = (qfot_type_t *) t;
return type.encoding;
}
static void type_free (void *t, void *unused)
{
qfot_type_t *type = (qfot_type_t *) t;
str_free (type.encoding);
switch (type.meta) {
case ty_basic:
case ty_array:
break;
case ty_struct:
case ty_union:
case ty_enum:
str_free (type.strct.tag);
for (int i = 0; i < type.strct.num_fields; i++) {
str_free (type.strct.fields[i].name);
}
break;
case ty_class:
str_free (type.class);
break;
case ty_alias:
str_free (type.alias.name);
break;
}
obj_free (t);
}
+initialize
{
qfot_type_encodings_t *encodings;
qfot_type_t *type;
static_encodings = Hash_NewTable (1023, type_get_key, nil, nil);
dynamic_encodings = Hash_NewTable (1023, type_get_key, type_free, nil);
encodings = PR_FindGlobal (".type_encodings");
for (type = encodings.types;
((int *)type - (int *) encodings.types) < encodings.size;
type = next_type (type)) {
printf ("%s\n", type.encoding);
Hash_Add (static_encodings, type);
}
return self;
}
+(qfot_type_t *) getType:(unsigned)typeAddr fromTarget:(qdb_target_t)target
{
qfot_type_t buffer = {};
string encoding;
qfot_type_t *type;
if (!qdb_get_data (target, typeAddr, TYPESIZE, &buffer)) {
return nil;
}
if (!buffer.encoding) {
return nil;
}
encoding = qdb_get_string (target, buffer.encoding);
if (!encoding) {
return nil;
}
if ((type = Hash_Find (static_encodings, encoding))) {
return type;
}
if ((type = Hash_Find (dynamic_encodings, encoding))) {
return type;
}
type = obj_calloc (1, buffer.size);
if (!qdb_get_data (target, typeAddr, TYPESIZE, &buffer)) {
goto error;
}
if (!(type.encoding = qdb_get_string (target, type.encoding))) {
goto error;
}
switch (type.meta) {
case ty_basic:
case ty_array:
goto hash_type;
case ty_struct:
case ty_union:
case ty_enum:
if (!(type.strct.tag = qdb_get_string (target, type.strct.tag))) {
goto error;
}
for (int i = 0; i < type.strct.num_fields; i++) {
qfot_var_t *var = &type.strct.fields[i];
if (!(var.name = qdb_get_string (target, var.name))) {
goto error;
}
}
goto hash_type;
case ty_class:
if (!(type.class = qdb_get_string (target, type.class))) {
goto error;
}
goto hash_type;
case ty_alias:
if (!(type.alias.name = qdb_get_string (target, type.alias.name))) {
goto error;
}
goto hash_type;
}
goto error;
hash_type:
printf ("fetched type %s\n", type.encoding);
Hash_Add (dynamic_encodings, type);
return type;
// not a valid type
error:
type_free (type, nil);
return nil;
}
@end

View file

@ -80,7 +80,7 @@ arp_end (void)
for (int i = [debuggers count]; i-- > 0; ) {
debugger = [debuggers objectAtIndex: i];
if ([debugger debug_target].handle == target.handle) {
if ([debugger target].handle == target.handle) {
return debugger;
}
}