Fix qfo line info dumping

The addition of xdef data has made qfo_to_progs unusable in qfprogs,
resulting in various invalid memory accesses. It always was an ugly hack
anyway, so this is the first step to proper qfo support in qfprogs.
This commit is contained in:
Bill Currie 2020-02-23 14:39:02 +09:00
parent 155a633ebe
commit 81293d98dd
3 changed files with 139 additions and 120 deletions

View file

@ -56,6 +56,7 @@ void dump_strings (struct progs_s *pr);
void qfo_globals (struct qfo_s *qfo);
void qfo_functions (struct qfo_s *qfo);
void qfo_lines (struct qfo_s *qfo);
void qfo_relocs (struct qfo_s *qfo);
void qfo_types (struct qfo_s *qfo);

View file

@ -41,49 +41,151 @@
#include <stdlib.h>
#include "QF/progs.h"
#include "QF/pr_type.h"
#include "obj_file.h"
#include "qfprogs.h"
void
dump_lines (progs_t *pr)
typedef struct {
const char *source_name;
const char *source_file;
pr_uint_t source_line;
pr_int_t first_statement;
pointer_t return_type;
pr_uint_t local_defs;
pr_uint_t num_locals;
pr_uint_t line_info;
pr_uint_t function;
} func_data_t;
typedef func_data_t *(*get_func_data_t)(unsigned func, void *data);
static func_data_t *
progs_get_func_data (unsigned func_index, void *data)
{
unsigned int i, line, addr;
pr_lineno_t *lineno;
pr_auxfunction_t *aux_func = 0;
dfunction_t *func = 0;
static func_data_t func_data;
progs_t *pr = (progs_t *) data;
pr_auxfunction_t *aux_func;
dfunction_t *func;
if (!pr->debug)
return;
for (i = 0; i < pr->debug->num_linenos; i++) {
lineno = &pr->linenos[i];
memset (&func_data, 0, sizeof (func_data));
if (func_index < pr->debug->num_auxfunctions) {
aux_func = pr->auxfunctions + func_index;
func_data.source_line = aux_func->source_line;
func_data.return_type = aux_func->return_type;
func_data.num_locals = aux_func->num_locals;
func_data.local_defs = aux_func->local_defs;
func_data.line_info = aux_func->line_info;
func_data.function = aux_func->function;
if (aux_func->function < (unsigned int) pr->progs->numfunctions) {
func = pr->pr_functions + aux_func->function;
func_data.source_file = pr->pr_strings + func->s_file;
func_data.source_name = pr->pr_strings + func->s_name;
func_data.first_statement = func->first_statement;
}
return &func_data;
}
return 0;
}
static void
dump_line_set (pr_lineno_t *lineno, unsigned count,
get_func_data_t get_func_data, void *data)
{
unsigned int line, addr;
func_data_t *func_data = 0;
for (; count-- > 0; lineno++) {
if (!lineno->line) {
aux_func = 0;
func = 0;
if (lineno->fa.func < pr->debug->num_auxfunctions)
aux_func = pr->auxfunctions + lineno->fa.func;
if (aux_func
&& aux_func->function < (unsigned int) pr->progs->numfunctions)
func = pr->pr_functions + aux_func->function;
func_data = get_func_data(lineno->fa.func, data);
}
printf ("%5u %5u", lineno->fa.addr, lineno->line);
line = addr = -1;
if (aux_func)
line = aux_func->source_line + lineno->line;
if (func)
addr = lineno->line ? lineno->fa.addr
: (unsigned int) func->first_statement;
if (aux_func && func)
printf (" %05x %s:%u %s+%u %d", addr, pr->pr_strings + func->s_file,
line, pr->pr_strings + func->s_name,
addr - func->first_statement, aux_func->return_type);
else if (aux_func)
printf ("%u %u %u %u %u %d", aux_func->function, line,
aux_func->line_info, aux_func->local_defs,
aux_func->num_locals, aux_func->return_type);
else if (lineno->line)
if (func_data) {
line = func_data->source_line + lineno->line;
if (func_data->source_name) {
addr = lineno->line ? (pr_int_t) lineno->fa.addr
: func_data->first_statement;
printf (" %05x %s:%u %s+%u %d", addr, func_data->source_file,
line, func_data->source_name,
addr - func_data->first_statement,
func_data->return_type);
} else {
printf ("%u %u %u %u %u %d", func_data->function, line,
func_data->line_info, func_data->local_defs,
func_data->num_locals, func_data->return_type);
}
} else if (lineno->line) {
printf ("%5x", lineno->fa.addr);
}
printf ("\n");
}
}
void
dump_lines (progs_t *pr)
{
if (!pr->debug)
return;
dump_line_set (pr->linenos, pr->debug->num_linenos,
progs_get_func_data, pr);
}
static func_data_t *
qfo_get_func_data (unsigned func_index, void *data)
{
return (func_data_t *) data;
}
static void
qfo_set_func_data (qfo_t *qfo, qfo_func_t *func, func_data_t *func_data)
{
qfot_type_t *type;
func_data->source_line = func->line;
//FIXME check type
type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, func->type);
func_data->return_type = type->t.func.return_type;
func_data->num_locals = -1;
if (func->locals_space < qfo->num_spaces) {
func_data->num_locals = qfo->spaces[func->locals_space].num_defs;
}
func_data->local_defs = func->locals_space;
func_data->line_info = func->line_info;
func_data->function = func - qfo->funcs;
func_data->source_file = QFO_GETSTR (qfo, func->file);
func_data->source_name = QFO_GETSTR (qfo, func->name);
func_data->first_statement = func->code;
}
void
qfo_lines (qfo_t *qfo)
{
static func_data_t func_data;
pr_lineno_t *start_lineno = 0;
pr_lineno_t *lineno;
qfo_func_t *func = 0;
for (func = qfo->funcs; func - qfo->funcs < qfo->num_funcs; func++) {
if (!func->line_info) {
// builtin
continue;
}
if (func->line_info >= qfo->num_lines) {
printf ("%s: bad line info: %u >= %u\n",
QFO_GETSTR (qfo, func->name),
func->line_info, qfo->num_lines);
continue;
}
qfo_set_func_data(qfo, func, &func_data);
start_lineno = qfo->lines + func->line_info;
for (lineno = start_lineno + 1;
lineno - qfo->lines < qfo->num_lines && lineno->line;
lineno++)
{
}
dump_line_set (start_lineno, lineno-start_lineno,
qfo_get_func_data, &func_data);
}
}

View file

@ -128,7 +128,6 @@ static edict_t *edicts;
static int num_edicts;
static int reserved_edicts = 1;
static progs_t pr;
static int need_progs;
static qfo_t *qfo;
static const char *source_path = "";
@ -234,7 +233,7 @@ init_qf (void)
{
Sys_Init ();
Cvar_Get ("pr_debug", va ("%d", verbosity), 0, 0, "");
Cvar_Get ("pr_debug", va ("%d", 1+verbosity), 0, 0, "");
Cvar_Get ("pr_source_path", source_path, 0, 0, "");
PR_Init_Cvars ();
PR_Init ();
@ -251,87 +250,6 @@ init_qf (void)
Hash_SetHashCompare (func_tab, func_hash, func_compare);
}
static void
convert_qfo (void)
{
int size;
int i;
xdef_t *xdef = 0;
pr_xdefs_t *xdefs = 0;
ddef_t *xdefs_def = 0;
ddef_t *global_ddefs;
ddef_t *field_ddefs;
pr.progs = qfo_to_progs (qfo, &size);
#define P(t,o) ((t *)((char *)pr.progs + pr.progs->o))
pr.pr_statements = P (dstatement_t, ofs_statements);
pr.pr_strings = P (char, ofs_strings);
pr.pr_stringsize = pr.progs->numstrings;
pr.pr_functions = P (dfunction_t, ofs_functions);
global_ddefs = P (ddef_t, ofs_globaldefs);
field_ddefs = P (ddef_t, ofs_fielddefs);
pr.pr_globals = P (pr_type_t, ofs_globals);
pr.globals_size = pr.progs->numglobals;
pr.pr_edict_size = max (1, pr.progs->entityfields) * 4;
pr.pr_edictareasize = 1 * pr.pr_edict_size;
#undef P
pr.pr_globaldefs = malloc ((pr.progs->numglobaldefs
+ pr.progs->numfielddefs)
* sizeof (pr_def_t));
pr.pr_fielddefs = pr.pr_globaldefs + pr.progs->numglobaldefs;
// can't use PR_FindGlobal yet as pr_globaldefs is still uninitialized
for (i = 0; i < (int) pr.progs->numglobaldefs; i++) {
ddef_t *ddef = global_ddefs + i;
if (!strcmp (PR_GetString (&pr, ddef->s_name), ".xdefs")) {
xdefs_def = ddef;
break;
}
}
if (xdefs_def) {
xdefs = &G_STRUCT (&pr, pr_xdefs_t, xdefs_def->ofs);
xdef = &G_STRUCT (&pr, xdef_t, xdefs->xdefs);
}
for (i = 0; i < (int) pr.progs->numglobaldefs; i++, xdef++) {
ddef_t *ddef = global_ddefs + i;
pr_def_t *def = pr.pr_globaldefs + i;
def->type = ddef->type;
def->ofs = xdefs ? xdef->ofs : ddef->ofs;
def->name = ddef->s_name;
def->type_encoding = xdefs ? xdef->type : 0;
}
for (i = 0; i < (int) pr.progs->numfielddefs; i++, xdef++) {
ddef_t *ddef = field_ddefs + i;
pr_def_t *def = pr.pr_fielddefs + i;
def->type = ddef->type;
def->ofs = xdefs ? xdef->ofs : ddef->ofs;
def->name = ddef->s_name;
def->type_encoding = xdefs ? xdef->type : 0;
}
if (verbosity) {
pr.debug = qfo_to_sym (qfo, &size);
#define P(t,o) ((t *)((char *)pr.debug + pr.debug->o))
pr.auxfunctions = P (pr_auxfunction_t, auxfunctions);
pr.linenos = P (pr_lineno_t, linenos);
pr.local_defs = P (pr_def_t, locals);
#undef P
pr.local_defs = calloc (qfo->num_defs, sizeof (ddef_t));
pr.auxfunction_map = calloc (pr.progs->numfunctions,
sizeof (pr_auxfunction_t *));
for (i = 0; (int) i < pr.progs->numfunctions; i++) //FIXME (cast)
pr.auxfunction_map[i] = 0;
for (i = 0; i < (int) pr.debug->num_auxfunctions; i++) {
pr_auxfunction_t *aux = pr.auxfunctions + i;
pr.auxfunction_map[aux->function] = aux;
}
}
}
static int
load_progs (const char *name)
{
@ -349,6 +267,7 @@ load_progs (const char *name)
Qread (file, buff, 4);
buff[4] = 0;
Qseek (file, 0, SEEK_SET);
qfo = 0;
if (!strcmp (buff, QFO)) {
qfo = qfo_read (file);
Qclose (file);
@ -356,9 +275,7 @@ load_progs (const char *name)
if (!qfo)
return 0;
if (!need_progs)
return 1;
convert_qfo ();
return 1;
} else {
pr.progs_name = name;
pr.max_edicts = 1;
@ -392,7 +309,7 @@ operation_t operations[] = {
{dump_strings, 0}, // strings
{dump_fields, 0}, // fields
{dump_functions, qfo_functions}, // functions
{dump_lines, 0}, // lines
{dump_lines, qfo_lines}, // lines
{dump_modules, 0}, // modules
{0, qfo_relocs}, // relocs
{dump_types, qfo_types}, // types
@ -451,12 +368,11 @@ main (int argc, char **argv)
}
init_qf ();
while (optind < argc) {
need_progs = !func->qfo;
if (!load_progs (argv[optind++]))
return 1;
if (qfo && func->qfo)
func->qfo (qfo);
else if (func->progs)
else if (!qfo && func->progs)
func->progs (&pr);
else
fprintf (stderr, "can't process %s\n", argv[optind - 1]);