diff --git a/tools/qfcc/include/qfprogs.h b/tools/qfcc/include/qfprogs.h index b5803ce61..a77bb68a1 100644 --- a/tools/qfcc/include/qfprogs.h +++ b/tools/qfcc/include/qfprogs.h @@ -7,10 +7,11 @@ struct qfo_s; extern int sorted; extern int verbosity; +extern const char *reloc_names[]; + void disassemble_progs (struct progs_s *pr); void dump_globals (struct progs_s *pr); -void qfo_globals (struct qfo_s *qfo); void dump_fields (struct progs_s *pr); void dump_functions (struct progs_s *pr); @@ -22,4 +23,7 @@ struct dfunction_s *func_find (int st_num); void dump_strings (struct progs_s *pr); +void qfo_globals (struct qfo_s *qfo); +void qfo_relocs (struct qfo_s *qfo); + #endif//__qfprogs_h diff --git a/tools/qfcc/source/globals.c b/tools/qfcc/source/globals.c index 015671a5a..cddfabcc3 100644 --- a/tools/qfcc/source/globals.c +++ b/tools/qfcc/source/globals.c @@ -48,6 +48,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "obj_file.h" #include "qfprogs.h" +#include "reloc.h" static int cmp (const void *_a, const void *_b) @@ -101,6 +102,8 @@ dump_globals (progs_t *pr) comment = va (" %d = illegal function", func); } } + if (def->type == ev_field) + comment = va (" %d", G_INT (pr, offset)); printf ("%d %d %s %s%s\n", offset, saveglobal, name, type, comment); } @@ -193,3 +196,92 @@ qfo_globals (qfo_t *qfo) puts (""); } } + +void +qfo_relocs (qfo_t *qfo) +{ + qfo_reloc_t *reloc; + qfo_def_t *def; + qfo_func_t *func; + int i; + + for (i = 0; i < qfo->num_relocs; i++) { + reloc = qfo->relocs + i; + if ((unsigned) reloc->type > rel_def_field_ofs) { + printf ("%d unknown reloc: %d\n", i, reloc->type); + continue; + } + printf ("%s", reloc_names[reloc->type]); + def = 0; + func = 0; + switch ((reloc_type) reloc->type) { + case rel_none: + break; + case rel_op_a_def: + case rel_op_b_def: + case rel_op_c_def: + def = qfo->defs + reloc->def; + printf (" op.%c %d %d %s", reloc->type - rel_op_a_def + 'a', + reloc->ofs, def->ofs, qfo->strings + def->name); + break; + case rel_op_a_op: + case rel_op_b_op: + case rel_op_c_op: + printf (" op.%c op@%d", reloc->type - rel_op_a_def + 'a', + reloc->ofs); + break; + case rel_def_op: + printf (" def@%d op@%d", reloc->ofs, reloc->def); + break; + case rel_def_def: + def = qfo->defs + reloc->def; + printf (" def@%d def@%d %s", reloc->ofs, reloc->def, + qfo->strings + def->name); + break; + case rel_def_func: + func = qfo->funcs + reloc->def; + printf (" def@%d func@%d %s", reloc->ofs, reloc->def, + qfo->strings + func->name); + break; + case rel_def_string: + printf (" def@%d string:`%s'", reloc->ofs, + qfo->strings + qfo->data[reloc->ofs].string_var); + break; + case rel_def_field: + def = qfo->defs + reloc->def; + printf (" def@%d def@%d %s", reloc->ofs, reloc->def, + qfo->strings + def->name); + break; + case rel_op_a_def_ofs: + case rel_op_b_def_ofs: + case rel_op_c_def_ofs: + def = qfo->defs + reloc->def; + printf (" op.%c %d %d %s", reloc->type - rel_op_a_def + 'a', + reloc->ofs, def->ofs, qfo->strings + def->name); + break; + case rel_def_def_ofs: + def = qfo->defs + reloc->def; + printf (" def@%d def@%d+%d %s+%d", reloc->ofs, reloc->def, + qfo->data[reloc->ofs].integer_var, + qfo->strings + def->name, + qfo->data[reloc->ofs].integer_var); + break; + case rel_def_field_ofs: + def = qfo->defs + reloc->def; + printf (" def@%d def@%d+%d %s+%d", reloc->ofs, reloc->def, + qfo->data[reloc->ofs].integer_var, + qfo->strings + def->name, + qfo->data[reloc->ofs].integer_var); + break; + } + if (def && def->flags & QFOD_EXTERNAL) + printf (" external"); + if (func && qfo->defs[func->def].flags & QFOD_EXTERNAL) + printf (" external"); + if (def && (i < def->relocs || i >= def->relocs + def->num_relocs)) + printf (" BOGUS reloc!"); + if (func && (i < func->relocs || i >= func->relocs + func->num_relocs)) + printf (" BOGUS reloc!"); + puts (""); + } +} diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 62f667864..9833acd41 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -99,6 +99,7 @@ static const struct option long_options[] = { {"functions", no_argument, 0, 'F'}, {"lines", no_argument, 0, 'l'}, {"modules", no_argument, 0, 'M'}, + {"relocs", no_argument, 0, 'r'}, {"path", required_argument, 0, 'P'}, {"verbose", no_argument, 0, 'v'}, {"numeric", no_argument, 0, 'n'}, @@ -476,13 +477,14 @@ typedef struct { } operation_t; operation_t operations[] = { - {disassemble_progs, 0}, // disassemble + {disassemble_progs, 0}, // disassemble {dump_globals, qfo_globals}, // globals - {dump_strings, 0}, // strings - {dump_fields, 0}, // fields - {dump_functions, 0}, // functions - {dump_lines, 0}, // lines - {dump_modules, 0}, // modules + {dump_strings, 0}, // strings + {dump_fields, 0}, // fields + {dump_functions, 0}, // functions + {dump_lines, 0}, // lines + {dump_modules, 0}, // modules + {0, qfo_relocs}, // relocs }; int @@ -492,7 +494,7 @@ main (int argc, char **argv) operation_t *func = &operations[0]; while ((c = getopt_long (argc, argv, - "dgsfFlMP:vn", long_options, 0)) != EOF) { + "rdgsfFlMP:vn", long_options, 0)) != EOF) { switch (c) { case 'd': func = &operations[0]; @@ -515,6 +517,9 @@ main (int argc, char **argv) case 'M': func = &operations[6]; break; + case 'r': + func = &operations[7]; + break; case 'P': source_path = strdup (optarg); break; @@ -534,8 +539,10 @@ main (int argc, char **argv) return 1; if (qfo && func->qfo) func->qfo (qfo); - else + else if (func->progs) func->progs (&pr); + else + fprintf (stderr, "can't process %s\n", argv[optind - 1]); } return 0; }