/* * tkMacOSXDebug.c -- * * Implementation of Macintosh specific functions for debugging MacOS * events, regions, etc... * * Copyright 2001-2009, Apple Inc. * Copyright (c) 2006-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id$ */ #include "tkMacOSXPrivate.h" #include "tkMacOSXDebug.h" #ifdef TK_MAC_DEBUG #include #include /* *---------------------------------------------------------------------- * * TkMacOSXGetNamedDebugSymbol -- * * Dynamically acquire address of a named symbol from a loaded dynamic * library, so that we can use API that may not be available on all OS * versions. For debugging purposes, if we cannot find the symbol with * the usual dynamic library APIs, we manually walk the symbol table of * the loaded library. This allows access to unexported symbols such as * private_extern internal debugging functions. If module is NULL or the * empty string, search all loaded libraries (could be very expensive and * should be avoided). * * THIS FUCTION IS ONLY TO BE USED FOR DEBUGGING PURPOSES, IT MAY BREAK * UNEXPECTEDLY IN THE FUTURE! * * Results: * Address of given symbol or NULL if unavailable. * * Side effects: * None. * *---------------------------------------------------------------------- */ MODULE_SCOPE void * TkMacOSXGetNamedDebugSymbol( const char *module, const char *symbol) { void *addr = TkMacOSXGetNamedSymbol(module, symbol); #ifndef __LP64__ if (!addr) { const struct mach_header *mh = NULL; uint32_t i, n = _dyld_image_count(); size_t module_len = 0; if (module && *module) { module_len = strlen(module); } for (i = 0; i < n; i++) { if (module && *module) { /* Find image with given module name */ char *name; const char *path = _dyld_get_image_name(i); if (!path) { continue; } name = strrchr(path, '/') + 1; if (strncmp(name, module, module_len) != 0) { continue; } } mh = _dyld_get_image_header(i); if (mh) { struct load_command *lc; struct symtab_command *st = NULL; struct segment_command *sg = NULL; uint32_t j, m, nsect = 0, txtsectx = 0; lc = (struct load_command*)((const char*) mh + sizeof(struct mach_header)); m = mh->ncmds; for (j = 0; j < m; j++) { /* Find symbol table and index of __text section */ if (lc->cmd == LC_SEGMENT) { /* Find last segment before symbol table */ sg = (struct segment_command*) lc; if (!txtsectx) { /* Count total sections until (__TEXT, __text) */ uint32_t k, ns = sg->nsects; if (strcmp(sg->segname, SEG_TEXT) == 0) { struct section *s = (struct section *)( (char *)sg + sizeof(struct segment_command)); for(k = 0; k < ns; k++) { if (strcmp(s->sectname, SECT_TEXT) == 0) { txtsectx = nsect+k+1; break; } s++; } } nsect += ns; } } else if (!st && lc->cmd == LC_SYMTAB) { st = (struct symtab_command *) lc; break; } lc = (struct load_command *)((char *) lc + lc->cmdsize); } if (st && sg && txtsectx) { intptr_t base, slide = _dyld_get_image_vmaddr_slide(i); char *strings; struct nlist *sym; uint32_t strsize = st->strsize; int32_t strx; /* * Offset file positions by difference to actual position * in memory of last segment before symbol table: */ base = (intptr_t) sg->vmaddr + slide - sg->fileoff; strings = (char *) (base + st->stroff); sym = (struct nlist *) (base + st->symoff); m = st->nsyms; for (j = 0; j < m; j++) { /* Find symbol with given name in __text section */ strx = sym->n_un.n_strx; if ((sym->n_type & N_TYPE) == N_SECT && sym->n_sect == txtsectx && strx > 0 && (uint32_t) strx < strsize && strcmp(strings + strx, symbol) == 0) { addr = (char*) sym->n_value + slide; break; } sym++; } } } if (module && *module) { /* If given a module name, only search corresponding image */ break; } } } #endif /* __LP64__ */ return addr; } #endif /* TK_MAC_DEBUG */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 79 * coding: utf-8 * End: */