2 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
3 * Copyright (C) 2006 Graham Dennis. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #import <Cocoa/Cocoa.h>
31 #include <mach-o/dyld.h>
33 #include <mach-o/loader.h>
34 #include <mach-o/nlist.h>
37 static void cleanUpAfterOurselves(void) __attribute__ ((constructor));
39 void *symbol_lookup(char *symbol);
41 void cleanUpAfterOurselves(void)
43 char **args = *(char***)_NSGetArgv();
44 char **procPath = symbol_lookup("___CFProcessPath");
45 char *procPathBackup = *procPath;
47 CFBundleGetMainBundle();
48 *procPath = procPathBackup;
49 unsetenv("DYLD_INSERT_LIBRARIES");
50 unsetenv("CFProcessPath");
54 #define LC_SEGMENT_COMMAND LC_SEGMENT_64
55 #define macho_header mach_header_64
56 #define macho_segment_command segment_command_64
57 #define macho_section section_64
58 #define getsectdatafromheader getsectdatafromheader_64
59 #define macho_nlist nlist_64
61 #define LC_SEGMENT_COMMAND LC_SEGMENT
62 #define macho_header mach_header
63 #define macho_segment_command segment_command
64 #define macho_section section
65 #define macho_nlist nlist
68 void *GDSymbolLookup(const struct macho_header *header, const char *symbol);
70 void *symbol_lookup(char *symbol)
73 for(i=0;i<_dyld_image_count();i++)
75 void *symbolResult = GDSymbolLookup((const struct macho_header*)_dyld_get_image_header(i), symbol);
82 void *GDSymbolLookup(const struct macho_header *header, const char *symbol)
84 if (!header || !symbol)
86 if ((header->magic != MH_MAGIC) && (header->magic != MH_MAGIC_64))
90 const struct load_command *loadCommand = (const struct load_command *)( ((void *)header) + sizeof(struct macho_header));
91 const struct macho_segment_command *segCommand;
93 const struct symtab_command *symtabCommand = NULL;
94 const struct dysymtab_command *dysymtabCommand = NULL;
95 const struct macho_segment_command *textSegment = NULL;
96 const struct macho_segment_command *linkEditSegment = NULL;
98 for (currCommand = 0; currCommand < header->ncmds; currCommand++)
100 switch (loadCommand->cmd)
102 case LC_SEGMENT_COMMAND:
103 segCommand = (const struct macho_segment_command *)loadCommand;
104 if (strcmp(segCommand->segname, "__TEXT")==0)
105 textSegment = segCommand;
106 else if (strcmp(segCommand->segname, "__LINKEDIT")==0)
107 linkEditSegment = segCommand;
111 symtabCommand = (const struct symtab_command *)loadCommand;
115 dysymtabCommand = (const struct dysymtab_command *)loadCommand;
119 loadCommand = (const struct load_command *)(((void*)loadCommand) + loadCommand->cmdsize);
121 if (textSegment==NULL || linkEditSegment==NULL || symtabCommand==NULL || dysymtabCommand==NULL) {
125 typedef enum { Start = 0, LocalSymbols, ExternalSymbols, Done } SymbolSearchState;
126 uint32_t currentSymbolIndex;
127 uint32_t maximumSymbolIndex;
128 SymbolSearchState state;
130 for (state = Start + 1; state < Done; state++)
134 currentSymbolIndex = dysymtabCommand->ilocalsym;
135 maximumSymbolIndex = dysymtabCommand->ilocalsym + dysymtabCommand->nlocalsym;
138 case ExternalSymbols:
139 currentSymbolIndex = dysymtabCommand->iextdefsym;
140 maximumSymbolIndex = dysymtabCommand->nextdefsym;
146 for (; currentSymbolIndex < maximumSymbolIndex; currentSymbolIndex++)
148 const struct macho_nlist *symbolTableEntry;
149 symbolTableEntry = (const struct macho_nlist *)(currentSymbolIndex*sizeof(struct macho_nlist)
150 + (ptrdiff_t)header + symtabCommand->symoff
151 + linkEditSegment->vmaddr - linkEditSegment->fileoff
152 - textSegment->vmaddr);
153 int32_t stringTableIndex = symbolTableEntry->n_un.n_strx;
154 if (stringTableIndex<0)
156 const char *stringTableEntry = (const char*)(stringTableIndex + (ptrdiff_t)header + symtabCommand->stroff
157 + linkEditSegment->vmaddr - linkEditSegment->fileoff
158 - textSegment->vmaddr);
159 if (strcmp(symbol, stringTableEntry)==0) {
160 return ((void*)header) - textSegment->vmaddr + symbolTableEntry->n_value;