new tool: qfprogs. currently only disassembles progs, but the idea is for it

to become a progs oriented nm, objdump etc
This commit is contained in:
Bill Currie 2002-05-13 19:37:36 +00:00
parent 09366866f7
commit 91779b04f7
15 changed files with 367 additions and 9 deletions

View file

@ -1852,8 +1852,15 @@ AC_SUBST(QFCC_LIBS)
AC_SUBST(QFCC_DEPS) AC_SUBST(QFCC_DEPS)
AC_SUBST(QFCC_INCS) AC_SUBST(QFCC_INCS)
QFPROGS_DEPS='$(top_builddir)/libs/gamecode/engine/libQFgamecode.la $(top_builddir)/libs/util/libQFutil.la'
QFPROGS_LIBS="${QFPROGS_DEPS} ${WINMM}"
QFPROGS_INCS='-I$(top_srcdir)/tools/qfprogs/include'
AC_SUBST(QFPROGS_LIBS)
AC_SUBST(QFPROGS_DEPS)
AC_SUBST(QFPROGS_INCS)
PAK_DEPS='$(top_builddir)/libs/util/libQFutil.la' PAK_DEPS='$(top_builddir)/libs/util/libQFutil.la'
PAK_LIBS="${QFCC_DEPS} ${WINMM}" PAK_LIBS="${PAK_DEPS} ${WINMM}"
PAK_INCS="" PAK_INCS=""
AC_SUBST(PAK_LIBS) AC_SUBST(PAK_LIBS)
AC_SUBST(PAK_DEPS) AC_SUBST(PAK_DEPS)
@ -1926,6 +1933,9 @@ AC_OUTPUT(
tools/qfcc/doc/man/Makefile tools/qfcc/doc/man/Makefile
tools/qfcc/include/Makefile tools/qfcc/include/Makefile
tools/qfcc/source/Makefile tools/qfcc/source/Makefile
tools/qfprogs/Makefile
tools/qfprogs/include/Makefile
tools/qfprogs/source/Makefile
cs-code/Makefile cs-code/Makefile
cs-code/menu.src cs-code/menu.src

View file

@ -256,7 +256,7 @@ typedef enum {
OP_GT_P, OP_GT_P,
} pr_opcode_e; } pr_opcode_e;
typedef struct typedef struct opcode_s
{ {
const char *name; const char *name;
const char *opname; const char *opname;
@ -276,7 +276,7 @@ typedef struct statement_s
unsigned short a,b,c; unsigned short a,b,c;
} dstatement_t; } dstatement_t;
typedef struct typedef struct ddef_s
{ {
unsigned short type; // if DEF_SAVEGLOBGAL bit is set unsigned short type; // if DEF_SAVEGLOBGAL bit is set
// the variable needs to be saved in savegames // the variable needs to be saved in savegames
@ -288,7 +288,7 @@ typedef struct
#define MAX_PARMS 8 #define MAX_PARMS 8
typedef struct typedef struct dfunction_s
{ {
int first_statement; // negative numbers are builtins int first_statement; // negative numbers are builtins
int parm_start; int parm_start;
@ -307,7 +307,7 @@ typedef struct
#define PROG_ID_VERSION 6 #define PROG_ID_VERSION 6
#define PROG_VERSION 0x00fff002 // MMmmmRRR 0.fff.002 (hex) #define PROG_VERSION 0x00fff002 // MMmmmRRR 0.fff.002 (hex)
typedef struct typedef struct dprograms_s
{ {
int version; int version;
int crc; // check of header file int crc; // check of header file

View file

@ -341,7 +341,6 @@ PR_GlobalString (progs_t * pr, int ofs, etype_t type)
char *s; char *s;
int i; int i;
ddef_t *def = 0; ddef_t *def = 0;
void *val;
static char line[128]; static char line[128];
if (type == ev_short) { if (type == ev_short) {
@ -350,7 +349,6 @@ PR_GlobalString (progs_t * pr, int ofs, etype_t type)
} }
if (pr_debug->int_val && pr->debug) if (pr_debug->int_val && pr->debug)
def = PR_Get_Local_Def (pr, ofs); def = PR_Get_Local_Def (pr, ofs);
val = (void *) &pr->pr_globals[ofs];
if (!def) if (!def)
def = ED_GlobalAtOfs (pr, ofs); def = ED_GlobalAtOfs (pr, ofs);
if (!def && type == ev_void) if (!def && type == ev_void)
@ -365,7 +363,10 @@ PR_GlobalString (progs_t * pr, int ofs, etype_t type)
if (type != def->type) if (type != def->type)
oi = "!"; oi = "!";
} }
s = PR_ValueString (pr, type, val); if (ofs > pr->globals_size)
s = "Out of bounds";
else
s = PR_ValueString (pr, type, &pr->pr_globals[ofs]);
snprintf (line, sizeof (line), "%i(%s%s)%s", ofs, oi, name, s); snprintf (line, sizeof (line), "%i(%s%s)%s", ofs, oi, name, s);
} }

View file

@ -324,6 +324,7 @@ check_global (progs_t *pr, dstatement_t *st, opcode_t *op, etype_t type,
} }
return; return;
error: error:
PR_PrintStatement (pr, st);
PR_Error (pr, "PR_Check_Opcodes: %s (statement %ld: %s)\n", msg, PR_Error (pr, "PR_Check_Opcodes: %s (statement %ld: %s)\n", msg,
(long)(st - pr->pr_statements), op->opname); (long)(st - pr->pr_statements), op->opname);
} }

View file

@ -1 +1 @@
SUBDIRS=pak qfcc SUBDIRS=pak qfcc qfprogs

11
tools/qfprogs/.gitignore vendored Normal file
View file

@ -0,0 +1,11 @@
.vimrc
ChangeLog
Makefile
Makefile.in
aclocal.m4
confdefs.h
configure
config.log
config.cache
config.status
qfcc.lsm

24
tools/qfprogs/Makefile.am Normal file
View file

@ -0,0 +1,24 @@
AUTOMAKE_OPTIONS= foreign
SUBDIRS= include source
#EXTRA_DIST=qfcc.lsm.in
dist-zip: distdir
-chmod -R a+r $(distdir)
ZIP="-r9q" zip $(distdir).zip $(NOCONV_DIST)
ZIP="-r9ql" zip $(distdir).zip $(distdir) -x $(NOCONV_DIST)
-rm -rf $(distdir)
dist-bz2: distdir
-chmod -R a+r $(distdir)
BZIP2="-9" $(TAR) Ichof $(distdir).tar.bz2 $(distdir)
-rm -rf $(distdir)
dist-all-local: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
BZIP2="-9" $(TAR) Ichof $(distdir).tar.bz2 $(distdir)
ZIP="-r9q" zip $(distdir).zip $(NOCONV_DIST)
ZIP="-r9ql" zip $(distdir).zip $(distdir) -x $(NOCONV_DIST)
-rm -rf $(distdir)

6
tools/qfprogs/include/.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
.vimrc
config.h.in
Makefile.in
Makefile
config.h
stamp-*

View file

@ -0,0 +1,3 @@
AUTOMAKE_OPTIONS= foreign
EXTRA_DIST=

View file

@ -0,0 +1,8 @@
#ifndef __disassemble_h
#define __disassemble_h
struct progs_s;
void disassemble_progs (struct progs_s *pr);
#endif//__disassemble_h

View file

@ -0,0 +1,8 @@
#ifndef __qfprogs_h
#define __qfprogs_h
struct progs_s;
struct dfunction_s *func_find (int st_num);
#endif//__qfprogs_h

6
tools/qfprogs/source/.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
.deps
.libs
.vimrc
Makefile.in
Makefile
qfprogs

View file

@ -0,0 +1,15 @@
AUTOMAKE_OPTIONS= foreign
QFPROGS_LIBS=@QFPROGS_LIBS@
QFPROGS_DEPS=@QFPROGS_DEPS@
QFPROGS_INCS=@QFPROGS_INCS@
INCLUDES= -I$(top_srcdir)/include $(QFPROGS_INCS)
bin_PROGRAMS= qfprogs
#man_MANS= qfprogs.1
qfprogs_SOURCES= disassemble.c qfprogs.c
qfprogs_LDADD= $(QFPROGS_LIBS)
qfprogs_DEPENDENCIES= $(QFPROGS_DEPS)

View file

@ -0,0 +1,71 @@
/*
#FILENAME#
#DESCRIPTION#
Copyright (C) 2001 #AUTHOR#
Author: #AUTHOR#
Date: #DATE#
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
static const char rcsid[] =
"$Id$";
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <getopt.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_IO_H
# include <io.h>
#endif
#include <sys/types.h>
#include <sys/fcntl.h>
#include "QF/cmd.h"
#include "QF/cvar.h"
#include "QF/progs.h"
#include "QF/sys.h"
#include "QF/vfile.h"
#include "QF/zone.h"
#include "QF/vfile.h"
#include "qfprogs.h"
#include "disassemble.h"
void
disassemble_progs (progs_t *pr)
{
int i;
for (i = 0; i < pr->progs->numstatements; i++) {
dfunction_t *f = func_find (i);
if (f)
Sys_Printf ("%s:\n", PR_GetString (pr, f->s_name));
PR_PrintStatement (pr, &pr->pr_statements[i]);
}
}

View file

@ -0,0 +1,194 @@
/*
#FILENAME#
#DESCRIPTION#
Copyright (C) 2001 #AUTHOR#
Author: #AUTHOR#
Date: #DATE#
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
static const char rcsid[] =
"$Id$";
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <getopt.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_IO_H
# include <io.h>
#endif
#include <sys/types.h>
#include <sys/fcntl.h>
#include "QF/cmd.h"
#include "QF/cvar.h"
#include "QF/hash.h"
#include "QF/pr_comp.h"
#include "QF/progs.h"
#include "QF/sys.h"
#include "QF/vfile.h"
#include "QF/zone.h"
#include "QF/vfile.h"
#include "disassemble.h"
static edict_t *edicts;
static int num_edicts;
static int reserved_edicts = 1;
static progs_t pr;
static void *membase;
static int memsize = 1024*1024;
static hashtab_t *func_tab;
static void *
allocate_progs_mem (progs_t *pr, int size)
{
return malloc (size);
}
static void
free_progs_mem (progs_t *pr, void *mem)
{
free (mem);
}
static unsigned long
func_hash (void *func, void *unused)
{
return ((dfunction_t *) func)->first_statement;
}
static int
func_compare (void *f1, void *f2, void *unused)
{
return ((dfunction_t *) f1)->first_statement
== ((dfunction_t *) f2)->first_statement;
}
dfunction_t *
func_find (int st_ofs)
{
dfunction_t f;
f.first_statement = st_ofs;
return Hash_FindElement (func_tab, &f);
}
static void
init_qf (void)
{
Cvar_Init_Hash ();
Cmd_Init_Hash ();
Cvar_Init ();
Sys_Init_Cvars ();
Cbuf_Init ();
Cmd_Init ();
membase = malloc (memsize);
Memory_Init (membase, memsize);
Cvar_Get ("pr_debug", "1", 0, 0, "");
PR_Init_Cvars ();
PR_Init ();
pr.edicts = &edicts;
pr.num_edicts = &num_edicts;
pr.reserved_edicts = &reserved_edicts;
pr.allocate_progs_mem = allocate_progs_mem;
pr.free_progs_mem = free_progs_mem;
func_tab = Hash_NewTable (1021, 0, 0, 0);
Hash_SetHashCompare (func_tab, func_hash, func_compare);
}
static VFile *
open_file (const char *path, int *len)
{
int fd = open (path, O_RDONLY);
unsigned char id[2];
unsigned char len_bytes[4];
if (fd == -1) {
perror (path);
return 0;
}
read (fd, id, 2);
if (id[0] == 0x1f && id[1] == 0x8b) {
lseek (fd, -4, SEEK_END);
read (fd, len_bytes, 4);
*len = ((len_bytes[3] << 24)
| (len_bytes[2] << 16)
| (len_bytes[1] << 8)
| (len_bytes[0]));
} else {
*len = lseek (fd, 0, SEEK_END);
}
lseek (fd, 0, SEEK_SET);
return Qdopen (fd, "rbz");
}
int
load_progs (const char *name)
{
VFile *file;
int i, size;
file = open_file (name, &size);
if (!file) {
perror (name);
return 0;
}
Hash_FlushTable (func_tab);
pr.progs_name = name;
PR_LoadProgsFile (&pr, file, size, 0, 0);
Qclose (file);
PR_LoadStrings (&pr);
*pr.edicts = PR_InitEdicts (&pr, 1);
for (i = 0; i < pr.progs->numfunctions; i++) {
if (pr.pr_functions[i].first_statement > 0)// don't bother with builtins
Hash_AddElement (func_tab, &pr.pr_functions[i]);
}
//PR_LoadDebug (&pr);
return 1;
}
int
main (int argc, char **argv)
{
init_qf ();
while (*++argv) {
load_progs (*argv);
disassemble_progs (&pr);
}
return 0;
}