1/* 2 * tkMacOSXDebug.c -- 3 * 4 * Implementation of Macintosh specific functions for debugging MacOS 5 * events, regions, etc... 6 * 7 * Copyright 2001-2009, Apple Inc. 8 * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net> 9 * 10 * See the file "license.terms" for information on usage and redistribution 11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 12 * 13 * RCS: @(#) $Id$ 14 */ 15 16#include "tkMacOSXPrivate.h" 17#include "tkMacOSXDebug.h" 18 19#ifdef TK_MAC_DEBUG 20 21#include <mach-o/dyld.h> 22#include <mach-o/nlist.h> 23 24/* 25 *---------------------------------------------------------------------- 26 * 27 * TkMacOSXGetNamedDebugSymbol -- 28 * 29 * Dynamically acquire address of a named symbol from a loaded dynamic 30 * library, so that we can use API that may not be available on all OS 31 * versions. For debugging purposes, if we cannot find the symbol with 32 * the usual dynamic library APIs, we manually walk the symbol table of 33 * the loaded library. This allows access to unexported symbols such as 34 * private_extern internal debugging functions. If module is NULL or the 35 * empty string, search all loaded libraries (could be very expensive and 36 * should be avoided). 37 * 38 * THIS FUCTION IS ONLY TO BE USED FOR DEBUGGING PURPOSES, IT MAY BREAK 39 * UNEXPECTEDLY IN THE FUTURE! 40 * 41 * Results: 42 * Address of given symbol or NULL if unavailable. 43 * 44 * Side effects: 45 * None. 46 * 47 *---------------------------------------------------------------------- 48 */ 49 50MODULE_SCOPE void * 51TkMacOSXGetNamedDebugSymbol( 52 const char *module, 53 const char *symbol) 54{ 55 void *addr = TkMacOSXGetNamedSymbol(module, symbol); 56 57#ifndef __LP64__ 58 if (!addr) { 59 const struct mach_header *mh = NULL; 60 uint32_t i, n = _dyld_image_count(); 61 size_t module_len = 0; 62 63 if (module && *module) { 64 module_len = strlen(module); 65 } 66 for (i = 0; i < n; i++) { 67 if (module && *module) { 68 /* Find image with given module name */ 69 char *name; 70 const char *path = _dyld_get_image_name(i); 71 72 if (!path) { 73 continue; 74 } 75 name = strrchr(path, '/') + 1; 76 if (strncmp(name, module, module_len) != 0) { 77 continue; 78 } 79 } 80 mh = _dyld_get_image_header(i); 81 if (mh) { 82 struct load_command *lc; 83 struct symtab_command *st = NULL; 84 struct segment_command *sg = NULL; 85 uint32_t j, m, nsect = 0, txtsectx = 0; 86 87 lc = (struct load_command*)((const char*) mh + 88 sizeof(struct mach_header)); 89 m = mh->ncmds; 90 for (j = 0; j < m; j++) { 91 /* Find symbol table and index of __text section */ 92 if (lc->cmd == LC_SEGMENT) { 93 /* Find last segment before symbol table */ 94 sg = (struct segment_command*) lc; 95 if (!txtsectx) { 96 /* Count total sections until (__TEXT, __text) */ 97 uint32_t k, ns = sg->nsects; 98 99 if (strcmp(sg->segname, SEG_TEXT) == 0) { 100 struct section *s = (struct section *)( 101 (char *)sg + 102 sizeof(struct segment_command)); 103 104 for(k = 0; k < ns; k++) { 105 if (strcmp(s->sectname, SECT_TEXT) == 0) { 106 txtsectx = nsect+k+1; 107 break; 108 } 109 s++; 110 } 111 } 112 nsect += ns; 113 } 114 } else if (!st && lc->cmd == LC_SYMTAB) { 115 st = (struct symtab_command *) lc; 116 break; 117 } 118 lc = (struct load_command *)((char *) lc + lc->cmdsize); 119 } 120 if (st && sg && txtsectx) { 121 intptr_t base, slide = _dyld_get_image_vmaddr_slide(i); 122 char *strings; 123 struct nlist *sym; 124 uint32_t strsize = st->strsize; 125 int32_t strx; 126 127 /* 128 * Offset file positions by difference to actual position 129 * in memory of last segment before symbol table: 130 */ 131 132 base = (intptr_t) sg->vmaddr + slide - sg->fileoff; 133 strings = (char *) (base + st->stroff); 134 sym = (struct nlist *) (base + st->symoff); 135 m = st->nsyms; 136 for (j = 0; j < m; j++) { 137 /* Find symbol with given name in __text section */ 138 strx = sym->n_un.n_strx; 139 if ((sym->n_type & N_TYPE) == N_SECT && 140 sym->n_sect == txtsectx && 141 strx > 0 && (uint32_t) strx < strsize && 142 strcmp(strings + strx, symbol) == 0) { 143 addr = (char*) sym->n_value + slide; 144 break; 145 } 146 sym++; 147 } 148 } 149 } 150 if (module && *module) { 151 /* If given a module name, only search corresponding image */ 152 break; 153 } 154 } 155 } 156#endif /* __LP64__ */ 157 return addr; 158} 159#endif /* TK_MAC_DEBUG */ 160 161/* 162 * Local Variables: 163 * mode: c 164 * c-basic-offset: 4 165 * fill-column: 79 166 * coding: utf-8 167 * End: 168 */ 169