Home
       nm.c - scc - simple c99 compiler
  HTML git clone git://git.simple-cc.org/scc
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
       nm.c (4797B)
       ---
            1 #include <ctype.h>
            2 #include <errno.h>
            3 #include <stdarg.h>
            4 #include <stdint.h>
            5 #include <stdio.h>
            6 #include <stdlib.h>
            7 #include <string.h>
            8 
            9 #include <scc/ar.h>
           10 #include <scc/arg.h>
           11 #include <scc/mach.h>
           12 
           13 
           14 struct symtbl {
           15         Symbol **buf;
           16         size_t nsyms;
           17 };
           18 
           19 char *argv0;
           20 static int status, multi;
           21 static int radix = 16;
           22 static int Pflag;
           23 static int Aflag;
           24 static int vflag;
           25 static int gflag;
           26 static int uflag;
           27 static int fflag;
           28 static char *filename, *membname;
           29 
           30 static void
           31 error(char *fmt, ...)
           32 {
           33         va_list va;
           34 
           35         va_start(va, fmt);
           36         fprintf(stderr, "nm: %s: ", filename);
           37         if (membname)
           38                 fprintf(stderr, "%s: ", membname);
           39         vfprintf(stderr, fmt, va);
           40         putc('\n', stderr);
           41         va_end(va);
           42 
           43         status = EXIT_FAILURE;
           44 }
           45 
           46 static int
           47 cmp(const void *p1, const void *p2)
           48 {
           49         Symbol **s1 = (Symbol **) p1, **s2 = (Symbol **) p2;
           50         Symbol *sym1 = *s1, *sym2 = *s2;
           51 
           52         if (vflag) {
           53                 if (sym1->value > sym2->value)
           54                         return 1;
           55                 if (sym1->value < sym2->value)
           56                         return -1;
           57                 if (sym1->type == 'U' && sym2->type == 'U')
           58                         return 0;
           59                 if (sym1->type == 'U')
           60                         return -1;
           61                 if (sym2->type == 'U')
           62                         return 1;
           63                 return 0;
           64         } else {
           65                 return strcmp(sym1->name, sym2->name);
           66         }
           67 }
           68 
           69 static void
           70 printsyms(Symbol **syms, size_t nsym)
           71 {
           72         size_t i;
           73 
           74         if (nsym == 0) {
           75                 error("no symbols");
           76                 return;
           77         }
           78         qsort(syms, nsym, sizeof(syms), cmp);
           79 
           80         if (!Aflag) {
           81                 if (multi || membname)
           82                         printf("%s:\n", (membname) ? membname : filename);
           83         }
           84 
           85         for (i = 0; i < nsym; i++) {
           86                 Symbol *sym = syms[i];
           87                 int type = sym->type;
           88                 char *fmt;
           89 
           90                 if (Aflag) {
           91                         fmt = (membname) ? "%s[%s]: " : "%s: ";
           92                         printf(fmt, filename, membname);
           93                 }
           94 
           95                 if (Pflag) {
           96                         printf("%s %c", sym->name, sym->type);
           97                         if (type != 'U') {
           98                                 if (radix == 8)
           99                                         fmt = " %016.16llo %lo";
          100                                 else if (radix == 10)
          101                                         fmt = " %016.16llu %lu";
          102                                 else
          103                                         fmt = " %016.16llx %lx";
          104                                 printf(fmt, sym->value, sym->size);
          105                         }
          106                 } else {
          107                         if (type == 'U')
          108                                 fmt = "                ";
          109                         else if (radix == 8)
          110                                 fmt = "%016.16llo";
          111                         else if (radix == 10)
          112                                 fmt = "%016.16lld";
          113                         else
          114                                 fmt = "%016.16llx";
          115                         printf(fmt, sym->value);
          116                         printf(" %c %s", sym->type, sym->name);
          117                 }
          118                 putchar('\n');
          119         }
          120 }
          121 
          122 static int
          123 newsym(Symbol *sym, struct symtbl *tbl)
          124 {
          125         Symbol **p, *s;
          126         size_t n, size;
          127         int type = sym->type;
          128         int stype = sym->stype;
          129 
          130         if (type == '?' && !fflag
          131         || type == 'N' && !fflag
          132         || stype != SYMFUNC && stype != SYMOBJECT && !fflag
          133         || uflag && type != 'U'
          134         || gflag && !isupper(type)) {
          135                 return 0;
          136         }
          137 
          138         n = tbl->nsyms+1;
          139         size = n *sizeof(*p);
          140         p = realloc(tbl->buf, size);
          141         s = malloc(sizeof(*s));
          142         if (!p || !s) {
          143                 free(p);
          144                 free(s);
          145                 error(strerror(errno));
          146                 return -1;
          147         }
          148 
          149         *s = *sym;
          150         tbl->buf = p;
          151         p[tbl->nsyms++] = s;
          152         return 0;
          153 }
          154 
          155 static void
          156 nmobj(FILE *fp, int type)
          157 {
          158         int i, err = 1;
          159         Obj *obj;
          160         Symbol sym;
          161         struct symtbl tbl = {NULL, 0};
          162 
          163         if ((obj = newobj(type)) == NULL) {
          164                 error(strerror(errno));
          165                 goto err1;
          166         }
          167 
          168         if (readobj(obj, fp) < 0)
          169                 goto err2;
          170 
          171         for (i = 0; getsym(obj, &i, &sym); i++) {
          172                 if (newsym(&sym, &tbl) < 0)
          173                         goto err3;
          174         }
          175 
          176         printsyms(tbl.buf, tbl.nsyms);
          177         err = 0;
          178 
          179 err3:
          180         free(tbl.buf);
          181 err2:
          182         delobj(obj);
          183 err1: 
          184         if (err)
          185                 error("object file corrupted");
          186 }
          187 
          188 static void
          189 nmlib(FILE *fp)
          190 {
          191         int t;
          192         long off, cur;
          193         char memb[SARNAM+1];
          194 
          195         for (;;) {
          196                 cur = ftell(fp);
          197                 off = armember(fp, memb);
          198                 switch (off) {
          199                 case -1:
          200                         error("library corrupted");
          201                         if (ferror(fp))
          202                                 error(strerror(errno));
          203                 case 0:
          204                         return;
          205                 default:
          206                         membname = memb;
          207                         if ((t = objprobe(fp, NULL)) != -1)
          208                                 nmobj(fp, t);
          209                         membname = NULL;
          210                         fseek(fp, cur, SEEK_SET);
          211                         fseek(fp, off, SEEK_CUR);
          212                         break;
          213                 }
          214         }
          215 }
          216 
          217 static void
          218 nm(char *fname)
          219 {
          220         int t;
          221         FILE *fp;
          222 
          223         filename = fname;
          224         membname = NULL;
          225 
          226         if ((fp = fopen(fname, "rb")) == NULL) {
          227                 error(strerror(errno));
          228                 return;
          229         }
          230 
          231         if ((t = objprobe(fp, NULL)) != -1)
          232                 nmobj(fp, t);
          233         else if (archive(fp))
          234                 nmlib(fp);
          235         else
          236                 error("bad format");
          237 
          238         fclose(fp);
          239 }
          240 
          241 static void
          242 usage(void)
          243 {
          244         fputs("nm [-APvfa][-g|-u][-t format] [file...]\n", stderr);
          245         exit(1);
          246 }
          247 
          248 int
          249 main(int argc, char *argv[])
          250 {
          251         char *t;
          252 
          253         ARGBEGIN {
          254         case 'P':
          255                 Pflag = 1;
          256                 break;
          257         case 'A':
          258                 Aflag = 1;
          259                 break;
          260         case 'g':
          261                 gflag = 1;
          262                 break;
          263         case 'a':
          264         case 'f':
          265                 fflag = 1;
          266                 break;
          267         case 'u':
          268                 uflag = 1;
          269                 break;
          270         case 'v':
          271                 vflag = 1;
          272                 break;
          273         case 't':
          274                 t = EARGF(usage());
          275                 if (!strcmp(t, "o"))
          276                         radix = 8;
          277                 else if (!strcmp(t, "d"))
          278                         radix = 10;
          279                 else if (!strcmp(t, "x"))
          280                         radix = 16;
          281                 else
          282                         usage();
          283                 break;
          284         default:
          285                 usage();
          286         } ARGEND
          287 
          288         if (argc == 0) {
          289                 nm("a.out");
          290         } else {
          291                 if (argc > 1)
          292                         multi = 1;
          293                 for ( ; *argv; ++argv)
          294                         nm(*argv);
          295         }
          296 
          297         if (fflush(stdout) == EOF) {
          298                 fprintf(stderr,
          299                         "nm: error writing in output:%s\n",
          300                         strerror(errno));
          301                 status = 1;
          302         }
          303 
          304         return status;
          305 }