mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 23:32:09 +00:00
[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:
parent
ddec80edc1
commit
1c13339bbe
11 changed files with 199 additions and 23 deletions
|
@ -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;
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
13
ruamoko/qwaq/debugger/typeencodings.h
Normal file
13
ruamoko/qwaq/debugger/typeencodings.h
Normal 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
|
146
ruamoko/qwaq/debugger/typeencodings.r
Normal file
146
ruamoko/qwaq/debugger/typeencodings.r
Normal 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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue