home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / debug / Common / SegmentManager.m < prev   
Encoding:
Text File  |  1995-07-28  |  14.9 KB  |  639 lines

  1. #import "SegmentManager.h"
  2. #import <stdlib.h>
  3. #import <string.h>
  4. #import <mach-o/loader.h>
  5. #import <sys/types.h>
  6. #import <sys/stat.h>
  7. #import <mach-o/ldsyms.h>
  8. #import <libc.h>
  9. #import <objc/maptable.h>
  10. #import <mach-o/fat.h>
  11.  
  12. #define REALLY_SWAP_LONG(a) ( ((a) << 24) | \
  13.               (((a) << 8) & 0x00ff0000) | \
  14.               (((a) >> 8) & 0x0000ff00) | \
  15.     ((unsigned long)(a) >> 24) )
  16.  
  17. #define SWAP_LONG(a) (shouldSwap ? REALLY_SWAP_LONG(a) : (a))
  18.  
  19. @implementation SegmentManager
  20.  
  21. static NXMapTable *managers = NULL;
  22.  
  23. +initialize
  24. {
  25.     static BOOL beenHere = NO;
  26.     
  27.     if (!beenHere) {
  28.     beenHere = YES;
  29.     managers = NXCreateMapTable(NXStrValueMapPrototype, 0);
  30.     }
  31.     return self;
  32. }
  33.  
  34. -init
  35. {
  36.     relocSize = sizeof(Segment);
  37.     rmFlags.shouldSortRelocs = YES;
  38.     [self readInAllRelocs];
  39.     lastReloc = NULL;
  40.     if (numRelocs) {
  41.     if (images[0].name)
  42.         NXMapInsert(managers, images[0].name, self);
  43.     return self;
  44.     } else {
  45.     [self free];
  46.     return nil;
  47.     }
  48. }
  49.  
  50. -(void)setCpuType: (cpu_type_t)type
  51. {
  52.     static cpu_type_t defaultCpuType = 0;
  53.     if (type)
  54.     cpuType = type;
  55.     else {
  56.     if (!defaultCpuType) {
  57.         struct host_basic_info host_basic_info;
  58.         unsigned int count = HOST_BASIC_INFO_COUNT;
  59.         
  60.         if (host_info(host_self(), HOST_BASIC_INFO,
  61.               (host_info_t)(&host_basic_info),
  62.               &count) == KERN_SUCCESS)
  63.         defaultCpuType = host_basic_info.cpu_type;
  64.     }
  65.     cpuType = defaultCpuType;
  66.     }
  67. }
  68.  
  69. -initFile: (STR)theName skipShlibs: (BOOL)shouldSkipShlibs withDesc: (int)desc cpuType: (cpu_type_t)type
  70. {
  71.     SegmentManager *oldManager;
  72.     if (oldManager = NXMapGet(managers, theName)) {
  73.     close(desc);
  74.     [self free];
  75.     return oldManager;
  76.     } else  {
  77.     name = malloc(strlen(theName) + 1);
  78.     strcpy(name, theName);
  79.     skipShlibs = shouldSkipShlibs;
  80.     imageFd = desc;
  81.     [self setCpuType: type];
  82.     [self getImages];
  83.     return [self init];
  84.     }
  85. }
  86.  
  87. static const char loadedName[] = "loaded file";
  88.  
  89. -(struct mach_header *)headerFromStart: (void *)start
  90. {
  91.     struct mach_header *header = start;
  92.     if (header->magic == MH_MAGIC && header->cputype == cpuType)
  93.     return header;
  94.     else {
  95.     struct fat_header *fatHeader = start;
  96.     if ((fatHeader->magic == FAT_MAGIC)
  97.         || (fatHeader->magic == REALLY_SWAP_LONG(FAT_MAGIC))) {
  98.         BOOL shouldSwap = !(fatHeader->magic == FAT_MAGIC);
  99.         unsigned int nArches;
  100.         struct fat_arch *fatArch, *foundArch;
  101.         
  102.         for (nArches = SWAP_LONG(fatHeader->nfat_arch),
  103.          fatArch = (struct fat_arch *)(fatHeader + 1),
  104.          foundArch = NULL;
  105.          nArches && !foundArch;
  106.          fatArch++, nArches--) {
  107.         if (cpuType == SWAP_LONG(fatArch->cputype))
  108.             foundArch = fatArch;
  109.         }
  110.         if (foundArch)
  111.         return start + SWAP_LONG(foundArch->offset);
  112.         else
  113.         return NULL;
  114.     } else
  115.         return NULL;
  116.     }
  117. }
  118.  
  119. -initHeader: (struct mach_header *)header withSize: (int)size andSlide:(unsigned long)slide
  120. {
  121.     numImages = 1;
  122.     [self setCpuType: 0];
  123.     images = malloc(sizeof(*images));
  124.     images->header = [self headerFromStart: header];
  125.     images->size = size;
  126.     images->name = NULL;
  127.     images->mtime = 0;
  128.     images->slide = slide;
  129.     name = malloc(sizeof(loadedName));
  130.     strcpy(name, loadedName);
  131.     return [self init];
  132. }
  133.  
  134. // Assume header and all of it's load commands have been 
  135. // warped onto the current memory space.
  136.  
  137. -initHeader: (struct mach_header *)header withSlide:(unsigned long)slide
  138. {
  139.   int i;
  140.   struct load_command* cmd;
  141.   unsigned long maxAddr;
  142.   unsigned long hAddr;
  143.  
  144.   // Compute the size of the module from the load commands.
  145.  
  146.   [self setCpuType: 0];
  147.   maxAddr = hAddr = (unsigned) header = [self headerFromStart:header];
  148.  
  149.   for (cmd = (struct load_command *)(header + 1), i = 0;
  150.        i < header->ncmds;
  151.        ((void *)cmd) += cmd->cmdsize, i++) {
  152.  
  153.     unsigned long topAddr;
  154.  
  155.     if (cmd->cmd == LC_SEGMENT)
  156.       {
  157.     struct segment_command *segCmd = (struct segment_command *)cmd;
  158.     topAddr = segCmd->vmaddr + segCmd->vmsize + slide;
  159.  
  160.     if (topAddr > maxAddr)
  161.       maxAddr = topAddr;
  162.       }
  163.   }
  164.  
  165.   return [self initHeader: header 
  166.              withSize: maxAddr - (unsigned)header
  167.              andSlide: slide];
  168. }
  169.  
  170. +newHeader:(struct mach_header*)header withSlide:(unsigned long)slide
  171. {
  172.   return [[self alloc] initHeader:header withSlide:slide];
  173. }
  174.  
  175. -initHeader: (struct mach_header *)header withSize: (int)size
  176. {
  177.   return [self initHeader:header withSize:size andSlide:0];
  178. }
  179.  
  180. -initHeader: (struct mach_header *)header
  181. {
  182.   return [self initHeader:header withSlide:0];
  183. }
  184.  
  185. -initFile: (STR)theName
  186. {
  187.     return [self initFile: theName skipShlibs: NO withDesc: -1 cpuType: 0];
  188. }
  189.  
  190. +newExecutable: (STR)theName skipShlibs: (BOOL)shouldSkipShlibs withDesc: (int)desc cpuType: (cpu_type_t)type
  191. {
  192.     SegmentManager *sm = [[super alloc] initFile: (STR)theName
  193.                                     skipShlibs: shouldSkipShlibs
  194.                       withDesc: desc
  195.                    cpuType: type];
  196.     if (sm && [sm isExecutable])
  197.      return sm;
  198.     else {
  199.     [sm free];
  200.     return nil;
  201.     }
  202. }
  203.  
  204. +newExecutable: (STR)theName
  205. {
  206.     return [self newExecutable: theName skipShlibs: NO withDesc: -1 cpuType: 0];
  207. }
  208.  
  209. +newCore: (STR)theName
  210. {
  211.     SegmentManager *sm = [[super alloc] initFile: (STR)theName];
  212.     if (sm && [sm isCore])
  213.      return sm;
  214.     else {
  215.     [sm free];
  216.     return nil;
  217.     }
  218. }
  219.  
  220. +newFile: (STR)theName
  221. {
  222.     return [[super alloc] initFile: (STR)theName];
  223. }
  224.  
  225. +newShlib: (STR)theName cpuType: (cpu_type_t)type
  226. {
  227.     SegmentManager *sm = [[super alloc] initFile: (STR)theName
  228.                                     skipShlibs: YES
  229.                       withDesc: -1
  230.                        cpuType: type];
  231.     if (sm && [sm isShlib])
  232.      return sm;
  233.     else {
  234.     [sm free];
  235.     return nil;
  236.     }
  237. }
  238.  
  239. +newShlib: (STR)theName
  240. {
  241.     return [self newShlib: theName cpuType: 0];
  242. }
  243.  
  244. +newHeader: (struct mach_header *)header withSize: (int)size
  245. {
  246.     return [[super alloc] initHeader: header withSize: size];
  247. }
  248.  
  249. -(STR)executableName
  250. {
  251.     return name;
  252. }
  253.  
  254. -(long)mtime
  255. {
  256.     return images[0].mtime;
  257. }
  258.  
  259. -free
  260. {
  261.     NXMapRemove(managers, name);
  262.     free(name); name = NULL;
  263.     return [super free];
  264. }
  265.  
  266. -invalidate
  267. {
  268.     int count;
  269.     Image *image;
  270.     
  271.     if (images) {
  272.     for (count = numImages, image = images; count; count--, image++) {
  273.         if (image->deallocate)
  274.         vm_deallocate(task_self(),
  275.                 (vm_address_t)image->header,
  276.                 image->size);
  277.     }
  278.     free(images); images = NULL;
  279.     numImages = 0;
  280.     }
  281.     return [super invalidate];
  282. }
  283.  
  284. -(void)getImages
  285. {
  286.     struct stat imageStat;
  287.     struct load_command *loadCmd;
  288.     struct fvmlib_command *fvmCmd;
  289.     struct mach_header *header;
  290.     int i;
  291.     Image *image;
  292.     numImages = 0;
  293.     if (imageFd < 0)
  294.     imageFd = open(name, O_RDONLY, 0);
  295.     if (imageFd >= 0) {
  296.     extern int errno;
  297.     errno = 0;
  298.     fstat(imageFd, &imageStat);
  299.     if (map_fd(imageFd,
  300.            0,
  301.            (vm_address_t *)&header,
  302.            YES,
  303.            imageStat.st_size) == 0) {
  304. //        printf("Map_fp successfull.\n");
  305.         if (header && (header = [self headerFromStart: header])) {
  306. //            printf("Got header.\n");
  307.         numImages = 1;
  308.         if (skipShlibs) {
  309.             images = malloc(sizeof(Image));
  310.             images->name = name;
  311.             images->header = header;
  312.             images->size = imageStat.st_size;
  313.             images->deallocate = YES;
  314.             images->slide = 0;
  315.             images->mtime = imageStat.st_mtime;
  316.         } else {
  317.             for (i = 0, loadCmd = (struct load_command *)(header + 1);
  318.              i < header->ncmds;
  319.              i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  320.             if (loadCmd->cmd == LC_LOADFVMLIB) 
  321.                 numImages++;
  322.             }
  323.             image
  324.             = images
  325.             = calloc(numImages, sizeof(Image));
  326.             image->name = name;
  327.             image->header = header;
  328.             image->size = imageStat.st_size;
  329.             image->deallocate = YES;
  330.             image->slide = 0;
  331.             image->mtime = imageStat.st_mtime;
  332.             image++;
  333.             for (i = 0, loadCmd = (struct load_command *)(header + 1);
  334.              i < header->ncmds;
  335.              i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  336.             int shlibFd;
  337.             if (loadCmd->cmd == LC_LOADFVMLIB) {
  338.                 fvmCmd = (struct fvmlib_command *)loadCmd;
  339.                 image->name
  340.                 = (void *)fvmCmd + fvmCmd->fvmlib.name.offset;
  341.                 shlibFd = open(image->name, O_RDONLY, 0);
  342.                 if (shlibFd >= 0) {
  343.                 fstat(shlibFd, &imageStat);
  344.                 image->size = imageStat.st_size;
  345.                 image->mtime = imageStat.st_mtime;
  346.                 if (map_fd(shlibFd,
  347.                        0,
  348.                        (vm_address_t *)&image->header,
  349.                        YES,
  350.                        image->size)
  351.                       == 0) {
  352.                         image->header
  353.                     = [self headerFromStart: image->header];
  354.                     image->deallocate = YES;
  355.                     image++;
  356.                 } else
  357.                     numImages--;
  358.                 close(shlibFd);
  359.                 } else
  360.                 numImages--;
  361.             }
  362.             }
  363.         }
  364.         } else {
  365.         printf("Error: file had bad header.\n");
  366.         }
  367.     } else {
  368. //        printf("Map_fd failed, errno = %d.\n", errno);
  369.     }
  370.     close(imageFd);
  371.     imageFd = -1;
  372.     }
  373. }
  374.                             
  375. -(int)numSegments
  376. {
  377.     int count, numSegs = 0, i;
  378.     Image *image;
  379.     struct load_command *loadCmd;
  380.     struct mach_header *header;
  381.     for (count = numImages,
  382.      image = images;
  383.      count;
  384.      count--, image++) {
  385.     header = image->header;
  386.     for (i = 0, loadCmd = (struct load_command *)(header + 1);
  387.          i < header->ncmds;
  388.          i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  389.         if (loadCmd->cmd == LC_SEGMENT) 
  390.         numSegs++;
  391.     }
  392.     }
  393.     return numSegs;
  394. }
  395.  
  396. -(BOOL)validate
  397. {
  398.     int nImages, i;
  399.     Image *image;
  400.     struct mach_header *header;
  401.     struct load_command *loadCmd;
  402.     struct segment_command *segCmd;
  403.     BOOL allOK = YES;
  404.     for (nImages = numImages,
  405.      image = images;
  406.      allOK && nImages;
  407.      nImages--, image++) {
  408.     header = image->header;
  409.     for (i = 0, loadCmd = (struct load_command *)(header + 1);
  410.          allOK && i < header->ncmds;
  411.          i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  412.         if (loadCmd->cmd == LC_SEGMENT) {
  413.         segCmd = (struct segment_command *)loadCmd;
  414.         if ((segCmd->fileoff + segCmd->vmsize) > image->size)
  415.             allOK = NO;
  416.         }
  417.         if (!loadCmd->cmdsize)
  418.         allOK = NO;
  419.     }
  420.     }
  421.     return allOK;
  422. }
  423.  
  424. -(void)readInSegments
  425. {
  426.     int nImages, i;
  427.     Image *image;
  428.     struct mach_header *header;
  429.     struct load_command *loadCmd;
  430.     struct segment_command *segCmd;
  431.     Segment *segment = relocs;
  432.     for (nImages = numImages,
  433.      image = images;
  434.      nImages;
  435.      nImages--, image++) {
  436.     header = image->header;
  437.     for (i = 0, loadCmd = (struct load_command *)(header + 1);
  438.          i < header->ncmds;
  439.          i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  440.         if (loadCmd->cmd == LC_SEGMENT) {
  441.         segCmd = (struct segment_command *)loadCmd;
  442.         segment->address = segCmd->vmaddr + image->slide;
  443.         segment->size = segCmd->vmsize;
  444.         segment->data = (vm_address_t)header + segCmd->fileoff;
  445.         segment->maxAddress = segment->address + segment->size;
  446.         segment->displacement = segment->data - segment->address;
  447.         segment->maxData = segment->data + segment->size;
  448.         segment->segName = segCmd->segname;
  449.         segment->rFlags.readIn = YES;
  450.         ((void *)segment) += relocSize;
  451.         }
  452.     }
  453.     }
  454. }
  455.  
  456. -(void)_readInAllRelocs
  457. {
  458.     numRelocs = [self numSegments];
  459.     relocs = calloc(numRelocs, relocSize);
  460.     [self readInSegments];
  461.     rmFlags.invalid = NO;
  462. }
  463.  
  464. -(struct mach_header *)getMachHeader
  465. {
  466.     if (numImages)
  467.     return images[0].header;
  468.     else
  469.     return NULL;
  470. }
  471.  
  472. -(unsigned)getSlide
  473. {
  474.   if (numImages)
  475.     return images[0].slide;
  476.   else
  477.     return 0;
  478. }
  479.  
  480. -(int)getNumMachHeaders
  481. {
  482.     return numImages;
  483. }
  484.  
  485. -(struct mach_header **)getMachHeaders
  486. {
  487.     struct mach_header **headers;
  488.     int headerIndex;
  489.     headers = malloc((numImages + 1) * sizeof(*headers));
  490.     for (headerIndex = 0; headerIndex < numImages; headerIndex++)
  491.     headers[headerIndex] = images[headerIndex].header;
  492.     headers[numImages] = NULL;
  493.     return headers;
  494. }
  495.  
  496. -(unsigned*)getSlides
  497. {
  498.     unsigned *slides;
  499.     int slideIndex;
  500.     slides = malloc((numImages + 1) * sizeof(*slides));
  501.     for (slideIndex = 0; slideIndex < numImages; slideIndex++)
  502.     slides[slideIndex] = images[slideIndex].slide;
  503.     slides[numImages] = 0;
  504.     return slides;
  505. }
  506.  
  507. -(struct mach_header **)getMachHeadersWithNames: (char ***)names
  508. {
  509.     struct mach_header **headers;
  510.     char **theNames;
  511.     int headerIndex;
  512.     headers = malloc((numImages + 1) * sizeof(*headers));
  513.     *names = theNames = malloc((numImages + 1) * sizeof(*theNames));
  514.     for (headerIndex = 0; headerIndex < numImages; headerIndex++) {
  515.     headers[headerIndex] = images[headerIndex].header;
  516.     theNames[headerIndex] = images[headerIndex].name;
  517.     }
  518.     headers[numImages] = NULL;
  519.     theNames[numImages] = NULL;
  520.     return headers;
  521. }
  522.  
  523. -(unsigned *)getSlidesWithNames: (char ***)names
  524. {
  525.     unsigned *slides;
  526.     char **theNames;
  527.     int slideIndex;
  528.     slides = malloc((numImages + 1) * sizeof(*slides));
  529.     *names = theNames = malloc((numImages + 1) * sizeof(*theNames));
  530.     for (slideIndex = 0; slideIndex < numImages; slideIndex++) {
  531.     slides[slideIndex] = images[slideIndex].slide;
  532.     theNames[slideIndex] = images[slideIndex].name;
  533.     }
  534.     slides[numImages] = 0;
  535.     theNames[numImages] = NULL;
  536.     return slides;
  537. }
  538.  
  539. -(struct load_command *)findLoadCommand: (unsigned long)command
  540.                               forHeader: (struct mach_header *)header
  541. {
  542.     int i;
  543.     struct load_command *loadCmd, *foundCmd = NULL;
  544.     for (i = 0, loadCmd = (struct load_command *)(header + 1);
  545.      i < header->ncmds && !foundCmd;
  546.      i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  547.     if (loadCmd->cmd == command)
  548.         foundCmd = loadCmd;
  549.     }
  550.     return foundCmd;
  551. }
  552.  
  553. -(int)numCommands: (unsigned long)command
  554.         forHeader: (struct mach_header *)header
  555. {
  556.     int i, nCommands = 0;
  557.     struct load_command *loadCmd;
  558.     for (i = 0, loadCmd = (struct load_command *)(header + 1);
  559.      i < header->ncmds;
  560.      i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  561.     if (loadCmd->cmd == command)
  562.         nCommands++;
  563.     }
  564.     return nCommands;
  565. }
  566.  
  567. -(struct symtab_command *)symCmd
  568. {
  569.     return (struct symtab_command *)
  570.              [self findLoadCommand: LC_SYMTAB
  571.                      forHeader: images[0].header];
  572. }
  573.  
  574. -(struct dysymtab_command *)dysymCmd
  575. {
  576.     return (struct dysymtab_command *)
  577.              [self findLoadCommand: LC_DYSYMTAB
  578.                      forHeader: images[0].header];
  579. }
  580.  
  581. -(char *)stringTable
  582. {
  583.     struct symtab_command *symCmd = [self symCmd];
  584.     return (char *)(images[0].header) + symCmd->stroff;
  585. }
  586.  
  587. -(struct nlist *)symbolTable
  588. {
  589.     struct symtab_command *symCmd = [self symCmd];
  590.     return (struct nlist*)((char *)(images[0].header) + symCmd->symoff);
  591. }
  592.  
  593. -(BOOL)isDylib
  594. {
  595.   return images && images[0].header->filetype == MH_DYLIB;
  596. }
  597.  
  598. -(BOOL)isCore
  599. {
  600.     return images && images[0].header->filetype == MH_CORE;
  601. }
  602.  
  603. -(BOOL)isShlib
  604. {
  605.     return images && images[0].header->filetype == MH_FVMLIB;
  606. }
  607.  
  608. -(BOOL)isExecutable
  609. {
  610.     BOOL ret = images && ((images[0].header->filetype == MH_EXECUTE)
  611.               || (images[0].header->filetype == MH_OBJECT)
  612.                       || (images[0].header->filetype == MH_PRELOAD));
  613. //    if (ret)
  614. //    printf("Is executable.\n");
  615. //    else
  616. //    printf("Isn't executable.\n");
  617.     return ret;
  618. }
  619.  
  620. -(BOOL)isSymbolStub:(void*)pc
  621. {
  622.   const struct section *sec;
  623.   sec = [self getSeg:"__TEXT" sect:"__picsymbol_stub"];
  624.   if (sec == 0)
  625.     sec = [self getSeg:"__TEXT" sect:"__symbol_stub"];
  626.   
  627.   if (sec 
  628.       && pc >= (void *) ((char *) 0 + (sec->addr + [self getSlide]))
  629.       && pc <  (void *) ((char *) 0 + (sec->addr + [self getSlide] 
  630.                                  + sec->size)))
  631.     return 1;
  632.   else
  633.     return 0;
  634. }
  635.  
  636. @end
  637.  
  638.  
  639.