home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.mdf / Apps / DevTools / MachOViewer / Source / LoadCommand.m < prev    next >
Encoding:
Text File  |  1994-05-28  |  11.8 KB  |  638 lines

  1. #import <LoadCommand.h>
  2. /*
  3.  * $Log:    LoadCommand.m,v $
  4. Revision 1.12  94/05/28  16:17:05  ediger
  5. added LoadCommand -getUpperAddress and - (struct load_command *)loadCommandAddress
  6.  
  7. Revision 1.11  94/01/30  16:25:39  ediger
  8. added working version of -(unsigned long)pc method
  9.  
  10. Revision 1.10  93/12/28  23:09:05  ediger
  11. removed printfs for memory leak checking.
  12.  
  13. Revision 1.9  93/12/28  23:07:40  ediger
  14. Fixed memory leak caused by sections instance var of SegmentCommand
  15. subclass not getting freed.  overrode -free method for that subclass.
  16. Left in the debug statements
  17.  
  18. Revision 1.8  93/12/08  00:52:12  ediger
  19. added some assert()s in accordance with new ideology
  20.  
  21. Revision 1.7  93/12/02  00:45:36  ediger
  22. fixed a renamed method (initFromFile: becomes initFromFileNamed:)
  23.  
  24. Revision 1.6  93/10/31  21:36:40  ediger
  25. changed initialization of new LoadCommand object from 'new'
  26. to 'alloc] init]'.
  27.  
  28. Revision 1.3  93/10/28  00:07:08  ediger
  29. correct a few typos, add better commentary
  30.  
  31. Revision 1.2  93/10/27  23:43:04  ediger
  32. changed to one subclass per type of load command
  33.  
  34.  */
  35.  
  36. @implementation LoadCommand
  37.  
  38. static char rcsident[] = "@(#) $Id: LoadCommand.m,v 1.12 94/05/28 16:17:05 ediger Exp Locker: ediger $";
  39.  
  40. //M+    LoadCommand +new
  41. //M-
  42. + new
  43. {
  44.     LoadCommand *oNew = [[LoadCommand alloc] init];
  45.     assert(oNew != NULL);
  46.     return oNew;
  47. }
  48.  
  49. //M+    LoadCommand +new:
  50. //        Accounts for cheesy polymorphism of Mach-O load commands.
  51. //        Each of them begins with a struct load_command, but
  52. //        a variable amount of stuff follows (and subsumes)
  53. //        each struct load_command.
  54. //M-
  55. + new: (caddr_t)loadCommandAddress;
  56. {
  57.     id oNew = Nil;
  58.     struct load_command *lc = (struct load_command *)loadCommandAddress;
  59.  
  60.     assert(NULL != loadCommandAddress);
  61.  
  62.     switch (lc->cmd)
  63.     {
  64.     case LC_SEGMENT:
  65.         oNew = [[SegmentCommand alloc] init];
  66.         break;
  67.     case LC_IDFVMLIB:
  68.         oNew = [[IdFVMLibCommand alloc] init];
  69.         break;
  70.     case LC_LOADFVMLIB:
  71.         oNew = [[LoadFVMLibCommand alloc] init];
  72.         break;
  73.     case LC_FVMFILE:
  74.         oNew = [[FVMFileCommand alloc] init];
  75.         break;
  76.     case LC_SYMTAB:
  77.         oNew = [[SymTabCommand alloc] init];
  78.         break;
  79.     case LC_SYMSEG:
  80.         oNew = [[SymSegCommand alloc] init];
  81.         break;
  82.     case LC_THREAD:
  83.         oNew = [[ThreadCommand alloc] init];
  84.         break;
  85.     case LC_UNIXTHREAD:
  86.         oNew = [[UnixThreadCommand alloc] init];
  87.         break;
  88.     case LC_IDENT:
  89.         oNew = [[IdentCommand alloc] init];
  90.         break;
  91.     default:
  92.         oNew = [[LoadCommand alloc] init];
  93.         break;
  94.     }
  95.  
  96.     assert(Nil != oNew);
  97.  
  98.     [oNew setLoadCommand:loadCommandAddress];
  99.  
  100.     if (lc->cmd == LC_SEGMENT)
  101.         [oNew fillSections];
  102.  
  103.     return oNew;
  104. }
  105.  
  106. //M+    LoadCommand -init
  107. // Assumes that "self" is already allocated.
  108. //M-
  109. - init
  110. {
  111.     [super init];
  112.     loadCommand = NULL;
  113.     mapped = FALSE;
  114.     otherFile = FALSE;
  115.     return self;
  116. }
  117.  
  118. //M+    LoadCommand -free
  119. //M-
  120. - free
  121. {
  122.     [super free];
  123.     return self;
  124. }
  125.  
  126. //M+    LoadCommand -setSegmentCommand
  127. //M-
  128. - setLoadCommand: (caddr_t)loadCommandAddress;
  129. {
  130.     assert(loadCommandAddress != NULL);
  131.     loadCommand = (struct load_command *)loadCommandAddress;
  132.     return self;
  133. }
  134.  
  135. //M+    LoadCommand -isMapped
  136. //        Does the object represent a memory-mapped piece
  137. //        of the file?  Probably not.
  138. //M-
  139. - (BOOL)isMapped
  140. {
  141.     return mapped;
  142. }
  143.  
  144. //M+    LoadCommand -isThread
  145. //        Does the object represent a thread of some sort.
  146. //        of the file?  Again, Probably not.
  147. //M-
  148. - (BOOL)isThread
  149. {
  150.     return FALSE;
  151. }
  152.  
  153. //M+    LoadCommand -representsMappedFile
  154. //        Does the object represent a load command
  155. //        that would end up causing some other file
  156. //        to be memory-mapped into the task's address
  157. //        space?
  158. //M-
  159. - (BOOL)representsMappedFile
  160. {
  161.     return otherFile;
  162. }
  163.  
  164.  
  165. //M+    LoadCommand -getBaseAddress
  166. //M-
  167. - (unsigned long)getBaseAddress
  168. {
  169.     return -1;
  170. }
  171.  
  172. //M+    LoadCommand -getUpperAddress
  173. //M-
  174. - (unsigned long)getUpperAddress
  175. {
  176.     return -1;
  177. }
  178.  
  179. //M+    LoadCommand -(unsigned long)commandSize
  180. //M-
  181. - (unsigned long)commandSize
  182. {
  183.     return loadCommand->cmdsize;
  184. }
  185.  
  186. //M+    LoadCommand -(char *)commandName
  187. //M-
  188. - (char *)commandName
  189. {
  190.     return "load command";
  191. }
  192.  
  193. //M+    LoadCommand - (int)numberOfSections
  194. //        Only struct segment_commands have sections,
  195. //        but it's handy to use this as a flag.
  196. //M-
  197. - (int)numberOfSections
  198. {
  199.     return 0;
  200. }
  201.  
  202. //M+    LoadCommand -struct load_command *)loadCommandAddress
  203. //M-
  204. - (struct load_command *)loadCommandAddress
  205. {
  206.     return loadCommand;
  207. }
  208.  
  209. @end
  210.  
  211.  
  212. @implementation SegmentCommand
  213.  
  214. //M+    SegmentCommand -init
  215. //M-
  216. - init
  217. {
  218.     [super init];
  219.     sections       = NULL;
  220.     segmentCommand = NULL;
  221.     mapped         = TRUE;  // struct segment_commands do map
  222.     return self;
  223. }
  224.  
  225. //M+    SegmentCommand -free
  226. //        Had to override so as to free sections instance var
  227. //M-
  228. - free
  229. {
  230.     if (NULL != sections)
  231.         free(sections);
  232.     [super free];
  233.     return self;
  234. }
  235.  
  236. //M+    SegmentCommand -fillSections
  237. //        Create a quick-to-access array of pointers to
  238. //        the struct sections in this load command.
  239. //M-
  240. - fillSections
  241. {
  242.     assert(segmentCommand != NULL);
  243.     sections
  244.          = (struct section **)malloc(
  245.             sizeof(struct section)*segmentCommand->nsects);
  246.  
  247.     if (sections != NULL)
  248.     {    int iCC;
  249.         struct section *spSection
  250.              = (struct section *)((unsigned long)segmentCommand
  251.                  + sizeof(struct segment_command));
  252.  
  253.         for (iCC = 0; iCC < segmentCommand->nsects; ++iCC)
  254.             sections[iCC] = spSection++;
  255.     }
  256.  
  257.     return self;
  258. }
  259.  
  260. //M+    SegmentCommand -getBaseAddress
  261. //M-
  262. - (unsigned long)getBaseAddress
  263. {
  264.     assert(segmentCommand != NULL);
  265.     return segmentCommand->vmaddr;
  266. }
  267.  
  268. //M+    SegmentCommand -getUpperAddress
  269. //M-
  270. - (unsigned long)getUpperAddress
  271. {
  272.     assert(segmentCommand != NULL);
  273.     return segmentCommand->vmaddr + segmentCommand->vmsize;
  274. }
  275.  
  276. //M+    SegmentCommand -setLoadCommand
  277. //M-
  278. - setLoadCommand: (caddr_t)loadCommandAddress;
  279. {
  280.     assert(loadCommandAddress != NULL);
  281.     [super setLoadCommand: loadCommandAddress];
  282.     segmentCommand = (struct segment_command *)loadCommandAddress;
  283.     return self;
  284. }
  285.  
  286.  
  287. //M+    SegmentCommand -(char *)commandName
  288. //M-
  289. - (char *)commandName
  290. {
  291.     assert(segmentCommand != NULL);
  292.     if (segmentCommand->segname == NULL || strlen(segmentCommand->segname) <= 0)
  293.         return "LC_SEGMENT";  // relocatable object files?
  294.     else
  295.         return segmentCommand->segname;
  296. }
  297.  
  298. //M+    SegmentCommand -numberOfSections
  299. //M-
  300. - (int)numberOfSections
  301. {
  302.     assert(segmentCommand != NULL);
  303.     return segmentCommand->nsects;
  304. }
  305.  
  306.  
  307. //M+    SegmentCommand -(struct section *)getSection:(int)sectionNumber
  308. //M-
  309. - (struct section *)getSection:(int)sectionNumber
  310. {
  311.     assert(segmentCommand != NULL);
  312.     if (sections != NULL && sectionNumber < segmentCommand->nsects)
  313.         return sections[sectionNumber];
  314.  
  315.     return NULL;
  316. }
  317.  
  318. @end
  319.  
  320. @implementation LoadFVMLibCommand
  321.  
  322. //M+    LoadFVMLibCommand -init
  323. //M-
  324. - init
  325. {
  326.     [super init];
  327.     fvmlibCommand = NULL;
  328.     mapped = FALSE;
  329.     otherFile = TRUE;
  330.     theOtherFile = Nil;
  331.     return self;
  332. }
  333.  
  334. //M+    LoadFVMLibCommand -getBaseAddress
  335. //M-
  336. - (unsigned long)getBaseAddress
  337. {
  338.     assert(fvmlibCommand != NULL);
  339.     return fvmlibCommand->fvmlib.header_addr;
  340. }
  341.  
  342. //M+    LoadFVMLibCommand -setLoadCommand
  343. //M-
  344. - setLoadCommand: (caddr_t)loadCommandAddress;
  345. {
  346.     assert(loadCommandAddress != NULL);
  347.     [super setLoadCommand: loadCommandAddress];
  348.     fvmlibCommand = (struct fvmlib_command *)loadCommandAddress;
  349.     return self;
  350. }
  351.  
  352. //M+    LoadFVMLibCommand -(char *)commandName
  353. //M-
  354. - (char *)commandName
  355. {
  356.     assert(fvmlibCommand != NULL);
  357.     return (char *)((unsigned long)fvmlibCommand
  358.             + fvmlibCommand->fvmlib.name.offset);
  359. }
  360.  
  361. //M+    LoadFVMLibCommand -loadOtherFile
  362. //M-
  363. - loadOtherFile
  364. {
  365.     if (fvmlibCommand != NULL)
  366.     {    theOtherFile = [[MachOFile alloc] init];
  367.         [theOtherFile fillFromFileNamed:[self commandName]];
  368.     }
  369.  
  370.     return self;
  371. }
  372.  
  373. //M+    LoadFVMLibCommand -otherFile
  374. //M-
  375. - otherFile
  376. {
  377.     return theOtherFile;
  378. }
  379.  
  380. //M+    LoadFVMLibCommand -free
  381. //        Had to override this to ditch any other mapped files. 
  382. //M-
  383. - free
  384. {
  385.     if (theOtherFile != Nil)
  386.         [theOtherFile free];
  387.  
  388.     [super free];
  389.  
  390.     return self;
  391. }
  392.  
  393. @end
  394.  
  395. @implementation IdFVMLibCommand
  396.  
  397. //M+    IdFVMLibCommand -init
  398. //M-
  399. - init
  400. {
  401.     [super init];
  402.     namebuf = NULL;
  403.     mapped = FALSE;
  404.     return self;
  405. }
  406.  
  407. //M+    IdFVMLibCommand -commandName
  408. //        This is cheesy, but it separates the ident sections from
  409. //        the mapped sections.
  410. //M-
  411. - (char *)commandName
  412. {
  413.     char *filename;
  414. #define IDENT_PHRASE "FVM Lib ident: "
  415.  
  416.     if (namebuf != NULL)
  417.         free(namebuf);
  418.  
  419.     filename = [super commandName];
  420.  
  421.     namebuf = malloc(strlen(filename) + strlen(IDENT_PHRASE) + 1);
  422.  
  423.     if (namebuf != NULL)
  424.         strcat(strcpy(namebuf, IDENT_PHRASE), filename);
  425.  
  426.     return namebuf;
  427. }
  428.  
  429. //M+    IdFVMLibCommand -free
  430. //        Possibly this object has allocated some memory for its
  431. //        own purposes.  Free it.
  432. //M-
  433. - free
  434. {
  435.     if (namebuf != NULL)
  436.         free(namebuf);
  437.  
  438.     [super free];
  439.  
  440.     return self;
  441. }
  442.  
  443. @end
  444.  
  445. @implementation FVMFileCommand
  446.  
  447. //M+    FVMFileCommand -init
  448. /*
  449.  * The fvmfile_command contains a reference to a file to be loaded at the
  450.  * specified virtual address.  (Presently, this command is reserved for NeXT
  451.  * internal use.  The kernel ignores this command when loading a program into
  452.  * memory).
  453.  */
  454. //M-
  455. - init
  456. {
  457.     [super init];
  458.     mapped = TRUE;
  459.     return self;
  460. }
  461.  
  462. //M+    FVMFileCommand -getBaseAddress
  463. //M-
  464. - (unsigned long)getBaseAddress
  465. {
  466.     assert(fvmFileCommand != NULL);
  467.     return fvmFileCommand->header_addr;  // address of FVM file's header
  468. }
  469.  
  470. //M+    FVMFileCommand -setLoadCommand
  471. //M-
  472. - setLoadCommand: (caddr_t)loadCommandAddress;
  473. {
  474.     assert(loadCommandAddress != NULL);
  475.     [super setLoadCommand: loadCommandAddress];
  476.     fvmFileCommand = (struct fvmfile_command *)loadCommandAddress;
  477.     return self;
  478. }
  479.  
  480. //M+    FVMFileCommand -(char *)commandName
  481. //M-
  482. - (char *)commandName
  483. {
  484.     assert(fvmFileCommand != NULL);
  485.     return (char *)((unsigned long)fvmFileCommand
  486.             + fvmFileCommand->name.offset);
  487. }
  488.  
  489. @end
  490.  
  491. @implementation SymTabCommand
  492.  
  493. //M+    SymTabCommand -init
  494. //M-
  495. - init
  496. {
  497.     [super init];
  498.     mapped = FALSE;
  499.     return self;
  500. }
  501.  
  502. //M+    SymTabCommand -setLoadCommand
  503. //M-
  504. - setLoadCommand: (caddr_t)loadCommandAddress;
  505. {
  506.     [super setLoadCommand: loadCommandAddress];
  507.     symTabCommand = (struct symtab_command *)loadCommandAddress;
  508.     return self;
  509. }
  510.  
  511. //M+    SymTabCommand -(char *)commandName
  512. //M-
  513. - (char *)commandName
  514. {
  515.     return "LC_SYMTAB";
  516. }
  517. @end
  518.  
  519. @implementation SymSegCommand
  520.  
  521. //M+    SymSegCommand -init
  522. //M-
  523. - init
  524. {
  525.     [super init];
  526.     mapped = FALSE;
  527.     return self;
  528. }
  529.  
  530. //M+    SymSegCommand -setLoadCommand
  531. //M-
  532. - setLoadCommand: (caddr_t)loadCommandAddress;
  533. {
  534.     assert(loadCommandAddress != NULL);
  535.     [super setLoadCommand: loadCommandAddress];
  536.     symSegCommand = (struct symseg_command *)loadCommandAddress;
  537.     return self;
  538. }
  539.  
  540. //M+    SymSegCommand -(char *)commandName
  541. //M-
  542. - (char *)commandName
  543. {
  544.     return "LC_SYMSEG";
  545. }
  546. @end
  547.  
  548. @implementation ThreadCommand
  549. //M+    ThreadCommand +new
  550.  
  551. //M+    ThreadCommand -init
  552. //M-
  553. - init
  554. {
  555.     [super init];
  556.     mapped = FALSE;
  557.     return self;
  558. }
  559.  
  560. //M+    ThreadCommand -setLoadCommand
  561. //M-
  562. - setLoadCommand: (caddr_t)loadCommandAddress;
  563. {
  564.     assert(loadCommandAddress != NULL);
  565.     [super setLoadCommand: loadCommandAddress];
  566.     threadCommand = (struct thread_command *)loadCommandAddress;
  567.     return self;
  568. }
  569.  
  570. //M+    ThreadCommand -(char *)commandName
  571. //M-
  572. - (char *)commandName
  573. {
  574.     return "LC_THREAD";
  575. }
  576.  
  577. //M+    ThreadCommand -(BOOL)isThread
  578. //M-
  579. - (BOOL)isThread
  580. {
  581.     return TRUE;
  582. }
  583.  
  584. - (unsigned long)pc
  585. {
  586.     struct thread_state_flavor *spThreadStateFlavor;
  587.     unsigned long               lNextAddress;
  588.     unsigned int irPC = -1;
  589.  
  590.     spThreadStateFlavor =
  591.      (struct thread_state_flavor *)((unsigned long)threadCommand
  592.         + sizeof(struct thread_command));
  593.  
  594.     lNextAddress = (unsigned long)spThreadStateFlavor
  595.         + sizeof(struct thread_state_flavor);
  596.  
  597.     switch(spThreadStateFlavor->flavor)
  598.     {
  599.     case M68K_THREAD_STATE_REGS:
  600.         irPC = ((struct m68k_thread_state_regs *)lNextAddress)->pc;
  601.         break;
  602.     case M68K_THREAD_STATE_68882:
  603.         irPC = ((struct m68k_thread_state_68882 *)lNextAddress)->iar;
  604.         break;
  605.     case M68K_THREAD_STATE_USER_REG:
  606.         irPC = ((struct m68k_thread_state_user_reg *)lNextAddress)->user_reg;
  607.         break;
  608.     case i386_THREAD_STATE:
  609.         irPC = ((i386_thread_state_t *)lNextAddress)->eip;
  610.         break;
  611.     }
  612.      
  613.     return irPC;
  614. }
  615.  
  616. @end
  617.  
  618. @implementation UnixThreadCommand
  619.  
  620. //M+    UnixThreadCommand -(char *)commandName
  621. //M-
  622. - (char *)commandName
  623. {
  624.     return "LC_UNIXTHREAD";
  625. }
  626.  
  627. @end
  628.  
  629. @implementation IdentCommand
  630.  
  631. //M+    IdentCommand -(char *)commandName
  632. //M-
  633. - (char *)commandName
  634. {
  635.     return "LC_IDENT";
  636. }
  637. @end
  638.