This is dis.c in view mode; [Download] [Up]
/* NeXT disassembly tool Copyright (C) 1989 by Bill Spitzak. See Copyright notice in makefile */ #include "dis.h" char *objectfile; /* name of the object file */ char *map; /* the file, mapped into memory with neat Mach stuff */ /* Disassembly switches: */ int decimalrange=127;/* -d */ flag globalscode; /* -g */ int printpass=100; /* -p n */ flag xlabels; /* -x */ flag onlysymbols; /* -t */ flag noextern; /* -e */ long filelength(int handle) { long ltmp, ltmp2; ltmp=lseek(handle,0L,1); ltmp2=lseek(handle,0L,2); lseek(handle,ltmp,0); return(ltmp2); } /* This is part of main() - see if file is an archive, and if so map one of the archive entries: */ int archeck(int i, char *objname, char *libname) { struct { /* the header for an archive entry */ char name[16]; char date[12]; char uid[6]; char gid[6]; char mode[8]; char size[10]; char fmag[2]; } ar; int size; /* see if magic string is at the start: */ read(i,&ar,8); if (strncmp(ar.name,"!<arch>\n",8)) return(FALSE); if (!objname) {printf("%s is a library.\n",libname); goto FAIL;} while (read(i,&ar,sizeof(ar)) == sizeof(ar)) { if (strncmp(ar.fmag,"`\n",2)) break; /* perhaps junk at eof? */ size = atoi(ar.size); if (!strncmp(ar.name,"__.SYMDEF",9)); else if (!strncmp(objname,ar.name,strlen(objname))) { map_fd(i,lseek(i,0,1),&map,TRUE,size); return(TRUE); } if (size&1) size++; lseek(i,size,1); } printf("%s not found in library %s.\n",objname,libname); FAIL: printf("Recommend you do the following to find a symbol:\n" " nm -gop %s | grep <symbol>\n",libname); exit(1); return(FALSE); /* make cc not complain */ } int main(int argc, char **argv) { int i,fd; char *c; for (i=1; c = argv[i++];) { if (*c=='-') for (;*++c;) { switch(*c) { case 'd': decimalrange = atoi(argv[i++]); break; case 'e': noextern = TRUE; break; case 'g': globalscode = TRUE; break; case 'G': globalscode = 2; break; case 'p': printpass = atoi(argv[i++]); break; case 't': onlysymbols = TRUE; break; case 'x': xlabels = TRUE; break; } } else break; } if (!c) { puts(" dis: the Mach-O/NeXT disassembler.\n" " Written by Bill Spitzak (SPITZAK@MCIMAIL.COM) Sep 1989\n" " This software is distributed FREE and may not be sold.\n" "\n" "dis {-xxx} name\t\t: disassemble executable\n" "dis {-xxx} name.o\t: disassemble object\n" "dis {-xxx} lib.a name.o\t: disassemble object in library\n" "\n" "switches:\n" "-d #\t: print constants larger than # in hex (default=127)\n" "-e\t: don't print .globl declarations for externals\n" "-g\t: assumme all globals in .text segment are code\n" "-G\t: assumme everything in .text is code\n" "-p #\t: print during pass # (0 is first pass)\n" "-t\t: print only the symbols, no code\n" "-x\t: print address in hex before each line\n" "\n"); return(1); } fd = open(c,0); if (fd<0) {printf("Can't open %s, %s\n",c,strerror()); return(1);} if (archeck(fd,argv[i],c)) objectfile = argv[i]; else {objectfile = c; map_fd(fd,0,&map,TRUE,filelength(fd));} close(fd); disasmmappedfile(); /* we could go on to do multiple files here... */ return(0); } /*======================= print routines ========================*/ /* These routines are called to print all the output. So they and the calling routines can be identified if we ever improve this to produce graphical output. */ flag printit; /* if false, disable printing for pre-passes */ static flag linestarted; /* multiple \n preventer */ void startline(long unsigned address) { if (!printit) return; if (linestarted) putchar('\n'); if (xlabels) printf("%7x ",address); linestarted = TRUE; } void startlinenoaddress(void) { if (!printit) return; if (linestarted) putchar('\n'); if (xlabels) printf(" "); linestarted = TRUE; } void endline(void) { /* this only needs to be called at eof! */ if (linestarted) putchar('\n'); linestarted = FALSE; } void cprint(int c) {if (printit) putchar(c);} void sprint(char *s) {if (printit) printf("%s",s);} void fprint(f,i1,i2,i3) {if (printit) printf((char *)f,i1,i2,i3);} /*==================================================================*/ symbol *sourcesymtab; /* points to symbol list, for items that index it */ char *symnametable; /* the source file symbol name table */ struct section *sectiontable[50]; /* note that index of 1 is location 0! */ disasmmappedfile() { /* do exactly one, already mapped, object file */ int i,j,sectn; unsigned startaddress=1; struct segment_command *p; struct section *q; symbol *n; int pass; extern int newlabels; extern flag incode; struct mach_header *header = (struct mach_header *)map; if (header->magic != 0xfeedface) { printf("%s is not a Mach-O file (bad magic number)!\n",objectfile); exit(1); } if (header->cputype != 6) printf("Cputype is %d (MC68030==6 so disassembly may be wrong)\n",header->cputype); if (header->cpusubtype != 1) printf("Wrong machine (cpusubtype is %d, NeXT==1)?\n",header->cpusubtype); sectn = 0; for (i=0, p = (struct segment_command*)(header+1); i<header->ncmds; i++) { switch(p->cmd) { case 1: /* a segment load command, get all the sections: */ for (j=0,q=(struct section *)(p+1); j<p->nsects; q++,j++) { sectiontable[sectn++] = q; } break; case 2: /* load the symbol table, sort it: */ sourcesymtab = n = (symbol *)(map+((struct symtab_command*)p)->symoff); symnametable = map+((struct symtab_command*)p)->stroff; for (j = ((struct symtab_command*)p)->nsyms; j>0; j--,n++) { if (n->name) n->name = symnametable+(int)n->name; if ((n->type&-2)==N_ABS && !n->section) n->section=sectn+1; addsymbol(n); } break; case 5: /* a unix-thread thing */ startaddress = ((struct unixthread *)p)->pc; break; } p = (struct segment_command *)((void *)p + p->cmdsize); } if (startaddress != 1) { n = findlabel(startaddress); if (n) n->desc = CODE; else createlabel(startaddress,1,CODE,"start"); } sortreltables(); /* do non-printing passes until no more symbols: */ printit = FALSE; for (pass=0; pass<printpass; pass++) { newlabels = 0; sectn=0; for (i=0, p = (struct segment_command*)(header+1); i<header->ncmds; i++, p = (struct segment_command *)((void *)p + p->cmdsize) ) if (p->cmd==1) { /* for each section */ for (j=0,q=(struct section *)(p+1); j<p->nsects; q++,j++) { sectn++; /* for each segment */ incode = sectn==1; disasmblock(q->vmaddr,q->vmaddr+q->vmsize,p->vmaddr, q->fileoff ? p->vmaddr+p->vmsize:0, (unsigned)map+p->fileoff-p->vmaddr, (struct relocation_info *)(map+q->reloff), q->nreloc,sectn); } } if (!newlabels) break; printf("| Pass %d, %d new labels\n",pass,newlabels); } startaddress = 0; printit = TRUE; sectn=0; if (!onlysymbols) for (i=0, p = (struct segment_command*)(header+1); i<header->ncmds; i++, p = (struct segment_command *)((void *)p + p->cmdsize) ) if (p->cmd==1) { /* for each section */ for (j=0,q=(struct section *)(p+1); j<p->nsects; q++,j++) { if (!j) disasmsymbols(startaddress,q->vmaddr,FALSE); startaddress = q->vmaddr+q->vmsize; sectn++; /* for each segment */ incode = sectn==1; if (!strcmp(q->sectname,"__text") || !strcmp(q->sectname,"__data") || !strcmp(q->sectname,"__bss")) { if (!q->vmsize) continue; startline(q->vmaddr); cprint('.'); sprint(q->sectname+2); } else { startline(q->vmaddr); fprint(".segment %s; .section %s:", q->segname,q->sectname); } disasmblock(q->vmaddr,q->vmaddr+q->vmsize,p->vmaddr, q->fileoff ? p->vmaddr+p->vmsize:0, (unsigned)map+p->fileoff-p->vmaddr, (struct relocation_info *)(map+q->reloff), q->nreloc,sectn); } } disasmsymbols(startaddress,0,TRUE); endline(); } sortreltables() { int sectn; struct section *q; struct relocation_info *r,*s,temp; char *p; char *sym; int off; int i,j; for (sectn = 0; q = sectiontable[sectn]; sectn++) { /* sort into descending order: */ for (i=0, r=(struct relocation_info *)(map+q->reloff); i<q->nreloc; i++) { for (j=i-1; j>=0 && r[j].address<r[i].address; j--); j++; if (j<i) { temp = r[i]; movmem(r+j,r+j+1,(i-j)*sizeof(struct relocation_info)); r[j] = temp; } } } } disasmsymbols( unsigned start, /* address to start at */ unsigned end, /* address to end at */ int rest) /* ignore end, print all of them */ { symbol *n; extern unsigned symaddress; n = firstsymbol(start); while (n && (rest || symaddress<end)) { printsymbol(n); n = nextsymbol(); } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.