mirror of
https://github.com/golang/go
synced 2024-11-22 21:40:03 -07:00
add nm
R=r DELTA=339 (339 added, 0 deleted, 0 changed) OCL=13786 CL=13794
This commit is contained in:
parent
34514bdb72
commit
7b3771401c
@ -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 ..
|
||||
|
24
src/cmd/nm/Makefile
Normal file
24
src/cmd/nm/Makefile
Normal file
@ -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)
|
344
src/cmd/nm/nm.c
Normal file
344
src/cmd/nm/nm.c
Normal file
@ -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";
|
||||
}
|
Loading…
Reference in New Issue
Block a user