quakeforge/ruamoko/qwaq/debugger/localsdata.r
Bill Currie c6aa061229 [qwaq] Fetch Ruamoko progs locals from the stack frame
Now that the data is fetched from the correct location, the locals view
is useful again :). However, there seems to be a problem with array
views: not sure they're showing the correct data as I was getting
unexpected values in the display but normal vars seem to be ok.
2022-02-12 10:19:45 +09:00

170 lines
3.6 KiB
R

#include <stdlib.h>
#include <string.h>
#include <types.h>
#include "ruamoko/qwaq/debugger/views/defview.h"
#include "ruamoko/qwaq/debugger/views/nameview.h"
#include "ruamoko/qwaq/debugger/localsdata.h"
#include "ruamoko/qwaq/ui/listener.h"
@implementation LocalsData
-initWithTarget:(qdb_target_t) target
{
if (!(self = [super init])) {
return nil;
}
self.target = target;
qdb_def_t encodings_def = qdb_find_global (target, ".type_encodings");
qdb_get_data (target, encodings_def.offset, sizeof(target_encodings),
&target_encodings);
self.has_stack = qdb_has_data_stack (target);
self.onRowCountChanged = [[ListenerGroup listener] retain];
return self;
}
+(LocalsData *)withTarget:(qdb_target_t)target
{
return [[[self alloc] initWithTarget:target] autorelease];
}
static void
free_defs (LocalsData *self)
{
obj_free (self.defs);
self.defs = nil;
for (int i = 0; i < self.num_user_defs; i++) {
[self.def_views[i] release];
}
obj_free (self.def_views);
self.def_views = nil;
obj_free (self.def_rows);
self.def_rows = nil;
}
-(void)dealloc
{
[onRowCountChanged release];
if (defs) {
free_defs (self);
}
if (data) {
obj_free (data);
data = nil;
}
[super dealloc];
}
-setFunction:(unsigned) fnum
{
if (current_fnum == fnum) {
return self;
}
current_fnum = fnum;
if (defs) {
free_defs (self);
}
if (data) {
obj_free (data);
data = nil;
}
func = qdb_get_function (target, fnum);
if (func && func.local_size) {
data = obj_malloc (func.local_size);
}
aux_func = qdb_get_auxfunction (target, fnum);
num_user_defs = 0;
if (aux_func) {
defs = qdb_get_local_defs (target, fnum);
for (int i = 0; i < aux_func.num_locals; i++) {
string def_name = qdb_get_string (target, defs[i].name);
if (str_mid (def_name, 0, 1) != ".") {
num_user_defs++;
}
}
def_views = obj_malloc (num_user_defs);
def_rows = obj_malloc (num_user_defs + 1);
def_rows[0] = 0;
for (int i = 0, j = 0; i < aux_func.num_locals; i++) {
string def_name = qdb_get_string (target, defs[i].name);
if (str_mid (def_name, 0, 1) == ".") {
continue;
}
def_views[j] = [[DefView withDef:defs[i] in:data target:target]
retain];
def_rows[j + 1] = [def_views[j] rows];
j++;
}
prefixsum (def_rows, num_user_defs + 1);
}
[onRowCountChanged respond:self];
return self;
}
-fetchData
{
if (data && func.local_size) {
unsigned local_data = func.local_data;
if (has_stack) {
unsigned stack_ptr = qdb_get_frame_addr (target);
local_data = 0;
if (stack_ptr) {
local_data = stack_ptr - func.local_data;
}
}
if (local_data) {
qdb_get_data (target, local_data, func.local_size, data);
}
}
int rowCount = def_rows[num_user_defs];
if (aux_func) {
def_rows[0] = 0;
for (int i = 0; i < num_user_defs; i++) {
[def_views[i] fetchData];
def_rows[i + 1] = [def_views[i] rows];
}
prefixsum (def_rows, num_user_defs + 1);
}
if (rowCount != def_rows[num_user_defs]) {
[onRowCountChanged respond:self];
}
return self;
}
-(ListenerGroup *)onRowCountChanged
{
return onRowCountChanged;
}
-(int)numberOfRows:(TableView *)tableview
{
if (aux_func) {
if (!num_user_defs) {
return 0;
}
return def_rows[num_user_defs];
} else if (func) {
return (func.local_size + 3) / 4;
}
return 0;
}
-(View *)tableView:(TableView *)tableview
forColumn:(TableViewColumn *)column
row:(int)row
{
View *view = nil;
int *index = fbsearch (&row, def_rows, num_user_defs, 1, nil);
if (index) {
DefView *dv = def_views[index - def_rows];
int r = row - *index;
view = [dv viewAtRow: r forColumn:column];
}
return view;
}
@end