This is dis.m in view mode; [Download] [Up]
/* NeXT disassembly tool Copyright (C) 1989 by Bill Spitzak. See Copyright notice in makefile */ /* $Log: dis.m,v $ Revision 1.3 94/08/24 22:42:48 ediger changed a comment Revision 1.2 94/08/22 22:32:31 ediger added some comments Revision 1.1 94/05/31 22:06:37 ediger Initial revision * */ static char rcsident[] = "$Id: dis.m,v 1.3 94/08/24 22:42:48 ediger Exp Locker: ediger $"; #include <dis.h> #include <sys/stat.h> #import <MappedFile.h> /* Disassembly switches: */ int decimalrange = 127; /* -d */ flag globalscode = FALSE; /* -g */ int printpass = 100; /* -p n */ flag xlabels = FALSE; /* -x */ flag onlysymbols = FALSE; /* -t */ flag noextern = FALSE; /* -e */ flag printit; /* fwd declarations of functions in this file */ long filelength(int); void endline(void); int main(int, char **); long filelength(int handle) { struct stat sStat; assert(handle >= 0); if (fstat(handle, &sStat) < 0) perror("finding file size"); return sStat.st_size; } extern int optind; extern char *optarg; void usage(void); int main(int argc, char **argv) { int iOption; MappedFile *oMappedFile; while ((iOption = getopt(argc, argv, "d:egGtxp:")) != EOF) { switch (iOption) { case 'd': decimalrange = atoi(optarg); break; case 'e': noextern = TRUE; break; case 'g': globalscode = TRUE; break; case 'G': globalscode = 2; break; case 'p': printpass = atoi(optarg); break; case 't': onlysymbols = TRUE; break; case 'x': xlabels = TRUE; break; default: usage(); break; } } if (argv[optind] == NULL) usage(); oMappedFile = [[[MappedFile alloc] init] filename:argv[optind]]; if (oMappedFile == NULL) { fprintf(stderr, "Failed to memory-map \"%s\"\n", argv[optind]); exit(33); } else if (![oMappedFile map]) { fprintf(stderr, "Failed to memory-map \"%s\": %s\n", argv[optind], [oMappedFile errorString]); [oMappedFile free]; exit(33); } disasmmappedfile([oMappedFile address]); /* we could go on to do multiple files here... */ if (![oMappedFile unmap]) fprintf(stderr, "Failed to UNmemory-map \"%s\": %s\n", argv[optind], [oMappedFile errorString]); [oMappedFile free]; return (0); } /* do exactly one, already mapped, object file */ void disasmmappedfile(char *map) { int i, j, sectn = 0; unsigned startaddress = 1; struct segment_command *p; struct section *q; struct nlist *n; int pass; extern int newlabels; extern flag incode; struct mach_header *header = (struct mach_header *)map; check_header(header); /* * This next for/switch combo appears to be order of section dependent. * That is, loading the symbol table correctly means having the section * total count correct. */ p = (struct segment_command *)(header + 1); for (i = 0; i < header->ncmds; i++) { switch (p->cmd) { case LC_SEGMENT: /* a segment load command, get all the sections: */ sectn = set_sections(p); break; case LC_SYMTAB: /* load the symbol table */ load_symbol_table(map, (struct symtab_command *)p, sectn); break; case LC_THREAD: /* a thread thing */ case LC_UNIXTHREAD: /* a unix-thread thing */ startaddress = thread_prog_counter(p); break; case LC_LOADFVMLIB: /* should pick up the symbols out of this thing */ break; } p = (struct segment_command *) ((void *)p + p->cmdsize); } if (startaddress != 1) { n = findlabel(startaddress); if (n) n->n_desc = CODE; else createlabel(startaddress, 1, CODE, "start"); } /* have to sort the relocation info because getlabel() looks * in the current relocation info table (rtab global) to find * a label for the address passed in */ sortreltables(map); /* do non-printing passes until no more symbols: */ printit = FALSE; for (pass = 0; pass < printpass; pass++) { newlabels = 0; sectn = 0; p = (struct segment_command *) (header + 1); for (i = 0; i < header->ncmds; i++) { if (p->cmd == LC_SEGMENT) { /* for each section */ q = (struct section *)(p + 1); for (j = 0; j < p->nsects; q++, j++) { sectn++; /* for each segment */ incode = (sectn == 1); disasmblock(p, q, sectn, map); } } p = (struct segment_command *)((void *)p + p->cmdsize); } if (!newlabels) break; printf("| Pass %d, %d new labels\n", pass, newlabels); } startaddress = 0; printit = TRUE; sectn = 0; if (!onlysymbols) { p = (struct segment_command *)(header + 1); for (i = 0; i < header->ncmds; i++) { if (p->cmd == LC_SEGMENT) { /* for each section */ q = (struct section *)(p + 1); for (j = 0; j < p->nsects; q++, j++) { if (j == 0) disasmsymbols(startaddress, q->addr, FALSE); startaddress = q->addr + q->size; sectn++; /* for each segment */ incode = sectn == 1; if (!strcmp(q->sectname, "__text") || !strcmp(q->sectname, "__data") || !strcmp(q->sectname, "__bss")) { if (!q->size) continue; startline(q->addr); cprint('.'); sprint(q->sectname + 2); } else { startline(q->addr); fprint(".segment %s; .section %s:", q->segname, q->sectname); } disasmblock(p, q, sectn, map); } } p = (struct segment_command *)((void *)p + p->cmdsize); } } disasmsymbols(startaddress, 0, TRUE); endline(); } void disasmsymbols( unsigned start, /* address to start at */ unsigned end, /* address to end at */ int rest /* ignore end, print all of them */ ) { struct nlist *n; extern unsigned symaddress; n = firstsymbol(start); while (n && (rest || symaddress < end)) { printsymbol(n); n = nextsymbol(); } } unsigned int thread_prog_counter(struct segment_command *spSegmentCmd) { struct thread_command *spThreadCmd; struct thread_state_flavor *spThreadStateFlavor; unsigned long lNextAddress; unsigned int irPC = -1; assert(NULL != spSegmentCmd); spThreadCmd = (struct thread_command *)spSegmentCmd; spThreadStateFlavor = (struct thread_state_flavor *)(spThreadCmd + 1); lNextAddress = (unsigned long)(spThreadStateFlavor + 1); switch(spThreadStateFlavor->flavor) { case M68K_THREAD_STATE_REGS: irPC = ((struct m68k_thread_state_regs *)lNextAddress)->pc; break; case M68K_THREAD_STATE_68882: irPC = ((struct m68k_thread_state_68882 *)lNextAddress)->iar; break; case M68K_THREAD_STATE_USER_REG: irPC = ((struct m68k_thread_state_user_reg *)lNextAddress)->user_reg; break; case i386_THREAD_STATE: irPC = ((i386_thread_state_t *)lNextAddress)->eip; break; } return irPC; } void check_header(struct mach_header *header) { if (header->magic != MH_MAGIC) { printf("Not a Mach-O file (bad magic number 0x%x)!\n", header->magic); exit(1); } if (header->cputype != CPU_TYPE_MC680x0) printf("Cputype is %d (Not MC68030 so disassembly may be wrong)\n", header->cputype); if (header->cpusubtype != CPU_SUBTYPE_MC680x0_ALL) printf("Wrong machine (cpusubtype is %d, MC680x0 is 1)?\n", header->cpusubtype); } void usage() { 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: assume all globals in .text segment are code\n" "-G\t: assume 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"); exit (1); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.