This is LoadCommand.m in view mode; [Download] [Up]
#import <LoadCommand.h> /* * $Log: LoadCommand.m,v $ Revision 1.12 94/05/28 16:17:05 ediger added LoadCommand -getUpperAddress and - (struct load_command *)loadCommandAddress Revision 1.11 94/01/30 16:25:39 ediger added working version of -(unsigned long)pc method Revision 1.10 93/12/28 23:09:05 ediger removed printfs for memory leak checking. Revision 1.9 93/12/28 23:07:40 ediger Fixed memory leak caused by sections instance var of SegmentCommand subclass not getting freed. overrode -free method for that subclass. Left in the debug statements Revision 1.8 93/12/08 00:52:12 ediger added some assert()s in accordance with new ideology Revision 1.7 93/12/02 00:45:36 ediger fixed a renamed method (initFromFile: becomes initFromFileNamed:) Revision 1.6 93/10/31 21:36:40 ediger changed initialization of new LoadCommand object from 'new' to 'alloc] init]'. Revision 1.3 93/10/28 00:07:08 ediger correct a few typos, add better commentary Revision 1.2 93/10/27 23:43:04 ediger changed to one subclass per type of load command */ @implementation LoadCommand static char rcsident[] = "@(#) $Id: LoadCommand.m,v 1.12 94/05/28 16:17:05 ediger Exp Locker: ediger $"; //M+ LoadCommand +new //M- + new { LoadCommand *oNew = [[LoadCommand alloc] init]; assert(oNew != NULL); return oNew; } //M+ LoadCommand +new: // Accounts for cheesy polymorphism of Mach-O load commands. // Each of them begins with a struct load_command, but // a variable amount of stuff follows (and subsumes) // each struct load_command. //M- + new: (caddr_t)loadCommandAddress; { id oNew = Nil; struct load_command *lc = (struct load_command *)loadCommandAddress; assert(NULL != loadCommandAddress); switch (lc->cmd) { case LC_SEGMENT: oNew = [[SegmentCommand alloc] init]; break; case LC_IDFVMLIB: oNew = [[IdFVMLibCommand alloc] init]; break; case LC_LOADFVMLIB: oNew = [[LoadFVMLibCommand alloc] init]; break; case LC_FVMFILE: oNew = [[FVMFileCommand alloc] init]; break; case LC_SYMTAB: oNew = [[SymTabCommand alloc] init]; break; case LC_SYMSEG: oNew = [[SymSegCommand alloc] init]; break; case LC_THREAD: oNew = [[ThreadCommand alloc] init]; break; case LC_UNIXTHREAD: oNew = [[UnixThreadCommand alloc] init]; break; case LC_IDENT: oNew = [[IdentCommand alloc] init]; break; default: oNew = [[LoadCommand alloc] init]; break; } assert(Nil != oNew); [oNew setLoadCommand:loadCommandAddress]; if (lc->cmd == LC_SEGMENT) [oNew fillSections]; return oNew; } //M+ LoadCommand -init // Assumes that "self" is already allocated. //M- - init { [super init]; loadCommand = NULL; mapped = FALSE; otherFile = FALSE; return self; } //M+ LoadCommand -free //M- - free { [super free]; return self; } //M+ LoadCommand -setSegmentCommand //M- - setLoadCommand: (caddr_t)loadCommandAddress; { assert(loadCommandAddress != NULL); loadCommand = (struct load_command *)loadCommandAddress; return self; } //M+ LoadCommand -isMapped // Does the object represent a memory-mapped piece // of the file? Probably not. //M- - (BOOL)isMapped { return mapped; } //M+ LoadCommand -isThread // Does the object represent a thread of some sort. // of the file? Again, Probably not. //M- - (BOOL)isThread { return FALSE; } //M+ LoadCommand -representsMappedFile // Does the object represent a load command // that would end up causing some other file // to be memory-mapped into the task's address // space? //M- - (BOOL)representsMappedFile { return otherFile; } //M+ LoadCommand -getBaseAddress //M- - (unsigned long)getBaseAddress { return -1; } //M+ LoadCommand -getUpperAddress //M- - (unsigned long)getUpperAddress { return -1; } //M+ LoadCommand -(unsigned long)commandSize //M- - (unsigned long)commandSize { return loadCommand->cmdsize; } //M+ LoadCommand -(char *)commandName //M- - (char *)commandName { return "load command"; } //M+ LoadCommand - (int)numberOfSections // Only struct segment_commands have sections, // but it's handy to use this as a flag. //M- - (int)numberOfSections { return 0; } //M+ LoadCommand -struct load_command *)loadCommandAddress //M- - (struct load_command *)loadCommandAddress { return loadCommand; } @end @implementation SegmentCommand //M+ SegmentCommand -init //M- - init { [super init]; sections = NULL; segmentCommand = NULL; mapped = TRUE; // struct segment_commands do map return self; } //M+ SegmentCommand -free // Had to override so as to free sections instance var //M- - free { if (NULL != sections) free(sections); [super free]; return self; } //M+ SegmentCommand -fillSections // Create a quick-to-access array of pointers to // the struct sections in this load command. //M- - fillSections { assert(segmentCommand != NULL); sections = (struct section **)malloc( sizeof(struct section)*segmentCommand->nsects); if (sections != NULL) { int iCC; struct section *spSection = (struct section *)((unsigned long)segmentCommand + sizeof(struct segment_command)); for (iCC = 0; iCC < segmentCommand->nsects; ++iCC) sections[iCC] = spSection++; } return self; } //M+ SegmentCommand -getBaseAddress //M- - (unsigned long)getBaseAddress { assert(segmentCommand != NULL); return segmentCommand->vmaddr; } //M+ SegmentCommand -getUpperAddress //M- - (unsigned long)getUpperAddress { assert(segmentCommand != NULL); return segmentCommand->vmaddr + segmentCommand->vmsize; } //M+ SegmentCommand -setLoadCommand //M- - setLoadCommand: (caddr_t)loadCommandAddress; { assert(loadCommandAddress != NULL); [super setLoadCommand: loadCommandAddress]; segmentCommand = (struct segment_command *)loadCommandAddress; return self; } //M+ SegmentCommand -(char *)commandName //M- - (char *)commandName { assert(segmentCommand != NULL); if (segmentCommand->segname == NULL || strlen(segmentCommand->segname) <= 0) return "LC_SEGMENT"; // relocatable object files? else return segmentCommand->segname; } //M+ SegmentCommand -numberOfSections //M- - (int)numberOfSections { assert(segmentCommand != NULL); return segmentCommand->nsects; } //M+ SegmentCommand -(struct section *)getSection:(int)sectionNumber //M- - (struct section *)getSection:(int)sectionNumber { assert(segmentCommand != NULL); if (sections != NULL && sectionNumber < segmentCommand->nsects) return sections[sectionNumber]; return NULL; } @end @implementation LoadFVMLibCommand //M+ LoadFVMLibCommand -init //M- - init { [super init]; fvmlibCommand = NULL; mapped = FALSE; otherFile = TRUE; theOtherFile = Nil; return self; } //M+ LoadFVMLibCommand -getBaseAddress //M- - (unsigned long)getBaseAddress { assert(fvmlibCommand != NULL); return fvmlibCommand->fvmlib.header_addr; } //M+ LoadFVMLibCommand -setLoadCommand //M- - setLoadCommand: (caddr_t)loadCommandAddress; { assert(loadCommandAddress != NULL); [super setLoadCommand: loadCommandAddress]; fvmlibCommand = (struct fvmlib_command *)loadCommandAddress; return self; } //M+ LoadFVMLibCommand -(char *)commandName //M- - (char *)commandName { assert(fvmlibCommand != NULL); return (char *)((unsigned long)fvmlibCommand + fvmlibCommand->fvmlib.name.offset); } //M+ LoadFVMLibCommand -loadOtherFile //M- - loadOtherFile { if (fvmlibCommand != NULL) { theOtherFile = [[MachOFile alloc] init]; [theOtherFile fillFromFileNamed:[self commandName]]; } return self; } //M+ LoadFVMLibCommand -otherFile //M- - otherFile { return theOtherFile; } //M+ LoadFVMLibCommand -free // Had to override this to ditch any other mapped files. //M- - free { if (theOtherFile != Nil) [theOtherFile free]; [super free]; return self; } @end @implementation IdFVMLibCommand //M+ IdFVMLibCommand -init //M- - init { [super init]; namebuf = NULL; mapped = FALSE; return self; } //M+ IdFVMLibCommand -commandName // This is cheesy, but it separates the ident sections from // the mapped sections. //M- - (char *)commandName { char *filename; #define IDENT_PHRASE "FVM Lib ident: " if (namebuf != NULL) free(namebuf); filename = [super commandName]; namebuf = malloc(strlen(filename) + strlen(IDENT_PHRASE) + 1); if (namebuf != NULL) strcat(strcpy(namebuf, IDENT_PHRASE), filename); return namebuf; } //M+ IdFVMLibCommand -free // Possibly this object has allocated some memory for its // own purposes. Free it. //M- - free { if (namebuf != NULL) free(namebuf); [super free]; return self; } @end @implementation FVMFileCommand //M+ FVMFileCommand -init /* * The fvmfile_command contains a reference to a file to be loaded at the * specified virtual address. (Presently, this command is reserved for NeXT * internal use. The kernel ignores this command when loading a program into * memory). */ //M- - init { [super init]; mapped = TRUE; return self; } //M+ FVMFileCommand -getBaseAddress //M- - (unsigned long)getBaseAddress { assert(fvmFileCommand != NULL); return fvmFileCommand->header_addr; // address of FVM file's header } //M+ FVMFileCommand -setLoadCommand //M- - setLoadCommand: (caddr_t)loadCommandAddress; { assert(loadCommandAddress != NULL); [super setLoadCommand: loadCommandAddress]; fvmFileCommand = (struct fvmfile_command *)loadCommandAddress; return self; } //M+ FVMFileCommand -(char *)commandName //M- - (char *)commandName { assert(fvmFileCommand != NULL); return (char *)((unsigned long)fvmFileCommand + fvmFileCommand->name.offset); } @end @implementation SymTabCommand //M+ SymTabCommand -init //M- - init { [super init]; mapped = FALSE; return self; } //M+ SymTabCommand -setLoadCommand //M- - setLoadCommand: (caddr_t)loadCommandAddress; { [super setLoadCommand: loadCommandAddress]; symTabCommand = (struct symtab_command *)loadCommandAddress; return self; } //M+ SymTabCommand -(char *)commandName //M- - (char *)commandName { return "LC_SYMTAB"; } @end @implementation SymSegCommand //M+ SymSegCommand -init //M- - init { [super init]; mapped = FALSE; return self; } //M+ SymSegCommand -setLoadCommand //M- - setLoadCommand: (caddr_t)loadCommandAddress; { assert(loadCommandAddress != NULL); [super setLoadCommand: loadCommandAddress]; symSegCommand = (struct symseg_command *)loadCommandAddress; return self; } //M+ SymSegCommand -(char *)commandName //M- - (char *)commandName { return "LC_SYMSEG"; } @end @implementation ThreadCommand //M+ ThreadCommand +new //M+ ThreadCommand -init //M- - init { [super init]; mapped = FALSE; return self; } //M+ ThreadCommand -setLoadCommand //M- - setLoadCommand: (caddr_t)loadCommandAddress; { assert(loadCommandAddress != NULL); [super setLoadCommand: loadCommandAddress]; threadCommand = (struct thread_command *)loadCommandAddress; return self; } //M+ ThreadCommand -(char *)commandName //M- - (char *)commandName { return "LC_THREAD"; } //M+ ThreadCommand -(BOOL)isThread //M- - (BOOL)isThread { return TRUE; } - (unsigned long)pc { struct thread_state_flavor *spThreadStateFlavor; unsigned long lNextAddress; unsigned int irPC = -1; spThreadStateFlavor = (struct thread_state_flavor *)((unsigned long)threadCommand + sizeof(struct thread_command)); lNextAddress = (unsigned long)spThreadStateFlavor + sizeof(struct thread_state_flavor); 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; } @end @implementation UnixThreadCommand //M+ UnixThreadCommand -(char *)commandName //M- - (char *)commandName { return "LC_UNIXTHREAD"; } @end @implementation IdentCommand //M+ IdentCommand -(char *)commandName //M- - (char *)commandName { return "LC_IDENT"; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.