URI:
       tnm.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tnm.c (4945B)
       ---
            1 /*
            2  * nm.c -- drive nm
            3  */
            4 #include <u.h>
            5 #include <libc.h>
            6 #include <ar.h>
            7 #include <bio.h>
            8 #include <mach.h>
            9 
           10 enum{
           11         CHUNK        =        256        /* must be power of 2 */
           12 };
           13 
           14 char        *errs;                        /* exit status */
           15 char        *filename;                /* current file */
           16 char        symname[]="__.SYMDEF";        /* table of contents file name */
           17 int        multifile;                /* processing multiple files */
           18 int        aflag;
           19 int        gflag;
           20 int        hflag;
           21 int        nflag;
           22 int        sflag;
           23 int        uflag;
           24 
           25 Symbol        **fnames;                /* file path translation table */
           26 Symbol        **symptr;
           27 int        nsym;
           28 Biobuf        bout;
           29 
           30 int        cmp(void*, void*);
           31 void        error(char*, ...);
           32 void        execsyms(int);
           33 void        psym(Symbol*, void*);
           34 void        printsyms(Symbol**, long);
           35 void        doar(Biobuf*);
           36 void        dofile(Biobuf*);
           37 void        zenter(Symbol*);
           38 
           39 void
           40 main(int argc, char *argv[])
           41 {
           42         int i;
           43         Biobuf        *bin;
           44 
           45         Binit(&bout, 1, OWRITE);
           46         argv0 = argv[0];
           47         ARGBEGIN {
           48         case 'a':        aflag = 1; break;
           49         case 'g':        gflag = 1; break;
           50         case 'h':        hflag = 1; break;
           51         case 'n':        nflag = 1; break;
           52         case 's':        sflag = 1; break;
           53         case 'u':        uflag = 1; break;
           54         } ARGEND
           55         if (argc > 1)
           56                 multifile++;
           57         for(i=0; i<argc; i++){
           58                 filename = argv[i];
           59                 bin = Bopen(filename, OREAD);
           60                 if(bin == 0){
           61                         error("cannot open %s", filename);
           62                         continue;
           63                 }
           64                 if (isar(bin))
           65                         doar(bin);
           66                 else{
           67                         Bseek(bin, 0, 0);
           68                         dofile(bin);
           69                 }
           70                 Bterm(bin);
           71         }
           72         exits(errs);
           73 }
           74 
           75 /*
           76  * read an archive file,
           77  * processing the symbols for each intermediate file in it.
           78  */
           79 void
           80 doar(Biobuf *bp)
           81 {
           82         int offset, size, obj;
           83         char membername[SARNAME];
           84 
           85         multifile = 1;
           86         for (offset = Boffset(bp);;offset += size) {
           87                 size = nextar(bp, offset, membername);
           88                 if (size < 0) {
           89                         error("phase error on ar header %ld", offset);
           90                         return;
           91                 }
           92                 if (size == 0)
           93                         return;
           94                 if (strcmp(membername, symname) == 0)
           95                         continue;
           96                 obj = objtype(bp, 0);
           97                 if (obj < 0) {
           98                         error("inconsistent file %s in %s",
           99                                         membername, filename);
          100                         return;
          101                 }
          102                 if (!readar(bp, obj, offset+size, 1)) {
          103                         error("invalid symbol reference in file %s",
          104                                         membername);
          105                         return;
          106                 }
          107                 filename = membername;
          108                 nsym=0;
          109                 objtraverse(psym, 0);
          110                 printsyms(symptr, nsym);
          111         }
          112 }
          113 
          114 /*
          115  * process symbols in a file
          116  */
          117 void
          118 dofile(Biobuf *bp)
          119 {
          120         int obj;
          121 
          122         obj = objtype(bp, 0);
          123         if (obj < 0)
          124                 execsyms(Bfildes(bp));
          125         else
          126         if (readobj(bp, obj)) {
          127                 nsym = 0;
          128                 objtraverse(psym, 0);
          129                 printsyms(symptr, nsym);
          130         }
          131 }
          132 
          133 /*
          134  * comparison routine for sorting the symbol table
          135  *        this screws up on 'z' records when aflag == 1
          136  */
          137 int
          138 cmp(void *vs, void *vt)
          139 {
          140         Symbol **s, **t;
          141 
          142         s = vs;
          143         t = vt;
          144         if(nflag)
          145                 if((*s)->value < (*t)->value)
          146                         return -1;
          147                 else
          148                         return (*s)->value > (*t)->value;
          149         return strcmp((*s)->name, (*t)->name);
          150 }
          151 /*
          152  * enter a symbol in the table of filename elements
          153  */
          154 void
          155 zenter(Symbol *s)
          156 {
          157         static int maxf = 0;
          158 
          159         if (s->value > maxf) {
          160                 maxf = (s->value+CHUNK-1) &~ (CHUNK-1);
          161                 fnames = realloc(fnames, (maxf+1)*sizeof(*fnames));
          162                 if(fnames == 0) {
          163                         error("out of memory", argv0);
          164                         exits("memory");
          165                 }
          166         }
          167         fnames[s->value] = s;
          168 }
          169 
          170 /*
          171  * get the symbol table from an executable file, if it has one
          172  */
          173 void
          174 execsyms(int fd)
          175 {
          176         Fhdr f;
          177         Symbol *s;
          178         long n;
          179 
          180         seek(fd, 0, 0);
          181         if (crackhdr(fd, &f) == 0) {
          182                 error("Can't read header for %s", filename);
          183                 return;
          184         }
          185         if (syminit(fd, &f) < 0)
          186                 return;
          187         s = symbase(&n);
          188         nsym = 0;
          189         while(n--)
          190                 psym(s++, 0);
          191 
          192         printsyms(symptr, nsym);
          193 }
          194 
          195 void
          196 psym(Symbol *s, void* p)
          197 {
          198         USED(p);
          199         switch(s->type) {
          200         case 'T':
          201         case 'L':
          202         case 'D':
          203         case 'B':
          204                 if (uflag)
          205                         return;
          206                 if (!aflag && ((s->name[0] == '.' || s->name[0] == '$')))
          207                         return;
          208                 break;
          209         case 'b':
          210         case 'd':
          211         case 'l':
          212         case 't':
          213                 if (uflag || gflag)
          214                         return;
          215                 if (!aflag && ((s->name[0] == '.' || s->name[0] == '$')))
          216                         return;
          217                 break;
          218         case 'U':
          219                 if (gflag)
          220                         return;
          221                 break;
          222         case 'Z':
          223                 if (!aflag)
          224                         return;
          225                 break;
          226         case 'm':
          227         case 'f':        /* we only see a 'z' when the following is true*/
          228                 if(!aflag || uflag || gflag)
          229                         return;
          230                 if (strcmp(s->name, ".frame"))
          231                         zenter(s);
          232                 break;
          233         case 'a':
          234         case 'p':
          235         case 'z':
          236         default:
          237                 if(!aflag || uflag || gflag)
          238                         return;
          239                 break;
          240         }
          241         symptr = realloc(symptr, (nsym+1)*sizeof(Sym*));
          242         if (symptr == 0) {
          243                 error("out of memory");
          244                 exits("memory");
          245         }
          246         symptr[nsym++] = s;
          247 }
          248 
          249 void
          250 printsyms(Symbol **symptr, long nsym)
          251 {
          252         Symbol *s;
          253         char *cp;
          254         char path[512];
          255 
          256         if(!sflag)
          257                 qsort(symptr, nsym, sizeof(*symptr), cmp);
          258         while (nsym-- > 0) {
          259                 s = *symptr++;
          260                 if (multifile && !hflag)
          261                         Bprint(&bout, "%s:", filename);
          262                 if (s->type == 'z') {
          263                         fileelem(fnames, (uchar *) s->name, path, 512);
          264                         cp = path;
          265                 } else
          266                         cp = s->name;
          267                 if (s->value || s->type == 'a' || s->type == 'p')
          268                         Bprint(&bout, "%8lux %c %s\n", s->value, s->type, cp);
          269                 else
          270                         Bprint(&bout, "         %c %s\n", s->type, cp);
          271         }
          272 }
          273 
          274 void
          275 error(char *fmt, ...)
          276 {
          277         Fmt f;
          278         char buf[128];
          279         va_list arg;
          280 
          281         fmtfdinit(&f, 2, buf, sizeof buf);
          282         fmtprint(&f, "%s: ", argv0);
          283         va_start(arg, fmt);
          284         fmtvprint(&f, fmt, arg);
          285         va_end(arg);
          286         fmtprint(&f, "\n");
          287         fmtfdflush(&f);
          288         errs = "errors";
          289 }