Annotation of GNUtools/debug/Common/RegionManager.m, revision 1.1

1.1     ! root        1: #import "RegionManager.h"
        !             2: #import <stdlib.h>
        !             3: #import <string.h>
        !             4: #import <mach/mach.h>
        !             5: #import <mach-o/loader.h>
        !             6: #import <mach/vm_param.h>
        !             7: 
        !             8: kern_return_t static inline vmRegion(task_t task, 
        !             9:                                     vm_address_t address,
        !            10:                                     Region *region)
        !            11: {
        !            12:     vm_offset_t        offset;
        !            13:     vm_prot_t maxProtection;
        !            14:     vm_inherit_t inheritance;
        !            15:     boolean_t shared;
        !            16:     port_t objectName;
        !            17:     region->reloc.address = address;
        !            18:     return vm_region(task,
        !            19:                     &region->reloc.address,
        !            20:                     &region->reloc.size,
        !            21:                     &region->protection,
        !            22:                     &maxProtection,
        !            23:                     &inheritance,
        !            24:                     &shared,
        !            25:                     &objectName,
        !            26:                     &offset);
        !            27: }
        !            28: 
        !            29: @implementation RegionManager
        !            30: 
        !            31: -initTask: (vm_task_t)theTask readInRegions: (BOOL)readInRegions
        !            32: {
        !            33:     vm_statistics_data_t vm_stats;
        !            34:     
        !            35:     task = theTask;
        !            36:     vm_statistics(theTask, &vm_stats);
        !            37:     pageSize = vm_stats.pagesize;
        !            38:     relocSize = sizeof(Region);
        !            39:     rmFlags.shouldSortRelocs = NO;
        !            40:     if (readInRegions)
        !            41:        [self readInAllRelocs];
        !            42:     else
        !            43:        rmFlags.invalid = YES;
        !            44:     return self;
        !            45: }
        !            46: 
        !            47: -(BOOL)isTask
        !            48: {
        !            49:     struct task_basic_info taskInfo;
        !            50:     unsigned int taskInfoCount;
        !            51:     BOOL ret;
        !            52:     
        !            53:     taskInfoCount = TASK_BASIC_INFO_COUNT;
        !            54:     ret = (task_info(task,
        !            55:                        TASK_BASIC_INFO,
        !            56:                       (task_info_t)&taskInfo,
        !            57:                       &taskInfoCount) == KERN_SUCCESS) ? YES : NO;
        !            58:     if (!ret && taskGoneCallBack)
        !            59:        (*taskGoneCallBack)();
        !            60:     return ret;
        !            61: }
        !            62: 
        !            63: -(void)setTaskGoneCallBack: (TaskGoneCallBack)theCallBack
        !            64: {
        !            65:     taskGoneCallBack = theCallBack;
        !            66: }
        !            67: 
        !            68: +newTask: (vm_task_t)theTask
        !            69: {
        !            70:     return [[super new] initTask: theTask readInRegions: YES];
        !            71: }
        !            72: 
        !            73: +newTask: (vm_task_t)theTask readInRegions: (BOOL)readInRegions
        !            74: {
        !            75:     return [[super new] initTask: theTask readInRegions: readInRegions];
        !            76: }
        !            77: 
        !            78: -invalidate
        !            79: {
        !            80:     if (rmFlags.invalid)
        !            81:        return self;
        !            82:     else {
        !            83:        Region *region;
        !            84:        int count;
        !            85:        if (relocs) {
        !            86:            for (count = numRelocs, region = (Region *)relocs;
        !            87:                 count; 
        !            88:                 count--, region++) {
        !            89:                if (region->reloc.rFlags.readIn)
        !            90:                    vm_deallocate(task_self(),
        !            91:                                  region->reloc.data,
        !            92:                                  region->reloc.size);
        !            93:            }
        !            94:        }
        !            95:        if (pages) {
        !            96:            free(pages);
        !            97:            pages = NULL;
        !            98:        }
        !            99:        return [super invalidate];
        !           100:     }
        !           101: }
        !           102: 
        !           103: -(void)getStartPage: (void **)startPage andSize: (int *)sizePage
        !           104:          forPointer: (void *)start      andSize: (int)numBytes
        !           105: {
        !           106:     vm_address_t offset = ((vm_address_t)start % pageSize);
        !           107:     vm_address_t s = numBytes + offset;
        !           108:     
        !           109:     *startPage = start - offset;
        !           110:     *sizePage =  (s - (s % pageSize)) + pageSize;
        !           111: }
        !           112:                
        !           113: -(void)protectDataAt: (const void *)start for: (int)numBytes
        !           114: {
        !           115:     vm_address_t offset = ((vm_address_t)start % pageSize);
        !           116:     vm_address_t startPage = (vm_address_t)start - offset;
        !           117:     size_t sizePage = numBytes + offset;
        !           118:     
        !           119:     vm_protect(task, startPage, pageSize, NO, VM_PROT_READ);
        !           120: }
        !           121: 
        !           122: -(void)unProtectDataAt: (const void *)start for: (int)numBytes
        !           123: {
        !           124:     vm_address_t offset = ((vm_address_t)start % pageSize);
        !           125:     vm_address_t startPage = (vm_address_t)start - offset;
        !           126:     size_t sizePage = numBytes + offset;
        !           127:     
        !           128:     vm_protect(task, startPage, pageSize, NO, VM_PROT_READ | VM_PROT_WRITE);
        !           129: }
        !           130: 
        !           131: -(int)writeDataAt: (const void *)start for: (int)numBytes reloc: (Region *)region markOnly: (BOOL)markOnly
        !           132: {
        !           133:     vm_address_t offset = ((vm_address_t)start % pageSize);
        !           134:     vm_address_t startPage = (vm_address_t)start - offset;
        !           135:     size_t sizePage = numBytes + offset;
        !           136:     pointer_t startData;
        !           137:     kern_return_t ret = 0;
        !           138:     unsigned char *pPage;
        !           139:     
        !           140:     if (markOnly) {
        !           141:        if (!region->pagesInvalid)
        !           142:            regionsInvalid++;
        !           143:     }
        !           144:     for (sizePage += (pageSize - (sizePage % pageSize)),
        !           145:          startData = region->reloc.data
        !           146:                      + ((pointer_t)startPage - region->reloc.address),
        !           147:          pPage = region->pages
        !           148:                 + (((pointer_t)startPage - region->reloc.address) / pageSize);
        !           149:          sizePage && !ret;
        !           150:         sizePage -= pageSize, startData += pageSize, startPage += pageSize,
        !           151:         pPage++) {
        !           152:        if (markOnly) {
        !           153:            if (!(*pPage & PAGEINVALID)) {
        !           154:                *pPage |= PAGEINVALID;
        !           155:                region->pagesInvalid++;
        !           156:            }
        !           157:        } else {
        !           158:            *pPage &= ~PAGEINVALID;
        !           159:            if (*pPage & VM_PROT_WRITE)
        !           160:                ret = vm_write(task, startPage, startData, pageSize);
        !           161:            else {
        !           162:                vm_protect(task, startPage, pageSize, NO, VM_PROT_WRITE);
        !           163:                ret = vm_write(task, startPage, startData, pageSize);
        !           164:                vm_protect(task, startPage, pageSize, NO,
        !           165:                            (vm_prot_t)(*pPage & 0x7));
        !           166:            }
        !           167:        }
        !           168:     }
        !           169:     if (ret == KERN_SUCCESS)
        !           170:        return numBytes;
        !           171:     else {
        !           172:        [self isTask];
        !           173:        return 0;
        !           174:     }
        !           175: }
        !           176: 
        !           177: -(int)writeDataAt: (const void *)start for: (int)numBytes reloc: (Region *)region
        !           178: {
        !           179:     return [self writeDataAt: start for: numBytes reloc: region markOnly: NO];
        !           180: }
        !           181: 
        !           182: -(int)putDataAt: (void *)start for: (int)numBytes from: (const void *)data markOnly: (BOOL)markOnly
        !           183: {
        !           184:     int numBytesInRegion;
        !           185:     Reloc *reloc = [self relocFor: start];
        !           186:     if (reloc) {
        !           187:         numBytesInRegion = reloc->maxAddress - (int)start;
        !           188:         if (numBytes > numBytesInRegion)
        !           189:            numBytes = numBytesInRegion;
        !           190:        if (numBytes == 1)
        !           191:            *(char *)(reloc->data + ((pointer_t)start - reloc->address))
        !           192:            = *(char *)data;
        !           193:        else
        !           194:            memcpy((void *)(reloc->data + ((pointer_t)start - reloc->address)),
        !           195:                   data,
        !           196:                   numBytes);
        !           197:        return [self writeDataAt: start for: numBytes  reloc: (Region *)reloc markOnly: markOnly];
        !           198:     } else
        !           199:        return 0;
        !           200: }
        !           201: 
        !           202: -(int)putDataAt: (void *)start for: (int)numBytes from: (const void *)data
        !           203: {
        !           204:     return [self putDataAt: start for: numBytes from: data markOnly: NO];
        !           205: }
        !           206: 
        !           207: -(void)flushMarkedPages
        !           208: {
        !           209:     int ret = 0;
        !           210:     while (regionsInvalid) {
        !           211:        int i;
        !           212:        Region *region;
        !           213:        
        !           214:        for (i = 0, region = (Region *)relocs;
        !           215:             i < numRelocs;
        !           216:             i++, ((void *)region) += relocSize) {
        !           217:            if (region->pagesInvalid) {
        !           218:                unsigned char *p = region->pages;
        !           219:                while (region->pagesInvalid) {
        !           220:                    if (*p & PAGEINVALID) {
        !           221:                        int numPage = p - region->pages;
        !           222:                        pointer_t startPage, startData;
        !           223:                        
        !           224:                        startPage
        !           225:                        = region->reloc.address + (numPage * pageSize);
        !           226:                        startData
        !           227:                        = region->reloc.data + (numPage * pageSize);
        !           228:                        *p &= ~PAGEINVALID;
        !           229:                        region->pagesInvalid--;
        !           230:                        if (*p & VM_PROT_WRITE)
        !           231:                            ret = vm_write(task, startPage, startData, pageSize);
        !           232:                        else {
        !           233:                            vm_protect(task, startPage, pageSize, NO, VM_PROT_WRITE);
        !           234:                            ret = vm_write(task, startPage, startData, pageSize);
        !           235:                            vm_protect(task, startPage, pageSize, NO,
        !           236:                                        (vm_prot_t)(*p & 0x7));
        !           237:                        }
        !           238:                    }
        !           239:                    p++;
        !           240:                }
        !           241:                regionsInvalid--;
        !           242:            }
        !           243:        }
        !           244:     }
        !           245:     if (ret) 
        !           246:        [self isTask];
        !           247: }
        !           248: 
        !           249: -(int)writeDataAt: (const void *)start for: (int)numBytes;
        !           250: {
        !           251:     Reloc *reloc = [self relocFor: start];
        !           252:     if (reloc)
        !           253:        return [self writeDataAt: start for: numBytes reloc: (Region *)reloc];
        !           254:     else
        !           255:        return NO;
        !           256: }
        !           257: 
        !           258: -(BOOL)readInReloc: (Reloc *)reloc
        !           259: {
        !           260:     kern_return_t ret;
        !           261:     unsigned int nData;
        !           262:     if (reloc->rFlags.readIn) {
        !           263:        return YES;
        !           264:     } else {
        !           265:        ret = vm_read(task, reloc->address, reloc->size, &reloc->data, &nData);
        !           266:        if (ret == KERN_SUCCESS) {
        !           267:            reloc->maxData = reloc->data + reloc->size;
        !           268:            reloc->displacement = reloc->data - reloc->address;
        !           269:            reloc->rFlags.readIn = YES;
        !           270:            return YES;
        !           271:        } else {
        !           272:            [self isTask];
        !           273:            return NO;
        !           274:        }
        !           275:     }
        !           276: }
        !           277: 
        !           278: -(void)combineRegions: (BOOL)combineRegions
        !           279: { dontCombineRegions = !combineRegions;}
        !           280: 
        !           281: -(void)_readInAllRelocs
        !           282: {
        !           283:     kern_return_t error = 0;
        !           284:     vm_address_t address = VM_MIN_ADDRESS;
        !           285:     Region *theRegion, *regions, *newRegion, *nextRegion, *lastRegion;
        !           286:     int count = 0, numPages = 0, numAlloced = 16, nPages;
        !           287:     unsigned char *thePage;
        !           288:     
        !           289:     if ([self isTask]) {
        !           290:        theRegion = regions = malloc(numAlloced * sizeof(Region));
        !           291:        bzero(regions, numAlloced * sizeof(Region));
        !           292:        while (!error) {
        !           293:            error = vmRegion(task, address, theRegion);
        !           294:            address = theRegion->reloc.address + theRegion->reloc.size;
        !           295:            if (!error) {
        !           296:                if (theRegion->protection & VM_PROT_READ) {
        !           297:                    count++;
        !           298:                    numPages += theRegion->reloc.size / pageSize;
        !           299:                    if (count < numAlloced)
        !           300:                        theRegion++;
        !           301:                    else {
        !           302:                        numAlloced *= 2;
        !           303:                        regions = realloc(regions,
        !           304:                                          numAlloced * sizeof(Region));
        !           305:                        theRegion = regions + count;
        !           306:                        bzero(theRegion, count * sizeof(Region));
        !           307:                    }
        !           308:                }
        !           309:                if (address < theRegion->reloc.address)
        !           310:                    error = KERN_NO_SPACE;
        !           311:            }
        !           312:        }
        !           313:        if (error == KERN_NO_SPACE) {
        !           314:            lastRegion = theRegion;
        !           315:        
        !           316:            pages = malloc(numPages);
        !           317:            for (theRegion = regions, thePage = pages;
        !           318:                 theRegion < lastRegion;
        !           319:                 theRegion++) {
        !           320:                theRegion->pages = thePage;
        !           321:                nPages = theRegion->reloc.size / pageSize;
        !           322:                while(nPages--)
        !           323:                    *(thePage++) = (unsigned char)theRegion->protection;
        !           324:            }
        !           325:            
        !           326:            if (dontCombineRegions) {
        !           327:                for (theRegion = regions; theRegion < lastRegion; theRegion++)
        !           328:                    theRegion->reloc.maxAddress
        !           329:                    = theRegion->reloc.address + theRegion->reloc.size;
        !           330:                relocs = regions;
        !           331:                numRelocs = count;
        !           332:            } else {
        !           333:                relocs = malloc(count * sizeof(Region));
        !           334:                bzero(relocs, count * sizeof(Region));
        !           335:                for (theRegion = regions, newRegion = relocs;
        !           336:                    theRegion < lastRegion;
        !           337:                    theRegion = nextRegion, newRegion++) {
        !           338:                    for (nextRegion = theRegion + 1;
        !           339:                        (nextRegion < lastRegion
        !           340:                        && ((theRegion->reloc.address + theRegion->reloc.size)
        !           341:                            == nextRegion->reloc.address));
        !           342:                        nextRegion++) {
        !           343:                        theRegion->reloc.size += nextRegion->reloc.size;
        !           344:                    }
        !           345:                    *newRegion = *theRegion;
        !           346:                    newRegion->reloc.maxAddress
        !           347:                    = newRegion->reloc.address + newRegion->reloc.size;
        !           348:                }
        !           349:                numRelocs = newRegion - (Region *)relocs;
        !           350:                relocs = realloc(relocs, numRelocs * sizeof(Region));
        !           351:                free(regions);
        !           352:            }
        !           353:            rmFlags.invalid = NO;
        !           354:        } else
        !           355:            free(regions);
        !           356:            
        !           357:        if (error != KERN_NO_SPACE) 
        !           358:            [self isTask];
        !           359:     } 
        !           360: }
        !           361: 
        !           362: -(struct mach_header *)getMachHeader
        !           363: {
        !           364:     Reloc *reloc;
        !           365:     int count;
        !           366:     struct mach_header *header, *foundHeader;
        !           367: 
        !           368:     if (rmFlags.invalid)
        !           369:        [self readInAllRelocs];
        !           370:     reloc = relocs;
        !           371:     for (foundHeader = NULL, count = 0;
        !           372:          !foundHeader && count < numRelocs;
        !           373:         count++) {
        !           374:        [self readInReloc: reloc];
        !           375:        header = [self pointerFor: (void *)reloc->address
        !           376:                         withSize: sizeof(*header)];
        !           377:        if (header
        !           378:            && (header->magic == MH_MAGIC)
        !           379:            && ([self pointerFor: (void *)reloc->address
        !           380:                        withSize: header->sizeofcmds]))
        !           381:            foundHeader = header;
        !           382:        else
        !           383:            ((void *)reloc) += relocSize;
        !           384:     }
        !           385:     return foundHeader;
        !           386: }
        !           387: 
        !           388: -(int)getNumMachHeaders
        !           389: {
        !           390:     struct mach_header *myHeader;
        !           391:     int numHeaders, i;
        !           392:     struct fvmlib_command *loadCmd;
        !           393:     if (myHeader = [self getMachHeader]) {
        !           394:        numHeaders = 1;
        !           395:        for (i = 0, loadCmd = (struct fvmlib_command *)(myHeader + 1);
        !           396:             i < myHeader->ncmds;
        !           397:             i++,
        !           398:             loadCmd = ((void *)loadCmd + loadCmd->cmdsize)) {
        !           399:            if (loadCmd->cmd == LC_LOADFVMLIB)
        !           400:                numHeaders++;
        !           401:        }
        !           402:     } else
        !           403:        numHeaders = 0;
        !           404:     return numHeaders;
        !           405: }
        !           406: 
        !           407: -(struct mach_header **)getMachHeadersWithNames: (char ***)names
        !           408: {
        !           409:     struct mach_header *myHeader, **headers, *header;
        !           410:     char **theNames = NULL;
        !           411:     struct fvmlib_command *loadCmd;
        !           412:     int numHeaders, headerIndex;
        !           413:     numHeaders = [self getNumMachHeaders];
        !           414:     myHeader = [self getMachHeader];
        !           415:     headers = malloc((numHeaders + 1) * sizeof(*headers));
        !           416:     if (names) {
        !           417:        *names = theNames = malloc((numHeaders + 1) * sizeof(*theNames));
        !           418:        theNames[0] = NULL;
        !           419:     }
        !           420:     headers[0] = myHeader;
        !           421:     for (headerIndex = 1, loadCmd = (struct fvmlib_command *)(myHeader + 1); 
        !           422:         headerIndex < numHeaders;
        !           423:         loadCmd = ((void *)loadCmd + loadCmd->cmdsize)) {
        !           424:        if (loadCmd->cmd == LC_LOADFVMLIB) {
        !           425:            header = [self pointerFor: (void *)(loadCmd->fvmlib.header_addr) 
        !           426:                             withSize: sizeof(*header)];
        !           427:            if (header)
        !           428:                headers[headerIndex]
        !           429:                = [self pointerFor: (void *)(loadCmd->fvmlib.header_addr)
        !           430:                          withSize: header->sizeofcmds];
        !           431:            if (names)
        !           432:                theNames[headerIndex]
        !           433:                = (char *)loadCmd
        !           434:                            + ((struct fvmlib_command *)loadCmd)
        !           435:                            ->fvmlib.name.offset; 
        !           436:            headerIndex++;
        !           437:        }
        !           438:     }
        !           439:     headers[numHeaders] = NULL;
        !           440:     if (names)
        !           441:        theNames[numHeaders] = NULL;
        !           442:     return headers;
        !           443: }
        !           444: 
        !           445: -(struct mach_header **)getMachHeaders
        !           446: {
        !           447:     return [self getMachHeadersWithNames: NULL];
        !           448: }
        !           449: 
        !           450: @end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.