home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.mdf / Apps / DevTools / MachOViewer / Source / RCS / MachOFile.m,v < prev    next >
Encoding:
Text File  |  1994-05-03  |  22.2 KB  |  1,137 lines

  1. head     1.11;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ediger:1.11;
  6. comment  @@;
  7.  
  8.  
  9. 1.11
  10. date     94.05.04.11.19.29;  author ediger;  state Exp;
  11. branches ;
  12. next     1.10;
  13.  
  14. 1.10
  15. date     94.05.01.17.31.33;  author ediger;  state Exp;
  16. branches ;
  17. next     1.9;
  18.  
  19. 1.9
  20. date     94.02.07.21.36.27;  author ediger;  state Exp;
  21. branches ;
  22. next     1.8;
  23.  
  24. 1.8
  25. date     94.01.30.16.26.59;  author ediger;  state Exp;
  26. branches ;
  27. next     1.7;
  28.  
  29. 1.7
  30. date     93.12.20.20.49.20;  author ediger;  state Exp;
  31. branches ;
  32. next     1.6;
  33.  
  34. 1.6
  35. date     93.12.18.22.46.51;  author ediger;  state Exp;
  36. branches ;
  37. next     1.5;
  38.  
  39. 1.5
  40. date     93.12.07.23.30.31;  author ediger;  state Exp;
  41. branches ;
  42. next     1.4;
  43.  
  44. 1.4
  45. date     93.12.02.00.44.23;  author ediger;  state Exp;
  46. branches ;
  47. next     1.3;
  48.  
  49. 1.3
  50. date     93.10.31.21.32.13;  author ediger;  state Exp;
  51. branches ;
  52. next     1.2;
  53.  
  54. 1.2
  55. date     93.10.27.23.44.09;  author ediger;  state Exp;
  56. branches ;
  57. next     1.1;
  58.  
  59. 1.1
  60. date     93.10.25.17.59.44;  author ediger;  state Exp;
  61. branches ;
  62. next     ;
  63.  
  64.  
  65. desc
  66. @definition/implementation of MachOFile object
  67. @
  68.  
  69.  
  70. 1.11
  71. log
  72. @support for finding which segment a thread's pc is in
  73. @
  74. text
  75. @/*
  76.  * $Log:    MachOFile.m,v $
  77. Revision 1.10  94/05/01  17:31:33  ediger
  78. added - (struct section *)sectionNamed:: method
  79.  
  80. Revision 1.9  94/02/07  21:36:27  ediger
  81. Use memory-mapped file object, add segment name display, change
  82. to using a matrix of buttons for choice of what to display.
  83.  
  84. Revision 1.8  94/01/30  16:26:59  ediger
  85. add threadList List instance var to hold all thread_command load commands
  86. seperately.
  87.  
  88. Revision 1.7  93/12/20  20:49:20  ediger
  89. better method of transferring load commands from a LoadFVMLibCommand
  90. LoadCommand object to the current MachOFile object's mapped segment list.
  91.  
  92. Revision 1.6  93/12/18  22:46:51  ediger
  93. changed -initFromFileNamed: method to -fillFromFileNamed: to reflect
  94. a bit more accuratly its function.
  95. Changed the way that subsidiary file's mapped segments get added in
  96. to the mapped segment list.  That process didn't work the old way.
  97.  
  98. Revision 1.5  93/12/07  23:30:31  ediger
  99. added some assert()s and cpuType and cpuSubtype methods
  100.  
  101. Revision 1.4  93/12/02  00:44:23  ediger
  102. added fileType method, and a load of comments
  103.  
  104. Revision 1.3  93/10/31  21:32:13  ediger
  105. ditched the -printSegments method, had been #ifdef'ed out anyway.
  106.  
  107. Revision 1.2  93/10/27  23:44:09  ediger
  108. Definition of MachOFile object that uses LoadCommand subclasses
  109.  
  110.  */
  111. #import <MachOFile.h>
  112.  
  113. @@implementation MachOFile
  114.  
  115. static char rcsident[] = "$Id: MachOFile.m,v 1.10 94/05/01 17:31:33 ediger Exp Locker: ediger $";
  116.  
  117. //M+    -init
  118. //    PURPOSE:
  119. //    Set up a MachOFile object as much as possible without knowing
  120. //    anything about the file it is to represent.
  121. //
  122. //    EDITORIAL:
  123. //    Assumes that "self" is already allocated.
  124. //M-
  125. - init
  126. {
  127.     [super init];
  128.  
  129.     mappedSegmentList   = [SortedList alloc];
  130.     unmappedSegmentList = [List alloc];
  131.     threadList          = [List alloc];
  132.  
  133.     fileHeader    = NULL;
  134.     threadSegment = NULL;
  135.  
  136.     fileDescriptor = -1;
  137.  
  138.     mappedFileAddress = (vm_offset_t)0;
  139.  
  140.     addMappedFiles = FALSE;
  141.  
  142.     mapsFile = FALSE;
  143.  
  144.     return self;
  145. }
  146.  
  147. //M+    -free
  148. //    PURPOSE:
  149. //    Clean up after a MachOFile object as much as possible.
  150. //
  151. //    EDITORIAL:
  152. //M-
  153. - free
  154. {
  155.     if (mapsFile == TRUE && mappedFileAddress != 0)
  156.     {    kern_return_t tRet = vm_deallocate(task_self(),
  157.             (vm_address_t)mappedFileAddress, mappedFileSize);
  158.         if (tRet != KERN_SUCCESS)
  159.         {    lastErrno = 0;
  160.             lastKernReturn = tRet;
  161.         }
  162.     }
  163.  
  164.     if (fileDescriptor != -1 && close(fileDescriptor) < 0)
  165.     {    lastErrno = errno;
  166.         lastKernReturn = 0;
  167.     }
  168.  
  169.     fileDescriptor = -1;
  170.  
  171.     [[mappedSegmentList freeObjects] free];
  172.     [[unmappedSegmentList freeObjects] free];
  173.     [[threadList freeObjects] free];
  174.  
  175.     mappedSegmentList = NULL;
  176.     unmappedSegmentList = NULL;
  177.     threadList = NULL;
  178.  
  179.     if (threadSegment) free(threadSegment);
  180.     threadSegment = NULL;
  181.  
  182.     return [super free];
  183. }
  184.  
  185. // M+    -initLoadCommandLists:
  186. //    PURPOSE:
  187. //    Set up the sorted lists based on number of commands.
  188. //
  189. //    EDITORIAL:
  190. //    Overallocates.  mapped segment list _and_ unmapped segment list
  191. //    both are set up to have the total number of segments in them.
  192. // M-
  193. -initLoadCommandLists:(int)numberOfCommands
  194. {
  195.     assert(unmappedSegmentList != NULL && mappedSegmentList != NULL);
  196.  
  197.     [unmappedSegmentList initCount:numberOfCommands];
  198.     [mappedSegmentList   initCount:numberOfCommands];
  199.     [threadList initCount:1];
  200.  
  201.     [mappedSegmentList   setSortOrder:DESCENDING];
  202.     [mappedSegmentList   setKeyDataType:UNSIGNED_LONG];
  203.     [mappedSegmentList   setKeyMethod:@@selector(getBaseAddress)];
  204.  
  205.     return self;
  206. }
  207.  
  208. // M+    -addLoadCommand:
  209. //    PURPOSE:
  210. //    Stick a new load command segment into the appropriate SortedList
  211. // M-
  212. -addLoadCommand:oNewSegment
  213. {
  214.     assert(oNewSegment != Nil);
  215.  
  216.     if ([oNewSegment isMapped])
  217.         [mappedSegmentList addObject:oNewSegment];
  218.     else if ([oNewSegment isThread])
  219.         [threadList addObject:oNewSegment];
  220.     else
  221.         [unmappedSegmentList addObject:oNewSegment];
  222.     return self;
  223. }
  224.  
  225. // M+    -addLoadCommandsFrom:
  226. //    PURPOSE:
  227. //    Based on a load command that represents a subsidiary file,
  228. //    account for the load commands of that subsidiary file.
  229. // M-
  230. -addLoadCommandsFrom:oNewSegment
  231. {
  232.     id otherFile;
  233.  
  234.     assert(oNewSegment != Nil);
  235.  
  236.     otherFile = [[oNewSegment loadOtherFile] otherFile];
  237.  
  238.     assert(otherFile != Nil);
  239.  
  240.     if ([otherFile mappedSegments] > 0)
  241.     {    id oOtherFileSegment;
  242.  
  243.         // Possibly too clever use of the fact that List objects contract
  244.         // dynamically when you take an element out of them.
  245.         while (Nil != (oOtherFileSegment = [otherFile mappedSegment:0]))
  246.         {    [mappedSegmentList addObject:oOtherFileSegment];
  247.             [otherFile removeSegment:oOtherFileSegment];
  248.         }
  249.     }
  250.  
  251.     return self;
  252. }
  253.  
  254. //M+    -fillFromFileNamed:
  255. //    PURPOSE:
  256. //    Fill in a MachOFile object now that it is known what file it represents.
  257. //M-
  258. - fillFromFileNamed: (char *) filename
  259. {
  260.     assert(filename != NULL);
  261.  
  262.     if ([self mapFile:filename])
  263.     {
  264.         mapsFile = TRUE;
  265.         [self fillFromAddress:(char *)mappedFileAddress];
  266.     }
  267.  
  268.     return self;
  269. }
  270.  
  271. //M+    -fillFromAddress:
  272. //    PURPOSE:
  273. //    Fill in a MachOFile object whose header is mapped in at the
  274. //    address passed as argument.
  275. //M-
  276. - fillFromAddress: (char *) address
  277. {
  278.  
  279.     int     iCC, iSegments;
  280.     caddr_t    tAddress;
  281.  
  282.     assert(address != NULL);
  283.  
  284.     fileHeader = (struct mach_header *)address;
  285.  
  286.     // cheesy check for a legit Mach-O file
  287.     if (fileHeader->magic != MH_MAGIC)
  288.     {    [self free];
  289.         return Nil;
  290.     }
  291.  
  292.     [self initLoadCommandLists:fileHeader->ncmds];
  293.  
  294.     tAddress = (caddr_t)(fileHeader + 1);
  295.  
  296.     for (iCC = 0; iCC < fileHeader->ncmds; ++iCC)
  297.     {    id oNewSegment = [LoadCommand new:tAddress];
  298.  
  299.         tAddress += [oNewSegment commandSize];
  300.  
  301.         [self addLoadCommand:oNewSegment];
  302.  
  303.         if (addMappedFiles && [oNewSegment representsMappedFile])
  304.             [self addLoadCommandsFrom:oNewSegment];
  305.     }
  306.  
  307.     // set up array of thread number to segment number mapping.
  308.     // thread number is index, segment number is value contained in
  309.     // the array at that index.
  310.     if ([self threads])
  311.     {
  312.         threadSegment = (int *)malloc([self threads] * sizeof(int));
  313.         iSegments = [self mappedSegments];
  314.         for (iCC = [self threads] - 1; iCC > -1; --iCC)
  315.         {
  316.             unsigned long ulThreadAddr = [[self thread:iCC] pc];
  317.             int i;
  318.     
  319.             threadSegment[iCC] = -1;
  320.  
  321.             for (i = 0; i < iSegments; ++i)
  322.             {
  323.                 id oSegment = [self mappedSegment:i];
  324.     
  325.                 if ([oSegment getBaseAddress] <= ulThreadAddr
  326.                     && [oSegment getUpperAddress] >= ulThreadAddr)
  327.                 {
  328.                     threadSegment[iCC] = i;
  329.                     break;
  330.                 }
  331.             }
  332.         }
  333.     }
  334.  
  335.     return self;
  336. }
  337.  
  338. //M+    -(int)mapFile:
  339. //    PURPOSE:
  340. //    Perform stuff to memory map the Mach-O file under consideration.
  341. //
  342. //    RETURN:
  343. //    1 on success, 0 on failure.
  344. //
  345. //    EDITORIAL:
  346. //    Apparently you must vm_deallocate() the stuff mapped in by map_fd().
  347. //    Call -free on this object or else.
  348. //M-
  349. - (int)mapFile: (char *)filename
  350. {
  351.     struct stat sStat;
  352.     int         irSuccess = 0;
  353.  
  354.     assert(filename != NULL);
  355.  
  356.     if (stat(filename, &sStat) < 0) {
  357.         lastErrno = errno;
  358.         lastKernReturn = 0;
  359.     } else if ((fileDescriptor = open(filename, O_RDONLY)) < 0) {
  360.         lastErrno = errno;
  361.         lastKernReturn = 0;
  362.     } else {
  363.         kern_return_t tRet;
  364.  
  365.         tRet = map_fd(fileDescriptor, (vm_offset_t)0, &mappedFileAddress, TRUE,
  366.             (size_t)sStat.st_size);
  367.  
  368.         if (tRet != KERN_SUCCESS) {
  369.             lastErrno = 0;
  370.             lastKernReturn = tRet;
  371.         } else if ((vm_address_t)mappedFileAddress != (vm_address_t)NULL) {
  372.  
  373.             struct mach_header *mhdr = (struct mach_header *)mappedFileAddress;
  374.             mappedFileSize = mhdr->sizeofcmds;
  375.  
  376.             tRet = vm_deallocate(task_self(),
  377.                 (vm_address_t)mappedFileAddress, (size_t)sStat.st_size);
  378.             if (tRet != KERN_SUCCESS) {
  379.                 lastErrno = 0;
  380.                 lastKernReturn = tRet;
  381.             } else {
  382.  
  383.                 tRet = map_fd(fileDescriptor, (vm_offset_t)0,
  384.                     &mappedFileAddress, TRUE,
  385.                     (size_t)mappedFileSize);
  386.  
  387.                 if (tRet != KERN_SUCCESS) {
  388.                     lastErrno = 0;
  389.                     lastKernReturn = tRet;
  390.                 } else
  391.                     irSuccess = 1;
  392.             }
  393.         }
  394.     }
  395.  
  396.     return irSuccess;
  397. }
  398.  
  399. //M+    -mappedSegments
  400. //    PURPOSE:
  401. //    Return number of load commands that represent stuff memory mapped
  402. //    from a file.
  403. //M-
  404. - (int)mappedSegments
  405. {
  406.     assert(mappedSegmentList != NULL);
  407.     return [mappedSegmentList count];
  408. }
  409.  
  410. //M+    -unmappedSegments
  411. //    PURPOSE:
  412. //    Return number of load commands that are aren't memory mapped from a file
  413. //M-
  414. - (int)unmappedSegments
  415. {
  416.     assert(unmappedSegmentList != NULL);
  417.     return [unmappedSegmentList count];
  418. }
  419.  
  420. //M+    -threads
  421. //    PURPOSE:
  422. //    Return number of load commands that represent threads
  423. //M-
  424. - (int)threads
  425. {
  426.     assert(threadList != NULL);
  427.     return [threadList count];
  428. }
  429.  
  430. //M+    -mappedSegment:
  431. //M-
  432. - mappedSegment:(int)segmentNumber
  433. {
  434.     assert(mappedSegmentList != NULL);
  435.     return [mappedSegmentList objectAt:segmentNumber];
  436. }
  437.  
  438. //M+    -unmappedSegment:
  439. //M-
  440. - unmappedSegment:(int)segmentNumber
  441. {
  442.     assert(unmappedSegmentList != NULL);
  443.     return [unmappedSegmentList objectAt:segmentNumber];
  444. }
  445.  
  446. //M+    -thread:
  447. //M-
  448. - thread:(int)threadNumber
  449. {
  450.     assert(threadList != NULL);
  451.     return [threadList objectAt:threadNumber];
  452. }
  453.  
  454. //M+    -considerMappedFiles
  455. //        Make an instance variable TRUE.  This instance var causes the object
  456. //        to also represent the mapped segments of the subsidiary files
  457. //        referenced by load commands.
  458. //M-
  459. - considerMappedFiles
  460. {
  461.     addMappedFiles = TRUE;
  462.     return self;
  463. }
  464.  
  465. //M+    -unconsiderMappedFiles
  466. //        Make an instance variable FALSE.  This instance var causes the object
  467. //        to also represent the mapped segments of the subsidiary files
  468. //        referenced by load commands.
  469. //M-
  470. - unconsiderMappedFiles
  471. {
  472.     addMappedFiles = FALSE;
  473.     return self;
  474. }
  475.  
  476. //M+    MachOFile -removeSegment:aLoadCommand
  477. //        Doesn't ever get called with an "unmapped" load command.
  478. //M-
  479. - removeSegment:aLoadCommand
  480. {
  481.     assert(mappedSegmentList != NULL);
  482.     assert(NX_NOT_IN_LIST != [mappedSegmentList indexOf:aLoadCommand]);
  483.     [mappedSegmentList removeObject:aLoadCommand];
  484.     return self;
  485. }
  486.  
  487. // M+    -(char *)fileType
  488. //    PURPOSE:
  489. //        Allow for the "type" of Mach-O file that this object represents
  490. //        to be discovered.
  491. //    EDITORIAL:
  492. //        This may be a bit less than generally useful.
  493. //        Should maybe just give back the _number_ of the filetype, lettting
  494. //        something else decide what phrase to use.
  495. // M-
  496. - (char *)fileType
  497. {
  498.     char *pc = NULL;
  499.     static char cBuf[512];
  500.  
  501.     assert(fileHeader != NULL);
  502.  
  503.     switch (fileHeader->filetype) {
  504.     case MH_OBJECT:
  505.         pc = "relocatable object file";
  506.         break;
  507.     case MH_EXECUTE:
  508.         pc = "demand paged executable file";
  509.         break;
  510.     case MH_FVMLIB:
  511.         pc = "fixed VM shared library file";
  512.         break;
  513.     case MH_CORE:
  514.         pc = "core file";
  515.         break;
  516.     case MH_PRELOAD:
  517.         pc = "preloaded executable file";
  518.         break;
  519.     default:
  520.         sprintf(cBuf, "Odd file type: 0x%lx\n", fileHeader->filetype);
  521.         pc = cBuf;
  522.         break;
  523.     }
  524.  
  525.     assert(pc != NULL);
  526.  
  527.     return pc;
  528. }
  529.  
  530. // M+    -(char *)cpuType
  531. //    PURPOSE:
  532. //        Allow for the type of cpu that the Mach-O file that this object
  533. //        represents to be discovered.
  534. //    EDITORIAL:
  535. //        This may be a bit less than generally useful.
  536. // M-
  537. - (char *)cpuType
  538. {
  539.     char *pc = NULL;
  540.     static char cBuf[512];
  541.  
  542.     assert(fileHeader != NULL);
  543.  
  544.     switch (fileHeader->cputype) {
  545.     case CPU_TYPE_VAX:
  546.         pc = "VAX";
  547.         break;
  548.     case CPU_TYPE_ROMP:
  549.         pc = "ROMP";
  550.         break;
  551.     case CPU_TYPE_NS32032:
  552.         pc = "NS32032";
  553.         break;
  554.     case CPU_TYPE_NS32332:
  555.         pc = "NS32332";
  556.         break;
  557.     case CPU_TYPE_NS32532:
  558.         pc = "NS32532";
  559.         break;
  560.     case CPU_TYPE_MC680x0:
  561.         pc = "MC680x0";
  562.         break;
  563.     case CPU_TYPE_I386:
  564.         pc = "I386";
  565.         break;
  566.     case CPU_TYPE_MIPS:
  567.         pc = "MIPS";
  568.         break;
  569.     case CPU_TYPE_HPPA:
  570.         pc = "HP-PA";
  571.         break;
  572.     case CPU_TYPE_ARM:
  573.         pc = "ARM";
  574.         break;
  575.     case CPU_TYPE_MC88000:
  576.         pc = "MC88000";
  577.         break;
  578.     case CPU_TYPE_SPARC:
  579.         pc = "SPARC";
  580.         break;
  581.     case CPU_TYPE_I860:
  582.         pc = "I860, big-endian";
  583.         break;
  584.     case CPU_TYPE_I860_LITTLE:
  585.         pc = "I860, little-endian";
  586.         break;
  587.     case CPU_TYPE_RS6000:
  588.         pc = "RS/6000";
  589.         break;
  590.     default:
  591.         sprintf(cBuf, "Odd CPU type: 0x%lx\n",
  592.             (unsigned long)fileHeader->cputype);
  593.         pc = cBuf;
  594.         break;
  595.     }
  596.  
  597.     assert(pc != NULL);
  598.  
  599.     return pc;
  600. }
  601.  
  602. // M+    -(char *)cpuSubtype
  603. //    PURPOSE:
  604. //        Allow for the subtype of cpu that the Mach-O file that this object
  605. //        represents to be discovered.
  606. //    EDITORIAL:
  607. //        This may be a bit less than generally useful.
  608. //        Doesn't have all of the cpu subtypes.  680x0 and Intel 80x86 only.
  609. // M-
  610. - (char *)cpuSubtype
  611. {
  612.     char *pc = NULL;
  613.     static char cBuf[512];
  614.  
  615.     assert(fileHeader != NULL);
  616.  
  617.     switch (fileHeader->cputype) {
  618.     case CPU_TYPE_MC680x0:
  619.         switch (fileHeader->cpusubtype) {
  620.         case    CPU_SUBTYPE_MC680x0_ALL:
  621.             pc = "all MC680x0";
  622.             break;
  623.         case CPU_SUBTYPE_MC68040:
  624.             pc = "MC68040";
  625.             break;
  626.         case    CPU_SUBTYPE_MC68030_ONLY:
  627.             pc = "MC68030 only";
  628.             break;
  629.         default:
  630.             sprintf(cBuf, "Odd MC680x0 CPU subtype: 0x%lx\n",
  631.                 (unsigned long)fileHeader->cpusubtype);
  632.             pc = cBuf;
  633.             break;
  634.         }
  635.         break;
  636.  
  637.     case CPU_TYPE_I386:
  638.         switch (fileHeader->cpusubtype) {
  639.         case CPU_SUBTYPE_I386_ALL:
  640.             pc = "all i386";
  641.             break;
  642.         case CPU_SUBTYPE_486:
  643.             pc = "80486";
  644.             break;
  645.         default:
  646.             sprintf(cBuf, "Odd I386 CPU subtype: 0x%lx\n",
  647.                 (unsigned long)fileHeader->cpusubtype);
  648.             pc = cBuf;
  649.             break;
  650.         }
  651.         break;
  652.  
  653.     default:
  654.         pc = " ";
  655.         break;
  656.     }
  657.  
  658.     assert(pc != NULL);
  659.  
  660.     return pc;
  661. }
  662.  
  663.  
  664. //M+
  665. //M-
  666. - (struct section *)sectionNamed:(char *)sectName inSegNamed:(char *)segName
  667. {
  668.     int        iSegments;
  669.     int        iCC;
  670.     struct section *sprAddr = NULL;
  671.  
  672.     assert(sectName != NULL && segName != NULL);
  673.  
  674.     iSegments = [self mappedSegments];
  675.     for (iCC = 0; iCC < iSegments && sprAddr == NULL; ++iCC)
  676.     {    id oLdCmd = [self mappedSegment:iCC];
  677.  
  678.         assert(oLdCmd != Nil);
  679.  
  680.         if (!strcmp(segName, [oLdCmd commandName]))
  681.         {    int iSect, iNumSects;
  682.  
  683.             iNumSects = [oLdCmd numberOfSections];
  684.             for( iSect = 0; iSect < iNumSects; ++iSect)
  685.             {    struct section *spSection;
  686.  
  687.                 spSection = [oLdCmd getSection:iSect];
  688.                 assert(spSection != NULL);
  689.  
  690.                 if (!strcmp(spSection->sectname, sectName))
  691.                 {    sprAddr = spSection;
  692.                     break;
  693.                 }
  694.             }
  695.         }
  696.     }
  697.  
  698.     return sprAddr;
  699. }
  700.  
  701. //M+ - (int)segmentOfThread:(int)threadNumber
  702. //    PURPOSE:
  703. //        return the segment number that contains address of thread
  704. //        threadNumber.
  705. //    RETURN:
  706. //        -1 if the segment number is invalid, or some error occurs.
  707. //        abort() call does something weird in kernel address space.
  708. //        no segment will contain program counter of that thread.
  709. //M-
  710. - (int)segmentOfThread:(int)threadNumber
  711. {
  712.     int irSegNo = -1;
  713.  
  714.     // not really an error condition if threadSegment is NULL
  715.     if (threadSegment && threadNumber < [self threads])
  716.         irSegNo = threadSegment[threadNumber];
  717.  
  718.     return irSegNo;
  719. }
  720.  
  721. @@end
  722. @
  723.  
  724.  
  725. 1.10
  726. log
  727. @added - (struct section *)sectionNamed:: method
  728. @
  729. text
  730. @d3 3
  731. d41 1
  732. a41 1
  733. static char rcsident[] = "$Id: MachOFile.m,v 1.9 94/02/07 21:36:27 ediger Exp Locker: ediger $";
  734. d59 2
  735. a60 1
  736.     fileHeader = NULL;
  737. d105 3
  738. d124 1
  739. a124 1
  740.     [mappedSegmentList initCount:numberOfCommands];
  741. a125 3
  742.     [mappedSegmentList setSortOrder:DESCENDING];
  743.     [mappedSegmentList setKeyDataType:UNSIGNED_LONG];
  744.     [mappedSegmentList setKeyMethod:@@selector(getBaseAddress)];
  745. d127 4
  746. d164 2
  747. d205 1
  748. a205 1
  749.     int     iCC;
  750. d233 28
  751. d604 2
  752. d614 1
  753. d626 21
  754. @
  755.  
  756.  
  757. 1.9
  758. log
  759. @Use memory-mapped file object, add segment name display, change
  760. to using a matrix of buttons for choice of what to display.
  761. @
  762. text
  763. @d3 4
  764. d38 1
  765. a38 1
  766. static char rcsident[] = "$Id: MachOFile.m,v 1.8 94/01/30 16:26:59 ediger Exp Locker: ediger $";
  767. d551 34
  768. @
  769.  
  770.  
  771. 1.8
  772. log
  773. @add threadList List instance var to hold all thread_command load commands
  774. seperately.
  775. @
  776. text
  777. @d3 4
  778. d34 1
  779. a34 1
  780. static char rcsident[] = "$Id: MachOFile.m,v 1.7 93/12/20 20:49:20 ediger Exp Locker: ediger $";
  781. d60 2
  782. d73 1
  783. a73 1
  784.     if (mappedFileAddress != 0)
  785. d175 4
  786. a178 2
  787.     {    int     iCC;
  788.         caddr_t    tAddress;
  789. d180 2
  790. a181 6
  791.         fileHeader = (struct mach_header *)mappedFileAddress;
  792.         // check for a legit Mach-O file
  793.         if (fileHeader->magic != MH_MAGIC)
  794.         {    [self free];
  795.             return Nil;
  796.         }
  797. d183 7
  798. a189 1
  799.         [self initLoadCommandLists:fileHeader->ncmds];
  800. d191 2
  801. a192 2
  802.         tAddress = (caddr_t)((unsigned long)mappedFileAddress
  803.              + sizeof(struct mach_header));
  804. d194 1
  805. a194 2
  806.         for (iCC = 0; iCC < fileHeader->ncmds; ++iCC)
  807.         {    id oNewSegment = [LoadCommand new:tAddress];
  808. d196 1
  809. a196 1
  810.             tAddress += [oNewSegment commandSize];
  811. d198 5
  812. a202 1
  813.             [self addLoadCommand:oNewSegment];
  814. d204 13
  815. a216 3
  816.             if (addMappedFiles && [oNewSegment representsMappedFile])
  817.                 [self addLoadCommandsFrom:oNewSegment];
  818.         }
  819. @
  820.  
  821.  
  822. 1.7
  823. log
  824. @better method of transferring load commands from a LoadFVMLibCommand
  825. LoadCommand object to the current MachOFile object's mapped segment list.
  826. @
  827. text
  828. @d3 4
  829. d30 1
  830. a30 1
  831. static char rcsident[] = "$Id: MachOFile.m,v 1.6 93/12/18 22:46:51 ediger Exp Locker: ediger $";
  832. d46 1
  833. d85 1
  834. d89 1
  835. d108 1
  836. d126 2
  837. d281 3
  838. a283 1
  839. //M+    -mappedSegment
  840. d285 8
  841. d299 1
  842. a299 1
  843. //M+    -unmappedSegment
  844. d305 8
  845. @
  846.  
  847.  
  848. 1.6
  849. log
  850. @changed -initFromFileNamed: method to -fillFromFileNamed: to reflect
  851. a bit more accuratly its function.
  852. Changed the way that subsidiary file's mapped segments get added in
  853. to the mapped segment list.  That process didn't work the old way.
  854. @
  855. text
  856. @d3 6
  857. d26 1
  858. a26 1
  859. static char rcsident[] = "$Id: MachOFile.m,v 1.5 93/12/07 23:30:31 ediger Exp Locker: ediger $";
  860. d129 1
  861. a129 1
  862. {    int iSegs, iCount;
  863. d134 1
  864. a134 1
  865.     [oNewSegment loadOtherFile];
  866. d136 2
  867. a137 1
  868.     otherFile = [oNewSegment otherFile];
  869. d139 5
  870. a143 12
  871.     iSegs = [otherFile mappedSegments];
  872.     
  873.     if (iSegs > 0)
  874.     {    id otherFilesSegments = [[List alloc] init];
  875.  
  876.         for (iCount = 0; iCount < iSegs; ++iCount)
  877.         {    id oOtherFileSegment = [otherFile mappedSegment:iCount];
  878.     
  879.             if ([oOtherFileSegment isMapped])
  880.             {    [mappedSegmentList addObject:oOtherFileSegment];
  881.                 [otherFilesSegments addObject:oOtherFileSegment];
  882.             }
  883. d145 1
  884. a146 4
  885.         iSegs = [otherFilesSegments count];
  886.         for (iCount = 0; iCount < iSegs; ++iCount)
  887.             [otherFile removeSegment:[otherFilesSegments objectAt:iCount]];
  888.     }
  889. @
  890.  
  891.  
  892. 1.5
  893. log
  894. @added some assert()s and cpuType and cpuSubtype methods
  895. @
  896. text
  897. @d3 3
  898. d20 1
  899. a20 1
  900. static char rcsident[] = "$Id: MachOFile.m,v 1.4 93/12/02 00:44:23 ediger Exp Locker: ediger $";
  901. d133 3
  902. d137 8
  903. a144 2
  904.     for (iCount = 0; iCount < [otherFile mappedSegments]; ++iCount)
  905.     {    id oOtherFileSegment = [otherFile mappedSegment:iCount];
  906. d146 3
  907. a148 4
  908.         if ([oOtherFileSegment isMapped])
  909.         {    [mappedSegmentList addObject:oOtherFileSegment];
  910.             [otherFile removeSegment:oOtherFileSegment];
  911.         }
  912. d153 1
  913. a153 1
  914. //M+    -initFromFileNamed:
  915. d157 1
  916. a157 1
  917. - initFromFileNamed: (char *) filename
  918. a158 2
  919.     [self init];
  920.  
  921. d318 1
  922. d329 2
  923. d457 1
  924. a457 1
  925.             pc = "MC680x0";
  926. d466 1
  927. a466 1
  928.             sprintf(cBuf, "Odd MC680x0 CPU type: 0x%lx\n",
  929. d476 1
  930. a476 1
  931.             pc = "All i386";
  932. d480 5
  933. @
  934.  
  935.  
  936. 1.4
  937. log
  938. @added fileType method, and a load of comments
  939. @
  940. text
  941. @d3 3
  942. d17 1
  943. a17 1
  944. static char rcsident[] = "$Id: MachOFile.m,v 1.3 93/10/31 21:32:13 ediger Exp Locker: ediger $";
  945. d57 3
  946. a59 1
  947.             mach_error("Trouble deallocating mapped Mach-O file", tRet);
  948. d63 3
  949. a65 1
  950.             perror("Closing Mach-O file descriptor");
  951. d67 2
  952. d72 3
  953. d88 2
  954. d105 2
  955. d123 2
  956. d150 2
  957. d157 5
  958. d199 9
  959. a207 5
  960.     if (stat(filename, &sStat) < 0)
  961.         perror("Mach-O file stat");
  962.     else if ((fileDescriptor = open(filename, O_RDONLY)) < 0)
  963.         perror("opening Mach-O file");
  964.     else {
  965. d213 5
  966. a217 4
  967.         if (tRet != KERN_SUCCESS)
  968.             mach_error("Trouble mapping Mach-O file descriptor", tRet);
  969.         else if ((vm_address_t)mappedFileAddress != (vm_address_t)NULL)
  970.         {
  971. d223 4
  972. a226 3
  973.             if (tRet != KERN_SUCCESS)
  974.                 mach_error("Trouble deallocating mapped Mach-O file", tRet);
  975.             else {
  976. d232 4
  977. a235 3
  978.                 if (tRet != KERN_SUCCESS)
  979.                     mach_error("Trouble mapping Mach-O file descriptor", tRet);
  980.                 else
  981. d251 1
  982. d261 1
  983. d269 1
  984. d277 1
  985. d308 1
  986. d325 2
  987. d344 1
  988. a344 1
  989.         sprintf(cBuf, "Odd file type: 0x%x\n", fileHeader->filetype);
  990. d348 130
  991. @
  992.  
  993.  
  994. 1.3
  995. log
  996. @ditched the -printSegments method, had been #ifdef'ed out anyway.
  997. @
  998. text
  999. @d3 3
  1000. d14 1
  1001. a14 1
  1002. static char rcsident[] = "$Id: MachOFile.m,v 1.2 93/10/27 23:44:09 ediger Exp Locker: ediger $";
  1003. d66 8
  1004. d85 4
  1005. d98 5
  1006. d124 1
  1007. a124 1
  1008. //M+    -initFromFile:
  1009. d128 1
  1010. a128 1
  1011. - initFromFile: (char *) filename
  1012. d213 3
  1013. d223 2
  1014. d246 3
  1015. d257 3
  1016. d274 37
  1017. @
  1018.  
  1019.  
  1020. 1.2
  1021. log
  1022. @Definition of MachOFile object that uses LoadCommand subclasses
  1023. @
  1024. text
  1025. @d2 4
  1026. a5 1
  1027.  * $Log$
  1028. d11 1
  1029. a11 1
  1030. static char rcsident[] = "$Id$";
  1031. a12 8
  1032. //M+    +new
  1033. //M-
  1034. + new
  1035. {
  1036.     MachOFile *oNew = [[MachOFile alloc] init];
  1037.     return oNew;
  1038. }
  1039.  
  1040. d60 1
  1041. a60 1
  1042.     return self;
  1043. d67 1
  1044. a67 1
  1045.     [mappedSegmentList setSortOrder:ASCENDING];
  1046. d110 2
  1047. d151 2
  1048. a152 2
  1049.     struct stat   sStat;
  1050.     int           irSuccess = 0;
  1051. d166 2
  1052. a167 1
  1053.         else if ((vm_address_t)mappedFileAddress != (vm_addr_t)NULL) {
  1054. d177 2
  1055. a178 1
  1056.                 tRet = map_fd(fileDescriptor, (vm_offset_t)0, &mappedFileAddress, TRUE,
  1057. a232 30
  1058.     return self;
  1059. }
  1060.  
  1061. //M+    -printSegments
  1062. //M-
  1063. -printSegments
  1064. {
  1065.     int iCC;
  1066.     int iTotal = [unmappedSegmentList count];
  1067.  
  1068.     printf("Unmapped load commands:\n");
  1069.     for (iCC = 0; iCC < iTotal; ++iCC)
  1070.     {    id oSegment = [unmappedSegmentList objectAt:iCC];
  1071.  
  1072.         printf("Segment with name \"%s\"\n", [oSegment commandName]);
  1073.     }
  1074.  
  1075.     iTotal = [mappedSegmentList count];
  1076.  
  1077.     printf("\nMapped load commands:\n");
  1078.     for (iCC = 0; iCC < iTotal; ++iCC)
  1079.     {    id oSegment = [mappedSegmentList objectAt:iCC];
  1080.  
  1081.         if ([oSegment numberOfSections] > 0)
  1082.             [oSegment printSections];
  1083.  
  1084.         printf("Segment with base address 0x%lx named \"%s\"\n",
  1085.             [oSegment getBaseAddress], [oSegment commandName]);
  1086.     }
  1087.  
  1088. @
  1089.  
  1090.  
  1091. 1.1
  1092. log
  1093. @Initial revision
  1094. @
  1095. text
  1096. @d1 3
  1097. d8 2
  1098. d30 2
  1099. a31 1
  1100.     segmentList = [SortedList alloc];
  1101. d39 2
  1102. d62 4
  1103. a65 1
  1104.     return [[segmentList freeObjects] free];
  1105. d68 41
  1106. d121 1
  1107. a121 4
  1108.         [segmentList initCount:fileHeader->ncmds];
  1109.         [segmentList setSortOrder:ASCENDING];
  1110.         [segmentList setKeyDataType:UNSIGNED_LONG];
  1111.         [segmentList setKeyMethod:@@selector(getBaseAddress)];
  1112. d127 2
  1113. a128 2
  1114.         {    LoadCommand *oNewSegment = [LoadCommand new];
  1115.             [oNewSegment setLoadCommand:tAddress];
  1116. d130 5
  1117. a134 1
  1118.             [segmentList addObject:oNewSegment];
  1119. d169 19
  1120. a187 2
  1121.         else
  1122.             irSuccess = 1;
  1123. d193 44
  1124. d242 1
  1125. a242 1
  1126.     int iTotal = [segmentList count];
  1127. d244 1
  1128. d246 1
  1129. a246 1
  1130.     {    LoadCommand *oSegment = [segmentList objectAt:iCC];
  1131. d248 2
  1132. a249 1
  1133.         [oSegment printSections];
  1134. d251 9
  1135. d266 11
  1136. @
  1137.