|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.0 (the 'License'). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License." ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: #import <libc.h> ! 26: #import <stdio.h> ! 27: #import <streams/streams.h> ! 28: #import <mach-o/loader.h> ! 29: ! 30: #define SIZEHASHTABLE 821 ! 31: ! 32: typedef struct optHashedSelector OHASH, *POHASH; ! 33: ! 34: struct optHashedSelector { ! 35: POHASH next; ! 36: const char * key_uid; ! 37: }; ! 38: ! 39: #define MAP_HASH(x) \ ! 40: (x ? (void *) ((int) hashtable + (int) (x) - hashtable_addr) : NULL) ! 41: #define MAP_STRING(x) \ ! 42: (x ? (void *) ((int) strings + (int) (x) - strings_addr): NULL) ! 43: #define UNMAP_HASH(x) \ ! 44: (x ? (void *) (hashtable_addr + (int) (x) - (int) hashtable) : NULL) ! 45: ! 46: int main (int argc, char *argv[]) ! 47: { ! 48: NXStream *stream; ! 49: char *buffer; ! 50: int length, allocLength; ! 51: const struct mach_header *header; ! 52: const struct section *section; ! 53: POHASH *hashtable; ! 54: const char *strings; ! 55: int hashtable_addr, strings_addr, strings_size, hashtable_size; ! 56: unsigned int i; ! 57: unsigned int maxLength = 0; ! 58: unsigned int total = 0; ! 59: unsigned int emptyBuckets = 0; ! 60: ! 61: if (argc != 2) ! 62: { ! 63: fprintf (stderr, "usage: %s filename\n", argv[0]); ! 64: return EXIT_FAILURE; ! 65: } ! 66: ! 67: stream = NXMapFile (argv[1], NX_READONLY); ! 68: ! 69: NXGetMemoryBuffer (stream, &buffer, &length, &allocLength); ! 70: ! 71: header = (const struct mach_header *) buffer; ! 72: ! 73: section = getsectbynamefromheader (header, "__OBJC", "__runtime_setup"); ! 74: ! 75: if (!section || section->size == 0) ! 76: { ! 77: fprintf (stderr, "cannot find __runtime_setup section\n"); ! 78: exit (EXIT_FAILURE); ! 79: } ! 80: ! 81: hashtable_addr = (int) section->addr; ! 82: hashtable_size = (int) section->size; ! 83: hashtable = (POHASH *) (buffer + section->offset); ! 84: ! 85: printf ("%d hashtable entries from 0x%x to 0x%x\n", ! 86: SIZEHASHTABLE, ! 87: hashtable_addr, ! 88: hashtable_addr + SIZEHASHTABLE * sizeof (POHASH)); ! 89: printf ("%d buckets from 0x%x to 0x%x\n", ! 90: (hashtable_size - SIZEHASHTABLE * sizeof (POHASH)) / sizeof (OHASH), ! 91: hashtable_addr + SIZEHASHTABLE * sizeof (POHASH), ! 92: hashtable_addr + hashtable_size); ! 93: ! 94: section = getsectbynamefromheader (header, "__OBJC", "__meth_var_names"); ! 95: ! 96: if (!section || section->size == 0) ! 97: section = getsectbynamefromheader (header, "__OBJC", "__selector_strs"); ! 98: ! 99: if (!section || section->size == 0) ! 100: { ! 101: fprintf (stderr, ! 102: "cannot find __meth_var_names or __selector_strs section\n"); ! 103: exit (EXIT_FAILURE); ! 104: } ! 105: ! 106: strings_addr = (int) section->addr; ! 107: strings_size = (int) section->size; ! 108: strings = (const char *) (buffer + section->offset); ! 109: ! 110: printf ("%d bytes of strings from 0x%x to 0x%x\n", ! 111: strings_size, ! 112: strings_addr, ! 113: strings_addr + strings_size); ! 114: ! 115: for (i = 0; i < SIZEHASHTABLE; i++) ! 116: { ! 117: POHASH target = MAP_HASH (hashtable[i]); ! 118: int length = 0; ! 119: ! 120: // printf ("hash[%d]:", i); ! 121: ! 122: while (target) ! 123: { ! 124: POHASH next; ! 125: const char *string = MAP_STRING (target->key_uid); ! 126: ! 127: length++; ! 128: ! 129: if (string < strings || strings >= strings + strings_size) ! 130: { ! 131: printf ("Bad string pointer 0x%x in entry %d at address 0x%x\n", ! 132: string, i, UNMAP_HASH (&target->key_uid)); ! 133: target = 0; ! 134: continue; ! 135: } ! 136: if (string != strings && string[-1] != '\0') ! 137: { ! 138: const char *start = strrchr (string - 1, '\0') + 1; ! 139: ! 140: printf ("bad string %s in entry %d (substring of %s)\n", ! 141: string, i, start); ! 142: } ! 143: // printf ( " %s", string); ! 144: next = MAP_HASH (target->next); ! 145: if (next && (next < (POHASH) &hashtable[SIZEHASHTABLE] ! 146: || next >= (POHASH) ((int) hashtable + hashtable_size))) ! 147: { ! 148: printf ("Bad next pointer 0x%x in entry %d at address 0x%x\n", ! 149: next, i, UNMAP_HASH (&target->next)); ! 150: next = 0; ! 151: } ! 152: target = next; ! 153: } ! 154: ! 155: // printf ("\n"); ! 156: ! 157: total += length; ! 158: ! 159: if (length == 0) ! 160: emptyBuckets++; ! 161: ! 162: if (length > maxLength) ! 163: maxLength = length; ! 164: } ! 165: ! 166: printf ("%d buckets\n", SIZEHASHTABLE); ! 167: printf ("%d entries\n", total); ! 168: printf ("%f average entries/bucket\n", (float) total / SIZEHASHTABLE); ! 169: printf ("%d maximum entries/bucket\n", maxLength); ! 170: printf ("%d empty buckets\n", emptyBuckets); ! 171: ! 172: return EXIT_SUCCESS; ! 173: } ! 174: ! 175: #if 0 ! 176: �� ! 177: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.