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