diff options
Diffstat (limited to 'macosx/tkMacOSXDebug.c')
-rw-r--r-- | macosx/tkMacOSXDebug.c | 134 |
1 files changed, 133 insertions, 1 deletions
diff --git a/macosx/tkMacOSXDebug.c b/macosx/tkMacOSXDebug.c index 77d700d..37d2750 100644 --- a/macosx/tkMacOSXDebug.c +++ b/macosx/tkMacOSXDebug.c @@ -50,13 +50,17 @@ * software in accordance with the terms specified in this * license. * - * RCS: @(#) $Id: tkMacOSXDebug.c,v 1.2.2.4 2005/11/27 02:36:46 das Exp $ + * RCS: @(#) $Id: tkMacOSXDebug.c,v 1.2.2.5 2006/01/10 05:38:20 das Exp $ */ +#include "tkMacOSXInt.h" #include "tkMacOSXDebug.h" #ifdef TK_MAC_DEBUG +#include <mach-o/dyld.h> +#include <mach-o/nlist.h> + typedef struct { EventKind kind; char * name; @@ -447,5 +451,133 @@ MouseTrackingResultToAscii(MouseTrackingResult r, char * buf) sprintf(buf, "Unknown mouse tracking result : %d", r); return buf; } + +/* + *---------------------------------------------------------------------- + * + * 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. + * + *---------------------------------------------------------------------- + */ + +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(); + + 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, strlen(name)) != 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*)((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 && strx < strsize && + strcmp(strings + strx, symbol) == 0) { + addr = (void*) 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 */ |