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