mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 07:11:41 +00:00
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:
parent
155a633ebe
commit
81293d98dd
3 changed files with 139 additions and 120 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
|
Loading…
Reference in a new issue