Annotation of GNUtools/debug/Common/RegionManager.m, revision 1.1.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.