mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 23:32:09 +00:00
perform relocations so disassembly dumps of qfo files make sense
This commit is contained in:
parent
16e4964a31
commit
394e83e419
1 changed files with 143 additions and 41 deletions
|
@ -67,6 +67,26 @@ static __attribute__ ((unused)) const char rcsid[] =
|
||||||
|
|
||||||
#include "obj_file.h"
|
#include "obj_file.h"
|
||||||
#include "qfprogs.h"
|
#include "qfprogs.h"
|
||||||
|
#include "reloc.h"
|
||||||
|
|
||||||
|
const char *reloc_names[] = {
|
||||||
|
"none",
|
||||||
|
"op_a_def",
|
||||||
|
"op_b_def",
|
||||||
|
"op_c_def",
|
||||||
|
"op_a_op",
|
||||||
|
"op_b_op",
|
||||||
|
"op_c_op",
|
||||||
|
"def_op",
|
||||||
|
"def_def",
|
||||||
|
"def_func",
|
||||||
|
"def_string",
|
||||||
|
"def_field",
|
||||||
|
"op_a_def_ofs",
|
||||||
|
"op_b_def_ofs",
|
||||||
|
"op_c_def_ofs",
|
||||||
|
"def_def_ofs",
|
||||||
|
};
|
||||||
|
|
||||||
int sorted = 0;
|
int sorted = 0;
|
||||||
int verbosity = 0;
|
int verbosity = 0;
|
||||||
|
@ -259,57 +279,37 @@ convert_def (const qfo_def_t *def, ddef_t *ddef)
|
||||||
static void
|
static void
|
||||||
convert_qfo (void)
|
convert_qfo (void)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j, num_locals = 0, num_externs = 0;
|
||||||
|
qfo_def_t *defs;
|
||||||
ddef_t *ld;
|
ddef_t *ld;
|
||||||
|
|
||||||
|
defs = malloc (qfo->num_defs * sizeof (qfo_def_t));
|
||||||
|
memcpy (defs, qfo->defs, qfo->num_defs * sizeof (qfo_def_t));
|
||||||
|
|
||||||
pr.progs = &progs;
|
pr.progs = &progs;
|
||||||
progs.version = PROG_VERSION;
|
progs.version = PROG_VERSION;
|
||||||
|
|
||||||
pr.pr_statements = qfo->code;
|
pr.pr_statements = malloc (qfo->code_size * sizeof (dstatement_t));
|
||||||
|
memcpy (pr.pr_statements, qfo->code,
|
||||||
|
qfo->code_size * sizeof (dstatement_t));
|
||||||
progs.numstatements = qfo->code_size;
|
progs.numstatements = qfo->code_size;
|
||||||
|
|
||||||
pr.pr_strings = qfo->strings;
|
pr.pr_strings = qfo->strings;
|
||||||
progs.numstrings = qfo->strings_size;
|
progs.numstrings = qfo->strings_size;
|
||||||
pr.pr_stringsize = qfo->strings_size;
|
pr.pr_stringsize = qfo->strings_size;
|
||||||
|
|
||||||
pr.pr_globals = qfo->data;
|
|
||||||
progs.numglobals = qfo->data_size;
|
|
||||||
|
|
||||||
progs.numglobaldefs = 0;
|
|
||||||
progs.numfielddefs = 0;
|
|
||||||
progs.entityfields = 0;
|
|
||||||
pr.pr_globaldefs = calloc (qfo->num_defs, sizeof (ddef_t));
|
|
||||||
pr.pr_fielddefs = calloc (qfo->num_defs, sizeof (ddef_t));
|
|
||||||
ld = pr.local_defs = calloc (qfo->num_defs, sizeof (ddef_t));
|
|
||||||
for (i = 0; i < qfo->num_defs; i++) {
|
|
||||||
qfo_def_t *def = qfo->defs + i;
|
|
||||||
ddef_t ddef;
|
|
||||||
|
|
||||||
if ((def->flags & QFOD_LOCAL) || !def->name)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
convert_def (def, &ddef);
|
|
||||||
pr.pr_globaldefs[progs.numglobaldefs++] = ddef;
|
|
||||||
if (ddef.type == ev_field) {
|
|
||||||
ddef.type = get_auxtype (qfo->types + def->full_type);
|
|
||||||
progs.entityfields += pr_type_size[ddef.type];
|
|
||||||
ddef.ofs = G_INT (&pr, ddef.ofs);
|
|
||||||
pr.pr_fielddefs[progs.numfielddefs++] = ddef;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pr.pr_edict_size = progs.entityfields * 4;
|
|
||||||
|
|
||||||
progs.numfunctions = qfo->num_funcs;
|
progs.numfunctions = qfo->num_funcs;
|
||||||
pr.pr_functions = calloc (qfo->num_funcs, sizeof (dfunction_t));
|
pr.pr_functions = calloc (qfo->num_funcs, sizeof (dfunction_t));
|
||||||
pr.pr_functions = calloc (qfo->num_funcs, sizeof (dfunction_t));
|
pr.pr_functions = calloc (qfo->num_funcs, sizeof (dfunction_t));
|
||||||
pr.auxfunctions = calloc (qfo->num_funcs, sizeof (pr_auxfunction_t));
|
pr.auxfunctions = calloc (qfo->num_funcs, sizeof (pr_auxfunction_t));
|
||||||
pr.auxfunction_map = calloc (qfo->num_funcs, sizeof (pr_auxfunction_t *));
|
pr.auxfunction_map = calloc (qfo->num_funcs, sizeof (pr_auxfunction_t *));
|
||||||
|
ld = pr.local_defs = calloc (qfo->num_defs, sizeof (ddef_t));
|
||||||
for (i = 0; i < qfo->num_funcs; i++) {
|
for (i = 0; i < qfo->num_funcs; i++) {
|
||||||
qfo_func_t *func = qfo->funcs + i;
|
qfo_func_t *func = qfo->funcs + i;
|
||||||
dfunction_t df;
|
dfunction_t df;
|
||||||
|
|
||||||
df.first_statement = func->builtin ? -func->builtin : func->code;
|
df.first_statement = func->builtin ? -func->builtin : func->code;
|
||||||
df.parm_start = 0;
|
df.parm_start = qfo->data_size;
|
||||||
df.locals = func->locals_size;
|
df.locals = func->locals_size;
|
||||||
df.profile = 0;
|
df.profile = 0;
|
||||||
df.s_name = func->name;
|
df.s_name = func->name;
|
||||||
|
@ -317,6 +317,9 @@ convert_qfo (void)
|
||||||
df.numparms = func->num_parms;
|
df.numparms = func->num_parms;
|
||||||
memcpy (df.parm_size, func->parm_size, sizeof (df.parm_size));
|
memcpy (df.parm_size, func->parm_size, sizeof (df.parm_size));
|
||||||
|
|
||||||
|
if (df.locals > num_locals)
|
||||||
|
num_locals = df.locals;
|
||||||
|
|
||||||
pr.pr_functions[i] = df;
|
pr.pr_functions[i] = df;
|
||||||
|
|
||||||
pr.auxfunction_map[i] = pr.auxfunctions + i;
|
pr.auxfunction_map[i] = pr.auxfunctions + i;
|
||||||
|
@ -326,10 +329,91 @@ convert_qfo (void)
|
||||||
pr.auxfunctions[i].local_defs = ld - pr.local_defs;
|
pr.auxfunctions[i].local_defs = ld - pr.local_defs;
|
||||||
pr.auxfunctions[i].num_locals = func->num_local_defs;
|
pr.auxfunctions[i].num_locals = func->num_local_defs;
|
||||||
|
|
||||||
for (j = 0; j < func->num_local_defs; j++)
|
for (j = 0; j < func->num_local_defs; j++) {
|
||||||
convert_def (qfo->defs + func->local_defs, ld++);
|
qfo_def_t *d = defs + func->local_defs + j;
|
||||||
|
convert_def (d, ld++);
|
||||||
|
d->ofs += qfo->data_size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
progs.numglobaldefs = 0;
|
||||||
|
progs.numfielddefs = 0;
|
||||||
|
progs.entityfields = 0;
|
||||||
|
pr.pr_globaldefs = calloc (qfo->num_defs, sizeof (ddef_t));
|
||||||
|
pr.pr_fielddefs = calloc (qfo->num_defs, sizeof (ddef_t));
|
||||||
|
for (i = 0; i < qfo->num_defs; i++) {
|
||||||
|
qfo_def_t *def = defs + i;
|
||||||
|
ddef_t ddef;
|
||||||
|
|
||||||
|
if (!(def->flags & QFOD_LOCAL) && def->name) {
|
||||||
|
if (def->flags & QFOD_EXTERNAL) {
|
||||||
|
int size = pr_type_size[def->basic_type]; //FIXME struct etc
|
||||||
|
if (!size)
|
||||||
|
size = 1;
|
||||||
|
def->ofs += qfo->data_size + num_locals + num_externs;
|
||||||
|
num_externs += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
convert_def (def, &ddef);
|
||||||
|
pr.pr_globaldefs[progs.numglobaldefs++] = ddef;
|
||||||
|
if (ddef.type == ev_field) {
|
||||||
|
ddef.type = get_auxtype (qfo->types + def->full_type);
|
||||||
|
progs.entityfields += pr_type_size[ddef.type];
|
||||||
|
ddef.ofs = qfo->data[ddef.ofs].integer_var;
|
||||||
|
pr.pr_fielddefs[progs.numfielddefs++] = ddef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (j = 0; j < def->num_relocs; j++) {
|
||||||
|
qfo_reloc_t *reloc = qfo->relocs + def->relocs + j;
|
||||||
|
printf ("%12s %04x %04x %s\n", reloc_names[reloc->type], reloc->ofs, def->ofs, qfo->strings + def->name);
|
||||||
|
switch ((reloc_type)reloc->type) {
|
||||||
|
case rel_none:
|
||||||
|
break;
|
||||||
|
case rel_op_a_def:
|
||||||
|
pr.pr_statements[reloc->ofs].a = def->ofs;
|
||||||
|
break;
|
||||||
|
case rel_op_b_def:
|
||||||
|
pr.pr_statements[reloc->ofs].b = def->ofs;
|
||||||
|
break;
|
||||||
|
case rel_op_c_def:
|
||||||
|
pr.pr_statements[reloc->ofs].c = def->ofs;
|
||||||
|
break;
|
||||||
|
case rel_op_a_def_ofs:
|
||||||
|
pr.pr_statements[reloc->ofs].a += def->ofs;
|
||||||
|
break;
|
||||||
|
case rel_op_b_def_ofs:
|
||||||
|
pr.pr_statements[reloc->ofs].b += def->ofs;
|
||||||
|
break;
|
||||||
|
case rel_op_c_def_ofs:
|
||||||
|
pr.pr_statements[reloc->ofs].c += def->ofs;
|
||||||
|
break;
|
||||||
|
case rel_def_def:
|
||||||
|
pr.pr_globals[reloc->ofs].integer_var = def->ofs;
|
||||||
|
break;
|
||||||
|
case rel_def_def_ofs:
|
||||||
|
pr.pr_globals[reloc->ofs].integer_var += def->ofs;
|
||||||
|
break;
|
||||||
|
// these are relative and fixed up before the .qfo is written
|
||||||
|
case rel_op_a_op:
|
||||||
|
case rel_op_b_op:
|
||||||
|
case rel_op_c_op:
|
||||||
|
// these aren't relevant here
|
||||||
|
case rel_def_func:
|
||||||
|
case rel_def_op:
|
||||||
|
case rel_def_string:
|
||||||
|
case rel_def_field:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
progs.numglobals = qfo->data_size;
|
||||||
|
pr.globals_size = progs.numglobals + num_locals + num_externs;
|
||||||
|
pr.pr_globals = calloc (pr.globals_size, sizeof (pr_type_t));
|
||||||
|
memcpy (pr.pr_globals, qfo->data, qfo->data_size * sizeof (pr_type_t));
|
||||||
|
|
||||||
|
pr.pr_edict_size = progs.entityfields * 4;
|
||||||
|
|
||||||
pr.linenos = qfo->lines;
|
pr.linenos = qfo->lines;
|
||||||
debug.num_auxfunctions = qfo->num_funcs;
|
debug.num_auxfunctions = qfo->num_funcs;
|
||||||
debug.num_linenos = qfo->num_lines;
|
debug.num_linenos = qfo->num_lines;
|
||||||
|
@ -385,35 +469,50 @@ load_progs (const char *name)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void (*progs) (progs_t *pr);
|
||||||
|
void (*qfo) (qfo_t *qfo);
|
||||||
|
} operation_t;
|
||||||
|
|
||||||
|
operation_t operations[] = {
|
||||||
|
{disassemble_progs, 0}, // disassemble
|
||||||
|
{dump_globals, 0}, // globals
|
||||||
|
{dump_strings, 0}, // strings
|
||||||
|
{dump_fields, 0}, // fields
|
||||||
|
{dump_functions, 0}, // functions
|
||||||
|
{dump_lines, 0}, // lines
|
||||||
|
{dump_modules, 0}, // modules
|
||||||
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
void (*func)(progs_t *pr) = dump_globals;
|
operation_t *func = &operations[0];
|
||||||
|
|
||||||
while ((c = getopt_long (argc, argv,
|
while ((c = getopt_long (argc, argv,
|
||||||
"dgsfFlMP:vn", long_options, 0)) != EOF) {
|
"dgsfFlMP:vn", long_options, 0)) != EOF) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'd':
|
case 'd':
|
||||||
func = disassemble_progs;
|
func = &operations[0];
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
func = dump_globals;
|
func = &operations[1];
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
func = dump_strings;
|
func = &operations[2];
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
func = dump_fields;
|
func = &operations[3];
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
func = dump_functions;
|
func = &operations[4];
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
func = dump_lines;
|
func = &operations[5];
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
func = dump_modules;
|
func = &operations[6];
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
source_path = strdup (optarg);
|
source_path = strdup (optarg);
|
||||||
|
@ -432,7 +531,10 @@ main (int argc, char **argv)
|
||||||
while (optind < argc) {
|
while (optind < argc) {
|
||||||
if (!load_progs (argv[optind++]))
|
if (!load_progs (argv[optind++]))
|
||||||
return 1;
|
return 1;
|
||||||
func (&pr);
|
if (qfo && func->qfo)
|
||||||
|
func->qfo (qfo);
|
||||||
|
else
|
||||||
|
func->progs (&pr);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue