2 * Copyright (c) 2001 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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@
29 #include "stuff/errors.h"
30 #include "stuff/breakout.h"
31 #include "stuff/rnd.h"
32 #include "stuff/allocate.h"
34 /* used by error routines as the name of the program */
35 char *progname
= NULL
;
44 static void write_on_input(
49 static void setup_object_symbolic_info(
50 struct object
*object
);
52 static void update_load_commands(
54 uint32_t *header_size
);
56 /* the argument to the -id option */
57 static char *id
= NULL
;
59 /* the arguments to the -change options */
64 static struct changes
*changes
= NULL
;
65 static uint32_t nchanges
= 0;
67 /* the arguments to the -rpath options */
73 static struct rpaths
*rpaths
= NULL
;
74 static uint32_t nrpaths
= 0;
76 /* the arguments to the -add_rpath options */
80 static struct add_rpaths
*add_rpaths
= NULL
;
81 static uint32_t nadd_rpaths
= 0;
83 /* the arguments to the -delete_rpath options */
84 struct delete_rpaths
{
88 static struct delete_rpaths
*delete_rpaths
= NULL
;
89 static uint32_t ndelete_rpaths
= 0;
92 * This is a pointer to an array of the original header sizes (mach header and
93 * load commands) for each architecture which is used when we are writing on the
96 static uint32_t *arch_header_sizes
= NULL
;
99 * The -o output option is not enabled as it is not needed and has the
100 * unintended side effect of changing the time stamps in LC_ID_DYLIB commands
101 * which is not the desired functionality of this command.
105 /* apple_version is created by the libstuff/Makefile */
106 extern char apple_version
[];
107 char *version
= apple_version
;
110 * The install_name_tool allow the dynamic shared library install names of a
111 * Mach-O binary to be changed. For this tool to work when the install names
112 * are larger the binary should be built with the ld(1)
113 * -headerpad_max_install_names option.
115 * Usage: install_name_tool [-change old new] ... [-rpath old new] ...
116 * [-add_rpath new] ... [-delete_rpath old] ... [-id name] input
118 * The "-change old new" option changes the "old" install name to the "new"
119 * install name if found in the binary.
121 * The "-rpath old new" option changes the "old" path name in the rpath to
122 * the "new" path name in an LC_RPATH load command in the binary.
124 * The "-add_rpath new" option adds an LC_RPATH load command.
126 * The "-delete_rpath old" option deletes the LC_RPATH load command with the
127 * "old" path name in the binary.
129 * The "-id name" option changes the install name in the LC_ID_DYLIB load
130 * command for a dynamic shared library.
149 for(i
= 1; i
< argc
; i
++){
151 if(strcmp(argv
[i
], "-o") == 0){
153 error("missing argument to: %s option", argv
[i
]);
157 error("more than one: %s option specified", argv
[i
]);
164 #endif /* OUTPUT_OPTION */
165 if(strcmp(argv
[i
], "-id") == 0){
167 error("missing argument to: %s option", argv
[i
]);
171 error("more than one: %s option specified", argv
[i
]);
177 else if(strcmp(argv
[i
], "-change") == 0){
179 error("missing argument(s) to: %s option", argv
[i
]);
182 changes
= reallocate(changes
,
183 sizeof(struct changes
) * (nchanges
+ 1));
184 changes
[nchanges
].old
= argv
[i
+1];
185 changes
[nchanges
].new = argv
[i
+2];
189 else if(strcmp(argv
[i
], "-rpath") == 0){
191 error("missing argument(s) to: %s option", argv
[i
]);
194 for(j
= 0; j
< nrpaths
; j
++){
195 if(strcmp(rpaths
[j
].old
, argv
[i
+1]) == 0){
196 if(strcmp(rpaths
[j
].new, argv
[i
+2]) == 0){
197 error("\"-rpath %s %s\" specified more than once",
198 argv
[i
+1], argv
[i
+2]);
201 error("can't specify both \"-rpath %s %s\" and "
202 "\"-rpath %s %s\"", rpaths
[j
].old
, rpaths
[j
].new,
203 argv
[i
+1], argv
[i
+2]);
206 if(strcmp(rpaths
[j
].new, argv
[i
+1]) == 0 ||
207 strcmp(rpaths
[j
].old
, argv
[i
+2]) == 0 ||
208 strcmp(rpaths
[j
].new, argv
[i
+2]) == 0){
209 error("can't specify both \"-rpath %s %s\" and "
210 "\"-rpath %s %s\"", rpaths
[j
].old
, rpaths
[j
].new,
211 argv
[i
+1], argv
[i
+2]);
215 for(j
= 0; j
< nadd_rpaths
; j
++){
216 if(strcmp(add_rpaths
[j
].new, argv
[i
+1]) == 0 ||
217 strcmp(add_rpaths
[j
].new, argv
[i
+2]) == 0){
218 error("can't specify both \"-add_rpath %s\" "
219 "and \"-rpath %s %s\"", add_rpaths
[j
].new,
220 argv
[i
+1], argv
[i
+2]);
224 for(j
= 0; j
< ndelete_rpaths
; j
++){
225 if(strcmp(delete_rpaths
[j
].old
, argv
[i
+1]) == 0 ||
226 strcmp(delete_rpaths
[j
].old
, argv
[i
+2]) == 0){
227 error("can't specify both \"-delete_rpath %s\" "
228 "and \"-rpath %s %s\"", delete_rpaths
[j
].old
,
229 argv
[i
+1], argv
[i
+2]);
233 rpaths
= reallocate(rpaths
,
234 sizeof(struct rpaths
) * (nrpaths
+ 1));
235 rpaths
[nrpaths
].old
= argv
[i
+1];
236 rpaths
[nrpaths
].new = argv
[i
+2];
237 rpaths
[nrpaths
].found
= FALSE
;
241 else if(strcmp(argv
[i
], "-add_rpath") == 0){
243 error("missing argument(s) to: %s option", argv
[i
]);
246 for(j
= 0; j
< nadd_rpaths
; j
++){
247 if(strcmp(add_rpaths
[j
].new, argv
[i
+1]) == 0){
248 error("\"-add_rpath %s\" specified more than once",
253 for(j
= 0; j
< nrpaths
; j
++){
254 if(strcmp(rpaths
[j
].old
, argv
[i
+1]) == 0 ||
255 strcmp(rpaths
[j
].new, argv
[i
+1]) == 0){
256 error("can't specify both \"-rpath %s %s\" and "
257 "\"-add_rpath %s\"", rpaths
[j
].old
, rpaths
[j
].new,
262 for(j
= 0; j
< ndelete_rpaths
; j
++){
263 if(strcmp(delete_rpaths
[j
].old
, argv
[i
+1]) == 0){
264 error("can't specify both \"-delete_rpath %s\" "
265 "and \"-add_rpath %s\"", delete_rpaths
[j
].old
,
270 add_rpaths
= reallocate(add_rpaths
,
271 sizeof(struct add_rpaths
) * (nadd_rpaths
+ 1));
272 add_rpaths
[nadd_rpaths
].new = argv
[i
+1];
276 else if(strcmp(argv
[i
], "-delete_rpath") == 0){
278 error("missing argument(s) to: %s option", argv
[i
]);
281 for(j
= 0; j
< ndelete_rpaths
; j
++){
282 if(strcmp(delete_rpaths
[j
].old
, argv
[i
+1]) == 0){
283 error("\"-delete_rpath %s\" specified more than once",
284 delete_rpaths
[j
].old
);
288 for(j
= 0; j
< nrpaths
; j
++){
289 if(strcmp(rpaths
[j
].old
, argv
[i
+1]) == 0 ||
290 strcmp(rpaths
[j
].new, argv
[i
+1]) == 0){
291 error("can't specify both \"-rpath %s %s\" and "
292 "\"-delete_rpath %s\"", rpaths
[j
].old
,
293 rpaths
[j
].new, argv
[i
+1]);
297 for(j
= 0; j
< nadd_rpaths
; j
++){
298 if(strcmp(add_rpaths
[j
].new, argv
[i
+1]) == 0){
299 error("can't specify both \"-add_rpath %s\" "
300 "and \"-delete_rpath %s\"", add_rpaths
[j
].new,
305 delete_rpaths
= reallocate(delete_rpaths
,
306 sizeof(struct delete_rpaths
) *
307 (ndelete_rpaths
+ 1));
308 delete_rpaths
[ndelete_rpaths
].old
= argv
[i
+1];
309 delete_rpaths
[ndelete_rpaths
].found
= FALSE
;
315 error("more than one input file specified (%s and %s)",
322 if(input
== NULL
|| (id
== NULL
&& nchanges
== 0 && nrpaths
== 0 &&
323 nadd_rpaths
== 0 && ndelete_rpaths
== 0))
326 breakout(input
, &archs
, &narchs
, FALSE
);
330 checkout(archs
, narchs
);
334 arch_header_sizes
= allocate(narchs
* sizeof(uint32_t));
335 process(archs
, narchs
);
340 writeout(archs
, narchs
, output
, 0777, TRUE
, FALSE
, FALSE
, NULL
);
342 write_on_input(archs
, narchs
, input
);
345 return(EXIT_FAILURE
);
347 return(EXIT_SUCCESS
);
351 * usage() prints the current usage message and exits indicating failure.
358 fprintf(stderr
, "Usage: %s [-change old new] ... [-rpath old new] ... "
359 "[-add_rpath new] ... [-delete_rpath old] ... "
363 #endif /* OUTPUT_OPTION */
375 struct object
*object
;
377 for(i
= 0; i
< narchs
; i
++){
378 if(archs
[i
].type
== OFILE_Mach_O
){
379 object
= archs
[i
].object
;
380 if(object
->mh_filetype
== MH_DYLIB_STUB
)
381 fatal("input file: %s is Mach-O dynamic shared library stub"
382 " file and can't be changed", archs
[i
].file_name
);
383 setup_object_symbolic_info(object
);
384 update_load_commands(archs
+ i
, arch_header_sizes
+ i
);
387 error("input file: %s is not a Mach-O file",archs
[i
].file_name
);
394 * write_on_input() takes the modified archs and writes the load commands
395 * directly into the input file.
405 uint32_t i
, offset
, size
, headers_size
;
407 struct mach_header
*mh
;
408 struct mach_header_64
*mh64
;
409 struct load_command
*lc
;
410 enum byte_sex host_byte_sex
;
412 host_byte_sex
= get_host_byte_sex();
414 fd
= open(input
, O_WRONLY
, 0);
416 system_error("can't open input file: %s for writing", input
);
418 for(i
= 0; i
< narchs
; i
++){
419 if(archs
[i
].fat_arch
!= NULL
)
420 offset
= archs
[i
].fat_arch
->offset
;
423 if(lseek(fd
, offset
, SEEK_SET
) == -1)
424 system_error("can't lseek to offset: %u in file: %s for "
425 "writing", offset
, input
);
427 * Since the new headers may be smaller than the old headers and
428 * we want to make sure any old unused bytes are zero in the file
429 * we allocate the size of the original headers into a buffer and
430 * zero it out. Then copy the new headers into the buffer and write
431 * out the size of the original headers to the file.
433 if(archs
[i
].object
->mh
!= NULL
){
434 headers_size
= sizeof(struct mach_header
) +
435 archs
[i
].object
->mh
->sizeofcmds
;
438 headers_size
= sizeof(struct mach_header_64
) +
439 archs
[i
].object
->mh64
->sizeofcmds
;
441 if(arch_header_sizes
[i
] > headers_size
)
442 size
= arch_header_sizes
[i
];
445 headers
= allocate(size
);
446 memset(headers
, '\0', size
);
448 if(archs
[i
].object
->mh
!= NULL
){
449 mh
= (struct mach_header
*)headers
;
450 lc
= (struct load_command
*)(headers
+
451 sizeof(struct mach_header
));
452 *mh
= *(archs
[i
].object
->mh
);
453 memcpy(lc
, archs
[i
].object
->load_commands
, mh
->sizeofcmds
);
454 if(archs
[i
].object
->object_byte_sex
!= host_byte_sex
)
455 if(swap_object_headers(mh
, lc
) == FALSE
)
456 fatal("internal error: swap_object_headers() failed");
459 mh64
= (struct mach_header_64
*)headers
;
460 lc
= (struct load_command
*)(headers
+
461 sizeof(struct mach_header_64
));
462 *mh64
= *(archs
[i
].object
->mh64
);
463 memcpy(lc
, archs
[i
].object
->load_commands
, mh64
->sizeofcmds
);
464 if(archs
[i
].object
->object_byte_sex
!= host_byte_sex
)
465 if(swap_object_headers(mh64
, lc
) == FALSE
)
466 fatal("internal error: swap_object_headers() failed");
469 if(write(fd
, headers
, size
) != (int)size
)
470 system_error("can't write new headers in file: %s", input
);
475 system_error("can't close written on input file: %s", input
);
480 setup_object_symbolic_info(
481 struct object
*object
)
484 if(object
->st
!= NULL
&& object
->st
->nsyms
!= 0){
485 object
->output_symbols
= (struct nlist
*)
486 (object
->object_addr
+ object
->st
->symoff
);
487 if(object
->object_byte_sex
!= get_host_byte_sex())
488 swap_nlist(object
->output_symbols
,
490 get_host_byte_sex());
491 object
->output_nsymbols
= object
->st
->nsyms
;
492 object
->output_strings
=
493 object
->object_addr
+ object
->st
->stroff
;
494 object
->output_strings_size
= object
->st
->strsize
;
495 object
->input_sym_info_size
=
496 object
->st
->nsyms
* sizeof(struct nlist
) +
498 object
->output_sym_info_size
=
499 object
->input_sym_info_size
;
501 if(object
->dyst
!= NULL
){
502 object
->output_ilocalsym
= object
->dyst
->ilocalsym
;
503 object
->output_nlocalsym
= object
->dyst
->nlocalsym
;
504 object
->output_iextdefsym
= object
->dyst
->iextdefsym
;
505 object
->output_nextdefsym
= object
->dyst
->nextdefsym
;
506 object
->output_iundefsym
= object
->dyst
->iundefsym
;
507 object
->output_nundefsym
= object
->dyst
->nundefsym
;
509 object
->output_loc_relocs
= (struct relocation_info
*)
510 (object
->object_addr
+ object
->dyst
->locreloff
);
511 object
->output_ext_relocs
= (struct relocation_info
*)
512 (object
->object_addr
+ object
->dyst
->extreloff
);
513 object
->output_indirect_symtab
= (uint32_t *)
514 (object
->object_addr
+ object
->dyst
->indirectsymoff
);
515 object
->output_tocs
=
516 (struct dylib_table_of_contents
*)
517 (object
->object_addr
+ object
->dyst
->tocoff
);
518 object
->output_ntoc
= object
->dyst
->ntoc
;
519 object
->output_mods
= (struct dylib_module
*)
520 (object
->object_addr
+ object
->dyst
->modtaboff
);
521 object
->output_nmodtab
= object
->dyst
->nmodtab
;
522 object
->output_refs
= (struct dylib_reference
*)
523 (object
->object_addr
+ object
->dyst
->extrefsymoff
);
524 object
->output_nextrefsyms
= object
->dyst
->nextrefsyms
;
525 if(object
->dyld_info
!= NULL
){
526 object
->input_sym_info_size
+= object
->dyld_info
->rebase_size
527 + object
->dyld_info
->bind_size
528 + object
->dyld_info
->weak_bind_size
529 + object
->dyld_info
->lazy_bind_size
530 + object
->dyld_info
->export_size
;
532 object
->input_sym_info_size
+=
533 object
->dyst
->nlocrel
*
534 sizeof(struct relocation_info
) +
535 object
->dyst
->nextrel
*
536 sizeof(struct relocation_info
) +
537 object
->dyst
->nindirectsyms
*
540 sizeof(struct dylib_table_of_contents
)+
541 object
->dyst
->nmodtab
*
542 sizeof(struct dylib_module
) +
543 object
->dyst
->nextrefsyms
*
544 sizeof(struct dylib_reference
);
545 object
->output_sym_info_size
+=
546 object
->dyst
->nlocrel
*
547 sizeof(struct relocation_info
) +
548 object
->dyst
->nextrel
*
549 sizeof(struct relocation_info
) +
550 object
->dyst
->nindirectsyms
*
553 sizeof(struct dylib_table_of_contents
)+
554 object
->dyst
->nmodtab
*
555 sizeof(struct dylib_module
) +
556 object
->dyst
->nextrefsyms
*
557 sizeof(struct dylib_reference
);
558 if(object
->split_info_cmd
!= NULL
){
559 object
->output_split_info_data
=
560 (object
->object_addr
+ object
->split_info_cmd
->dataoff
);
561 object
->output_split_info_data_size
=
562 object
->split_info_cmd
->datasize
;
563 object
->input_sym_info_size
+=
564 object
->split_info_cmd
->datasize
;
565 object
->output_sym_info_size
+=
566 object
->split_info_cmd
->datasize
;
568 if(object
->func_starts_info_cmd
!= NULL
){
569 object
->output_func_start_info_data
=
570 (object
->object_addr
+ object
->func_starts_info_cmd
->dataoff
);
571 object
->output_func_start_info_data_size
=
572 object
->func_starts_info_cmd
->datasize
;
573 object
->input_sym_info_size
+=
574 object
->func_starts_info_cmd
->datasize
;
575 object
->output_sym_info_size
+=
576 object
->func_starts_info_cmd
->datasize
;
578 if(object
->data_in_code_cmd
!= NULL
){
579 object
->output_data_in_code_info_data
=
580 (object
->object_addr
+ object
->data_in_code_cmd
->dataoff
);
581 object
->output_data_in_code_info_data_size
=
582 object
->data_in_code_cmd
->datasize
;
583 object
->input_sym_info_size
+=
584 object
->data_in_code_cmd
->datasize
;
585 object
->output_sym_info_size
+=
586 object
->data_in_code_cmd
->datasize
;
588 if(object
->code_sign_drs_cmd
!= NULL
){
589 object
->output_code_sign_drs_info_data
=
590 (object
->object_addr
+ object
->code_sign_drs_cmd
->dataoff
);
591 object
->output_code_sign_drs_info_data_size
=
592 object
->code_sign_drs_cmd
->datasize
;
593 object
->input_sym_info_size
+=
594 object
->code_sign_drs_cmd
->datasize
;
595 object
->output_sym_info_size
+=
596 object
->code_sign_drs_cmd
->datasize
;
598 if(object
->hints_cmd
!= NULL
){
599 object
->output_hints
= (struct twolevel_hint
*)
600 (object
->object_addr
+
601 object
->hints_cmd
->offset
);
602 object
->input_sym_info_size
+=
603 object
->hints_cmd
->nhints
*
604 sizeof(struct twolevel_hint
);
605 object
->output_sym_info_size
+=
606 object
->hints_cmd
->nhints
*
607 sizeof(struct twolevel_hint
);
609 if(object
->code_sig_cmd
!= NULL
){
610 object
->output_code_sig_data
= object
->object_addr
+
611 object
->code_sig_cmd
->dataoff
;
612 object
->output_code_sig_data_size
=
613 object
->code_sig_cmd
->datasize
;
614 object
->input_sym_info_size
=
615 rnd(object
->input_sym_info_size
, 16);
616 object
->input_sym_info_size
+=
617 object
->code_sig_cmd
->datasize
;
618 object
->output_sym_info_size
=
619 rnd(object
->output_sym_info_size
, 16);
620 object
->output_sym_info_size
+=
621 object
->code_sig_cmd
->datasize
;
624 #endif /* OUTPUT_OPTION */
628 * update_load_commands() changes the install names the LC_LOAD_DYLIB,
629 * LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_LOAD_UPWARD_DYLIB and
630 * LC_PREBOUND_DYLIB commands for the specified arch.
634 update_load_commands(
636 uint32_t *header_size
)
638 uint32_t i
, j
, new_sizeofcmds
, new_size
, linked_modules_size
, ncmds
,
639 sizeof_mach_header
, cmd_round
;
640 uint64_t low_fileoff
;
641 struct load_command
*lc1
, *lc2
, *new_load_commands
;
642 struct dylib_command
*dl_load1
, *dl_load2
, *dl_id1
, *dl_id2
;
643 struct prebound_dylib_command
*pbdylib1
, *pbdylib2
;
644 char *dylib_name1
, *dylib_name2
, *arch_name
, *linked_modules1
,
645 *linked_modules2
, *path1
, *path2
;
646 struct segment_command
*sg
;
647 struct segment_command_64
*sg64
;
649 struct section_64
*s64
;
650 struct arch_flag arch_flag
;
651 struct rpath_command
*rpath1
, *rpath2
;
655 * Make a pass through the load commands and figure out what the new
656 * size of the the commands needs to be and how much room there is for
659 if(arch
->object
->mh
!= NULL
){
660 new_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
661 ncmds
= arch
->object
->mh
->ncmds
;
662 sizeof_mach_header
= sizeof(struct mach_header
);
664 arch_flag
.cputype
= arch
->object
->mh
->cputype
;
665 arch_flag
.cpusubtype
= arch
->object
->mh
->cpusubtype
;
668 new_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
669 ncmds
= arch
->object
->mh64
->ncmds
;
670 sizeof_mach_header
= sizeof(struct mach_header_64
);
672 arch_flag
.cputype
= arch
->object
->mh64
->cputype
;
673 arch_flag
.cpusubtype
= arch
->object
->mh64
->cpusubtype
;
675 set_arch_flag_name(&arch_flag
);
676 arch_name
= arch_flag
.name
;
678 low_fileoff
= ULLONG_MAX
;
679 lc1
= arch
->object
->load_commands
;
680 for(i
= 0; i
< ncmds
; i
++){
683 dl_id1
= (struct dylib_command
*)lc1
;
684 dylib_name1
= (char *)dl_id1
+ dl_id1
->dylib
.name
.offset
;
686 new_size
= sizeof(struct dylib_command
) +
687 rnd(strlen(id
) + 1, cmd_round
);
688 new_sizeofcmds
+= (new_size
- dl_id1
->cmdsize
);
693 case LC_LOAD_WEAK_DYLIB
:
694 case LC_REEXPORT_DYLIB
:
695 case LC_LOAD_UPWARD_DYLIB
:
696 case LC_LAZY_LOAD_DYLIB
:
697 dl_load1
= (struct dylib_command
*)lc1
;
698 dylib_name1
= (char *)dl_load1
+ dl_load1
->dylib
.name
.offset
;
699 for(j
= 0; j
< nchanges
; j
++){
700 if(strcmp(changes
[j
].old
, dylib_name1
) == 0){
701 new_size
= sizeof(struct dylib_command
) +
702 rnd(strlen(changes
[j
].new) + 1,
704 new_sizeofcmds
+= (new_size
- dl_load1
->cmdsize
);
710 case LC_PREBOUND_DYLIB
:
711 pbdylib1
= (struct prebound_dylib_command
*)lc1
;
712 dylib_name1
= (char *)pbdylib1
+ pbdylib1
->name
.offset
;
713 for(j
= 0; j
< nchanges
; j
++){
714 if(strcmp(changes
[j
].old
, dylib_name1
) == 0){
715 linked_modules_size
= pbdylib1
->cmdsize
- (
716 sizeof(struct prebound_dylib_command
) +
717 rnd(strlen(dylib_name1
) + 1, cmd_round
));
718 new_size
= sizeof(struct prebound_dylib_command
) +
719 rnd(strlen(changes
[j
].new) + 1,
722 new_sizeofcmds
+= (new_size
- pbdylib1
->cmdsize
);
729 sg
= (struct segment_command
*)lc1
;
730 s
= (struct section
*)
731 ((char *)sg
+ sizeof(struct segment_command
));
733 for(j
= 0; j
< sg
->nsects
; j
++){
735 (s
->flags
& S_ZEROFILL
) != S_ZEROFILL
&&
736 (s
->flags
& S_THREAD_LOCAL_ZEROFILL
) !=
737 S_THREAD_LOCAL_ZEROFILL
&&
738 s
->offset
< low_fileoff
)
739 low_fileoff
= s
->offset
;
744 if(sg
->filesize
!= 0 && sg
->fileoff
< low_fileoff
)
745 low_fileoff
= sg
->fileoff
;
750 sg64
= (struct segment_command_64
*)lc1
;
751 s64
= (struct section_64
*)
752 ((char *)sg64
+ sizeof(struct segment_command_64
));
753 if(sg64
->nsects
!= 0){
754 for(j
= 0; j
< sg64
->nsects
; j
++){
756 (s64
->flags
& S_ZEROFILL
) != S_ZEROFILL
&&
757 (s64
->flags
& S_THREAD_LOCAL_ZEROFILL
) !=
758 S_THREAD_LOCAL_ZEROFILL
&&
759 s64
->offset
< low_fileoff
)
760 low_fileoff
= s64
->offset
;
765 if(sg64
->filesize
!= 0 && sg64
->fileoff
< low_fileoff
)
766 low_fileoff
= sg64
->fileoff
;
771 rpath1
= (struct rpath_command
*)lc1
;
772 path1
= (char *)rpath1
+ rpath1
->path
.offset
;
773 for(j
= 0; j
< nadd_rpaths
; j
++){
774 if(strcmp(add_rpaths
[j
].new, path1
) == 0){
775 error("for: %s (for architecture %s) option "
776 "\"-add_rpath %s\" would duplicate path, file "
777 "already has LC_RPATH for: %s", arch
->file_name
,
778 arch_name
, add_rpaths
[j
].new, path1
);
781 for(j
= 0; j
< nrpaths
; j
++){
782 if(strcmp(rpaths
[j
].old
, path1
) == 0){
783 rpaths
[j
].found
= TRUE
;
784 new_size
= rnd(sizeof(struct rpath_command
) +
785 strlen(rpaths
[j
].new) + 1,
787 new_sizeofcmds
+= (new_size
- rpath1
->cmdsize
);
791 for(j
= 0; j
< ndelete_rpaths
; j
++){
792 if(strcmp(delete_rpaths
[j
].old
, path1
) == 0){
793 delete_rpaths
[j
].found
= TRUE
;
794 new_sizeofcmds
-= rpath1
->cmdsize
;
800 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
803 for(i
= 0; i
< ndelete_rpaths
; i
++){
804 if(delete_rpaths
[i
].found
== FALSE
){
805 error("no LC_RPATH load command with path: %s found in: "
806 "%s (for architecture %s), required for specified option "
807 "\"-delete_rpath %s\"", delete_rpaths
[i
].old
,
808 arch
->file_name
, arch_name
, delete_rpaths
[i
].old
);
811 for(i
= 0; i
< nrpaths
; i
++){
812 if(rpaths
[i
].found
== FALSE
){
813 error("no LC_RPATH load command with path: %s found in: "
814 "%s (for architecture %s), required for specified option "
815 "\"-rpath %s %s\"", rpaths
[i
].old
, arch
->file_name
,
816 arch_name
, rpaths
[i
].old
, rpaths
[i
].new);
820 for(i
= 0; i
< nadd_rpaths
; i
++){
821 new_size
= rnd(sizeof(struct rpath_command
) +
822 strlen(add_rpaths
[i
].new) + 1, cmd_round
);
823 new_sizeofcmds
+= new_size
;
826 if(new_sizeofcmds
+ sizeof_mach_header
> low_fileoff
){
827 error("changing install names or rpaths can't be redone for: %s "
828 "(for architecture %s) because larger updated load commands "
829 "do not fit (the program must be relinked, and you may need "
830 "to use -headerpad or -headerpad_max_install_names)",
831 arch
->file_name
, arch_name
);
836 * Allocate space for the new load commands and zero it out so any holes
837 * will be zero bytes. Note this may be smaller than the original size
838 * of the load commands.
840 new_load_commands
= allocate(new_sizeofcmds
);
841 memset(new_load_commands
, '\0', new_sizeofcmds
);
844 * Fill in the new load commands by copying in the non-modified
845 * commands and updating ones with install name changes.
847 lc1
= arch
->object
->load_commands
;
848 lc2
= new_load_commands
;
849 for(i
= 0; i
< ncmds
; i
++){
854 memcpy(lc2
, lc1
, sizeof(struct dylib_command
));
855 dl_id2
= (struct dylib_command
*)lc2
;
856 dl_id2
->cmdsize
= sizeof(struct dylib_command
) +
857 rnd(strlen(id
) + 1, cmd_round
);
858 dl_id2
->dylib
.name
.offset
= sizeof(struct dylib_command
);
859 dylib_name2
= (char *)dl_id2
+ dl_id2
->dylib
.name
.offset
;
860 strcpy(dylib_name2
, id
);
863 memcpy(lc2
, lc1
, lc1
->cmdsize
);
868 case LC_LOAD_WEAK_DYLIB
:
869 case LC_REEXPORT_DYLIB
:
870 case LC_LOAD_UPWARD_DYLIB
:
871 case LC_LAZY_LOAD_DYLIB
:
872 dl_load1
= (struct dylib_command
*)lc1
;
873 dylib_name1
= (char *)dl_load1
+ dl_load1
->dylib
.name
.offset
;
874 for(j
= 0; j
< nchanges
; j
++){
875 if(strcmp(changes
[j
].old
, dylib_name1
) == 0){
876 memcpy(lc2
, lc1
, sizeof(struct dylib_command
));
877 dl_load2
= (struct dylib_command
*)lc2
;
878 dl_load2
->cmdsize
= sizeof(struct dylib_command
) +
879 rnd(strlen(changes
[j
].new) + 1,
881 dl_load2
->dylib
.name
.offset
=
882 sizeof(struct dylib_command
);
883 dylib_name2
= (char *)dl_load2
+
884 dl_load2
->dylib
.name
.offset
;
885 strcpy(dylib_name2
, changes
[j
].new);
890 memcpy(lc2
, lc1
, lc1
->cmdsize
);
894 case LC_PREBOUND_DYLIB
:
895 pbdylib1
= (struct prebound_dylib_command
*)lc1
;
896 dylib_name1
= (char *)pbdylib1
+ pbdylib1
->name
.offset
;
897 for(j
= 0; j
< nchanges
; j
++){
898 if(strcmp(changes
[j
].old
, dylib_name1
) == 0){
899 memcpy(lc2
, lc1
, sizeof(struct prebound_dylib_command
));
900 pbdylib2
= (struct prebound_dylib_command
*)lc2
;
901 linked_modules_size
= pbdylib1
->cmdsize
- (
902 sizeof(struct prebound_dylib_command
) +
903 rnd(strlen(dylib_name1
) + 1, cmd_round
));
905 sizeof(struct prebound_dylib_command
) +
906 rnd(strlen(changes
[j
].new) + 1, cmd_round
) +
909 pbdylib2
->name
.offset
=
910 sizeof(struct prebound_dylib_command
);
911 dylib_name2
= (char *)pbdylib2
+
912 pbdylib2
->name
.offset
;
913 strcpy(dylib_name2
, changes
[j
].new);
915 pbdylib2
->linked_modules
.offset
=
916 sizeof(struct prebound_dylib_command
) +
917 rnd(strlen(changes
[j
].new) + 1, cmd_round
);
918 linked_modules1
= (char *)pbdylib1
+
919 pbdylib1
->linked_modules
.offset
;
920 linked_modules2
= (char *)pbdylib2
+
921 pbdylib2
->linked_modules
.offset
;
922 memcpy(linked_modules2
, linked_modules1
,
923 linked_modules_size
);
928 memcpy(lc2
, lc1
, lc1
->cmdsize
);
933 rpath1
= (struct rpath_command
*)lc1
;
934 path1
= (char *)rpath1
+ rpath1
->path
.offset
;
935 for(j
= 0; j
< ndelete_rpaths
; j
++){
936 if(strcmp(delete_rpaths
[j
].old
, path1
) == 0){
943 for(j
= 0; j
< nrpaths
; j
++){
944 if(strcmp(rpaths
[j
].old
, path1
) == 0){
945 memcpy(lc2
, lc1
, sizeof(struct rpath_command
));
946 rpath2
= (struct rpath_command
*)lc2
;
947 rpath2
->cmdsize
= rnd(sizeof(struct rpath_command
) +
948 strlen(rpaths
[j
].new) + 1,
950 rpath2
->path
.offset
= sizeof(struct rpath_command
);
951 path2
= (char *)rpath2
+ rpath2
->path
.offset
;
952 strcpy(path2
, rpaths
[j
].new);
957 memcpy(lc2
, lc1
, lc1
->cmdsize
);
962 memcpy(lc2
, lc1
, lc1
->cmdsize
);
965 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
967 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
970 * Add the new rpath load commands.
972 for(i
= 0; i
< nadd_rpaths
; i
++){
973 rpath2
= (struct rpath_command
*)lc2
;
974 rpath2
->cmd
= LC_RPATH
;
975 rpath2
->cmdsize
= rnd(sizeof(struct rpath_command
) +
976 strlen(add_rpaths
[i
].new) + 1,
978 rpath2
->path
.offset
= sizeof(struct rpath_command
);
979 path2
= (char *)rpath2
+ rpath2
->path
.offset
;
980 strcpy(path2
, add_rpaths
[i
].new);
982 ncmds
+= nadd_rpaths
;
983 ncmds
-= ndelete_rpaths
;
986 * Finally copy the updated load commands over the existing load
987 * commands. Since the headers could be smaller we save away the old
988 * header_size (for use when writing on the input) and also put zero
989 * bytes on the part that is no longer used for headers.
991 if(arch
->object
->mh
!= NULL
){
992 *header_size
= sizeof(struct mach_header
) +
993 arch
->object
->mh
->sizeofcmds
;
994 if(new_sizeofcmds
< arch
->object
->mh
->sizeofcmds
){
995 memset(((char *)arch
->object
->load_commands
) + new_sizeofcmds
,
996 '\0', arch
->object
->mh
->sizeofcmds
- new_sizeofcmds
);
998 memcpy(arch
->object
->load_commands
, new_load_commands
,
1000 arch
->object
->mh
->sizeofcmds
= new_sizeofcmds
;
1001 arch
->object
->mh
->ncmds
= ncmds
;
1004 *header_size
= sizeof(struct mach_header_64
) +
1005 arch
->object
->mh64
->sizeofcmds
;
1006 if(new_sizeofcmds
< arch
->object
->mh64
->sizeofcmds
){
1007 memset(((char *)arch
->object
->load_commands
) + new_sizeofcmds
,
1008 '\0', arch
->object
->mh64
->sizeofcmds
- new_sizeofcmds
);
1010 memcpy(arch
->object
->load_commands
, new_load_commands
,
1012 arch
->object
->mh64
->sizeofcmds
= new_sizeofcmds
;
1013 arch
->object
->mh64
->ncmds
= ncmds
;
1016 free(new_load_commands
);
1018 /* reset the pointers into the load commands */
1019 lc1
= arch
->object
->load_commands
;
1020 for(i
= 0; i
< ncmds
; i
++){
1023 arch
->object
->st
= (struct symtab_command
*)lc1
;
1026 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
1028 case LC_TWOLEVEL_HINTS
:
1029 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
1031 case LC_PREBIND_CKSUM
:
1032 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
1035 sg
= (struct segment_command
*)lc1
;
1036 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
1037 arch
->object
->seg_linkedit
= sg
;
1040 sg64
= (struct segment_command_64
*)lc1
;
1041 if(strcmp(sg64
->segname
, SEG_LINKEDIT
) == 0)
1042 arch
->object
->seg_linkedit64
= sg64
;
1044 case LC_CODE_SIGNATURE
:
1045 arch
->object
->code_sig_cmd
=
1046 (struct linkedit_data_command
*)lc1
;
1048 case LC_SEGMENT_SPLIT_INFO
:
1049 arch
->object
->split_info_cmd
=
1050 (struct linkedit_data_command
*)lc1
;
1052 case LC_FUNCTION_STARTS
:
1053 arch
->object
->func_starts_info_cmd
=
1054 (struct linkedit_data_command
*)lc1
;
1056 case LC_DATA_IN_CODE
:
1057 arch
->object
->data_in_code_cmd
=
1058 (struct linkedit_data_command
*)lc1
;
1060 case LC_DYLIB_CODE_SIGN_DRS
:
1061 arch
->object
->code_sign_drs_cmd
=
1062 (struct linkedit_data_command
*)lc1
;
1065 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);