|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 7151 (0x1bef) Types: TextFile Notes: UNIX file Names: »nm.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─ ⟦this⟧ »cmd/nm.c«
/* * Print the name list of an object * file. */ #include <stdio.h> #include "n.out.h" #include <ar.h> #include <ctype.h> #include <canon.h> int aflag; int dflag; int gflag; int nflag; int oflag; int pflag; int rflag; int uflag; struct ldheader ldh; struct ldsym lds; char *fn; FILE *fp; int title; int amemb; struct ar_hdr ahb; int stuff; char usage[] = "Usage: nm [-adgnopru] [file ...]\n"; char *gn[] = { "SI", "PI", "BI", "SD", "PD", "BD", " D", " ", " ", " A", " C", "??" }; char *ln[] = { "si", "pi", "bi", "sd", "pd", "bd", " d", " ", " ", " a", " c", " ?" }; struct fmtab { char *f_fmt1; char *f_fmt2; }; char octb[] = " "; char octf[] = "%06O "; char hexb[] = " "; char hexf[] = "%04X "; char lngb[] = " "; char lngf[] = "%08X "; char segb[] = " "; char segf[] = "%06X "; struct fmtab fmtab[] = { octb, octf, /* Unused or unknown */ octb, octf, /* 11 */ lngb, lngf, /* VAX */ segb, segf, /* 360 */ lngb, lngf, /* Z-8001 */ hexb, hexf, /* Z-8002 */ hexb, hexf, /* 8086 */ hexb, hexf, /* 8080 and 8085 */ hexb, hexf, /* 6800 */ hexb, hexf, /* 6809 */ lngb, lngf /* 68000 */ }; #define MTYPES (sizeof(fmtab)/sizeof(struct fmtab)) main(argc, argv) char *argv[]; { register char *cp; register c, i; int nf; nf = argc-1; for (i=1; i<argc; ++i) { cp = argv[i]; if (cp[0] == '-') { argv[i] = NULL; --nf; while ((c = *++cp) != '\0') { switch (c) { case 'a': ++aflag; break; case 'd': ++dflag; break; case 'g': ++gflag; break; case 'n': ++nflag; break; case 'o': ++oflag; ++title; break; case 'p': ++pflag; break; case 'r': ++rflag; break; case 'u': ++uflag; break; default: fprintf(stderr, usage); exit(1); } } } } if (nf == 0) { fn = "l.out"; nm(); } else { if (nf > 1) title = 1; for (i=1; i<argc; ++i) if ((fn = argv[i]) != NULL) nm(); } exit(0); } /* * Level I. * Open and close files. * If an archive arrange that level * II is called on each member. * The file name is in `fn'. */ nm() { register long offs; int magic; amemb = 0; if ((fp = fopen(fn, "r")) == NULL) { nmerr("cannot open"); return; } magic = getw(fp); canshort(magic); if (magic == ARMAG) { title = amemb = 1; while (fread(&ahb, sizeof(ahb), 1, fp) == 1) { offs = ftell(fp); if (strncmp(ahb.ar_name, "__.SYMDEF", DIRSIZ) != 0) nm1(); cansize(ahb.ar_size); fseek(fp, offs+ahb.ar_size, 0); } } else { fseek(fp, (long)0, 0); nm1(); } fclose(fp); } /* * Level II. * You are seeked to the start of * an `l.out' file. * Read in symbols, sort if required * and print them out. */ nm1() { register struct ldsym *wstp; register i, t; register struct ldsym *stp, *estp; register long offs; register char *fmt1, *fmt2; int qscmp(); if (nmhdr(&ldh) != 0) return; if (ldh.l_ssize[L_SYM] == 0) { nmerr("no symbol table"); return; } i = ldh.l_ssize[L_SYM]; if ((ldh.l_flag & LF_32) == 0) i = i/(sizeof(lds)-2*sizeof(short)) * sizeof(lds); if ((stp = malloc(i)) == NULL) { nmerr("too many symbols"); return; } if ((t = ldh.l_machine) >= MTYPES) t = 0; fmt1 = fmtab[t].f_fmt1; fmt2 = fmtab[t].f_fmt2; offs = ldh.l_tbase; for (i=L_SHRI; i<L_SYM; ++i) if (i!=L_BSSI && i!=L_BSSD) offs += ldh.l_ssize[i]; fseek(fp, offs-sizeof(ldh), 1); wstp = stp; while (ldh.l_ssize[L_SYM] > 0) { if (readsym(wstp) != 0) break; if (gflag && (wstp->ls_type&L_GLOBAL)==0) continue; if ((wstp->ls_type&~L_GLOBAL) == L_REF) { if (dflag) continue; if (uflag && wstp->ls_addr!=0) continue; } else { if (uflag) continue; } if (!aflag && !csymbol(wstp)) continue; ++wstp; } if ((estp = wstp) == stp) { free((char *) stp); return; } if (!pflag) qsort(stp, estp-stp, sizeof(*stp), qscmp); if (title && !oflag) { if (stuff) printf("\n"); ++stuff; if (amemb) printf("%.*s:\n", DIRSIZ, ahb.ar_name); else printf("%s:\n", fn); } wstp = stp; while (wstp < estp) { if (title && oflag) { if (amemb) printf("%.*s ", DIRSIZ, ahb.ar_name); else printf("%s ", fn); } t = wstp->ls_type & ~L_GLOBAL; if (t<L_SHRI || t>L_REF) t = L_REF+1; if (t==L_REF && wstp->ls_addr==0) { printf(fmt1); putchar(' '); putchar((wstp->ls_type&L_GLOBAL)!=0 ? 'U' : 'u'); } else { printf(fmt2, wstp->ls_addr); printf((wstp->ls_type&L_GLOBAL)!=0 ? gn[t] : ln[t]); } printf(" %.*s\n", NCPLN, wstp->ls_id); ++wstp; } free((char *) stp); } /* * Read the l.out header and convert * old ones to new ones. Canonicalise * the result. */ nmhdr(ldhp) register struct ldheader *ldhp; { register int i; if ( fread((char *)ldhp, 1, sizeof(*ldhp), fp) < sizeof(*ldhp) - 2*sizeof(short)) { nmerr("read error"); return (1); } canshort(ldhp->l_magic); canshort(ldhp->l_flag); canshort(ldhp->l_machine); if (ldhp->l_magic != L_MAGIC) { nmerr("not an object file"); return (1); } if ((ldhp->l_flag&LF_32) == 0) { canshort(ldhp->l_tbase); ldhp->l_entry = ldhp->l_tbase; ldhp->l_tbase = sizeof(*ldhp) - 2*sizeof(short); } else { canshort(ldhp->l_tbase); canlong(ldhp->l_entry); } for (i=0; i<NLSEG; i++) cansize(ldhp->l_ssize[i]); return (0); } /* * Read in one entry from the symbol table. * Adjusts for 32-bit or 16-bit l.out formats. */ readsym(lsp) register struct ldsym *lsp; { vaddr_t vaddr; fread(lsp->ls_id, NCPLN, 1, fp); fread((char *)&lsp->ls_type, sizeof(int), 1, fp); if ((ldh.l_flag & LF_32) != 0) { fread((char *)&lsp->ls_addr, sizeof(long), 1, fp); canlong(lsp->ls_addr); ldh.l_ssize[L_SYM] -= sizeof(lds); } else { fread((char *)&vaddr, sizeof vaddr, 1, fp); canvaddr(vaddr); lsp->ls_addr = vaddr; ldh.l_ssize[L_SYM] -= sizeof(lds)-sizeof(short); } if (feof(fp)) { nmerr("read error"); return (1); } canint(lsp->ls_type); return (0); } /* * This routine gets called if we * are not in `-a' mode. It determines if * the symbol pointed to by `sp' is a C * style symbol (trailing `_' or longer than * 7 characters). If it is it eats the `_' * and returns true. */ csymbol(sp) register struct ldsym *sp; { register char *cp1, *cp2; cp1 = &sp->ls_id[0]; cp2 = &sp->ls_id[NCPLN]; while (cp2!=cp1 && *--cp2==0) ; if (*cp2 != 0) { if (*cp2 == '_') { *cp2 = 0; return (1); } if (cp2-cp1 >= 7) return (1); } return (0); } /* * Compare routine for `qsort'. * Handles the `-n' and `-r' command * line options. */ qscmp(sp1, sp2) register struct ldsym *sp1, *sp2; { register v; if (nflag) { if (sp1->ls_addr < sp2->ls_addr) v = -1; else if (sp1->ls_addr > sp2->ls_addr) v = 1; else v = 0; } else v = strncmp(sp1->ls_id, sp2->ls_id, NCPLN); if (rflag) return (-v); return (v); } /* * Give up. * Tag the line with the file * name. */ nmerr(a) { fprintf(stderr, "nm: "); if (amemb) fprintf(stderr, "%.*s (file %s): ", DIRSIZ, ahb.ar_name, fn); else fprintf(stderr, "%s: ", fn); fprintf(stderr, "%r\n", &a); }