]> Cypherpunks repositories - gostls13.git/commitdiff
add nm
authorRuss Cox <rsc@golang.org>
Mon, 4 Aug 2008 06:06:00 +0000 (23:06 -0700)
committerRuss Cox <rsc@golang.org>
Mon, 4 Aug 2008 06:06:00 +0000 (23:06 -0700)
R=r
DELTA=339  (339 added, 0 deleted, 0 changed)
OCL=13786
CL=13794

src/cmd/make.bash
src/cmd/nm/Makefile [new file with mode: 0644]
src/cmd/nm/nm.c [new file with mode: 0644]

index d705a51ce5d4a150758d0ba8b63db8957a451b92..84332440d0edfab61e4ec3f517d292ead64938df 100644 (file)
@@ -50,3 +50,8 @@ echo; echo; echo %%%% making db %%%%; echo
 cd db
 make install
 cd ..
+
+echo; echo; echo %%%% making nm %%%%; echo
+cd nm
+make install
+cd ..
diff --git a/src/cmd/nm/Makefile b/src/cmd/nm/Makefile
new file mode 100644 (file)
index 0000000..080d668
--- /dev/null
@@ -0,0 +1,24 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../Make.conf
+
+# The directory is nm because the source is portable and general.
+# We call the binary 6nm to avoid confusion and because this binary
+# is linked only with amd64 and x86 support.
+
+TARG=6nm
+OFILES=\
+       nm.$O\
+
+$(TARG): $(OFILES)
+       $(LD) -o $(TARG) -L$(GOROOT)/lib $(OFILES) -lmach_amd64 -lbio -l9
+
+clean:
+       rm -f $(OFILES) $(TARG)
+
+install: $(TARG)
+       cp $(TARG) $(BIN)/$(TARG)
+
+$(OFILES): $(HFILES)
diff --git a/src/cmd/nm/nm.c b/src/cmd/nm/nm.c
new file mode 100644 (file)
index 0000000..7c77f66
--- /dev/null
@@ -0,0 +1,344 @@
+// Inferno utils/nm/nm.c
+// http://code.google.com/p/inferno-os/source/browse/utils/nm/nm.c
+//
+//     Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright © 1997-1999 Vita Nuova Limited
+//     Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright © 2004,2006 Bruce Ellis
+//     Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+//     Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+/*
+ * nm.c -- drive nm
+ */
+#include <u.h>
+#include <libc.h>
+#include <ar.h>
+#include <bio.h>
+#include <mach_amd64.h>
+
+enum{
+       CHUNK   =       256     /* must be power of 2 */
+};
+
+char   *errs;                  /* exit status */
+char   *filename;              /* current file */
+char   symname[]="__.SYMDEF";  /* table of contents file name */
+int    multifile;              /* processing multiple files */
+int    aflag;
+int    gflag;
+int    hflag;
+int    nflag;
+int    sflag;
+int    uflag;
+int    Tflag;
+
+Sym    **fnames;               /* file path translation table */
+Sym    **symptr;
+int    nsym;
+Biobuf bout;
+
+int    cmp(void*, void*);
+void   error(char*, ...);
+void   execsyms(int);
+void   psym(Sym*, void*);
+void   printsyms(Sym**, long);
+void   doar(Biobuf*);
+void   dofile(Biobuf*);
+void   zenter(Sym*);
+
+void
+usage(void)
+{
+       fprint(2, "usage: nm [-aghnsTu] file ...\n");
+       exits("usage");
+}
+
+void
+main(int argc, char *argv[])
+{
+       int i;
+       Biobuf  *bin;
+
+       Binit(&bout, 1, OWRITE);
+       argv0 = argv[0];
+       ARGBEGIN {
+       default:        usage();
+       case 'a':       aflag = 1; break;
+       case 'g':       gflag = 1; break;
+       case 'h':       hflag = 1; break;
+       case 'n':       nflag = 1; break;
+       case 's':       sflag = 1; break;
+       case 'u':       uflag = 1; break;
+       case 'T':       Tflag = 1; break;
+       } ARGEND
+       if (argc == 0)
+               usage();
+       if (argc > 1)
+               multifile++;
+       for(i=0; i<argc; i++){
+               filename = argv[i];
+               bin = Bopen(filename, OREAD);
+               if(bin == 0){
+                       error("cannot open %s", filename);
+                       continue;
+               }
+               if (isar(bin))
+                       doar(bin);
+               else{
+                       Bseek(bin, 0, 0);
+                       dofile(bin);
+               }
+               Bterm(bin);
+       }
+       exits(errs);
+}
+
+/*
+ * read an archive file,
+ * processing the symbols for each intermediate file in it.
+ */
+void
+doar(Biobuf *bp)
+{
+       int offset, size, obj;
+       char membername[SARNAME];
+
+       multifile = 1;
+       for (offset = Boffset(bp);;offset += size) {
+               size = nextar(bp, offset, membername);
+               if (size < 0) {
+                       error("phase error on ar header %ld", offset);
+                       return;
+               }
+               if (size == 0)
+                       return;
+               if (strcmp(membername, symname) == 0)
+                       continue;
+               obj = objtype(bp, 0);
+               if (obj < 0) {
+                       error("inconsistent file %s in %s",
+                                       membername, filename);
+                       return;
+               }
+               if (!readar(bp, obj, offset+size, 1)) {
+                       error("invalid symbol reference in file %s",
+                                       membername);
+                       return;
+               }
+               filename = membername;
+               nsym=0;
+               objtraverse(psym, 0);
+               printsyms(symptr, nsym);
+       }
+}
+
+/*
+ * process symbols in a file
+ */
+void
+dofile(Biobuf *bp)
+{
+       int obj;
+
+       obj = objtype(bp, 0);
+       if (obj < 0)
+               execsyms(Bfildes(bp));
+       else
+       if (readobj(bp, obj)) {
+               nsym = 0;
+               objtraverse(psym, 0);
+               printsyms(symptr, nsym);
+       }
+}
+
+/*
+ * comparison routine for sorting the symbol table
+ *     this screws up on 'z' records when aflag == 1
+ */
+int
+cmp(void *vs, void *vt)
+{
+       Sym **s, **t;
+
+       s = vs;
+       t = vt;
+       if(nflag)
+               if((*s)->value < (*t)->value)
+                       return -1;
+               else
+                       return (*s)->value > (*t)->value;
+       return strcmp((*s)->name, (*t)->name);
+}
+/*
+ * enter a symbol in the table of filename elements
+ */
+void
+zenter(Sym *s)
+{
+       static int maxf = 0;
+
+       if (s->value > maxf) {
+               maxf = (s->value+CHUNK-1) &~ (CHUNK-1);
+               fnames = realloc(fnames, (maxf+1)*sizeof(*fnames));
+               if(fnames == 0) {
+                       error("out of memory", argv0);
+                       exits("memory");
+               }
+       }
+       fnames[s->value] = s;
+}
+
+/*
+ * get the symbol table from an executable file, if it has one
+ */
+void
+execsyms(int fd)
+{
+       Fhdr f;
+       Sym *s;
+       int32 n;
+
+       seek(fd, 0, 0);
+       if (crackhdr(fd, &f) == 0) {
+               error("Can't read header for %s", filename);
+               return;
+       }
+       if (syminit(fd, &f) < 0)
+               return;
+       s = symbase(&n);
+       nsym = 0;
+       while(n--)
+               psym(s++, 0);
+
+       printsyms(symptr, nsym);
+}
+
+void
+psym(Sym *s, void* p)
+{
+       USED(p);
+       switch(s->type) {
+       case 'T':
+       case 'L':
+       case 'D':
+       case 'B':
+               if (uflag)
+                       return;
+               if (!aflag && ((s->name[0] == '.' || s->name[0] == '$')))
+                       return;
+               break;
+       case 'b':
+       case 'd':
+       case 'l':
+       case 't':
+               if (uflag || gflag)
+                       return;
+               if (!aflag && ((s->name[0] == '.' || s->name[0] == '$')))
+                       return;
+               break;
+       case 'U':
+               if (gflag)
+                       return;
+               break;
+       case 'Z':
+               if (!aflag)
+                       return;
+               break;
+       case 'm':
+       case 'f':       /* we only see a 'z' when the following is true*/
+               if(!aflag || uflag || gflag)
+                       return;
+               if (strcmp(s->name, ".frame"))
+                       zenter(s);
+               break;
+       case 'a':
+       case 'p':
+       case 'z':
+       default:
+               if(!aflag || uflag || gflag)
+                       return;
+               break;
+       }
+       symptr = realloc(symptr, (nsym+1)*sizeof(Sym*));
+       if (symptr == 0) {
+               error("out of memory");
+               exits("memory");
+       }
+       symptr[nsym++] = s;
+}
+
+void
+printsyms(Sym **symptr, long nsym)
+{
+       int i, wid;
+       Sym *s;
+       char *cp;
+       char path[512];
+
+       if(!sflag)
+               qsort(symptr, nsym, sizeof(*symptr), (void*)cmp);
+       
+       wid = 0;
+       for (i=0; i<nsym; i++) {
+               s = symptr[i];
+               if (s->value && wid == 0)
+                       wid = 8;
+               else if (s->value >= 0x100000000LL && wid == 8)
+                       wid = 16;
+       }       
+       for (i=0; i<nsym; i++) {
+               s = symptr[i];
+               if (multifile && !hflag)
+                       Bprint(&bout, "%s:", filename);
+               if (s->type == 'z') {
+                       fileelem(fnames, (uchar *) s->name, path, 512);
+                       cp = path;
+               } else
+                       cp = s->name;
+               if (Tflag)
+                       Bprint(&bout, "%8ux ", s->sig);
+               if (s->value || s->type == 'a' || s->type == 'p')
+                       Bprint(&bout, "%*llux ", wid, s->value);
+               else
+                       Bprint(&bout, "%*s ", wid, "");
+               Bprint(&bout, "%c %s\n", s->type, cp);
+       }
+}
+
+void
+error(char *fmt, ...)
+{
+       Fmt f;
+       char buf[128];
+       va_list arg;
+
+       fmtfdinit(&f, 2, buf, sizeof buf);
+       fmtprint(&f, "%s: ", argv0);
+       va_start(arg, fmt);
+       fmtvprint(&f, fmt, arg);
+       va_end(arg);
+       fmtprint(&f, "\n");
+       fmtfdflush(&f);
+       errs = "errors";
+}