From fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Wed, 8 Jul 2015 20:46:52 -0400 Subject: Initial commit --- unix/shlib/edsym-sos4.c | 598 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 598 insertions(+) create mode 100644 unix/shlib/edsym-sos4.c (limited to 'unix/shlib/edsym-sos4.c') diff --git a/unix/shlib/edsym-sos4.c b/unix/shlib/edsym-sos4.c new file mode 100644 index 00000000..e81e83c1 --- /dev/null +++ b/unix/shlib/edsym-sos4.c @@ -0,0 +1,598 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include +#include +#include + +/* + * EDSYM -- Edit the symbol table of a process or object module which uses + * the IRAF shared library. + * + * Usage: edsym file shimage [flags] + * + * -d debug: show symbol table being edited + * -k keep: do not omit "uninteresting" symbols + * -n noact: do not modify any files + * -t delete symbols pointing into transfer vector + * -T delete all shared image symbols, keeping only client symbols + */ + +# ifdef i386 +#include +#include +#include + +#define AOUT +#include +#define N_name _n._n_name +#define N_zeroes _n._n_n._n_zeroes +#define N_offset _n._n_n._n_offset +#define N_abs -1 +#define HDROFF 0xd0 +#define OBJECT 0514 + +# else +#include + +#define HDROFF 0 +#define OBJECT 0407 +#define SYMESZ sizeof(struct nlist) +# endif + +#define DEF_SBUFSIZE 32768 +#define INC_SBUFSIZE 8192 +#define MAXLEN 256 +#define VHDRSIZE 0x1c +#define v_end vec[4] +#define IS_TVECT(a) ((a)>=(vshlib+VHDRSIZE)&&(a)=(b))?(a):(b)) + +static int debug = 0; /* print symbol table */ +static int noact = 0; /* do not modify any files */ +static int omit_tv = 0; /* omit transfer vector symbols */ +static int omit_shsym = 0; /* omit all shlib symbols */ +static int keep_sym = 0; /* do not omit uninteresting symbols */ + +static char *i_sbuf, *o_sbuf; +static char *op, *otop; +static int o_sbufsize; +extern char *malloc(); +extern char *realloc(); + + +/* EDSYM -- Edit the symbol table of a process which uses the IRAF shared + * library. For each symbol found which points to a location in the shared + * library transfer vector, add a V prefix to the symbol name, and add a + * symbol with the old name pointing to the actual function in the shared + * image. This is desirable before runtime debugging of processes linked + * with the shared library. + */ +main (argc, argv) +int argc; +char *argv[]; +{ + unsigned vshlib, vshend, vbase, vsize; + int offset, nbytes; +#ifdef i386 + struct filehdr fh, sh; + struct aouthdr ah; +#else + struct exec fh, sh; +#endif + + unsigned *vec; + char *fname, *shlib, *ip, *oop, *out; + int fd, nsym, nosym, arg; + int errcode = 0; + char tempfile[256]; + char shpath[256]; + struct nlist nl[3]; + FILE *fp, *tp; + int version; + + if (argc < 3) { + fprintf (stderr, "Usage: edsym [-dkntT]\n"); + exit (0); + + } else { + fname = argv[1]; + shlib = argv[2]; + for (arg=3; arg < argc; arg++) { + if (argv[arg][0] != '-') + continue; + for (ip=argv[arg]+1; *ip; ip++) { + switch (*ip) { + case 'd': /* print symbols */ + debug++; + break; + case 'k': /* do not omit uninteresting symbols */ + keep_sym++; + break; + case 'n': /* do not edit object file */ + noact++; + break; + case 't': /* omit transfer vector symbols */ + omit_tv++; + break; + case 'T': /* omit all shlib symbols */ + omit_shsym++; + break; + default: + fprintf (stderr, "edsym: unknown switch -%c\n", *ip); + } + } + } + + } + + /* Open the file to be edited. */ + if ((fp = fopen (fname, "r+")) == NULL) { + fprintf (stderr, "cannot open file %s\n", fname); + exit (1); + } else { + /* Get the file header. */ +#ifdef i386 + if (fread (&fh, sizeof(fh), 1, fp) != 1) { + errcode = 1; goto readerr; + } else if (!ISCOFF(fh.f_magic) && fh.f_magic != OBJECT) { + fprintf (stderr, "not a COFF format file\n"); + exit (2); + } else if (fh.f_symptr == 0 || fh.f_nsyms <= 0) { + fprintf (stderr, "%s has been stripped\n", fname); + exit (3); + } +#else + if (fread (&fh, sizeof(fh), 1, fp) != 1) { + errcode = 1; goto readerr; + } else if (N_BADMAG(fh) && fh.a_magic != OBJECT) { + fprintf (stderr, "not a valid executable or object file\n"); + /* exit (2); */ + } else if (fh.a_syms <= 0) { + fprintf (stderr, "%s has been stripped\n", fname); + exit (3); + } +#endif + } + + /* Get the shared image version number. This is stored in the + * first element of the ushlib vector in the file being edited. + */ +#ifdef i386 + nl[0].n_name = "ushlib_"; + nl[1].n_name = NULL; +#else + nl[0].n_un.n_name = "_ushlib_"; + nl[1].n_un.n_name = NULL; +#endif + if (nlist (fname, nl) != 0) { + fprintf (stderr, "cannot read name list from %s\n", fname); + exit (4); + } + +#ifdef i386 + lseek (fileno(fp), (unsigned)nl[0].n_value - 0x1000, L_SET); +#else + lseek (fileno(fp), (unsigned)nl[0].n_value - PAGSIZ, L_SET); +#endif + if (read (fileno(fp), &version, sizeof(version)) != sizeof(version)) { + fprintf (stderr, + "cannot read shared image version number from %s\n", fname); + exit (9); + } + + /* Use the correct version of the shared image. */ + for (ip=shlib, out=oop=shpath; *oop = *ip++; oop++) + if (*oop == '/') + out = oop + 1; + if (strcmp (out, "S.e") == 0) { + sprintf (out, "S%d.e", version); + shlib = shpath; + } + + if (debug) + printf ("use shared image %s\n", shlib); + + /* Get the location of the shared image transfer vector. */ +#ifdef i386 + nl[0].n_name = "vshlib_"; + nl[1].n_name = "vshend_"; + nl[2].n_name = NULL; +#else + nl[0].n_un.n_name = "_vshlib_"; + nl[1].n_un.n_name = "_vshend_"; + nl[2].n_un.n_name = NULL; +#endif + if (nlist (shlib, nl) != 0) { + fprintf (stderr, "cannot read name list from %s\n", shlib); + exit (4); + } + + /* Open the shared image. */ + if ((fd = open (shlib, O_RDONLY)) == -1) { + fprintf (stderr, "cannot open shared image %s\n", shlib); + exit (5); + + } else { +#ifdef i386 + /* Get the file header. */ + if (read (fd, &sh, sizeof(sh)) != sizeof(sh)) { + errcode = 2; goto readerr; + } else if (!ISCOFF(sh.f_magic)) { + fprintf (stderr, "not a COFF format file\n"); + exit (6); + } + + /* Get the system header. */ + if (read (fd, &ah, sizeof(ah)) != sizeof(ah)) { + errcode = 3; goto readerr; + } else if (ah.magic != 0413) { + fprintf (stderr, "bad magic %o in system header\n", ah.magic); + exit (7); + } +#else + /* Get the file header. */ + if (read (fd, &sh, sizeof(sh)) != sizeof(sh)) { + errcode = 2; goto readerr; + } else if (sh.a_magic != ZMAGIC) { + fprintf (stderr, "not a page-aligned executable file\n"); + exit (6); + } +#endif + /* Read the transfer vector. */ + vshlib = (unsigned) nl[0].n_value; + vshend = (unsigned) nl[1].n_value; + vsize = vshend - vshlib; +#ifdef i386 + vbase = ah.text_start; +#else + vbase = (sh.a_entry & ~0xffffff); +#endif + if (debug) { + printf ("vshlib=%x, vshend=%x, vbase=%x, vsize=%x\n", + vshlib, vshend, vbase, vsize); + } + + vec = (unsigned *) malloc (vsize); + if (vec == NULL) { + fprintf (stderr, "out of memory\n"); + exit (8); + } + + lseek (fd, vshlib - vbase + HDROFF, L_SET); + if (read (fd, vec, vsize) != vsize) { + fprintf (stderr, + "cannot read transfer vector from %s\n", shlib); + exit (9); + } + + close (fd); + } + + /* Now edit the symbol table of the object file. To do this we must + * first read the string buffer into memory. We then open a scratch + * file for symbol output. Successive symbols are read from the input + * file. For each symbol which points into the transfer vector area + * we output two symbols, one a copy of the input symbol with V + * prepended to the symbol name, the second a copy with the symbol + * value changed to point to the location of the actual procedure in + * the shared image. Other symbols are merely copied to the scratch + * file. When all symbols have been processed we overwrite the symbol + * table and string buffer of the file being edited with the contents + * of the scratch buffer (containing the new symbols) and the new + * string buffer, completing the editing operation. + */ + + /* Read the string buffer. */ +#ifdef i386 + if (fh.f_symptr != 0) { + offset = fh.f_symptr + (fh.f_nsyms * SYMESZ); +#else + if ((offset = N_STROFF(fh)) != 0) { +#endif + /* The size of the string buffer in bytes is stored in the first + * four bytes of the buffer. + */ + fseek (fp, offset, L_SET); + if (fread (&nbytes, sizeof(int), 1, fp) != 1) { + errcode = 5; goto readerr; + } + + i_sbuf = malloc (max(nbytes,DEF_SBUFSIZE)); + o_sbuf = malloc (o_sbufsize = max(nbytes,DEF_SBUFSIZE)); + if (i_sbuf == NULL || o_sbuf == NULL) { + fprintf (stderr, "out of memory\n"); + exit (8); + } + + fseek (fp, offset, L_SET); + if (fread (i_sbuf, 1, nbytes, fp) != nbytes) { + fprintf (stderr, "cannot read string buffer from %x\n", fname); + errcode = 5; goto readerr; + } + op = o_sbuf; + otop = o_sbuf + o_sbufsize; + } + + /* Open the scratch file. */ + sprintf (tempfile, "%s.T", fname); + if ((tp = fopen (tempfile, "w+")) == NULL) { + fprintf (stderr, "cannot create %s\n", tempfile); + exit (10); + } + + /* Process the symbol table, writing out two symbols for every + * function symbol pointing into the transfer vector, and copying + * all other symbols unmodified. + */ + fseek (tp, 0L, L_SET); +#ifdef i386 + fseek (fp, fh.f_symptr, L_SET); + for (nsym=fh.f_nsyms, nosym=0; --nsym >= 0; ) { + register int n, ch; + struct syment sym, osym; + char name[MAXLEN]; + int keep, naux; + unsigned v, *epa; + + if (fread (&sym, SYMESZ, 1, fp) != 1) { + errcode = 6; goto readerr; + } + v = (unsigned)sym.n_value; + if (sym.N_zeroes) { + strncpy (name, sym.N_name, 8); + name[8] = '\0'; + } else + strncpy (name, i_sbuf+sym.N_offset, MAXLEN-1); + + if (debug) { + printf ("%20s %8x %3d %6o %3d %2d", name, sym.n_value, + sym.n_scnum, sym.n_type, sym.n_sclass, sym.n_numaux); + } + + if ((sym.n_scnum != N_abs) || !IS_TVECT(v) || (name[0] == 'V')) { +#else + fseek (fp, N_SYMOFF(fh), L_SET); + for (nsym=(fh.a_syms/SYMESZ), nosym=0; --nsym >= 0; ) { + register int n, ch; + struct nlist sym, osym; + char name[MAXLEN]; + int keep, naux; + unsigned v, *epa; + + if (fread (&sym, SYMESZ, 1, fp) != 1) { + errcode = 6; goto readerr; + } + v = (unsigned)sym.n_value; + if (sym.n_un.n_strx) + strncpy (name, i_sbuf+sym.n_un.n_strx, MAXLEN-1); + + if (debug) { + printf ("%20s %3x %8x %6o", + name, sym.n_type, sym.n_value, sym.n_desc); + } + + if (!(sym.n_type & N_ABS) || !IS_TVECT(v) || (name[1] == 'V')) { +#endif + /* Omit "uninteresting" symbols. */ + ch = name[0]; + keep = (keep_sym || ( + !(ch == 'L') && + !(ch == 'v' && name[1] == '.') && + !(ch == 'V' && strncmp(name,"VAR_SEG",7)==0) && + !(ch == 'A' && strncmp(name,"ARR_SEG",7)==0) + /* + && !(n=strlen(name), (name[n-2] == '.' && name[n-1] == 'o')) + */ + )); + + if (keep && !(omit_shsym && v >= vshlib && v <= v_end)) { + editname (&sym, NULL); + fwrite (&sym, SYMESZ, 1, tp); + nosym++; + } else if (debug) + printf (" deleted"); + + if (debug) + printf ("\n"); + + } else { + /* Output the V symbol pointing to the transfer vector. + */ + if (!omit_tv && !omit_shsym) { + osym = sym; + editname (&osym, "V"); + fwrite (&osym, SYMESZ, 1, tp); + nosym++; + } + + /* Disassemble the JMP instruction in the transfer vector to + * get the address of the referenced procedure in the shared + * library. [extracted from os.zlocpr]. + */ + epa = (unsigned *)((char *)vec + (v - vshlib)); +#ifdef i386 + v = ((unsigned)v + *((unsigned *)((char *)epa + 1)) + 5); +#else +#ifdef mc68000 + v = *((unsigned *)((char *)epa + 2)); +#else +#ifdef sparc + v = (((*epa & 0x3fffff) << 10) | (*(epa+1) & 0x3ff)); +#endif +#endif +#endif + + /* Output the same-name symbol, pointing to the function + * pointed to by the transfer vector. + */ + if (!omit_shsym) { + osym = sym; + osym.n_value = v; + editname (&osym, NULL); + fwrite (&osym, SYMESZ, 1, tp); + nosym++; + + if (debug) + printf (" -> %x\n", v); + + } else if (debug) + printf (" deleted\n"); + } +#ifdef i386 + for (naux = sym.n_numaux; --naux >= 0; --nsym) { + if (fread (&sym, SYMESZ, 1, fp) != 1) { + errcode = 7; goto readerr; + } + editname (&sym, NULL); + fwrite (&sym, SYMESZ, 1, tp); + nosym++; + } +#endif + } + + if (!noact) { + /* Copy the new symbol table to the object file, replacing the old + * one. + */ + if (nosym > 0) { +#ifdef i386 + struct syment sym; + fseek (fp, fh.f_symptr, L_SET); +#else + struct nlist sym; + fseek (fp, N_SYMOFF(fh), L_SET); +#endif + fseek (tp, 0L, L_SET); + for (nsym=nosym; --nsym >= 0; ) { + if (fread (&sym, SYMESZ, 1, tp) != 1) { + errcode = 8; goto readerr; + } + fwrite (&sym, SYMESZ, 1, fp); + } + } + + /* Append the string buffer. */ + if (op > o_sbuf) { + *((int *)o_sbuf) = op - o_sbuf; + fwrite (o_sbuf, 1, op - o_sbuf, fp); + fflush (fp); + } + + /* Truncate the file at the point just past the string buffer. + */ + if (ftruncate (fileno(fp), ftell(fp)) != 0) + fprintf (stderr, "Warning: cannot truncate %s\n", fname); + + /* Update the file header. */ +#ifdef i386 + fh.f_nsyms = nosym; +#else + fh.a_syms = nosym * SYMESZ; +#endif + fseek (fp, 0L, L_SET); + fwrite (&fh, sizeof(fh), 1, fp); + fflush (fp); + } + + /* All done. */ + free (vec); + free (i_sbuf); + free (o_sbuf); + fclose (tp); + fclose (fp); + unlink (tempfile); + exit (0); + +readerr: + fprintf (stderr, "read error %d on %s\n", errcode, fname); + exit (11); +} + + +/* EDITNAME -- Replace the name 'name' of a symbol by 'Vname', copying the + * edited name to the output string buffer, and editing the symbol structure + * as necessary to point to the new name. If called with a NULL or null string + * prefix, this serves to copy out the symbol name. + */ +editname (sym, prefix) +#ifdef i386 +register struct syment *sym; +#else +register struct nlist *sym; +#endif +char *prefix; +{ + register char *ip, *np; + char name[MAXLEN]; + int used, n; + +#ifdef i386 + /* Construct the new name. */ + n = 0; + if (prefix) + for (ip=prefix; (name[n] = *ip++); n++) + ; + + if (sym->N_zeroes) { + strncpy (&name[n], sym->N_name, SYMNMLEN); + name[n+SYMNMLEN] = '\0'; + } else + strncpy (&name[n], i_sbuf + sym->N_offset, MAXLEN-n); + + /* If the new name is no longer than SYMNMLEN place it directly in + * the symstruct, else append it to the string buffer. + */ + if ((n = strlen(name)) <= SYMNMLEN) + strncpy (sym->N_name, name, SYMNMLEN); + else { + sym->N_zeroes = 0; + sym->N_offset = putname(name); + } +#else + /* Construct the new name. */ + if (sym->n_un.n_strx) { + /* Copy any leading underscores. */ + for (np = i_sbuf + sym->n_un.n_strx, n=0; *np == '_'; np++) + name[n++] = '_'; + + /* Add the prefix string, if any. */ + if (prefix) + for (ip=prefix; (name[n] = *ip++); n++) + ; + + /* Append the symbol name. */ + strncpy (&name[n], np, MAXLEN-n); + + /* Write the new symbol to the output symbol table. */ + sym->n_un.n_strx = putname(name); + } +#endif +} + + +/* PUTNAME -- Append a string to the output string buffer. + */ +putname (name) +char *name; +{ + register char *ip, *oop; + int used, offset; + + if (op == o_sbuf) + op = o_sbuf + sizeof(int); + + if (op + strlen(name) >= otop) { + used = op - o_sbuf; + o_sbuf = realloc (o_sbuf, o_sbufsize += INC_SBUFSIZE); + op = o_sbuf + used; + otop = o_sbuf + o_sbufsize; + } + + offset = op - o_sbuf; + for (ip=name, oop=op; *oop++ = *ip++; ) + ; + op = oop; + + return (offset); +} -- cgit