hartzell@boulder.colorado.edu (George Hartzell) (12/05/89)
Here is the shar file of the changes to the src files needed to get
ELK running on the MIPS. There are three other postings: a
README.MIPS and two patches[12].shar.
--------------------------------cut here---------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# README.MIPS
# alloca.s.mips
# dumpmips.c
# loadmips.c
# stabmips.c
# stack.s.mips
# This archive created: Mon Dec 4 11:12:33 1989
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README.MIPS'" '(6112 characters)'
if test -f 'README.MIPS'
then
echo shar: will not over-write existing file "'README.MIPS'"
else
sed 's/^ X//' << \SHAR_EOF > 'README.MIPS'
X
XHere are the changes necessary to get ELK to run on MIPS systems.
XThis work was done in the bsd43 environment under RISCos 4.01 on a
XMIPS M-2000. You *must* use the 2.10 compiler release (I used a beta
Xcopy) because previous releases don't support a stack-extending alloca
X(see below). One should be able to build it with gcc, but I haven't
Xtried it yet. This stuff should also be a good starting point for ELK
Xon the DECstation (I think that DEC is just about to release the 2.00
Xcompilers, so you'll have to use gcc or wait a bit longer for the 2.10
Xsuite).
X
XThe following features work:
X - the basic interpreter.
X - dumping preloaded executables.
X - dynamically loading object files (see below).
X - The xlib interface (if you have -G 0 compiled version of the
X X libraries. I made one from the X11R3 source. I haven't
X tested this very thoroughly yet...
X
XI don't know about:
X - the Xt interface. We don't have the HP widget set (yet), so
X I couldn't test it. The Xt stuff seems to have compiled
X correctly (see alloca changes below).
X
XThere are several types of changes that I had to make:
X - wrote the MIPS specific version of stack.s and created an
X empty alloca.s.mips to satisfy the Makefile.
X
X - rewrote the routines that need to work with MIPS' unique
X symbol table format. These changes were substantial enough
X that I just created a new file for the MIPS version, rather
X than try to #ifdef it into the original one. Elk's author
X may or may not stick with this scheme. The new files are
X dumpmips.c, stabmips.c, and loadmips.c. The Makefile in the
X src directory is modified by the SRC_PATCHES to use the mips
X version of these files. The file dumpmips.c explicitly
X calls "ld2.10". If/when the compilers are installed as the
X default, this should be changed to "/bsd43/bin/ld".
X
X - Change stuff to work with the 2.10 builtin alloca(). Any
X file that wants to use the builtin alloca needs to include
X the file <alloca.h>. I put this in the MIPS section of
X config.h, since it is included by scheme.h. I also had to
X work around the crippled nature of the alloca in the 2.10
X compiler suite. While it is a "true" stack extending alloca,
X it is implemented as an operator, and only works with
X "integral_types". For instance, this is legal:
X int size;
X foo = alloca(size);
X but this is not:
X int size;
X foo = alloca(size+1);
X I went through all of the sources and replaced every
X occurrence calls like:
X int size;
X ...
X foo = alloca(size+1);
X with something similar to:
X int size;
X ...
X #ifdef MIPS_ALLOCA
X foo = alloca(size+1);
X #else
X {
X int mips_alloca_size = size + 1;
X foo = alloca(mips_alloca_size);
X }
X #endif
X I dislike declaring variables in local blocks like this, but
X it seemed like the cleanest way to get things to work.
X
X[begin editorial comment]
X The comment in the alloca header file implies that the
X builtin alloca was implemented this way for efficiency...
X It seems to me that forcing me to go through all of the
X source code and make these changes is not the most efficient
X way to make it work. If there is really a neat/fast way to
X do the builtin alloca for "integral_types" (and it seems to
X me that there would be) then why not make the compiler
X smart enough to use it when appropriate, and handle the
X other cases as needed? Maybe the compiler people are
X planning this?
X[end editorial comment]
X
X The compiler becomes very unhappy (one of the ucode stages
X dumps core and dies) if you don't assign the pointer
X returned by the builtin alloca to something. For example,
X there are two places in scheme's main routine that do this:
X (void)alloca(something);
X These were changed to assign the returned value to a scratch
X variable. I don't know if this is a bug or a side effect of
X implementing the builtin alloca as an operator. One of the
X programs for testing stack.s also has this problem.
X
X - Any object file that will be fast loaded (dynamically
X loaded) needs to be compiled and linked with the -G 0 and
X without the -x flag. The interpreter doesn't need this, and
X should run more efficiently without it, so I changed the
X root Makefile to use a different set of compile and load
X flags when working on the src directory and all of the others.
X
X - All of the source file modifications are inside #ifdef's,
X using the following two identifiers:
X "MIPS_ALLOCA" for code that handles MIPS' alloca
X "mips" for two places (src/bignum.c and lib/xlib/font.c)
X where the code tickles some compiler bug. In both
X cases, breaking out the complicated expression
X fixed things.
X
X - The modifications to the root Makefile, the
X lib/xlib/Makefile and the lib/xt/Makefile just comment out
X the original lines. The modifications to the src Makefile
X replace dump.c with dumpmips.c, etc... because I was worried
X about putting a comment line inside the long set of "\"
X continued lines. It should be easy enough to change it
X back. A cleaner way to do this would be to define DUMP_SRC
X (etc...) at the top of the Makefile. I'll leave that to
X ELK's author for the next release.
X
X
XThree shar files (posted separately) contain the changes:
X sources.shar
X README.MIPS (this file)
X alloca.s.mips
X dumpmips.c
X loadmips.c
X stabmips.c
X stack.s.mips
X
X patches1.shar
X LIB_PATCHES
X LIB_UTIL_PATCHES
X LIB_XLIB_PATCHES
X LIB_XT_PATCHES
X
X patches2.shar
X ROOT_PATCHES
X SRC_PATCHES
X
XAll of the files from the sources.shar file should be put in the src
Xdirectory. I recommend making a MIPS directory in the root directory
Xand unpacking the patches there. Then just invoke patch as:
X patch -d .. < ROOT_PATCHES
X patch -d ../src < SRC_PATCHES
X patch -d ../lib < LIB_PATCHES
X patch -d ../lib/util < LIB_UTIL_PATCHES
X patch -d ../lib/xlib < LIB_XLIB_PATCHES
X patch -d ../lib/xt < LIB_XT_PATCHES
X
XGeorge Hartzell (303) 492-4535
X MCD Biology, University of Colorado-Boulder, Boulder, CO 80309
Xhartzell@Boulder.Colorado.EDU ..!{ncar,nbires}!boulder!hartzell
SHAR_EOF
if test 6112 -ne "`wc -c < 'README.MIPS'`"
then
echo shar: error transmitting "'README.MIPS'" '(should have been 6112 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'alloca.s.mips'" '(0 character)'
if test -f 'alloca.s.mips'
then
echo shar: will not over-write existing file "'alloca.s.mips'"
else
sed 's/^ X//' << \SHAR_EOF > 'alloca.s.mips'
SHAR_EOF
if test 0 -ne "`wc -c < 'alloca.s.mips'`"
then
echo shar: error transmitting "'alloca.s.mips'" '(should have been 0 character)'
fi
fi # end of overwriting check
echo shar: extracting "'dumpmips.c'" '(7965 characters)'
if test -f 'dumpmips.c'
then
echo shar: will not over-write existing file "'dumpmips.c'"
else
sed 's/^ X//' << \SHAR_EOF > 'dumpmips.c'
X/* Create a.out from running interpreter
X *
X * For MIPS ecoff format. Some parts cribbed from unexmips.c from
X * GNU emacs.
X * George Hartzell --- Mon Nov 13 09:55:01 1989
X *
X */
X
X#include <signal.h>
X#include "scheme.h"
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/file.h>
X#include <filehdr.h>
X#include <aouthdr.h>
X#include <scnhdr.h>
X#include <sym.h>
X
X#define BADAOUT(x) {close(newfd);close(aout_fd);Primitive_Error(x);}
X
X#define BADWRITE(x) {Saved_Errno = errno;\
X close(newfd);\
X close(aout_fd);\
X Primitive_Error(x);}
X
X#define CHECK_SCNHDR(ptr, name, flags) { \
X if (strcmp(hdr.section[i].s_name, name) == 0) { \
X if (hdr.section[i].s_flags != flags) { \
X Primitive_Error("dump: %x flags where %x were expected in %s section.\n", \
X hdr.section[i].s_flags, flags, name); \
X } \
X ptr = hdr.section + i; \
X i += 1; \
X } \
X else { \
X ptr = NULL; \
X } \
X}
X
X#define READ(_fd, _buffer, _size, _error_message, _error_arg) \
X errno = EEOF; \
X if (read(_fd, _buffer, _size) != _size) \
X Primitive_Error(_error_message, _error_arg);
X
X#define WRITE(_fd, _buffer, _size, _error_message) \
X if (write(_fd, _buffer, _size) != _size) \
X Primitive_Error(_error_message);
X
X#define SEEK(_fd, _position, _error_message, _error_arg) \
X if (lseek(_fd, _position, L_SET) != _position) \
X Primitive_Error(_error_message, _error_arg);
X
X#define BUFSIZE 8192
X
Xstatic struct scnhdr *text_section;
Xstatic struct scnhdr *init_section;
Xstatic struct scnhdr *rdata_section;
Xstatic struct scnhdr *data_section;
Xstatic struct scnhdr *lit8_section;
Xstatic struct scnhdr *lit4_section;
Xstatic struct scnhdr *sdata_section;
Xstatic struct scnhdr *sbss_section;
Xstatic struct scnhdr *bss_section;
X
Xstruct headers {
X struct filehdr fhdr;
X struct aouthdr aout;
X struct scnhdr section[10];
X};
X
XObject Dump_Control_Point;
X
XInit_Dump () {
X Global_GC_Link (Dump_Control_Point);
X}
X
XObject P_Dump (newfile)
X Object newfile;
X{
X
X Object port; /* the port for the new exectable */
X Object ret; /* the object from saveenv */
X char buf[BUFSIZE];
X int i; /* a simple counter */
X int newsyms;
X int symrel;
X int nread; /* number of bytes read */
X int newfd;
X int aout_fd;
X int pagesize; /* page size */
X int scnptr; /* the section being worked on */
X int size; /* size of stack */
X int vaddr;
X struct stat st;
X unsigned data_end;
X unsigned start_of_data;
X static struct headers hdr;
X GC_Node;
X
X /*
X * make sure that stdin and out aren't redirected.
X * flush and close them.
X */
X if (!EQ (Curr_Input_Port, Standard_Input_Port) ||
X !EQ (Curr_Output_Port, Standard_Output_Port))
X Primitive_Error ("cannot dump with current ports redirected");
X Flush_Output (Curr_Output_Port);
X Close_All_Files ();
X
X /*
X * make a point to jmpenv to.
X */
X GC_Link (newfile);
X size = stksize ();
X Dump_Control_Point = Make_Control_Point (size);
X SETFAST(ret,saveenv (CONTROL(Dump_Control_Point)->stack));
X if (TYPE(ret) != T_Special) {
X Enable_Interrupts;
X return ret;
X }
X GC_Unlink;
X
X /*
X * open the new executable file (newfile)
X */
X Disable_Interrupts;
X port = General_Open_File (newfile, 0, Null);
X newfd = dup (fileno (PORT(port)->file));
X P_Close_Port (port);
X if (newfd < 0)
X Primitive_Error ("out of file descriptors");
X
X /*
X * open the executable file (the one that contains our code.
X */
X if ((aout_fd = open (myname, 0)) == -1) {
X Saved_Errno = errno;
X close (newfd);
X Primitive_Error ("cannot open a.out file: ~E");
X }
X
X hdr = *((struct headers *) TEXT_START);
X
X if (hdr.fhdr.f_magic != MIPSELMAGIC && hdr.fhdr.f_magic != MIPSEBMAGIC)
X BADAOUT("dump: input file has bad magic number!\n");
X
X if (hdr.fhdr.f_opthdr != sizeof(hdr.aout))
X BADAOUT("dump: input file's a.out header is the wrong size!\n");
X
X if (hdr.aout.magic != ZMAGIC)
X BADAOUT("dump: input file is not a ZMAGIC file\n");
X
X i = 0;
X CHECK_SCNHDR(text_section, _TEXT, STYP_TEXT);
X CHECK_SCNHDR(init_section, _INIT, STYP_INIT);
X CHECK_SCNHDR(rdata_section, _RDATA, STYP_RDATA);
X CHECK_SCNHDR(data_section, _DATA, STYP_DATA);
X#ifdef _LIT8
X CHECK_SCNHDR(lit8_section, _LIT8, STYP_LIT8);
X CHECK_SCNHDR(lit4_section, _LIT4, STYP_LIT4);
X#endif /* _LIT8 */
X CHECK_SCNHDR(sdata_section, _SDATA, STYP_SDATA);
X CHECK_SCNHDR(sbss_section, _SBSS, STYP_SBSS);
X CHECK_SCNHDR(bss_section, _BSS, STYP_BSS);
X if (i != hdr.fhdr.f_nscns)
X Primitive_Error("dump: %d sections expected, %d found.\n",
X hdr.fhdr.f_nscns, i);
X
X dumped = 1;
X
X pagesize = getpagesize();
X data_end = ((unsigned)sbrk (0) + pagesize - 1) & (-pagesize);
X hdr.aout.dsize = data_end - DATA_START;
X hdr.aout.bsize =0;
X
X { extern __start();
X hdr.aout.entry = (unsigned)__start;
X }
X
X hdr.aout.bss_start = hdr.aout.data_start + hdr.aout.dsize;
X
X data_section->s_vaddr = DATA_START + rdata_section->s_size;
X data_section->s_paddr = DATA_START + rdata_section->s_size;
X
X data_section->s_size = data_end - DATA_START;
X data_section->s_scnptr = rdata_section->s_scnptr + rdata_section->s_size;
X
X vaddr = data_section->s_vaddr + data_section->s_size;
X scnptr = data_section->s_scnptr + data_section->s_size;
X if (lit8_section != NULL)
X {
X lit8_section->s_vaddr = data_section->s_vaddr + data_section->s_size;
X lit8_section->s_paddr = data_section->s_paddr + data_section->s_size;
X lit8_section->s_scnptr = data_section->s_scnptr + data_section->s_size;
X }
X if (sdata_section != NULL)
X {
X sdata_section->s_vaddr = lit8_section->s_vaddr + lit8_section->s_size;
X sdata_section->s_paddr = lit8_section->s_paddr + lit8_section->s_size;
X sdata_section->s_scnptr = lit8_section->s_scnptr + lit8_section->s_size;
X }
X if (sbss_section != NULL)
X {
X sbss_section->s_vaddr = sdata_section->s_vaddr + sdata_section->s_size;
X sbss_section->s_paddr = sdata_section->s_paddr + sdata_section->s_size;
X sbss_section->s_scnptr = sdata_section->s_scnptr + sdata_section->s_size;
X }
X if (bss_section != NULL)
X {
X bss_section->s_vaddr = sbss_section->s_vaddr + sbss_section->s_size;
X bss_section->s_paddr = sbss_section->s_paddr + sbss_section->s_size;
X bss_section->s_scnptr = sbss_section->s_scnptr + sbss_section->s_size;
X }
X
X WRITE(newfd, TEXT_START, hdr.aout.tsize,
X "dump: problem writing text section to output file");
X
X WRITE(newfd, DATA_START, hdr.aout.dsize,
X "dump: problem writing text section to output file");
X
X /*
X * set up and copy the symbol table to the new executable.
X *
X */
X SEEK(aout_fd, hdr.fhdr.f_symptr,
X "seeking to start of symbols in %s", myname);
X
X nread = read(aout_fd, buf, BUFSIZE);
X if (nread < sizeof(HDRR))
X Primitive_Error("dump: problem reading symbols from %s", myname);
X
X#define symhdr ((pHDRR)buf)
X newsyms = hdr.aout.tsize + hdr.aout.dsize;
X symrel = newsyms - hdr.fhdr.f_symptr;
X hdr.fhdr.f_symptr = newsyms;
X symhdr->cbLineOffset += symrel;
X symhdr->cbDnOffset += symrel;
X symhdr->cbPdOffset += symrel;
X symhdr->cbSymOffset += symrel;
X symhdr->cbOptOffset += symrel;
X symhdr->cbAuxOffset += symrel;
X symhdr->cbSsOffset += symrel;
X symhdr->cbSsExtOffset += symrel;
X symhdr->cbFdOffset += symrel;
X symhdr->cbRfdOffset += symrel;
X symhdr->cbExtOffset += symrel;
X#undef symhdr
X
X do
X {
X if (write(newfd, buf, nread) != nread)
X Primitive_Error("dump: writing symbols to output file");
X nread = read(aout_fd, buf, BUFSIZE);
X if (nread < 0)
X Primitive_Error("dump: reading symbols from %s", myname);
X } while (nread != 0);
X
X SEEK(newfd, 0, "dump: problem seeking to start of header in %s", myname);
X
X WRITE(newfd, &hdr, sizeof(hdr),
X "dump: problem writing header of output file");
X
X close (aout_fd);
X
X if (fstat (newfd, &st) != -1) {
X int omask = umask (0);
X (void)umask (omask);
X (void)fchmod (newfd, st.st_mode & 0777 | 0111 & ~omask);
X }
X
X close (newfd);
X Enable_Interrupts;
X
X return False;
X}
SHAR_EOF
if test 7965 -ne "`wc -c < 'dumpmips.c'`"
then
echo shar: error transmitting "'dumpmips.c'" '(should have been 7965 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'loadmips.c'" '(4506 characters)'
if test -f 'loadmips.c'
then
echo shar: will not over-write existing file "'loadmips.c'"
else
sed 's/^ X//' << \SHAR_EOF > 'loadmips.c'
X/* Loading of source and object files
X * Modified for MIPS ecoff format.
X * George Hartzell --- Mon Dec 4 10:58:59 1989
X */
X
X#include <signal.h>
X#include "scheme.h"
X
X#include <filehdr.h>
X#include <aouthdr.h>
X#include <scnhdr.h>
X#include <syms.h>
X
Xstatic Object V_Load_Path, V_Load_Noisilyp, V_Load_Libraries;
X
X#ifdef gcc
X# define Default_Load_Libraries "/usr/new/ghs/lib/libc.a"
X#else
X# define Default_Load_Libraries "-lc_G0"
X#endif
X
Xchar Loader_Input[20];
Xstatic char Loader_Output[20];
X
XInit_Load () {
X Define_Variable (&V_Load_Path, "load-path",
X Cons (Make_String (".", 1),
X Cons (Make_String (DEF_LOAD_DIR, sizeof (DEF_LOAD_DIR) - 1), Null)));
X Define_Variable (&V_Load_Noisilyp, "load-noisily?", False);
X Define_Variable (&V_Load_Libraries, "load-libraries",
X Make_String (Default_Load_Libraries, sizeof Default_Load_Libraries-1));
X}
X
XObject General_Load (name, env) Object name, env; {
X register char *p;
X register struct S_String *str;
X Object oldenv, port;
X GC_Node2;
X
X Check_Type (env, T_Environment);
X oldenv = The_Environment;
X GC_Link2 (env, oldenv);
X port = General_Open_File (name, P_INPUT, Val (V_Load_Path));
X str = STRING(PORT(port)->name);
X Switch_Environment (env);
X p = str->data + str->size;
X if (str->size >= 2 && *--p == 'o' && *--p == '.') {
X Load_Object (port, str);
X } else
X Load_Source (port);
X Switch_Environment (oldenv);
X GC_Unlink;
X return Void;
X}
X
XObject P_Load (argc, argv) register argc; register Object *argv; {
X return General_Load (argv[0], argc == 1 ? The_Environment : argv[1]);
X}
X
XLoad_Source (port) Object port; {
X Object val;
X GC_Node;
X
X GC_Link (port);
X while (1) {
X val = General_Read (port);
X if (TYPE(val) == T_End_Of_File)
X break;
X val = Eval (val);
X if (Truep (Val (V_Load_Noisilyp))) {
X Print (val);
X P_Newline (0);
X }
X }
X P_Close_Port (port);
X GC_Unlink;
X}
X
Xstruct headers {
X struct filehdr fhdr;
X struct aouthdr aout;
X struct scnhdr section[3];
X};
X
XLoad_Object (port, fn) Object port; register struct S_String *fn; {
X struct headers hdr;
X register char *brk, *obrk, *buf, *lp, *li;
X register n, f;
X Object libs;
X FILE *fp;
X int mipshit;
X
X n = fread ((char *)&hdr, sizeof (hdr), 1, PORT(port)->file);
X P_Close_Port (port);
X if (n == 0 || hdr.fhdr.f_magic != XLMAGIC)
X Primitive_Error ("not a valid object file");
X
X strcpy (Loader_Output, "/tmp/ldXXXXXX");
X mktemp (Loader_Output);
X mipshit = fn->size + strlen (myname) + 500;
X buf = alloca (mipshit);
X obrk = brk = sbrk (0);
X brk = (char *)((int)brk + 7 & ~7);
X libs = Val (V_Load_Libraries);
X if (TYPE(libs) == T_String) {
X if ((n = STRING(libs)->size) > 400)
X Primitive_Error ("too many load libraries");
X lp = STRING(libs)->data;
X } else {
X lp = "-lc"; n = 3;
X }
X li = Loader_Input;
X if (li[0] == 0)
X li = myname;
X#ifdef XFLAG_BROKEN
X sprintf (buf, "ld2.10 -systype bsd43 -N -A %s -T %x %.*s -o %s %.*s",
X#else
X sprintf (buf, "/bin/ld -x -N -A %s -T %x %.*s -o %s %.*s",
X#endif
X li, brk, fn->size, fn->data, Loader_Output, n, lp);
X if (system (buf) != 0) {
X (void)unlink (Loader_Output);
X Primitive_Error ("system linker failed");
X }
X Disable_Interrupts; /* To ensure that f gets closed */
X if ((f = open (Loader_Output, 0)) == -1) {
X (void)unlink (Loader_Output);
X Primitive_Error ("cannot open tempfile");
X }
X if (Loader_Input[0])
X (void)unlink(Loader_Input);
X strcpy (Loader_Input, Loader_Output);
X if (read (f, (char *)&hdr, sizeof (hdr)) != sizeof (hdr)) {
Xerr:
X close (f);
X Primitive_Error ("corrupt tempfile (/bin/ld is broken)");
X }
X n = hdr.aout.tsize + hdr.aout.dsize + hdr.aout.bsize;
X n += brk - obrk;
X if (sbrk (n) == (char *)-1) {
X close (f);
X Primitive_Error ("not enough memory to load object file");
X }
X bzero (obrk, n);
X n -= hdr.aout.bsize;
X
X if (lseek(f, hdr.section[0].s_scnptr, 0) == -1) {
X close (f);
X Primitive_Error ("failed to lseek.\n");
X }
X
X if (read (f, brk, n) != n) {
X close (f);
X Primitive_Error ("failed to read text and data segs.\n");
X }
X
X if ((fp = fdopen (f, "r")) == NULL) {
X close (f);
X Primitive_Error ("cannot fdopen object file");
X }
X
X if (The_Symbols)
X Free_Symbols (The_Symbols);
X The_Symbols = Snarf_Symbols (fp, &hdr);
X
X fclose (fp);
X Call_Initializers (The_Symbols, brk);
X Enable_Interrupts;
X}
X
XFinit_Load () {
X if (Loader_Input[0])
X (void)unlink (Loader_Input);
X}
SHAR_EOF
if test 4506 -ne "`wc -c < 'loadmips.c'`"
then
echo shar: error transmitting "'loadmips.c'" '(should have been 4506 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'stabmips.c'" '(4492 characters)'
if test -f 'stabmips.c'
then
echo shar: will not over-write existing file "'stabmips.c'"
else
sed 's/^ X//' << \SHAR_EOF > 'stabmips.c'
X/* Read and manage symbol tables from object modules
X * Modified for MIPS ecoff format.
X * George Hartzell --- Mon Dec 4 10:59:23 1989
X */
X
X#include "scheme.h"
X
X#include <filehdr.h>
X#include <aouthdr.h>
X#include <sys/file.h>
X#include <syms.h>
X
X#define READ(_fd, _buffer, _size, _error_message) \
X if (read(_fd, _buffer, _size) != _size) \
X Primitive_Error(_error_message);
X
X#define WRITE(_fd, _buffer, _size, _error_message) \
X if (write(_fd, _buffer, _size) != _size) \
X Primitive_Error(_error_message);
X
X#define SEEK(_fd, _position, _error_message) \
X if (lseek(_fd, _position, L_SET) != _position) \
X Primitive_Error(_error_message);
X
Xchar *Safe_Malloc (size) {
X char *ret;
X
X if ((ret = malloc (size)) == 0)
X Primitive_Error ("not enough memory to allocate ~s bytes",
X Make_Fixnum (size));
X return ret;
X}
X
XSYMTAB *Snarf_Symbols (fp)
X FILE *fp;
X{
X int fd; /* a file descriptor */
X long fdi; /* a counter for the file desc table */
X pFDR file_desc; /* pointer to the filedesc table */
X struct filehdr file_hdr; /* pointer to the file header */
X long sbase;
X char *strbase;
X char *strings;
X HDRR sym_hdr; /* pointer to symbolic header */
X long symi; /* a counter for the local symbol table */
X pSYMR symbol; /* pointer to symbol table */
X
X
X SYMTAB *tab;
X char *p;
X SYM *sp, **nextp;
X
X fd = fileno(fp);
X
X /* rewind the object file, since who knows what it's status is... */
X SEEK(fd, 0, "Unable to rewind object file.\n");
X
X /* read in the file header */
X READ(fd, &file_hdr, sizeof(file_hdr), "Unable to read file header.\n");
X
X /* seek to the start of the symbolic header */
X SEEK(fd, file_hdr.f_symptr, "Unable to seek to symbolic header.\n");
X
X /* read in the symbolic header */
X READ(fd, &sym_hdr, sizeof(sym_hdr), "Unable to read symbolic header\n");
X
X tab = (SYMTAB *)Safe_Malloc (sizeof (SYMTAB));
X tab->first = 0;
X tab->strings = 0;
X nextp = &tab->first;
X
X SEEK(fd, sym_hdr.cbSymOffset, "Unable to seek to symbol table.\n");
X if ((symbol = (pSYMR)malloc(sym_hdr.isymMax * sizeof (SYMR))) == (pSYMR)NULL)
X Primitive_Error("Unable to allocate memory for symbol table.\n");
X READ(fd, symbol, (sym_hdr.isymMax * sizeof(SYMR)),
X "Unable to read symbol tables.\n");
X
X SEEK(fd, sym_hdr.cbSsOffset, "Unable to seek to string space.\n");
X if ((strings = malloc(sym_hdr.issMax)) == NULL)
X Primitive_Error("Unable to allocate memory for string space.\n");
X READ(fd, strings, sym_hdr.issMax, "Unable to read symbol tables.\n");
X
X SEEK(fd, sym_hdr.cbFdOffset, "Unable to seek to file descriptors.\n");
X if((file_desc = (pFDR)malloc(sym_hdr.ifdMax * sizeof(FDR))) == (pFDR)NULL)
X Primitive_Error("Unable to allocate memory for fd's.\n");
X READ(fd, file_desc, (sym_hdr.ifdMax * sizeof(FDR)),
X "Unable to read file descriptor tables.\n");
X
X
X /* foreach file in
X * the file descriptor table
X * do:
X */
X for(fdi = 0; fdi < sym_hdr.ifdMax; fdi++) {
X strbase = strings + file_desc[fdi].issBase;
X for(symi=file_desc[fdi].isymBase;
X symi < file_desc[fdi].csym + file_desc[fdi].isymBase;
X symi++) {
X if (symbol[symi].st == stProc && symbol[symi].sc == scText) {
X p = symbol[symi].iss + strbase;
X
X /* allocate another node in the symbol table list */
X sp = (SYM *)Safe_Malloc (sizeof (SYM));
X sp->name = Safe_Malloc (strlen (p) + 1);
X
X /* set the new nodes values */
X strcpy (sp->name, p);
X sp->type = symbol[symi].st;
X sp->value = symbol[symi].value;
X
X /* link the node into the linked list */
X *nextp = sp;
X nextp = &sp->next;
X *nextp = 0;
X } /* end of if(symbol... */
X } /* end of for(symi=0... */
X } /* end of for(fdi=0... */
X return tab;
X} /* end of Snarf_Symbols() */
X
X
XSYMTAB *Open_File_And_Snarf_Symbols (name)
X char *name;
X{
X FILE *fp;
X SYMTAB *tab;
X
X if ((fp = fopen (name, "r")) == (FILE *)NULL)
X Primitive_Error ("cannot open a.out file:");
X
X tab = Snarf_Symbols (fp);
X
X close (fp);
X return tab;
X}
X
XFree_Symbols (tab) SYMTAB *tab; {
X register SYM *sp;
X
X for (sp = tab->first; sp; sp = sp->next) {
X free (sp->name);
X free ((char *)sp);
X }
X if (tab->strings)
X free (tab->strings);
X}
X
XCall_Initializers (tab, addr)
X SYMTAB *tab;
X char *addr;
X{
X register SYM *sp;
X
X /* procedure names don't have leading underscores... */
X for (sp = tab->first; sp; sp = sp->next) {
X if (((bcmp (sp->name, "init_", 5) == 0) ||
X (bcmp (sp->name, "_STI", 4) == 0))
X && (char *)sp->value >= addr)
X ((int (*)())sp->value)();
X }
X}
X
SHAR_EOF
if test 4492 -ne "`wc -c < 'stabmips.c'`"
then
echo shar: error transmitting "'stabmips.c'" '(should have been 4492 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'stack.s.mips'" '(2714 characters)'
if test -f 'stack.s.mips'
then
echo shar: will not over-write existing file "'stack.s.mips'"
else
sed 's/^ X//' << \SHAR_EOF > 'stack.s.mips'
X #
X # stack manipulation routines for elk on the MIPS chip.
X # George Hartzell --- Sat Dec 2 15:02:43 1989
X #
X # declare externals
X .extern stkbase 4
X # declare Special
X .extern Special 4
X
X ################################################################
X # int stksize();
X ################################################################
X .text
X .align 2
X .globl stksize
X .ent stksize
Xstksize:
X # set up the frame pointer
X .frame $sp, 0, $31
X # put the value of stkbase into register 8
X lw $8, stkbase
X # register 8 = stackbase - stackpointer
X subu $8, $8, $sp
X # give ourselves a safety margin (Don't seem to need this!!! gh.)
X # addu $8, $8, 100
X # move the size to register 2, where MIPS C expects the return value
X move $2, $8
X # return. return address is in $31
X j $31
X .end stksize
X
X ################################################################
X # int saveenv(char *buf)
X ################################################################
X .text
X .align 2
X .globl saveenv
X .ent saveenv
Xsaveenv:
X # set up the frame pointer
X .frame $sp, 0, $31
X # buf is in register 4.
X
X # copy the registers that seem to need to be saved :)
X sw $28, 4($4)
X sw $sp, 8($4)
X sw $31, 12($4)
X sw $fp, 16($4)
X
X # $9 points into buffer
X # $10 contains the stack base
X # $11 points into the stack.
X addu $9, $4, 20
X lw $10, stkbase
X move $11, $sp
Xrep1:
X # get a value from the stack and stuff it into the buffer
X # increment the pointers into the stack and the buffer
X # stop when you've copied the word at stkbase
X # e.g. when $11 has gone beyond stkbase
X lw $12, 0($11)
X sw $12, 0($9)
X addu $11, $11, 4
X addu $9, $9, 4
X bltu $11, $10, rep1
X
X # calculate the "relocation offset"
X subu $15, $9, $10
X sw $15, 0($4)
X # set up to return value of Special
X lw $2, Special
X # return. return address is in register 31.
X j $31
X .end saveenv
X
X
X ################################################################
X # dead jmpenv(const char *buf, int retcode);
X ################################################################
X .text
X .align 2
X .globl jmpenv
X .ent jmpenv 2
Xjmpenv:
X .frame $sp, 0, $31
X # copy the registers that seem to need to be saved :)
X lw $28, 4($4)
X lw $sp, 8($4)
X lw $31, 12($4)
X lw $fp, 16($4)
X
X # $9 points into buffer
X # $10 contains the stack base
X # $11 points into the stack.
X addu $9, $4, 20
X lw $10, stkbase
X move $11, $sp
Xrep2:
X # get a value from the buffer and stuff it into the stack
X # increment the pointers into the stack and the buffer
X # stop when you've copied the word at stkbase
X # e.g. when $11 has gone beyond stkbase
X lw $12, 0($9)
X sw $12, 0($11)
X addu $11, $11, 4
X addu $9, $9, 4
X bltu $11, $10, rep2
X
X # set up the return code
X move $2, $5
X # and return
X j $31
X .end jmpenv
X
X
X
SHAR_EOF
if test 2714 -ne "`wc -c < 'stack.s.mips'`"
then
echo shar: error transmitting "'stack.s.mips'" '(should have been 2714 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
George Hartzell (303) 492-4535
MCD Biology, University of Colorado-Boulder, Boulder, CO 80309
hartzell@Boulder.Colorado.EDU ..!{ncar,nbires}!boulder!hartzell