summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXDebug.c
diff options
context:
space:
mode:
Diffstat (limited to 'macosx/tkMacOSXDebug.c')
-rw-r--r--macosx/tkMacOSXDebug.c134
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 */