* Copyright (c) 1987 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
static char sccsid
[] = "@(#)nm.c 4.8 %G%";
* nm - print name list; VAX string table version
#define OARMAG 0177545 /* OLD archive magic number */
#define SELECT (archive ? archdr.ar_name : *xargv)
#define u_strx n_un.n_strx
#define u_name n_un.n_name
typedef struct nlist NLIST
;
union { /* exec header, or magic string from library */
char mag_armag
[SARMAG
+ 1];
struct ar_hdr archdr
; /* archive file header structure */
FILE *fi
; /* input file stream */
off_t off
; /* offset into file */
int aflg
, /* print debugger symbols */
gflg
, /* print only global (external symbols */
nflg
, /* sort numerically, not alphabetically */
oflg
, /* prepend element name to each output line */
rflg
= 1, /* how to sort */
uflg
, /* print only undefined symbols */
narg
, /* global number of arguments */
errs
, /* global error flag */
archive
; /* if file is an archive */
char **xargv
; /* global pointer to file name */
int ch
; /* getopts char */
while ((ch
= getopt(argc
, argv
, "agnopru")) != EOF
)
fputs("usage: nm [-agnopru] [file ...]\n", stderr
);
for (xargv
= argv
; argc
--; ++xargv
)
if (fi
= fopen(*xargv
, "r")) {
error(NO
, "cannot open");
register int symcount
, nsyms
;
static NLIST
*symp
, **list
;
static int lastnsyms
= -1,
char *malloc(), *realloc();
* read first few bytes, determine if an archive,
* or executable; if executable, check magic number
if (!fread((char *)&mag_un
, sizeof(mag_un
), 1, fi
)) {
error(NO
, "unable to read file");
if (mag_un
.mag_exp
.a_magic
== OARMAG
) {
error(NO
, "old archive");
if (bcmp(mag_un
.mag_armag
, ARMAG
, SARMAG
)) {
if (N_BADMAG(mag_un
.mag_exp
)) {
* if archive, skip first entry
* if ranlib'd, skip second entry
off
= SARMAG
; /* see nextel() */
if (!strcmp(RANLIBMAG
, archdr
.ar_name
))
printf("\n%s:\n", *xargv
);
/* check for bad magic number */
if (!fread((char *)&mag_un
.mag_exp
, sizeof(struct exec
), 1, fi
)) {
error(NO
, "unable to read magic number");
if (N_BADMAG(mag_un
.mag_exp
))
/* calculate number of symbols in object */
if (!(nsyms
= mag_un
.mag_exp
.a_syms
/ sizeof(NLIST
))) {
error(NO
, "no name list");
/* seek to and read symbols */
(void)fseek(fi
, (long)(N_SYMOFF(mag_un
.mag_exp
) - sizeof(struct exec
)), L_INCR
);
if (!symp
|| nsyms
> lastnsyms
) {
symp
= (NLIST
*)malloc((u_int
)(nsyms
* sizeof(NLIST
)));
list
= (NLIST
**)malloc((u_int
)(nsyms
* sizeof(NLIST
*)));
symp
= (NLIST
*)realloc((char *)symp
, (u_int
)(nsyms
* sizeof(NLIST
)));
list
= (NLIST
**)realloc((char *)list
, (u_int
)(nsyms
* sizeof(NLIST
*)));
error(YES
, "out of memory");
if (fread((char *)symp
, sizeof(NLIST
), nsyms
, fi
) != nsyms
) {
error(NO
, "bad symbol table");
/* read number of strings, string table */
if (!fread((char *)&strsiz
, sizeof(strsiz
), 1, fi
)) {
error(NO
, "no string table (old format .o?)");
if (!strp
|| strsiz
> laststrsiz
) {
strp
= strp
? realloc(strp
, (u_int
)strsiz
) : malloc((u_int
)strsiz
);
error(YES
, "out of memory");
if (!fread(strp
+ sizeof(strsiz
), 1, (int)(strsiz
- sizeof(strsiz
)), fi
)) {
error(NO
, "no string table (old format .o?)");
for (symcount
= nsyms
, L
= list
, N
= symp
;--nsyms
>= 0;++N
)
if (!(N
->n_type
& N_EXT
) && gflg
|| N
->n_type
& N_STAB
&& (!aflg
|| gflg
|| uflg
))
N
->u_name
= N
->u_strx
? strp
+ N
->u_strx
: "";
qsort(list
, symcount
, sizeof(NLIST
*), compare
);
if ((archive
|| narg
> 1) && !oflg
)
printf("\n%s:\n", SELECT
);
} while(archive
&& nextel());
printf("%08x - %02x %04x %5.5s %s\n", (int)L
->n_value
, L
->n_other
& 0xff, L
->n_desc
& 0xffff, stab(L
->n_type
), L
->u_name
);
type
= L
->n_value
? 'c' : 'u';
if (type
== 'u' || type
== 'U')
printf(N_FORMAT
, (int)L
->n_value
);
printf(" %c ", (char)type
);
if ((*p1
)->n_value
> (*p2
)->n_value
)
if ((*p1
)->n_value
< (*p2
)->n_value
)
return(rflg
* strcmp((*p1
)->u_name
, (*p2
)->u_name
));
(void)fseek(fi
, off
, L_SET
);
if (!fread((char *)&archdr
, sizeof(struct ar_hdr
), 1, fi
))
for (cp
= archdr
.ar_name
; cp
< &archdr
.ar_name
[sizeof(archdr
.ar_name
)]; ++cp
)
arsize
= atol(archdr
.ar_size
);
off
= ftell(fi
) + arsize
; /* beginning of next element */
register struct stabnames
*sp
;
for (sp
= stabnames
; sp
->st_value
; ++sp
)
(void)sprintf(prbuf
, "%02x", (int)val
);
fprintf(stderr
, "nm: %s:", *xargv
);
fprintf(stderr
, "(%s): %s\n", archdr
.ar_name
, msg
);
fprintf(stderr
, " %s\n", msg
);