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.