This is MachO.m in view mode; [Download] [Up]
#import <MachOFile.h> #import <MappedFile.h> /* * $Log: MachO.m,v $ Revision 1.5 94/05/28 16:17:33 ediger updated usage() to reflect actual options Revision 1.4 94/05/26 21:47:00 ediger "productionized" it Revision 1.1 94/02/19 14:29:20 ediger Initial revision */ static char MachORcsIdent[] = "$Id: MachO.m,v 1.5 94/05/28 16:17:33 ediger Exp Locker: ediger $"; // deal with user preference in which way "low memory" is on the printed // page. enum direction {UP, DOWN}; void print_segments(id mach_o_file, enum direction, BOOL printsects); void print_threads(id oFile); void do_cmd_line(int, char **); // Option flags: global to avoid complicating do_cmd_line() BOOL gyPrintThreads = FALSE; BOOL gyPrintSections = FALSE; BOOL gyPrintSegmentsVerbose = FALSE; BOOL gyPrintLibraries = FALSE; enum direction geDir = UP; void usage(char *); int main(int ac, char **av) { MachOFile *oFile; MappedFile *oMap; char *bpFileName = NULL; #ifdef MALLOCDEBUGGING char buf[256]; #endif do_cmd_line(ac, av); #ifdef MALLOCDEBUGGING puts("Hit return to continue..."); gets(buf); #endif bpFileName = av[optind]; if (bpFileName == NULL) { fprintf(stderr, "Specify file name on command line.\n"); usage(*av); exit(9); } oFile = [[MachOFile alloc] init]; oMap = [[[MappedFile alloc] init] filename:bpFileName]; if ([oMap map] == FALSE) { fprintf(stderr, "Trouble mapping \"%s\": %s\n", bpFileName, [oMap errorString]); [oFile free]; exit(1); } if (gyPrintLibraries == TRUE) [oFile considerMappedFiles]; if([oFile fillFromAddress:[oMap address]] == NULL) { fprintf(stderr, "\"%s\" is probably not a Mach-O file\n", bpFileName); exit(9); } if (gyPrintThreads == TRUE) print_threads(oFile); print_segments(oFile, geDir, gyPrintSections); [oFile free]; [oMap free]; #ifdef MALLOCDEBUGGING puts("Hit return to finish..."); gets(buf); #endif return 0; } void print_threads(oFile) id oFile; { int iThreads, iCC; iThreads = [oFile threads]; for (iCC = 0; iCC < iThreads; ++iCC) { id oThread = [oFile thread:iCC]; unsigned long ulAddr = [oThread pc]; printf("Thread's pc: 0x%lx\n", ulAddr); } } void print_segments(oFile, eDirection, ySections) id oFile; enum direction eDirection; BOOL ySections; { int iSegments, iCC; int iFrom, iTo, iIncr; iSegments = [oFile mappedSegments]; if (eDirection == UP) { iFrom = 0; iTo = iSegments; iIncr = 1; } else { iFrom = iSegments - 1; iTo = 0; iIncr = -1; } for (iCC = iFrom; eDirection == UP ? iCC < iTo : iCC >= iTo ; iCC += iIncr) { id oSegment = [oFile mappedSegment:iCC]; int iSections; if (eDirection == DOWN) { printf("Segment 0x%lx => 0x%lx named \"%s\"\n", [oSegment getBaseAddress], [oSegment getUpperAddress], [oSegment commandName]); if (gyPrintSegmentsVerbose) { struct segment_command *spSegCmd = (struct segment_command *)[oSegment loadCommandAddress]; printf("\tSegment at 0x%lx, size 0x%lx, offset in file 0x%lx, size 0x%lx\n", spSegCmd->vmaddr, spSegCmd->vmsize, spSegCmd->fileoff, spSegCmd->filesize); } } if (ySections == TRUE && (iSections = [oSegment numberOfSections]) > 0) { int iC; int iInFrom, iInTo, iInIncr; if (eDirection == UP) { iInFrom = iSections - 1; iInTo = 0; iInIncr = -1; } else { iInFrom = 0; iInTo = iSections; iInIncr = 1; } for (iC = iInFrom; eDirection == UP ? iC >= iInTo : iC < iInTo; iC += iInIncr) { struct section *sect = [oSegment getSection:iC]; printf("\t%s in seg %s - 0x%lx, %lu bytes\n", sect->sectname, sect->segname, sect->addr, sect->size); } } if (eDirection == UP) { printf("Segment 0x%lx => 0x%lx named \"%s\"\n", [oSegment getBaseAddress], [oSegment getUpperAddress], [oSegment commandName]); if (gyPrintSegmentsVerbose) { struct segment_command *spSegCmd = (struct segment_command *)[oSegment loadCommandAddress]; printf("\tSegment at 0x%lx, size 0x%lx, offset in file 0x%lx, size 0x%lx\n", spSegCmd->vmaddr, spSegCmd->vmsize, spSegCmd->fileoff, spSegCmd->filesize); } } } return; } void usage(char *abpProgName) { fprintf(stderr, "Usage: %s <options> filename\n", abpProgName); fprintf(stderr, "-t print thread info\n"); fprintf(stderr, "-s print info for sections of segments\n"); fprintf(stderr, "-v print info for sections of segments verbosely\n"); fprintf(stderr, "-l print info for segments of shared libraries used\n"); } extern char *optarg; extern int optind; void do_cmd_line(int ac, char **av) { int iOption; while ((iOption = getopt(ac, av, "vdtsl")) != EOF) switch (iOption) { case 't': gyPrintThreads = TRUE; break; case 's': gyPrintSections = TRUE; break; case 'l': gyPrintLibraries = TRUE; break; case 'v': gyPrintSegmentsVerbose = TRUE; break; case 'd': geDir = DOWN; break; default: usage(*av); exit(9); break; } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.