ld64 with ppc
[darwin-xtools.git] / cctools / libstuff / dylib_table.c
blob9a258986eea7b0e3f054fe7b5e924c5935bb90e9
1 /*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 #ifndef RLD
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <libc.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/mman.h>
30 #include <mach/mach.h>
32 #include "stuff/bool.h"
33 #include "stuff/ofile.h"
34 #include "stuff/errors.h"
35 #include "stuff/allocate.h"
36 #include "stuff/dylib_table.h"
37 /* This may change to "/MacOSX/System" someday */
38 #define SYSTEM_LIBRARY "/System/Library"
41 * parse_dylib_table() opens the file_name passed to it and parses it as a
42 * dylib table. The flag and argument parameters are used for error messages
43 * if there is a problem parsing the file. The file should
44 * contains lines of the form:
45 * <hex address> <short name>
46 * The fields are to be separated by spaces or tabs. Lines with just spaces
47 * and tabs are ignored. This routine returns the parsed table as an
48 * array of dylib_table structs and returns a pointer to the table. The last
49 * entry in the table has a NULL name.
51 struct dylib_table *
52 parse_dylib_table(
53 char *file_name,/* file name of dylib table file */
54 char *flag, /* "-dylib_file" or "default" */
55 char *argument) /* -dylib_file argument or "dylib table" */
57 int fd;
58 struct stat stat_buf;
59 uint32_t j, k, file_size, new_dylib_table_size;
60 char *file_addr, *endp;
61 struct dylib_table *new_dylib_table;
63 if((fd = open(file_name, O_RDONLY, 0)) == -1)
64 system_fatal("Can't open: %s for %s %s",
65 file_name, flag, argument);
66 if(fstat(fd, &stat_buf) == -1)
67 system_fatal("Can't stat file: %s for %s %s",
68 file_name, flag, argument);
70 * For some reason mapping files with zero size fails
71 * so it has to be handled specially.
73 file_addr = NULL;
74 if(stat_buf.st_size != 0){
75 file_addr = mmap(0, stat_buf.st_size, PROT_READ|PROT_WRITE,
76 MAP_FILE|MAP_PRIVATE, fd, 0);
77 if((intptr_t)file_addr == -1)
78 system_error("can't map file: %s for %s %s", file_name, flag,
79 argument);
81 else
82 fatal("Empty file: %s for %s %s", file_name, flag, argument);
83 close(fd);
84 file_size = stat_buf.st_size;
87 * Got the file mapped now parse it.
89 if(file_addr[file_size - 1] != '\n')
90 fatal("file: %s for %s %s does not end in new line",
91 file_name, flag, argument);
92 new_dylib_table_size = 0;
93 for(j = 1; j < file_size; j++){
94 if(file_addr[j] == '\n'){
95 new_dylib_table_size++;
98 new_dylib_table_size++;
99 new_dylib_table = allocate(sizeof(struct dylib_table) *
100 new_dylib_table_size);
101 k = 0;
102 for(j = 0; j < file_size; /* no increment expression */ ){
103 /* Skip blank lines */
104 while(file_addr[j] == ' ' || file_addr[j] == '\t')
105 j++;
106 if(file_addr[j] == '\n'){
107 j++;
108 continue;
110 new_dylib_table[k].seg1addr =
111 strtoul(file_addr + j, &endp, 16);
112 if(endp == NULL)
113 fatal("improper hexadecimal number on line %u in "
114 "file: %s for %s %s", j, file_name, flag, argument);
115 j = endp - file_addr;
116 if(j == file_size)
117 fatal("missing library name on line %u in file: "
118 "%s for %s %s", j, file_name, flag, argument);
120 * Since we checked to see the file ends in a '\n' we can
121 * be assured this won't run off the end of the file.
123 while(file_addr[j] == ' ' || file_addr[j] == '\t')
124 j++;
125 if(file_addr[j] == '\n')
126 fatal("missing library name on line %u in file: "
127 "%s for %s %s", j, file_name, flag, argument);
128 new_dylib_table[k].name = file_addr + j;
129 k++;
130 while(file_addr[j] != '\n')
131 j++;
132 file_addr[j] = '\0';
133 j++;
135 new_dylib_table[k].seg1addr = 0;
136 new_dylib_table[k].name = NULL;
137 return(new_dylib_table);
141 * parse_default_dylib_table() opens and parses ~rc/Data/DylibTable .
143 struct dylib_table *
144 parse_default_dylib_table(
145 char **file_name)
147 uint32_t i;
148 FILE *fp;
150 *file_name = allocate(MAXPATHLEN+1);
151 fp = popen("/bin/echo ~rc/Data/DylibTable", "r");
152 if(fp == NULL)
153 fatal("must use -dylib_table (popen failed on \"/bin/echo "
154 "~rc/Data/DylibTable\"");
155 if(fgets(*file_name, MAXPATHLEN, fp) == NULL)
156 fatal("must use -dylib_table (fgets failed from popen of "
157 "\"/bin/echo ~rc/Data/DylibTable\"");
158 i = strlen(*file_name);
159 if(i == 0 || (*file_name)[i-1] != '\n')
160 fatal("must use -dylib_table (file name from popen of "
161 "\"/bin/echo ~rc/Data/DylibTable\" greater than "
162 "MAXPATHLEN");
163 (*file_name)[i-1] = '\0';
164 pclose(fp);
165 return(parse_dylib_table(*file_name, "default", "dylib table"));
169 * search_dylib_table() searches the specified dylib table for the specified
170 * name and returns the entry to it if it is found. If it is not found NULL
171 * is returned.
173 struct dylib_table *
174 search_dylib_table(
175 struct dylib_table *dylib_table,
176 char *name)
178 struct dylib_table *p;
180 if(dylib_table == NULL)
181 return(NULL);
183 for(p = dylib_table; p->name != NULL; p++){
184 if(strcmp(p->name, name) == 0)
185 return(p);
187 return(NULL);
190 static char *versions[] = { "A", "B", "C", "0", NULL };
193 * guess_dylib_install_name() is passed a name from the dylib file and then
194 * the install name is guessed based on the files on the system the program is
195 * running on. This routines makes up conventional install names base on the
196 * name passed in and then sees if there is a file on the system with that
197 * install_name. If it finds one it returns the install_name else it returns
198 * NULL.
200 char *
201 guess_dylib_install_name(
202 char *name)
204 uint32_t i;
205 char *guess;
206 struct stat stat_buf;
208 for(i = 0; versions[i] != NULL; i++){
209 guess = makestr(
210 SYSTEM_LIBRARY,"/Frameworks/JavaVM.framework/Libraries/lib",
211 name, ".", versions[i], ".dylib", NULL);
212 if(stat(guess, &stat_buf) != -1)
213 return(guess);
214 free(guess);
217 for(i = 0; versions[i] != NULL; i++){
218 guess = makestr(SYSTEM_LIBRARY,"/Frameworks/", name,
219 ".framework/Versions/", versions[i], "/", name, NULL);
220 if(stat(guess, &stat_buf) != -1)
221 return(guess);
222 free(guess);
225 for(i = 0; versions[i] != NULL; i++){
226 guess = makestr(SYSTEM_LIBRARY,"/PrivateFrameworks/", name,
227 ".framework/Versions/", versions[i], "/", name, NULL);
228 if(stat(guess, &stat_buf) != -1)
229 return(guess);
230 free(guess);
233 for(i = 0; versions[i] != NULL; i++){
234 guess = makestr(SYSTEM_LIBRARY,"Printers/", name, ".",
235 versions[i],".dylib", NULL);
236 if(stat(guess, &stat_buf) != -1)
237 return(guess);
238 free(guess);
241 for(i = 0; versions[i] != NULL; i++){
242 #ifdef __GONZO_BUNSEN_BEAKER__
243 guess = makestr("/Local/Library/Frameworks/", name,
244 ".framework/Versions/", versions[i], "/", name, NULL);
245 #else
246 guess = makestr("/MacOSX/Library/Frameworks/", name,
247 ".framework/Versions/", versions[i], "/", name, NULL);
248 #endif
249 if(stat(guess, &stat_buf) != -1)
250 return(guess);
251 free(guess);
254 #ifndef __GONZO_BUNSEN_BEAKER__
255 for(i = 0; versions[i] != NULL; i++){
256 guess = makestr("/AppleInternal/Library/Frameworks/", name,
257 ".framework/Versions/", versions[i], "/", name, NULL);
258 if(stat(guess, &stat_buf) != -1)
259 return(guess);
260 free(guess);
262 #endif
264 for(i = 0; versions[i] != NULL; i++){
265 guess = makestr("/lib/", name, ".", versions[i], ".dylib", NULL);
266 if(stat(guess, &stat_buf) != -1)
267 return(guess);
268 free(guess);
271 for(i = 0; versions[i] != NULL; i++){
272 guess = makestr("/usr/lib/", name, ".", versions[i], ".dylib",
273 NULL);
274 if(stat(guess, &stat_buf) != -1)
275 return(guess);
276 free(guess);
279 for(i = 0; versions[i] != NULL; i++){
280 guess = makestr("/usr/lib/java/", name, ".", versions[i],
281 ".dylib", NULL);
282 if(stat(guess, &stat_buf) != -1)
283 return(guess);
284 free(guess);
287 for(i = 0; versions[i] != NULL; i++){
288 guess = makestr("/usr/local/lib/", name, ".", versions[i],
289 ".dylib", NULL);
290 if(stat(guess, &stat_buf) != -1)
291 return(guess);
292 free(guess);
295 for(i = 0; versions[i] != NULL; i++){
296 guess = makestr("/usr/canna/dylib/", name, ".", versions[i],
297 ".dylib", NULL);
298 if(stat(guess, &stat_buf) != -1)
299 return(guess);
300 free(guess);
302 /* From ALLOW_MACOSX_PR1_PATHS */
303 for(i = 0; versions[i] != NULL; i++){
304 guess = makestr(SYSTEM_LIBRARY,"/Frameworks/CarbonCore.framework/"
305 "Versions/", versions[i], "/Support/", name,
306 ".dylib", NULL);
307 if(stat(guess, &stat_buf) != -1)
308 return(guess);
309 free(guess);
311 for(i = 0; versions[i] != NULL; i++){
312 guess = makestr(SYSTEM_LIBRARY,"Frameworks/Carbon.framework/"
313 "Versions/", versions[i], "/Libraries/", name,
314 ".dylib", NULL);
315 if(stat(guess, &stat_buf) != -1)
316 return(guess);
317 free(guess);
319 for(i = 0; versions[i] != NULL; i++){
320 guess = makestr(SYSTEM_LIBRARY,"/Frameworks/CoreGraphics.framework/"
321 "Versions/", versions[i], "/Libraries/", name, ".",
322 versions[i], ".dylib", NULL);
323 if(stat(guess, &stat_buf) != -1)
324 return(guess);
325 free(guess);
327 /* From ALLOW_MACOSX_DP3_PATHS */
328 for(i = 0; versions[i] != NULL; i++){
329 guess = makestr(SYSTEM_LIBRARY,"/Components/", name, ".qtx", NULL);
330 if(stat(guess, &stat_buf) != -1)
331 return(guess);
332 free(guess);
334 for(i = 0; versions[i] != NULL; i++){
335 guess = makestr(SYSTEM_LIBRARY,"/Frameworks/Carbon.framework/"
336 "Versions/", versions[i], "/Resources//", name,
337 ".qtx", NULL);
338 if(stat(guess, &stat_buf) != -1)
339 return(guess);
340 free(guess);
342 for(i = 0; versions[i] != NULL; i++){
343 guess = makestr(SYSTEM_LIBRARY,"/Frameworks/CoreGraphics.framework/"
344 "Versions/", versions[i], "/Resources/", name, ".",
345 versions[i], ".qtx", NULL);
346 if(stat(guess, &stat_buf) != -1)
347 return(guess);
348 free(guess);
350 for(i = 0; versions[i] != NULL; i++){
351 guess = makestr(SYSTEM_LIBRARY,"/Frameworks/JavaVM.framework/"
352 "Versions/1.2/Libraries/", name, ".", versions[i],
353 ".dylib", NULL);
354 if(stat(guess, &stat_buf) != -1)
355 return(guess);
356 free(guess);
358 for(i = 0; versions[i] != NULL; i++){
359 guess = makestr(SYSTEM_LIBRARY,"/Frameworks/PrintingCore.framework/"
360 "Versions/", versions[i], "/Libraries/", name, ".",
361 versions[i], ".dylib", NULL);
362 if(stat(guess, &stat_buf) != -1)
363 return(guess);
364 free(guess);
366 for(i = 0; versions[i] != NULL; i++){
367 guess = makestr(SYSTEM_LIBRARY,"/Frameworks/QuickTime.framework/"
368 "Versions/", versions[i], "/", name, NULL);
369 if(stat(guess, &stat_buf) != -1)
370 return(guess);
371 free(guess);
374 return(NULL);
376 #endif /* !defined(RLD) */