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