libmach
This commit is contained in:
parent
0e3cc9f456
commit
a84cbb2a17
53 changed files with 12038 additions and 0 deletions
289
src/libmach/nm.c
Normal file
289
src/libmach/nm.c
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
* nm.c -- drive nm
|
||||
*/
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <ar.h>
|
||||
#include <bio.h>
|
||||
#include <mach.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;
|
||||
|
||||
Symbol **fnames; /* file path translation table */
|
||||
Symbol **symptr;
|
||||
int nsym;
|
||||
Biobuf bout;
|
||||
|
||||
int cmp(void*, void*);
|
||||
void error(char*, ...);
|
||||
void execsyms(int);
|
||||
void psym(Symbol*, void*);
|
||||
void printsyms(Symbol**, long);
|
||||
void doar(Biobuf*);
|
||||
void dofile(Biobuf*);
|
||||
void zenter(Symbol*);
|
||||
|
||||
void
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
Biobuf *bin;
|
||||
|
||||
Binit(&bout, 1, OWRITE);
|
||||
argv0 = argv[0];
|
||||
ARGBEGIN {
|
||||
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;
|
||||
} ARGEND
|
||||
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)
|
||||
{
|
||||
Symbol **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(Symbol *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;
|
||||
Symbol *s;
|
||||
long 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(Symbol *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(Symbol **symptr, long nsym)
|
||||
{
|
||||
Symbol *s;
|
||||
char *cp;
|
||||
char path[512];
|
||||
|
||||
if(!sflag)
|
||||
qsort(symptr, nsym, sizeof(*symptr), cmp);
|
||||
while (nsym-- > 0) {
|
||||
s = *symptr++;
|
||||
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 (s->value || s->type == 'a' || s->type == 'p')
|
||||
Bprint(&bout, "%8lux %c %s\n", s->value, s->type, cp);
|
||||
else
|
||||
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…
Add table
Add a link
Reference in a new issue