1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
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.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23#if !(defined(KLD) && defined(__STATIC__))
24#include <stdio.h>
25#include <mach/mach.h>
26#include <time.h>
27#else /* defined(KLD) && defined(__STATIC__) */
28#include <mach/kern_return.h>
29#endif /* !(defined(KLD) && defined(__STATIC__)) */
30#include <stdarg.h>
31#include <string.h>
32#include <mach-o/fat.h>
33#include <mach-o/loader.h>
34#include "stuff/bool.h"
35#include "stuff/bytesex.h"
36#include "stuff/guess_short_name.h"
37
38#include "dylibs.h"
39#include "ld.h"
40#include "live_refs.h"
41#include "objects.h"
42#include "pass1.h"
43#include "sections.h"
44
45__private_extern__ enum bool has_dynamic_linker_command = FALSE;
46
47#ifndef RLD
48
49/* the pointer to the head of the dynamicly linked shared library commands */
50__private_extern__ struct merged_dylib *merged_dylibs = NULL;
51
52/* the pointer to the merged the dynamic linker command if any */
53__private_extern__ struct merged_dylinker *merged_dylinker = NULL;
54
55/* the pointer to the merged sub_framework command if any */
56__private_extern__ struct merged_sub_frameworks *merged_sub_framework = NULL;
57
58/* the pointer to the head of the dynamicly linked shared library segments */
59__private_extern__ struct merged_segment *dylib_segments = NULL;
60
61/* the pointer to the merged sub_umbrella commands if any */
62__private_extern__ struct merged_sub_umbrella *merged_sub_umbrellas = NULL;
63
64/* the pointer to the merged sub_library commands if any */
65__private_extern__ struct merged_sub_library *merged_sub_librarys = NULL;
66
67/* the pointer to the merged sub_client commands if any */
68__private_extern__ struct merged_sub_client *merged_sub_clients = NULL;
69
70static struct merged_dylib *lookup_merged_dylib(
71    struct dylib_command *dl);
72
73/*
74 * create_dylib_id_command() creates the LC_ID_DYLIB load command from the
75 * command line argument values.  It is called from layout() when the output
76 * filetype is MH_DYLIB.
77 */
78__private_extern__
79void
80create_dylib_id_command(
81void)
82{
83    char *name;
84    unsigned long cmdsize;
85    struct dylib_command *dl;
86    struct merged_dylib *mdl;
87
88	if(dylib_install_name != NULL)
89	    name = dylib_install_name;
90	else
91	    name = outputfile;
92
93	cmdsize = sizeof(struct dylib_command) +
94		  rnd(strlen(name) + 1, sizeof(long));
95	dl = allocate(cmdsize);
96	memset(dl, '\0', cmdsize);
97	dl->cmd = LC_ID_DYLIB;
98	dl->cmdsize = cmdsize;
99	dl->dylib.name.offset = sizeof(struct dylib_command);
100	dl->dylib.timestamp = time(0);
101	dl->dylib.current_version = dylib_current_version;
102	dl->dylib.compatibility_version = dylib_compatibility_version;
103	strcpy((char *)dl + sizeof(struct dylib_command), name);
104
105	mdl = allocate(sizeof(struct merged_dylib));
106	memset(mdl, '\0', sizeof(struct merged_dylib));
107	mdl->dylib_name = name;
108	mdl->dl = dl;
109	mdl->output_id = TRUE;
110	mdl->next = merged_dylibs;
111	merged_dylibs = mdl;
112}
113
114/*
115 * merge_dylibs() merges in the dylib commands from the current object.
116 */
117__private_extern__
118void
119merge_dylibs(
120enum bool force_weak)
121{
122    unsigned long i;
123    struct mach_header *mh;
124    struct load_command *lc;
125    struct dylib_command *dl;
126    struct dylinker_command *dyld;
127    char *dyld_name;
128    struct merged_dylib *mdl;
129    struct dynamic_library *p;
130
131	/*
132	 * Process all the load commands for the dynamic shared libraries.
133	 */
134	mh = (struct mach_header *)cur_obj->obj_addr;
135	lc = (struct load_command *)((char *)cur_obj->obj_addr +
136				     sizeof(struct mach_header));
137	for(i = 0; i < mh->ncmds; i++){
138	    if(lc->cmd == LC_ID_DYLIB ||
139	       lc->cmd == LC_LOAD_DYLIB ||
140	       lc->cmd == LC_LOAD_WEAK_DYLIB ||
141	       lc->cmd == LC_REEXPORT_DYLIB){
142		/*
143		 * Do not record dynamic libraries dependencies in the output
144		 * file.  Only record the library itself.
145		 */
146		if((lc->cmd != LC_LOAD_DYLIB &&
147		    lc->cmd != LC_LOAD_WEAK_DYLIB &&
148		    lc->cmd != LC_REEXPORT_DYLIB) ||
149		   (mh->filetype != MH_DYLIB &&
150		    mh->filetype != MH_DYLIB_STUB) ){
151		    dl = (struct dylib_command *)lc;
152		    mdl = lookup_merged_dylib(dl);
153		    if(filetype == MH_DYLIB && dylib_install_name != NULL &&
154		       strcmp(mdl->dylib_name, dylib_install_name) == 0)
155			error_with_cur_obj("can't be linked because it has the "
156			   "same install_name (%s) as the output",
157			   dylib_install_name);
158		    p = add_dynamic_lib(DYLIB, dl, cur_obj);
159		    p->force_weak_dylib = force_weak;
160		    mdl->dynamic_library = p;
161		}
162	    }
163	    else if(lc->cmd == LC_LOAD_DYLINKER || lc->cmd == LC_ID_DYLINKER){
164		dyld = (struct dylinker_command *)lc;
165		dyld_name = (char *)dyld + dyld->name.offset;
166		if(merged_dylinker == NULL){
167		    merged_dylinker = allocate(sizeof(struct merged_dylinker));
168		    memset(merged_dylinker, '\0',
169			   sizeof(struct merged_dylinker));
170		    merged_dylinker->dylinker_name = dyld_name;
171		    merged_dylinker->definition_object = cur_obj;
172		    merged_dylinker->dyld = dyld;
173		    has_dynamic_linker_command = TRUE;
174		    if(save_reloc == FALSE)
175			output_for_dyld = TRUE;
176		}
177		else if(strcmp(dyld_name, merged_dylinker->dylinker_name) != 0){
178		    error("multiple dynamic linkers loaded (only one allowed)");
179		    print_obj_name(merged_dylinker->definition_object);
180		    print("loads dynamic linker %s\n",
181			  merged_dylinker->dylinker_name);
182		    print_obj_name(cur_obj);
183		    print("loads dynamic linker %s\n", dyld_name);
184		}
185	    }
186	    lc = (struct load_command *)((char *)lc + lc->cmdsize);
187	}
188}
189
190/*
191 * lookup_merged_dylib() adds a LC_LOAD_DYLIB command to it to the merged list
192 * of dynamic shared libraries for the load command passed to it.  It ignores
193 * the command if it see the same library twice.
194 */
195static
196struct merged_dylib *
197lookup_merged_dylib(
198struct dylib_command *dl)
199{
200    char *dylib_name;
201    struct merged_dylib **p, *mdl;
202
203	dylib_name = (char *)dl + dl->dylib.name.offset;
204	p = &merged_dylibs;
205	while(*p){
206	    mdl = *p;
207	    if(strcmp(mdl->dylib_name, dylib_name) == 0){
208		if(mdl->dl->cmd == LC_ID_DYLIB){
209		    /*
210		     * If the new one is also a LC_ID_DYLIB use the one with the
211		     * highest compatiblity number.  Else if the new one is just
212		     * an LC_LOAD_DYLIB ignore it and use the merged one that is
213		     * a LC_ID_DYLIB.
214		     */
215		    if(dl->cmd == LC_ID_DYLIB){
216		       if(dl->dylib.compatibility_version >
217			  mdl->dl->dylib.compatibility_version){
218			    if(strcmp(mdl->definition_object->file_name,
219				      cur_obj->file_name) != 0)
220				warning("multiple references to dynamic shared "
221				    "library: %s (from %s and %s, using %s "
222				    "which has higher compatibility_version)",
223				    dylib_name,
224				    mdl->definition_object->file_name,
225				    cur_obj->file_name, cur_obj->file_name);
226			    mdl->dylib_name = dylib_name;
227			    mdl->dl = dl;
228			    mdl->definition_object = cur_obj;
229			}
230		    }
231		}
232		else{
233		    if(dl->cmd == LC_ID_DYLIB){
234			mdl->dylib_name = dylib_name;
235			mdl->dl = dl;
236			mdl->definition_object = cur_obj;
237		    }
238		}
239		return(mdl);
240	    }
241	    p = &(mdl->next);
242	}
243	*p = allocate(sizeof(struct merged_dylib));
244	memset(*p, '\0', sizeof(struct merged_dylib));
245	mdl = *p;
246	mdl->dylib_name = dylib_name;
247	mdl->dl = dl;
248	mdl->definition_object = cur_obj;
249	mdl->output_id = FALSE;
250	return(mdl);
251}
252
253/*
254 * create_dylinker_id_command() creates the LC_ID_DYLINKER load command from the
255 * command line argument values.  It is called from layout() when the output
256 * filetype is MH_DYLINKER.
257 */
258__private_extern__
259void
260create_dylinker_id_command(
261void)
262{
263    char *name;
264    unsigned long cmdsize;
265    struct dylinker_command *dyld;
266    struct merged_dylinker *mdyld;
267
268	if(dylinker_install_name != NULL)
269	    name = dylinker_install_name;
270	else
271	    name = outputfile;
272
273	cmdsize = sizeof(struct dylinker_command) +
274		  rnd(strlen(name) + 1, sizeof(long));
275	dyld = allocate(cmdsize);
276	memset(dyld, '\0', cmdsize);
277	dyld->cmd = LC_ID_DYLINKER;
278	dyld->cmdsize = cmdsize;
279	dyld->name.offset = sizeof(struct dylinker_command);
280	strcpy((char *)dyld + sizeof(struct dylinker_command), name);
281
282	mdyld = allocate(sizeof(struct merged_dylinker));
283	memset(mdyld, '\0', sizeof(struct merged_dylinker));
284	mdyld->dylinker_name = name;
285	mdyld->dyld = dyld;
286	merged_dylinker = mdyld;
287}
288
289/*
290 * create_sub_framework_command() creates a LC_SUB_FRAMEWORK load command from
291 * the command line argument values.  It is called from layout() when the output
292 * filetype is MH_DYLIB and -sub_framework was specified.
293 */
294__private_extern__
295void
296create_sub_framework_command(
297void)
298{
299    char *name;
300    unsigned long cmdsize;
301    struct sub_framework_command *sub;
302    struct merged_sub_frameworks *msub;
303
304	name = umbrella_framework_name;
305
306	cmdsize = sizeof(struct sub_framework_command) +
307		  rnd(strlen(name) + 1, sizeof(long));
308	sub = allocate(cmdsize);
309	memset(sub, '\0', cmdsize);
310	sub->cmd = LC_SUB_FRAMEWORK;
311	sub->cmdsize = cmdsize;
312	sub->umbrella.offset = sizeof(struct sub_framework_command);
313	strcpy((char *)sub + sizeof(struct sub_framework_command), name);
314
315	msub = allocate(sizeof(struct merged_sub_frameworks));
316	memset(msub, '\0', sizeof(struct merged_sub_frameworks));
317	msub->unbrell_name = name;
318	msub->sub = sub;
319	merged_sub_framework = msub;
320}
321
322/*
323 * create_sub_umbrella_commands() creates the LC_SUB_UMBRELLA load commands from
324 * the command line options.  It is called from layout() when the output
325 * filetype is MH_DYLIB and one or more -sub_umbrella flags were specified.
326 * It returns the total size of the load commands it creates.
327 */
328__private_extern__
329unsigned long
330create_sub_umbrella_commands(
331void)
332{
333    unsigned long i;
334    char *name, *umbrella_framework_name, *has_suffix;
335    unsigned long cmdsize, sizeofcmds;
336    struct sub_umbrella_command *sub;
337    enum bool found, is_framework;
338    struct merged_dylib **p, *mdl;
339
340	sizeofcmds = 0;
341	merged_sub_umbrellas = allocate(sizeof(struct merged_sub_umbrella) *
342				        nsub_umbrellas);
343	for(i = 0; i < nsub_umbrellas ; i++){
344	    name = sub_umbrellas[i];
345
346	    found = FALSE;
347	    p = &merged_dylibs;
348	    while(*p){
349		mdl = *p;
350		umbrella_framework_name = guess_short_name(mdl->dylib_name,
351			&is_framework, &has_suffix);
352		if(umbrella_framework_name != NULL &&
353		   is_framework == TRUE &&
354		   strcmp(umbrella_framework_name, name) == 0){
355		    found = TRUE;
356		    break;
357		}
358		p = &(mdl->next);
359	    }
360	    if(found == FALSE)
361		error("-sub_umbrella %s specified but no framework by that "
362		      "name is linked in", name);
363
364	    cmdsize = sizeof(struct sub_umbrella_command) +
365		      rnd(strlen(name) + 1, sizeof(long));
366	    sub = allocate(cmdsize);
367	    memset(sub, '\0', cmdsize);
368	    sub->cmd = LC_SUB_UMBRELLA;
369	    sub->cmdsize = cmdsize;
370	    sub->sub_umbrella.offset = sizeof(struct sub_umbrella_command);
371	    strcpy((char *)sub + sizeof(struct sub_umbrella_command), name);
372
373	    sizeofcmds += cmdsize;
374	    merged_sub_umbrellas[i].sub = sub;
375	}
376	return(sizeofcmds);
377}
378
379/*
380 * create_sub_library_commands() creates the LC_SUB_LIBRARY load commands from
381 * the command line options.  It is called from layout() when the output
382 * filetype is MH_DYLIB and one or more -sub_library flags were specified.
383 * It returns the total size of the load commands it creates.
384 */
385__private_extern__
386unsigned long
387create_sub_library_commands(
388void)
389{
390    unsigned long i;
391    char *name, *library_name, *has_suffix;
392    unsigned long cmdsize, sizeofcmds;
393    struct sub_library_command *sub;
394    enum bool found, is_framework;
395    struct merged_dylib **p, *mdl;
396
397	sizeofcmds = 0;
398	merged_sub_librarys = allocate(sizeof(struct merged_sub_library) *
399				        nsub_librarys);
400	for(i = 0; i < nsub_librarys ; i++){
401	    name = sub_librarys[i];
402
403	    found = FALSE;
404	    p = &merged_dylibs;
405	    while(*p){
406		mdl = *p;
407		library_name = guess_short_name(mdl->dylib_name,
408			&is_framework, &has_suffix);
409		if(library_name != NULL &&
410		   is_framework == FALSE &&
411		   strcmp(library_name, name) == 0){
412		    found = TRUE;
413		    break;
414		}
415		p = &(mdl->next);
416	    }
417	    if(found == FALSE)
418		error("-sub_library %s specified but no library by that "
419		      "name is linked in", name);
420
421	    cmdsize = sizeof(struct sub_library_command) +
422		      rnd(strlen(name) + 1, sizeof(long));
423	    sub = allocate(cmdsize);
424	    memset(sub, '\0', cmdsize);
425	    sub->cmd = LC_SUB_LIBRARY;
426	    sub->cmdsize = cmdsize;
427	    sub->sub_library.offset = sizeof(struct sub_library_command);
428	    strcpy((char *)sub + sizeof(struct sub_library_command), name);
429
430	    sizeofcmds += cmdsize;
431	    merged_sub_librarys[i].sub = sub;
432	}
433	return(sizeofcmds);
434}
435
436/*
437 * create_sub_client_commands() creates the LC_SUB_CLIENT load commands from
438 * the command line options.  It is called from layout() when the output
439 * filetype is MH_DYLIB and one or more -allowable_client flags were specified.
440 * It returns the total size of the load commands it creates.
441 */
442__private_extern__
443unsigned long
444create_sub_client_commands(
445void)
446{
447    unsigned long i;
448    char *name;
449    unsigned long cmdsize, sizeofcmds;
450    struct sub_client_command *sub;
451
452	sizeofcmds = 0;
453	merged_sub_clients = allocate(sizeof(struct merged_sub_client) *
454				      nallowable_clients);
455	for(i = 0; i < nallowable_clients ; i++){
456	    name = allowable_clients[i];
457	    cmdsize = sizeof(struct sub_client_command) +
458		      rnd(strlen(name) + 1, sizeof(long));
459	    sub = allocate(cmdsize);
460	    memset(sub, '\0', cmdsize);
461	    sub->cmd = LC_SUB_CLIENT;
462	    sub->cmdsize = cmdsize;
463	    sub->client.offset = sizeof(struct sub_client_command);
464	    strcpy((char *)sub + sizeof(struct sub_client_command), name);
465
466	    sizeofcmds += cmdsize;
467	    merged_sub_clients[i].sub = sub;
468	}
469	return(sizeofcmds);
470}
471
472/*
473 * add_dylib_segment() adds the specified segment to the list of
474 * dylib_segments as comming from the specified dylib_name.
475 */
476__private_extern__
477void
478add_dylib_segment(
479struct segment_command *sg,
480char *dylib_name,
481enum bool split_dylib)
482{
483    struct merged_segment **p, *msg;
484
485	p = &dylib_segments;
486	while(*p){
487	    msg = *p;
488	    p = &(msg->next);
489	}
490	*p = allocate(sizeof(struct merged_segment));
491	msg = *p;
492	memset(msg, '\0', sizeof(struct merged_segment));
493	msg->sg = *sg;
494	msg->filename = dylib_name;
495	msg->split_dylib = split_dylib;
496}
497#endif /* !defined(RLD) */
498