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.