Reviewed by Darin, landed by Maciej.
[WebKit-https.git] / WebKitTools / WebKitLauncher / WebKitNightlyEnabler.m
1 /*
2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3  * Copyright (C) 2006 Graham Dennis.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
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. 
17  *
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.
28  */
29
30 #import <Cocoa/Cocoa.h>
31 #include <mach-o/dyld.h>
32 #include <dlfcn.h>
33 #include <mach-o/loader.h>
34 #include <mach-o/nlist.h>
35 #include <string.h>
36
37 static void cleanUpAfterOurselves(void) __attribute__ ((constructor));
38
39 void *symbol_lookup(char *symbol);
40
41 void cleanUpAfterOurselves(void)
42 {
43     char **args = *(char***)_NSGetArgv();
44     char **procPath = symbol_lookup("___CFProcessPath");
45     char *procPathBackup = *procPath;
46     *procPath = args[0];
47     CFBundleGetMainBundle();
48     *procPath = procPathBackup;
49     unsetenv("DYLD_INSERT_LIBRARIES");
50     unsetenv("CFProcessPath");
51 }
52
53 #if __LP64__
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
60 #else
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
66 #endif
67
68 void *GDSymbolLookup(const struct macho_header *header, const char *symbol);
69
70 void *symbol_lookup(char *symbol)
71 {
72     int i;
73     for(i=0;i<_dyld_image_count();i++)
74     {    
75         void *symbolResult = GDSymbolLookup((const struct macho_header*)_dyld_get_image_header(i), symbol);
76         if (symbolResult)
77             return symbolResult;
78     }
79     return NULL;
80 }
81
82 void *GDSymbolLookup(const struct macho_header *header, const char *symbol)
83 {
84     if (!header || !symbol)
85         return NULL;
86     if ((header->magic != MH_MAGIC) && (header->magic != MH_MAGIC_64))
87         return NULL;
88     
89     uint32_t currCommand;
90     const struct load_command *loadCommand = (const struct load_command *)( ((void *)header) + sizeof(struct macho_header));
91     const struct macho_segment_command *segCommand;
92     
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;
97     
98     for (currCommand = 0; currCommand < header->ncmds; currCommand++)
99     {
100         switch (loadCommand->cmd)
101         {
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;
108                     break;
109                 
110             case LC_SYMTAB:
111                 symtabCommand = (const struct symtab_command *)loadCommand;
112                 break;
113                 
114             case LC_DYSYMTAB:
115                 dysymtabCommand = (const struct dysymtab_command *)loadCommand;
116                 break;
117         }
118         
119         loadCommand = (const struct load_command *)(((void*)loadCommand) + loadCommand->cmdsize);
120     }
121     if (textSegment==NULL || linkEditSegment==NULL || symtabCommand==NULL || dysymtabCommand==NULL) {
122         return NULL;
123     }
124     
125     typedef enum { Start = 0, LocalSymbols, ExternalSymbols, Done } SymbolSearchState;
126     uint32_t currentSymbolIndex;
127     uint32_t maximumSymbolIndex;
128     SymbolSearchState state;
129     
130     for (state = Start + 1; state < Done; state++)
131     {
132         switch(state) {
133             case LocalSymbols:
134                 currentSymbolIndex = dysymtabCommand->ilocalsym;
135                 maximumSymbolIndex = dysymtabCommand->ilocalsym + dysymtabCommand->nlocalsym;
136                 break;
137                 
138             case ExternalSymbols:
139                 currentSymbolIndex = dysymtabCommand->iextdefsym;
140                 maximumSymbolIndex = dysymtabCommand->nextdefsym;
141                 break;
142                 
143             default:
144                 return NULL;
145         }
146         for (; currentSymbolIndex < maximumSymbolIndex; currentSymbolIndex++)
147         {
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)
155                 continue;
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;
161             }
162         }
163         state++;
164     }
165     return NULL;
166 }
167
168