/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg * * Permission is granted to anyone to use this software for any purpose * on any computer system, and to redistribute it freely, with the * following restrictions: * 1) No charge may be made other than reasonable charges for reproduction. * 2) Modified versions must be clearly marked as such. * 3) The authors are not responsible for any harmful consequences * of using this software, even if they result from defects in it. * * Alternative ST symbol table lister. */ /* highly munged from above, VERY quick and dirty nm, just enough here to find _stksize for fixstk.c and printstk.c, may be useful for other stuff. WARNING: -g option will not work with gcc-ld produced a.out ++jrb */ /* * Modified to handle expanded, GST linker derived, format for symbols. * This format is produced with -G flag to a proper version of gcc-ld. * -g flag also will work if ld coached properly. * * --mj */ /* * ++jrb rework and cleanup while adding A_TFILE A_TFARC */ #include #include #include #if __STDC__ #include #else extern char *malloc(), *realloc(); #endif #ifdef atarist # define READB "rb" #else # define READB "r" #endif #if !__STDC__ && !defined(hpux) typedef unsigned long size_t; #endif #ifndef WORD_ALIGNED # define SIZEOF_SYM ((size_t)sizeof(struct asym)) #else # define SIZEOF_SYM ((size_t)14) #endif struct xsym { char name[8]; union { unsigned char _flags[2]; unsigned short _sflgs; } u; unsigned long value; char tail[SIZEOF_SYM]; }; #define flags u._flags[0] #define xflags u._flags[1] #define sflgs u._sflgs #ifdef __STDC__ # define P(s) s #else # define P(s) () #endif int main P((int argc , char **argv )); int cmp P((struct xsym *s1 , struct xsym *s2 )); int doname P((char *s , int many )); long dohdr P((FILE *fd )); void dosym P((struct xsym *s )); int not_glob P((unsigned int x )); void sflags P((struct xsym *s )); void ckfread P((void *buf , int siz , int n , FILE *fp )); long readhead P((struct aexec *h , int n , FILE *fd )); int readsyms P((struct xsym *syms , int n , FILE *fd )); void usage P((void )); #undef P int gflag; int main(argc, argv) int argc; char **argv; { int c, status = 0; extern char *optarg; extern int optind; while ((c = getopt(argc, argv, "g")) != -1) switch (c) { case 'g': gflag = 1; break; case '?': usage(); } c = argc - optind; if(c <= 0) usage(); for (; optind < argc; optind++) status |= doname(argv[optind], (c > 1)); return status; } int cmp(s1, s2) struct xsym *s1, *s2; { return(s1->value - s2->value); } int doname(s, many) char *s; int many; { FILE *fd, *fopen(); long i, count; if(!(fd = fopen(s, READB))) { perror(s); return 2; } if (many) printf("\n%s:\n", s); if (i = dohdr(fd)) { struct xsym *syms, *savesyms; struct xsym *currsym; printf("%ld slots mem %ld\n", i, (long)(i*sizeof(struct xsym))); if((savesyms = syms = (struct xsym *)malloc(i*sizeof(struct xsym))) == NULL) { perror("Outa mem"); exit(4); } count = i; currsym = syms; while (count) { if(readsyms(currsym, 1, fd) != 1) { perror("reading syms"); exit(8); } if (--count) { if (A_LNAM == (currsym->xflags & A_LNAM)) { if(fread(currsym->tail, SIZEOF_SYM, 1, fd) != 1) { perror("reading syms"); exit(16); } --i; --count; } } else /* object was partially stripped */ currsym->xflags &= ~A_LNAM; if (gflag && not_glob((unsigned int)(currsym->flags))) --i; else currsym++; } fclose(fd); printf("%ld %s symbol(s)\n", i, (gflag ? "global ": "")); qsort(syms, i, sizeof(struct xsym), cmp); while (i--) { dosym(syms); syms += 1; } free(savesyms); } return 0; } long dohdr(fd) FILE *fd; { struct aexec h; long i; i = readhead(&h, 1, fd); if (i != 1 || h.a_magic != CMAGIC) { fprintf(stderr, "Bad header\n"); return 0L; } fseek(fd, (h.a_text + h.a_data), 1); return h.a_syms / SIZEOF_SYM; } void dosym(s) struct xsym *s; { printf("%-8.8s", s->name); printf("%-14.14s", (A_LNAM == (s->xflags & A_LNAM) ? s->tail : "")); printf("\t%8lx ", s->value); s->xflags &= ~A_LNAM; sflags(s); putchar('\n'); } char *fname[] = { "?0?", " bss", " text", "?3?", " data", "?5?", "?6?", "?7?" }; char *Fname[] = { "?0?", "Bss", "Text", "?3?", "Data", "?5?", "?6?", "?7?" }; int not_glob(x) unsigned int x; { x &= 0xff; if (x & 0x20) return 0; x &= ~0x20; if (x == 0x88) return 0; return 1; } void sflags(s) struct xsym *s; { unsigned int x = s->flags; char **category; int lflag; if(s->sflgs == A_TFILE) printf("text file"); else if (s->sflgs == A_TFARC) printf("text file archive"); else { if (0 != (lflag = not_glob(x))) category = fname; else category = Fname; x &= 0xff; if (x & 0x20) printf("global "); x &= ~0x20; if (x & 0xd8) { if (x & 0x08) printf (" external"); if (x & 0x50) { printf (" equ"); if (x & 0x10) printf (" reg"); } if (x & 0x80) printf (" abs"); if (!lflag) printf(" G"); } else { x &= 7; printf(category[x]); } } printf(" (0x%04x)",(unsigned int)(s->sflgs)); } void ckfread(buf, siz, n, fp) void *buf; int siz, n; FILE *fp; { if(fread(buf, siz, n, fp) != n) { perror("reading"); exit(32); } } long readhead(h, n, fd) struct aexec *h; int n; FILE *fd; { short i; long j; int k; for(k = 0; k < n; k++) { ckfread(&i, 2, 1, fd); h->a_magic = i; ckfread(&j, 4, 1, fd); h->a_text = j; ckfread(&j, 4, 1, fd); h->a_data = j; ckfread(&j, 4, 1, fd); h->a_bss = j; ckfread(&j, 4, 1, fd); h->a_syms = j; ckfread(&j, 4, 1, fd); h->a_AZero1 = j; ckfread(&j, 4, 1, fd); h->a_ldflgs = j; ckfread(&i, 2, 1, fd); h->a_isreloc = i; } return k; } int readsyms(syms, n, fd) struct xsym *syms; int n; FILE *fd; { int k; for(k = 0; k < n; k++, syms++) { ckfread(syms->name, 8, 1, fd); ckfread(&(syms->sflgs), 2, 1, fd); ckfread(&(syms->value), 4, 1, fd); } return k; } void usage() { fprintf(stderr, "cnm [-g] files...\n"); exit(1); } #if !defined(__GNUC__) && defined(hpux) char *xmalloc(n) int n; /* sigh! */ { char *ret = (char *)malloc(n); if(ret) return ret; perror("malloc"); exit(1); } char *xrealloc(b, n) char * b; int n; /* sigh! */ { char *ret = (char *)realloc(b, n); if(ret) return ret; perror("realloc"); exit(2); } #endif