home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / debug / Common / RelocManager.m < prev    next >
Encoding:
Text File  |  1997-02-25  |  10.2 KB  |  452 lines

  1. #import "RelocManager.h"
  2. #import <stdlib.h>
  3. #import <string.h>
  4. #import <mach-o/loader.h>
  5. #import <libc.h>
  6.  
  7. int slideWarpM = 0;
  8.  
  9. @implementation RelocManager
  10.  
  11. -init
  12. {
  13.     rmFlags.invalid = YES;
  14.     rmFlags.shouldSortRelocs = YES;
  15.     return self;
  16. }
  17.  
  18. -free
  19. {
  20.     [self invalidate];
  21.     return [super free];
  22. }
  23.  
  24. int compareRelocsSort(const void *v1, const void *v2)
  25. {
  26.     const Reloc *r1 = v1, *r2 = v2;
  27.     pointer_t a1 = r1->address, a2 = r2->address;
  28.     return a1 < a2 ? -1 : (a1 == a2 ? 0 : 1);
  29. }
  30.  
  31. int compareRelocsSearch(const void *v1, const void *v2)
  32. {
  33.     const Reloc *r1 = v1, *r2 = v2;
  34.     pointer_t address = r1->address;
  35.     return address < r2->address ? -1 : (address >= r2->maxAddress ? 1 : 0);
  36. }
  37.  
  38. -(Reloc *)relocFor: (const void *)pointer
  39. {
  40.     Reloc *reloc;
  41.     int count;
  42.     BOOL found, tooFar;
  43.     static BOOL retrying = NO;
  44.     
  45.     if (rmFlags.invalid)
  46.     [self readInAllRelocs];
  47.     if (lastReloc
  48.     && (lastReloc->address <= (pointer_t)pointer) 
  49.     && ((pointer_t)pointer < (lastReloc->maxAddress)))
  50.     return lastReloc;
  51.     else {
  52. #if 1 
  53.     Reloc keyReloc;
  54.     keyReloc.address = (pointer_t)pointer;
  55.     if (reloc = bsearch(&keyReloc, relocs, numRelocs, relocSize, compareRelocsSearch))
  56.         found = YES;
  57.     else
  58.         found = NO;
  59. #else
  60.     reloc = relocs;
  61.     for (count = numRelocs, found = NO, tooFar = NO;
  62.          count && !found && !tooFar; count--) {
  63.         if ((pointer_t)pointer < (reloc->maxAddress)) {
  64.         if (reloc->address <= (pointer_t)pointer)
  65.             found = YES;
  66.         else
  67.             tooFar = YES;
  68.         } else
  69.         ((void *)reloc) += relocSize;
  70.     }
  71. #endif
  72.     if (!found) return NULL;
  73.     
  74.     if (!reloc->rFlags.readIn) {
  75.       if (![self readInReloc: reloc]) {
  76. /* If there was an error during a read of this reloc, it could be that
  77.  * this reloc is just stale.  Refresh the relocs and retry once.
  78.  */
  79.           if (!retrying) {
  80.            retrying = YES;
  81.            [self invalidate];
  82.            reloc = [self relocFor:pointer];
  83.            retrying = NO;
  84.            }
  85.          else
  86.            reloc = NULL;
  87.         }
  88.       }
  89.     
  90.     if (reloc) 
  91.       lastReloc = reloc;
  92.     return reloc;
  93.   }
  94. }
  95.  
  96. -(BOOL)readInReloc: (Reloc *)reloc
  97. {
  98.     [self subclassResponsibility: _cmd];
  99.     return NO;
  100. }
  101.  
  102. -(void)_readInAllRelocs
  103. {
  104.     [self subclassResponsibility: _cmd];
  105. }
  106.  
  107. -(void)readInAllRelocs
  108. {
  109.     [self _readInAllRelocs];
  110.     if (rmFlags.shouldSortRelocs)
  111.     qsort(relocs, numRelocs, relocSize, compareRelocsSort);
  112. }
  113.  
  114. -invalidate
  115. {
  116.     if (rmFlags.invalid)
  117.     return self;
  118.     else {
  119.     if (relocs) {
  120.         free(relocs); relocs = NULL;
  121.     }
  122.     numRelocs = 0;
  123.     lastReloc = NULL;
  124.     rmFlags.invalid = YES;
  125.     return self;
  126.     }
  127. }
  128.  
  129. -(Reloc *)oldRelocFor: (const void *)pointer
  130. {
  131.    int count;
  132.    BOOL found;
  133.    Reloc *reloc;
  134.     if (lastReloc
  135.     && (lastReloc->data <= (pointer_t)pointer) 
  136.     && ((pointer_t)pointer < lastReloc->maxData))
  137.     return lastReloc;
  138.     else {
  139.     reloc = relocs;
  140.     for (count = numRelocs, found = NO; count && !found; count--) {
  141.         if (reloc->rFlags.readIn && (reloc->data <= (pointer_t)pointer) 
  142.         && ((pointer_t)pointer < reloc->maxData))
  143.         found = YES;
  144.         else
  145.         ((void *)reloc) += relocSize;
  146.     }
  147.     if (found) {
  148.         lastReloc = reloc;
  149.         return reloc;
  150.     } else
  151.         return NULL;
  152.     }
  153. }
  154.  
  155. -(void *)originalPointerFor: (const void *)pointer
  156. {    
  157.     Reloc *reloc = [self oldRelocFor: pointer];
  158.     if (reloc)
  159.     return (void *)(reloc->address + (pointer - reloc->data));
  160.     else 
  161.     return NULL;
  162. }
  163.  
  164. -(void *)pointerFor: (const void *)pointer
  165. {
  166.     Reloc *reloc;
  167.     if (pointer && (reloc = [self  relocFor: pointer])) 
  168.     return (void *)((pointer_t)pointer + reloc->displacement);
  169.     else
  170.     return NULL;
  171. }
  172.  
  173. -(char *)pointerForString: (const char *)pointer isNullTerminated: (BOOL *)isNT
  174. {
  175.     char *retPointer;
  176.     Reloc *reloc;
  177.     char *string;
  178.     if (pointer && (reloc = [self relocFor: pointer])) {
  179.         retPointer = (char *)((pointer_t)pointer + reloc->displacement);
  180.     for (string = retPointer;
  181.          *string && ((pointer_t)string < reloc->maxData);
  182.          string++);
  183.     *isNT = *string ? NO : YES;
  184.     return retPointer;
  185.     } else{
  186.     *isNT = NO;
  187.     return NULL;
  188.     }
  189. }
  190.  
  191. -(char *)pointerForString: (const char *)string
  192. {
  193.     BOOL isNT;
  194.     char *retPointer;
  195.     if ((retPointer = [self pointerForString: string isNullTerminated: &isNT])
  196.     && isNT)
  197.     return retPointer;
  198.     else
  199.     return NULL;
  200. }
  201.  
  202. -(void *)pointerFor: (const void *)pointer withSize: (int)size
  203. {
  204.     Reloc *reloc;
  205.     pointer_t newPointer;
  206.     if (pointer && (reloc = [self relocFor: pointer])) {
  207.     newPointer = (pointer_t)pointer + reloc->displacement;
  208.     if ((newPointer + size) <= reloc->maxData)
  209.         return (void *)newPointer;
  210.     else
  211.         return NULL;
  212.     } else
  213.     return NULL;
  214. }
  215.  
  216. -pointerForID: (const id)pointer
  217. {
  218.     Class theClass;
  219.     struct _ObjectID {
  220.     @defs(Object)
  221.     } *newID;
  222.     
  223.     if (pointer
  224.         && (newID = [self pointerFor: pointer withSize: sizeof(id)])
  225.     && (theClass = [self pointerFor: newID->isa
  226.                            withSize: sizeof(Class)])
  227.     && (newID
  228.         = [self pointerFor: pointer withSize: theClass->instance_size]))
  229.     return (id)newID;
  230.     else
  231.     return nil;
  232. }
  233.             
  234. -(int)getDataAt: (const void *)start for: (int)numBytes into: (void *)data
  235. {
  236.     Reloc *reloc = [self relocFor: start];
  237.     int numBytesInReloc;
  238.     
  239.     if (reloc) {
  240.         numBytesInReloc = reloc->maxAddress - (int)start;
  241.         if (numBytes > numBytesInReloc)
  242.         numBytes = numBytesInReloc;
  243.     memcpy(data,
  244.            (void *)(reloc->data + ((pointer_t)start - reloc->address)),
  245.            numBytes);
  246.     return numBytes;
  247.     } else
  248.     return 0;
  249. }
  250.  
  251. -(struct mach_header *)getMachHeader
  252. {
  253.     [self subclassResponsibility: _cmd];
  254.     return NULL;
  255. }
  256.  
  257. -(unsigned)getSlide
  258. {
  259.     [self subclassResponsibility: _cmd];
  260.     return 0;
  261. }
  262.  
  263. -(int)getNumMachHeaders
  264. {
  265.     [self subclassResponsibility: _cmd];
  266.     return 0;
  267. }
  268.  
  269. -(struct mach_header **)getMachHeaders
  270. {
  271.     [self subclassResponsibility: _cmd];
  272.     return NULL;
  273. }
  274.  
  275. -(unsigned*)getSlides
  276. {
  277.     [self subclassResponsibility: _cmd];
  278.     return NULL;
  279. }
  280.  
  281. -(struct mach_header **)getMachHeadersWithNames: (char ***)names
  282. {
  283.     [self subclassResponsibility: _cmd];
  284.     return NULL;
  285. }
  286.  
  287. -(unsigned*)getSlidesWithNames: (char ***)names
  288. {
  289.     [self subclassResponsibility: _cmd];
  290.     return NULL;
  291. }
  292.  
  293. -(void *)getSectData: (STR)segName 
  294.          section: (STR)sectName 
  295.         size: (int *)pSize 
  296.        forHeader: (struct mach_header *)header
  297.            withSlide: (unsigned)slide
  298. {
  299.     void *data = getsectdatafromheader(header, segName, sectName, pSize);
  300.     return [self pointerFor: (void*) ((char*) data + slide) withSize: *pSize];
  301. }
  302.  
  303. -(void *)getSectData: (STR)segName 
  304.          section: (STR)sectName 
  305.         size: (int *)pSize 
  306. {
  307.     return [self getSectData: segName 
  308.              section: sectName 
  309.             size: pSize 
  310.            forHeader: [self getMachHeader]
  311.                withSlide: [self getSlide]];
  312. }
  313.  
  314. -(const struct section *)getSeg: (STR)segName sect: (STR)sectName
  315. {
  316.     return getsectbynamefromheader([self getMachHeader], segName, sectName);
  317. }
  318.  
  319. -(const struct section *)firstSection
  320. {
  321.     struct mach_header *header = [self getMachHeader];
  322.     int i;
  323.     struct load_command *loadCmd;
  324.     
  325.     for (i = 0, loadCmd = (struct load_command *)(header + 1);
  326.      i < header->ncmds;
  327.      i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  328.     if (loadCmd->cmd == LC_SEGMENT) {
  329.         struct segment_command *segCmd = (struct segment_command *)loadCmd;
  330.         if (segCmd->nsects)
  331.         return (struct section *)(segCmd + 1);
  332.     }
  333.     }
  334.     return NULL;
  335. }
  336.         
  337. -(unsigned)getMaximumAddressForHeader: (struct mach_header *)header withSlide:(unsigned)slide
  338. {
  339.     int i;
  340.     struct load_command *loadCmd;
  341.     unsigned maxAddr = 0;
  342.     
  343.     for (i = 0, loadCmd = (struct load_command *)(header + 1);
  344.      i < header->ncmds;
  345.      i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  346.     if (loadCmd->cmd == LC_SEGMENT) {
  347.         struct segment_command *segCmd = (struct segment_command *)loadCmd;
  348.         if ((segCmd->vmaddr + segCmd->vmsize + slide) > maxAddr)
  349.         maxAddr = segCmd->vmaddr + segCmd->vmsize;
  350.     }
  351.     }
  352.     return maxAddr;
  353. }
  354.  
  355. -(struct segment_command *)getSegment: (const char *)segName
  356. {
  357.     int i;
  358.     struct load_command *loadCmd;
  359.     struct segment_command *foundSeg = NULL;
  360.     struct mach_header *header = [self getMachHeader];
  361.     
  362.     for (i = 0, loadCmd = (struct load_command *)(header + 1);
  363.      i < header->ncmds && !foundSeg;
  364.      i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  365.     if (loadCmd->cmd == LC_SEGMENT) {
  366.         struct segment_command *segCmd = (struct segment_command *)loadCmd;
  367.         if (strcmp(segName, segCmd->segname) == 0)
  368.         foundSeg = segCmd;
  369.     }
  370.     }
  371.     return foundSeg;
  372. }
  373.  
  374. -(unsigned)getMaximumAddressForSegment: (const char *)segName
  375. {
  376.     int i;
  377.     struct load_command *loadCmd;
  378.     unsigned maxAddr = 0;
  379.     struct mach_header *header = [self getMachHeader];
  380.     unsigned int slide = [self getSlide];
  381.     
  382.     for (i = 0, loadCmd = (struct load_command *)(header + 1);
  383.      i < header->ncmds;
  384.      i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  385.     if (loadCmd->cmd == LC_SEGMENT) {
  386.         struct segment_command *segCmd = (struct segment_command *)loadCmd;
  387.         struct section *section;
  388.         int nSects;
  389.         
  390.         for (nSects = segCmd->nsects,
  391.              section = (struct section *)(segCmd + 1);
  392.              nSects;
  393.          nSects--, section++) {
  394.         if (strcmp(section->segname, segName) == 0) {
  395.             if ((section->addr + section->size + slide) > maxAddr)
  396.             maxAddr = (section->addr + section->size + slide);
  397.         }
  398.         }
  399.     }
  400.     }
  401.     return maxAddr;
  402. }
  403.  
  404. -(unsigned)getMaximumAddress
  405. {
  406.     return [self getMaximumAddressForHeader: [self getMachHeader]
  407.          withSlide: [self getSlide]];
  408. }
  409.  
  410. -(unsigned)getMinimumAddressForSegment: (const char*)segName
  411. {
  412.   int i;
  413.   struct load_command *loadCmd;
  414.   unsigned minAddr = 0xffffffffU;
  415.   struct mach_header *header = [self getMachHeader];
  416.   unsigned int slide = [self getSlide];
  417.     
  418.   for (i = 0, loadCmd = (struct load_command *)(header + 1);
  419.        i < header->ncmds;
  420.        i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  421.     if (loadCmd->cmd == LC_SEGMENT) {
  422.       struct segment_command *segCmd = (struct segment_command *)loadCmd;
  423.       struct section *section;
  424.       int nSects;
  425.         
  426.       for (nSects = segCmd->nsects,
  427.        section = (struct section *)(segCmd + 1);
  428.        nSects;
  429.        nSects--, section++) {
  430.     if (strcmp(section->segname, segName) == 0) {
  431.       if ((section->addr + slide) < minAddr)
  432.         minAddr = (section->addr + slide);
  433.     }
  434.       }
  435.     }
  436.   }
  437.   
  438.   return minAddr;
  439. }
  440.  
  441. -(unsigned)getMaximumTextAddress
  442. {
  443.     return [self getMaximumAddressForSegment: "__TEXT"];
  444. }
  445.  
  446. -(unsigned)getMaximumDataAddress
  447. {
  448.     return [self getMaximumAddressForSegment: "__DATA"];
  449. }
  450.  
  451. @end
  452.