2 * Copyright (c) 1999 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@
24 * The strip(1) and nmedit(l) program. This understands only Mach-O format
25 * files (with the restriction the symbol table is at the end of the file) and
26 * fat files with Mach-O files in them.
34 #include <sys/types.h>
36 #include <mach-o/loader.h>
37 #include <mach-o/reloc.h>
38 #include <mach-o/nlist.h>
39 #include <mach-o/stab.h>
40 #include "stuff/breakout.h"
41 #include "stuff/allocate.h"
42 #include "stuff/errors.h"
43 #include "stuff/rnd.h"
44 #include "stuff/reloc.h"
45 #include "stuff/reloc.h"
46 #include "stuff/symbol_list.h"
47 #include "stuff/unix_standard_mode.h"
48 #include "stuff/execute.h"
50 #include <mach-o/prune_trie.h>
51 #endif /* TRIE_SUPPORT */
53 /* These are set from the command line arguments */
55 char *progname
= NULL
; /* name of the program for error messages (argv[0]) */
56 static char *output_file
;/* name of the output file */
57 static char *sfile
; /* filename of global symbol names to keep */
58 static char *Rfile
; /* filename of global symbol names to remove */
59 static uint32_t Aflag
; /* save only absolute symbols with non-zero value and
60 .objc_class_name_* symbols */
61 static uint32_t iflag
; /* -i ignore symbols in -s file not in object */
63 static uint32_t pflag
; /* make all defined global symbols private extern */
64 #else /* !defined(NMEDIT) */
65 static char *dfile
; /* filename of filenames of debugger symbols to keep */
66 static uint32_t uflag
; /* save undefined symbols */
67 static uint32_t rflag
; /* save symbols referenced dynamically */
68 static uint32_t nflag
; /* save N_SECT global symbols */
69 static uint32_t Sflag
; /* -S strip only debugger symbols N_STAB */
70 static uint32_t xflag
; /* -x strip non-globals */
71 static uint32_t Xflag
; /* -X strip local symbols with 'L' names */
72 static uint32_t cflag
; /* -c strip section contents from dynamic libraries
73 files to create stub libraries */
74 static uint32_t no_uuid
;/* -no_uuid strip LC_UUID load commands */
75 static uint32_t vflag
; /* -v for verbose debugging ld -r executions */
76 static uint32_t lflag
; /* -l do ld -r executions even if it has bugs */
77 static uint32_t strip_all
= 1;
79 * This is set on an object by object basis if the strip_all flag is still set
80 * and the object is an executable that is for use with the dynamic linker.
81 * This has the same effect as -r and -u.
83 static enum bool default_dyld_executable
= FALSE
;
87 * Data structures to perform selective stripping of symbol table entries.
88 * save_symbols is the names of the symbols from the -s <file> argument.
89 * remove_symbols is the names of the symbols from the -R <file> argument.
91 static struct symbol_list
*save_symbols
= NULL
;
92 static uint32_t nsave_symbols
= 0;
93 static struct symbol_list
*remove_symbols
= NULL
;
94 static uint32_t nremove_symbols
= 0;
97 * saves points to an array of uint32_t's that is allocated. This array is a
98 * map of old symbol indexes to new symbol indexes. The new symbol indexes are
99 * plus 1 and zero value means that old symbol is not in the new symbol table.
100 * ref_saves is used in the same way but for the reference table.
101 * nmedits is an array and indexed by the symbol index the value indicates if
102 * the symbol was edited and turned into a non-global.
104 static int32_t *saves
= NULL
;
106 static int32_t *ref_saves
= NULL
;
108 static enum bool *nmedits
= NULL
;
112 * These hold pointers to the symbol, string and indirect tables being worked on
113 * by strip_object and strip_symtab() from an input object file or possiblity
114 * changed to an ld -r (-S or -x) file by make_ld_r_object().
116 static struct nlist
*symbols
= NULL
;
117 static struct nlist_64
*symbols64
= NULL
;
118 static uint32_t nsyms
= 0;
119 static char *strings
= NULL
;
120 static uint32_t strsize
= 0;
121 static uint32_t *indirectsyms
= NULL
;
122 static uint32_t nindirectsyms
= 0;
125 * These hold the new symbol and string table created by strip_symtab()
126 * and the new counts of local, defined external and undefined symbols.
128 static struct nlist
*new_symbols
= NULL
;
129 static struct nlist_64
*new_symbols64
= NULL
;
130 static uint32_t new_nsyms
= 0;
131 static char *new_strings
= NULL
;
132 static uint32_t new_strsize
= 0;
133 static uint32_t new_nlocalsym
= 0;
134 static uint32_t new_nextdefsym
= 0;
135 static uint32_t new_nundefsym
= 0;
136 #if defined(TRIE_SUPPORT) && !defined(NMEDIT)
138 * The index into the new symbols where the defined external start.
140 static uint32_t inew_nextdefsym
= 0;
144 * These hold the new table of contents, reference table and module table for
147 static struct dylib_table_of_contents
*new_tocs
= NULL
;
148 static uint32_t new_ntoc
= 0;
149 static struct dylib_reference
*new_refs
= NULL
;
150 static uint32_t new_nextrefsyms
= 0;
152 static struct dylib_module
*new_mods
= NULL
;
153 static struct dylib_module_64
*new_mods64
= NULL
;
154 static uint32_t new_nmodtab
= 0;
159 * The list of file names to save debugging symbols from.
161 static char **debug_filenames
= NULL
;
162 static uint32_t ndebug_filenames
= 0;
169 struct nlist_64 symbol64
;
171 static char *qsort_strings
= NULL
;
172 #endif /* !defined(NMEDIT) */
175 /* Internal routines */
179 static void strip_file(
181 struct arch_flag
*arch_flags
,
182 uint32_t narch_flags
,
183 enum bool all_archs
);
185 static void strip_arch(
188 struct arch_flag
*arch_flags
,
189 uint32_t narch_flags
,
190 enum bool all_archs
);
192 static void strip_object(
194 struct member
*member
,
195 struct object
*object
);
197 static uint32_t get_starting_syminfo_offset(
198 struct object
*object
);
200 static void check_object_relocs(
202 struct member
*member
,
203 struct object
*object
,
208 struct relocation_info
*relocs
,
210 struct nlist
*symbols
,
211 struct nlist_64
*symbols64
,
214 int32_t *missing_reloc_symbols
,
215 enum byte_sex host_byte_sex
);
217 static void check_indirect_symtab(
219 struct member
*member
,
220 struct object
*object
,
223 uint32_t section_type
,
225 struct nlist
*symbols
,
226 struct nlist_64
*symbols64
,
229 int32_t *missing_reloc_symbols
,
230 enum byte_sex host_byte_sex
);
233 static enum bool strip_symtab(
235 struct member
*member
,
236 struct object
*object
,
237 struct dylib_table_of_contents
*tocs
,
239 struct dylib_module
*mods
,
240 struct dylib_module_64
*mods64
,
242 struct dylib_reference
*refs
,
243 uint32_t nextrefsyms
);
248 #endif /* TRIE_SUPPORT */
250 static void make_ld_r_object(
252 struct member
*member
,
253 struct object
*object
);
255 static void strip_LC_UUID_commands(
257 struct member
*member
,
258 struct object
*object
);
261 static void strip_LC_CODE_SIGNATURE_commands(
263 struct member
*member
,
264 struct object
*object
);
265 #endif /* !(NMEDIT) */
267 static enum bool private_extern_reference_by_module(
268 uint32_t symbol_index
,
269 struct dylib_reference
*refs
,
270 uint32_t nextrefsyms
);
272 static enum bool symbol_pointer_used(
273 uint32_t symbol_index
,
274 uint32_t *indirectsyms
,
275 uint32_t nindirectsyms
);
277 static int cmp_qsort_undef_map(
278 const struct undef_map
*sym1
,
279 const struct undef_map
*sym2
);
281 static int cmp_qsort_undef_map_64(
282 const struct undef_map64
*sym1
,
283 const struct undef_map64
*sym2
);
284 #endif /* !defined(NMEDIT) */
287 static enum bool edit_symtab(
289 struct member
*member
,
290 struct object
*object
,
291 struct nlist
*symbols
,
292 struct nlist_64
*symbols64
,
296 struct dylib_table_of_contents
*tocs
,
298 struct dylib_module
*mods
,
299 struct dylib_module_64
*mods64
,
301 struct dylib_reference
*refs
,
302 uint32_t nextrefsyms
);
306 static void setup_debug_filenames(
309 static int cmp_qsort_filename(
313 static int cmp_bsearch_filename(
320 * This variable and routines are used for nmedit(1) only.
322 static char *global_strings
= NULL
;
324 static int cmp_qsort_global(
325 const struct nlist
**sym1
,
326 const struct nlist
**sym2
);
328 static int cmp_qsort_global_64(
329 const struct nlist_64
**sym1
,
330 const struct nlist_64
**sym2
);
332 static int cmp_bsearch_global_stab(
334 const struct nlist
**sym
);
336 static int cmp_bsearch_global_stab_64(
338 const struct nlist_64
**sym
);
340 static int cmp_bsearch_global(
342 const struct nlist
**sym
);
344 static int cmp_bsearch_global_64(
346 const struct nlist_64
**sym
);
349 /* apple_version is created by the libstuff/Makefile */
350 extern char apple_version
[];
351 char *version
= apple_version
;
360 uint32_t j
, args_left
, files_specified
;
361 struct arch_flag
*arch_flags
;
362 uint32_t narch_flags
;
364 struct symbol_list
*sp
;
374 for (i
= 1; i
< argc
; i
++){
375 if(argv
[i
][0] == '-'){
376 if(argv
[i
][1] == '\0'){
380 if(strcmp(argv
[i
], "-o") == 0){
382 fatal("-o requires an argument");
383 if(output_file
!= NULL
)
384 fatal("only one -o option allowed");
385 output_file
= argv
[i
+ 1];
388 else if(strcmp(argv
[i
], "-s") == 0){
390 fatal("-s requires an argument");
392 fatal("only one -s option allowed");
396 else if(strcmp(argv
[i
], "-R") == 0){
398 fatal("-R requires an argument");
400 fatal("only one -R option allowed");
405 else if(strcmp(argv
[i
], "-d") == 0){
407 fatal("-d requires an argument");
409 fatal("only one -d option allowed");
413 else if(strcmp(argv
[i
], "-no_uuid") == 0){
416 #endif /* !defined(NMEDIT) */
417 else if(strcmp(argv
[i
], "-arch") == 0){
419 error("missing argument(s) to %s option", argv
[i
]);
422 if(strcmp("all", argv
[i
+1]) == 0){
426 arch_flags
= reallocate(arch_flags
,
427 (narch_flags
+ 1) * sizeof(struct arch_flag
));
428 if(get_arch_from_flag(argv
[i
+1],
429 arch_flags
+ narch_flags
) == 0){
430 error("unknown architecture specification flag: "
431 "%s %s", argv
[i
], argv
[i
+1]);
435 for(j
= 0; j
< narch_flags
; j
++){
436 if(arch_flags
[j
].cputype
==
437 arch_flags
[narch_flags
].cputype
&&
438 (arch_flags
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
439 (arch_flags
[narch_flags
].cpusubtype
&
440 ~CPU_SUBTYPE_MASK
) &&
441 strcmp(arch_flags
[j
].name
,
442 arch_flags
[narch_flags
].name
) == 0)
451 for(j
= 1; argv
[i
][j
] != '\0'; j
++){
457 #else /* !defined(NMEDIT) */
485 #endif /* !defined(NMEDIT) */
490 #endif /* !defined(NMEDIT) */
505 error("unrecognized option: %s", argv
[i
]);
515 files_specified
+= argc
- (i
+ 1);
517 if(files_specified
> 1 && output_file
!= NULL
){
518 error("-o <filename> can only be used when one file is specified");
523 setup_symbol_list(sfile
, &save_symbols
, &nsave_symbols
);
527 if(Rfile
== NULL
&& pflag
== 0){
528 error("-s <filename>, -R <filename> or -p argument required");
535 setup_symbol_list(Rfile
, &remove_symbols
, &nremove_symbols
);
537 for(j
= 0; j
< nremove_symbols
; j
++){
538 sp
= bsearch(remove_symbols
[j
].name
,
539 save_symbols
, nsave_symbols
,
540 sizeof(struct symbol_list
),
541 (int (*)(const void *, const void *))
542 symbol_list_bsearch
);
544 error("symbol name: %s is listed in both -s %s and -R "
545 "%s files (can't be both saved and removed)",
546 remove_symbols
[j
].name
, sfile
, Rfile
);
554 /* the default when no -arch flags is present is to strip all archs */
560 setup_debug_filenames(dfile
);
562 #endif /* !defined(NMEDIT) */
566 for (i
= 1; i
< argc
; i
++) {
567 if(args_left
&& argv
[i
][0] == '-'){
568 if(argv
[i
][1] == '\0')
570 else if(strcmp(argv
[i
], "-o") == 0 ||
571 strcmp(argv
[i
], "-s") == 0 ||
572 strcmp(argv
[i
], "-R") == 0 ||
574 strcmp(argv
[i
], "-d") == 0 ||
575 #endif /* !defined(NMEDIT) */
576 strcmp(argv
[i
], "-arch") == 0)
580 char resolved_path
[PATH_MAX
+ 1];
582 if(realpath(argv
[i
], resolved_path
) == NULL
)
583 strip_file(argv
[i
], arch_flags
, narch_flags
, all_archs
);
585 strip_file(resolved_path
, arch_flags
,narch_flags
,all_archs
);
589 if(files_specified
== 0)
590 fatal("no files specified");
593 return(EXIT_FAILURE
);
595 return(EXIT_SUCCESS
);
604 fprintf(stderr
, "Usage: %s [-AnuSXx] [-] [-d filename] [-s filename] "
605 "[-R filename] [-o output] file [...] \n", progname
);
606 #else /* defined(NMEDIT) */
607 fprintf(stderr
, "Usage: %s -s filename [-R filename] [-p] [-A] [-] "
608 "[-o output] file [...] \n",
618 struct arch_flag
*arch_flags
,
619 uint32_t narch_flags
,
625 struct stat stat_buf
;
626 uint32_t previous_errors
;
627 enum bool unix_standard_mode
;
636 previous_errors
= errors
;
639 /* breakout the file for processing */
640 ofile
= breakout(input_file
, &archs
, &narchs
, FALSE
);
644 /* checkout the file for symbol table replacement processing */
645 checkout(archs
, narchs
);
647 /* process the symbols in the input file */
648 strip_arch(archs
, narchs
, arch_flags
, narch_flags
, all_archs
);
650 free_archs(archs
, narchs
);
655 /* create the output file */
656 if(stat(input_file
, &stat_buf
) == -1)
657 system_error("can't stat input file: %s", input_file
);
658 if(output_file
!= NULL
){
659 writeout(archs
, narchs
, output_file
, stat_buf
.st_mode
& 0777,
660 TRUE
, FALSE
, FALSE
, NULL
);
663 unix_standard_mode
= get_unix_standard_mode();
667 output_file
= makestr(input_file
, ".nmedit", NULL
);
668 #else /* !defined(NMEDIT) */
670 * In UNIX standard conformance mode we are not allowed to replace
671 * a file that is not writeable.
673 if(unix_standard_mode
== TRUE
&&
674 access(input_file
, W_OK
) == -1){
675 system_error("file: %s is not writable", input_file
);
676 goto strip_file_return
;
678 output_file
= makestr(input_file
, ".strip", NULL
);
681 * The UNIX standard conformance test suite expects files of
682 * MAXPATHLEN to work.
684 if(strlen(output_file
) >= MAXPATHLEN
){
686 * If there is a directory path in the name try to change
687 * the current working directory to that path.
689 if((p
= rindex(output_file
, '/')) != NULL
){
690 if((cwd_fd
= open(".", O_RDONLY
, 0)) == -1){
691 system_error("can't open current working directory");
692 goto strip_file_return
;
695 if(chdir(output_file
) == -1){
696 system_error("can't change current working directory "
697 "to: %s", output_file
);
698 goto strip_file_return
;
700 p
= rindex(input_file
, '/');
701 rename_file
= makestr(p
+ 1, NULL
);
704 * Create what might be a short enough name.
707 output_file
= makestr("strip.XXXXXX", NULL
);
708 output_file
= mktemp(output_file
);
711 writeout(archs
, narchs
, output_file
, stat_buf
.st_mode
& 0777,
712 TRUE
, FALSE
, FALSE
, NULL
);
713 if(rename_file
!= NULL
){
714 if(rename(output_file
, rename_file
) == -1)
715 system_error("can't move temporary file: %s to file: %s",
716 output_file
, rename_file
);
720 if(rename(output_file
, input_file
) == -1)
721 system_error("can't move temporary file: %s to input "
722 "file: %s", output_file
, input_file
);
728 * If we changed the current working directory change back to
729 * the previous working directory.
732 if(fchdir(cwd_fd
) == -1)
733 system_error("can't change back to previous working "
735 if(close(cwd_fd
) == -1)
736 system_error("can't close previous working directory");
742 #endif /* !defined(NMEDIT) */
743 /* clean-up data structures */
744 free_archs(archs
, narchs
);
747 errors
+= previous_errors
;
755 struct arch_flag
*arch_flags
,
756 uint32_t narch_flags
,
759 uint32_t i
, j
, k
, offset
, size
, missing_syms
;
761 cpu_subtype_t cpusubtype
;
762 struct arch_flag host_arch_flag
;
763 enum bool arch_process
, any_processing
, *arch_flag_processed
, family
;
764 const struct arch_flag
*family_arch_flag
;
767 * Using the specified arch_flags process specified objects for those
770 any_processing
= FALSE
;
771 arch_flag_processed
= NULL
;
773 arch_flag_processed
= allocate(narch_flags
* sizeof(enum bool));
774 memset(arch_flag_processed
, '\0', narch_flags
* sizeof(enum bool));
775 for(i
= 0; i
< narchs
; i
++){
777 * Determine the architecture (cputype and cpusubtype) of arch[i]
781 if(archs
[i
].type
== OFILE_ARCHIVE
){
782 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
783 if(archs
[i
].members
[j
].type
== OFILE_Mach_O
){
784 cputype
= archs
[i
].members
[j
].object
->mh_cputype
;
785 cpusubtype
= archs
[i
].members
[j
].object
->mh_cpusubtype
;
790 else if(archs
[i
].type
== OFILE_Mach_O
){
791 cputype
= archs
[i
].object
->mh_cputype
;
792 cpusubtype
= archs
[i
].object
->mh_cpusubtype
;
794 else if(archs
[i
].fat_arch
!= NULL
){
795 cputype
= archs
[i
].fat_arch
->cputype
;
796 cpusubtype
= archs
[i
].fat_arch
->cpusubtype
;
798 arch_process
= FALSE
;
799 if(all_archs
== TRUE
){
802 else if(narch_flags
!= 0){
804 if(narch_flags
== 1){
806 get_arch_family_from_cputype(arch_flags
[0].cputype
);
807 if(family_arch_flag
!= NULL
)
809 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
810 (arch_flags
[0].cpusubtype
& ~CPU_SUBTYPE_MASK
));
812 for(j
= 0; j
< narch_flags
; j
++){
813 if(arch_flags
[j
].cputype
== cputype
&&
814 ((arch_flags
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
815 (cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
818 arch_flag_processed
[j
] = TRUE
;
824 (void)get_arch_from_host(&host_arch_flag
, NULL
);
825 if(host_arch_flag
.cputype
== cputype
&&
826 (host_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
827 (cpusubtype
& ~CPU_SUBTYPE_MASK
))
830 if(narchs
!= 1 && arch_process
== FALSE
)
832 any_processing
= TRUE
;
835 * Now this arch[i] has been selected to be processed so process it
836 * according to its type.
838 if(archs
[i
].type
== OFILE_ARCHIVE
){
839 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
840 if(archs
[i
].members
[j
].type
== OFILE_Mach_O
){
841 strip_object(archs
+ i
, archs
[i
].members
+ j
,
842 archs
[i
].members
[j
].object
);
847 for(k
= 0; k
< nsave_symbols
; k
++){
848 if(save_symbols
[k
].seen
== FALSE
){
849 if(missing_syms
== 0){
850 error_arch(archs
+ i
, NULL
, "symbols names "
851 "listed in: %s not in: ", sfile
);
854 fprintf(stderr
, "%s\n", save_symbols
[k
].name
);
858 for(k
= 0; k
< nsave_symbols
; k
++){
859 save_symbols
[k
].seen
= FALSE
;
863 for(k
= 0; k
< nremove_symbols
; k
++){
864 if(remove_symbols
[k
].seen
== FALSE
){
865 if(missing_syms
== 0){
866 error_arch(archs
+ i
, NULL
, "symbols names "
867 "listed in: %s not defined in: ",
871 fprintf(stderr
, "%s\n", remove_symbols
[k
].name
);
875 for(k
= 0; k
< nremove_symbols
; k
++){
876 remove_symbols
[k
].seen
= FALSE
;
879 * Reset the library offsets and size.
882 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
883 archs
[i
].members
[j
].offset
= offset
;
885 if(archs
[i
].members
[j
].member_long_name
== TRUE
){
886 size
= rnd(archs
[i
].members
[j
].member_name_size
, 8) +
887 (rnd(sizeof(struct ar_hdr
), 8) -
888 sizeof(struct ar_hdr
));
889 archs
[i
].toc_long_name
= TRUE
;
891 if(archs
[i
].members
[j
].object
!= NULL
){
893 rnd(archs
[i
].members
[j
].object
->object_size
-
894 archs
[i
].members
[j
].object
->input_sym_info_size
+
895 archs
[i
].members
[j
].object
->output_sym_info_size
,
897 sprintf(archs
[i
].members
[j
].ar_hdr
->ar_size
, "%-*ld",
898 (int)sizeof(archs
[i
].members
[j
].ar_hdr
->ar_size
),
901 * This has to be done by hand because sprintf puts a
902 * null at the end of the buffer.
904 memcpy(archs
[i
].members
[j
].ar_hdr
->ar_fmag
, ARFMAG
,
905 (int)sizeof(archs
[i
].members
[j
].ar_hdr
->ar_fmag
));
908 size
+= archs
[i
].members
[j
].unknown_size
;
910 offset
+= sizeof(struct ar_hdr
) + size
;
912 archs
[i
].library_size
= offset
;
914 else if(archs
[i
].type
== OFILE_Mach_O
){
915 strip_object(archs
+ i
, NULL
, archs
[i
].object
);
918 warning_arch(archs
+ i
, NULL
, "can't process non-object and "
919 "non-archive file: ");
923 if(all_archs
== FALSE
&& narch_flags
!= 0){
924 for(i
= 0; i
< narch_flags
; i
++){
925 if(arch_flag_processed
[i
] == FALSE
)
926 error("file: %s does not contain architecture: %s",
927 archs
[0].file_name
, arch_flags
[i
].name
);
929 free(arch_flag_processed
);
931 if(any_processing
== FALSE
)
932 fatal("no processing done on input file: %s (specify a -arch flag)",
940 struct member
*member
,
941 struct object
*object
)
943 enum byte_sex host_byte_sex
;
945 struct dylib_table_of_contents
*tocs
;
947 struct dylib_module
*mods
;
948 struct dylib_module_64
*mods64
;
950 struct dylib_reference
*refs
;
951 uint32_t nextrefsyms
;
953 struct load_command
*lc
;
954 struct segment_command
*sg
;
955 struct segment_command_64
*sg64
;
957 struct section_64
*s64
;
958 struct relocation_info
*relocs
;
959 struct scattered_relocation_info
*sreloc
;
960 int32_t missing_reloc_symbols
;
961 uint32_t stride
, section_type
, nitems
;
963 uint32_t dyld_info_start
;
964 uint32_t dyld_info_end
;
971 host_byte_sex
= get_host_byte_sex();
973 /* Don't do anything to stub dylibs which have no load commands. */
974 if(object
->mh_filetype
== MH_DYLIB_STUB
){
975 if((object
->mh
!= NULL
&& object
->mh
->ncmds
== 0) ||
976 (object
->mh64
!= NULL
&& object
->mh64
->ncmds
== 0)){
980 if(object
->mh_filetype
== MH_DSYM
)
981 fatal_arch(arch
, member
, "can't process dSYM companion file: ");
982 if(object
->st
== NULL
|| object
->st
->nsyms
== 0){
983 warning_arch(arch
, member
, "input object file stripped: ");
987 nsyms
= object
->st
->nsyms
;
988 if(object
->mh
!= NULL
){
989 symbols
= (struct nlist
*)
990 (object
->object_addr
+ object
->st
->symoff
);
991 if(object
->object_byte_sex
!= host_byte_sex
)
992 swap_nlist(symbols
, nsyms
, host_byte_sex
);
997 symbols64
= (struct nlist_64
*)
998 (object
->object_addr
+ object
->st
->symoff
);
999 if(object
->object_byte_sex
!= host_byte_sex
)
1000 swap_nlist_64(symbols64
, nsyms
, host_byte_sex
);
1002 strings
= object
->object_addr
+ object
->st
->stroff
;
1003 strsize
= object
->st
->strsize
;
1006 if(object
->mh
!= NULL
)
1007 flags
= object
->mh
->flags
;
1009 flags
= object
->mh64
->flags
;
1010 if(object
->mh_filetype
== MH_DYLIB
&&
1011 (flags
& MH_PREBOUND
) != MH_PREBOUND
){
1012 arch
->dont_update_LC_ID_DYLIB_timestamp
= TRUE
;
1014 if(object
->mh_filetype
!= MH_DYLIB
&& cflag
)
1015 fatal_arch(arch
, member
, "-c can't be used on non-dynamic "
1017 #endif /* !(NMEDIT) */
1018 if(object
->mh_filetype
== MH_DYLIB_STUB
)
1019 fatal_arch(arch
, member
, "dynamic stub library can't be changed "
1022 if(object
->mh_filetype
== MH_DYLIB
){
1023 tocs
= (struct dylib_table_of_contents
*)
1024 (object
->object_addr
+ object
->dyst
->tocoff
);
1025 ntoc
= object
->dyst
->ntoc
;
1026 nmodtab
= object
->dyst
->nmodtab
;
1027 if(object
->mh
!= NULL
){
1028 mods
= (struct dylib_module
*)
1029 (object
->object_addr
+ object
->dyst
->modtaboff
);
1030 if(object
->object_byte_sex
!= host_byte_sex
)
1031 swap_dylib_module(mods
, nmodtab
, host_byte_sex
);
1036 mods64
= (struct dylib_module_64
*)
1037 (object
->object_addr
+ object
->dyst
->modtaboff
);
1038 if(object
->object_byte_sex
!= host_byte_sex
)
1039 swap_dylib_module_64(mods64
, nmodtab
, host_byte_sex
);
1041 refs
= (struct dylib_reference
*)
1042 (object
->object_addr
+ object
->dyst
->extrefsymoff
);
1043 nextrefsyms
= object
->dyst
->nextrefsyms
;
1044 if(object
->object_byte_sex
!= host_byte_sex
){
1045 swap_dylib_table_of_contents(tocs
, ntoc
, host_byte_sex
);
1046 swap_dylib_reference(refs
, nextrefsyms
, host_byte_sex
);
1050 * In the -c flag is specified then strip the section contents of
1051 * this dynamic library and change it into a stub library. When
1052 * creating a stub library the timestamp is not changed.
1055 arch
->dont_update_LC_ID_DYLIB_timestamp
= TRUE
;
1057 lc
= object
->load_commands
;
1058 if(object
->mh
!= NULL
){
1059 ncmds
= object
->mh
->ncmds
;
1060 object
->mh_filetype
= MH_DYLIB_STUB
;
1061 object
->mh
->filetype
= MH_DYLIB_STUB
;
1064 ncmds
= object
->mh64
->ncmds
;
1065 object
->mh_filetype
= MH_DYLIB_STUB
;
1066 object
->mh64
->filetype
= MH_DYLIB_STUB
;
1068 for(i
= 0; i
< ncmds
; i
++){
1069 if(lc
->cmd
== LC_SEGMENT
){
1070 sg
= (struct segment_command
*)lc
;
1071 if(strcmp(sg
->segname
, SEG_LINKEDIT
) != 0){
1073 * Zero out the section offset, reloff, and size
1074 * fields as the section contents are being removed.
1076 s
= (struct section
*)
1077 ((char *)sg
+ sizeof(struct segment_command
));
1078 for(j
= 0; j
< sg
->nsects
; j
++){
1080 * For section types with indirect tables we
1081 * do not zero out the section size in a stub
1082 * library. As the section size is needed to
1083 * know now many indirect table entries the
1084 * section has. This is a bit odd but programs
1085 * dealing with MH_DYLIB_STUB filetypes special
1088 section_type
= s
[j
].flags
& SECTION_TYPE
;
1089 if(section_type
!= S_SYMBOL_STUBS
&&
1090 section_type
!= S_LAZY_SYMBOL_POINTERS
&&
1091 section_type
!= S_LAZY_DYLIB_SYMBOL_POINTERS
&&
1092 section_type
!= S_NON_LAZY_SYMBOL_POINTERS
){
1099 /* zero out file offset and size in the segment */
1104 else if(lc
->cmd
== LC_SEGMENT_64
){
1105 sg64
= (struct segment_command_64
*)lc
;
1106 if(strcmp(sg64
->segname
, SEG_LINKEDIT
) != 0){
1108 * Zero out the section offset, reloff, and size
1109 * fields as the section contents are being removed.
1111 s64
= (struct section_64
*)
1113 sizeof(struct segment_command_64
));
1114 for(j
= 0; j
< sg64
->nsects
; j
++){
1116 * For section types with indirect tables we
1117 * do not zero out the section size in a stub
1118 * library. As the section size is needed to
1119 * know now many indirect table entries the
1120 * section has. This is a bit odd but programs
1121 * dealing with MH_DYLIB_STUB filetypes special
1124 section_type
= s64
[j
].flags
& SECTION_TYPE
;
1125 if(section_type
!= S_SYMBOL_STUBS
&&
1126 section_type
!= S_LAZY_SYMBOL_POINTERS
&&
1127 section_type
!= S_LAZY_DYLIB_SYMBOL_POINTERS
&&
1128 section_type
!= S_NON_LAZY_SYMBOL_POINTERS
){
1135 /* zero out file offset and size in the segment */
1140 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1143 * To get the right amount of the file copied out by writeout()
1144 * for the case when we are stripping out the section contents
1145 * we reduce the object size by the size of the section contents
1146 * including the padding after the load commands. Then this
1147 * size minus the size of the input symbolic information is
1150 if(object
->mh
!= NULL
){
1151 object
->object_size
-= (object
->seg_linkedit
->fileoff
-
1152 (sizeof(struct mach_header
) +
1153 object
->mh
->sizeofcmds
));
1155 * Set the file offset to the link edit information to be
1156 * right after the load commands.
1158 object
->seg_linkedit
->fileoff
=
1159 sizeof(struct mach_header
) +
1160 object
->mh
->sizeofcmds
;
1163 object
->object_size
-= (object
->seg_linkedit64
->fileoff
-
1164 (sizeof(struct mach_header_64
) +
1165 object
->mh64
->sizeofcmds
));
1167 * Set the file offset to the link edit information to be
1168 * right after the load commands.
1170 object
->seg_linkedit64
->fileoff
=
1171 sizeof(struct mach_header_64
) +
1172 object
->mh64
->sizeofcmds
;
1175 #endif /* !(NMEDIT) */
1188 * coalesced symbols can be stripped only if they are not used via an
1189 * symbol pointer. So to know that strip_symtab() needs to be passed
1190 * the indirect symbol table.
1192 if(object
->dyst
!= NULL
&& object
->dyst
->nindirectsyms
!= 0){
1193 nindirectsyms
= object
->dyst
->nindirectsyms
;
1194 indirectsyms
= (uint32_t *)
1195 (object
->object_addr
+ object
->dyst
->indirectsymoff
);
1196 if(object
->object_byte_sex
!= host_byte_sex
)
1197 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
1201 indirectsyms
= NULL
;
1205 if(object
->mh
!= NULL
)
1206 object
->input_sym_info_size
=
1207 nsyms
* sizeof(struct nlist
) +
1210 object
->input_sym_info_size
=
1211 nsyms
* sizeof(struct nlist_64
) +
1214 if(object
->mh
!= NULL
)
1215 flags
= object
->mh
->flags
;
1217 flags
= object
->mh64
->flags
;
1219 (flags
& MH_DYLDLINK
) == MH_DYLDLINK
&&
1220 object
->mh_filetype
== MH_EXECUTE
)
1221 default_dyld_executable
= TRUE
;
1223 default_dyld_executable
= FALSE
;
1224 #endif /* !defined(NMEDIT) */
1227 if(sfile
!= NULL
|| Rfile
!= NULL
|| dfile
!= NULL
|| Aflag
|| uflag
||
1228 Sflag
|| xflag
|| Xflag
|| nflag
|| rflag
||
1229 default_dyld_executable
|| object
->mh_filetype
== MH_DYLIB
||
1230 object
->mh_filetype
== MH_DYLINKER
)
1231 #endif /* !defined(NMEDIT) */
1234 if(edit_symtab(arch
, member
, object
, symbols
, symbols64
, nsyms
,
1235 strings
, strsize
, tocs
, ntoc
, mods
, mods64
, nmodtab
, refs
,
1236 nextrefsyms
) == FALSE
)
1238 #else /* !defined(NMEDIT) */
1239 if(strip_symtab(arch
, member
, object
, tocs
, ntoc
, mods
, mods64
,
1240 nmodtab
, refs
, nextrefsyms
) == FALSE
)
1243 strip_LC_UUID_commands(arch
, member
, object
);
1244 #endif /* !defined(NMEDIT) */
1246 * The parts that make up output_sym_info_size must be added up in
1247 * the output order so that when the sizes of things are rounded up
1248 * before parts that must be aligned the final output_sym_info_size
1251 * Also the parts that make up input_sym_info_size must be added up
1252 * in the same way. And must be done here as the input file may
1253 * have been changed to and "ld -r" file and may not be the
1254 * the original input file.
1256 object
->output_sym_info_size
= 0;
1257 object
->input_sym_info_size
= 0;
1258 if(object
->dyld_info
!= NULL
){
1259 /* there are five parts to the dyld info, but
1260 strip does not alter them, so copy as a block */
1261 dyld_info_start
= 0;
1262 if (object
->dyld_info
->rebase_off
!= 0)
1263 dyld_info_start
= object
->dyld_info
->rebase_off
;
1264 else if (object
->dyld_info
->bind_off
!= 0)
1265 dyld_info_start
= object
->dyld_info
->bind_off
;
1266 else if (object
->dyld_info
->weak_bind_off
!= 0)
1267 dyld_info_start
= object
->dyld_info
->weak_bind_off
;
1268 else if (object
->dyld_info
->lazy_bind_off
!= 0)
1269 dyld_info_start
= object
->dyld_info
->lazy_bind_off
;
1270 else if (object
->dyld_info
->export_off
!= 0)
1271 dyld_info_start
= object
->dyld_info
->export_off
;
1273 if (object
->dyld_info
->export_size
!= 0)
1274 dyld_info_end
= object
->dyld_info
->export_off
1275 + object
->dyld_info
->export_size
;
1276 else if (object
->dyld_info
->lazy_bind_size
!= 0)
1277 dyld_info_end
= object
->dyld_info
->lazy_bind_off
1278 + object
->dyld_info
->lazy_bind_size
;
1279 else if (object
->dyld_info
->weak_bind_size
!= 0)
1280 dyld_info_end
= object
->dyld_info
->weak_bind_off
1281 + object
->dyld_info
->weak_bind_size
;
1282 else if (object
->dyld_info
->bind_size
!= 0)
1283 dyld_info_end
= object
->dyld_info
->bind_off
1284 + object
->dyld_info
->bind_size
;
1285 else if (object
->dyld_info
->rebase_size
!= 0)
1286 dyld_info_end
= object
->dyld_info
->rebase_off
1287 + object
->dyld_info
->rebase_size
;
1288 object
->output_dyld_info
= object
->object_addr
+dyld_info_start
;
1289 object
->output_dyld_info_size
= dyld_info_end
- dyld_info_start
;
1290 object
->output_sym_info_size
+= object
->output_dyld_info_size
;
1292 * Warn about strip -s or -R on a final linked image with
1295 if(nsave_symbols
!= 0){
1296 warning_arch(arch
, NULL
, "removing global symbols from a "
1297 "final linked no longer supported. Use "
1298 "-exported_symbols_list at link time when "
1301 object
->input_sym_info_size
+= object
->dyld_info
->rebase_size
1302 + object
->dyld_info
->bind_size
1303 + object
->dyld_info
->weak_bind_size
1304 + object
->dyld_info
->lazy_bind_size
1305 + object
->dyld_info
->export_size
;
1308 if(object
->dyst
!= NULL
){
1311 * When stripping out the section contents to create a
1312 * dynamic library stub the relocation info also gets
1316 #endif /* !(NMEDIT) */
1318 object
->output_sym_info_size
+=
1319 object
->dyst
->nlocrel
* sizeof(struct relocation_info
);
1321 object
->input_sym_info_size
+=
1322 object
->dyst
->nlocrel
* sizeof(struct relocation_info
);
1325 if(object
->split_info_cmd
!= NULL
){
1326 object
->output_split_info_data
= object
->object_addr
+
1327 object
->split_info_cmd
->dataoff
;
1328 object
->output_split_info_data_size
=
1329 object
->split_info_cmd
->datasize
;
1330 object
->input_sym_info_size
+= object
->split_info_cmd
->datasize
;
1331 object
->output_sym_info_size
+=
1332 object
->split_info_cmd
->datasize
;
1335 if(object
->func_starts_info_cmd
!= NULL
){
1336 object
->output_func_start_info_data
= object
->object_addr
+
1337 object
->func_starts_info_cmd
->dataoff
;
1338 object
->output_func_start_info_data_size
=
1339 object
->func_starts_info_cmd
->datasize
;
1340 object
->input_sym_info_size
+=
1341 object
->func_starts_info_cmd
->datasize
;
1342 object
->output_sym_info_size
+=
1343 object
->func_starts_info_cmd
->datasize
;
1346 if(object
->data_in_code_cmd
!= NULL
){
1347 object
->output_data_in_code_info_data
= object
->object_addr
+
1348 object
->data_in_code_cmd
->dataoff
;
1349 object
->output_data_in_code_info_data_size
=
1350 object
->data_in_code_cmd
->datasize
;
1351 object
->input_sym_info_size
+=
1352 object
->data_in_code_cmd
->datasize
;
1353 object
->output_sym_info_size
+=
1354 object
->data_in_code_cmd
->datasize
;
1357 if(object
->code_sign_drs_cmd
!= NULL
){
1358 object
->output_code_sign_drs_info_data
= object
->object_addr
+
1359 object
->code_sign_drs_cmd
->dataoff
;
1360 object
->output_code_sign_drs_info_data_size
=
1361 object
->code_sign_drs_cmd
->datasize
;
1362 object
->input_sym_info_size
+=
1363 object
->code_sign_drs_cmd
->datasize
;
1364 object
->output_sym_info_size
+=
1365 object
->code_sign_drs_cmd
->datasize
;
1368 if(object
->mh
!= NULL
){
1369 object
->input_sym_info_size
+= nsyms
* sizeof(struct nlist
);
1370 object
->output_symbols
= new_symbols
;
1371 object
->output_sym_info_size
+=
1372 new_nsyms
* sizeof(struct nlist
);
1375 object
->input_sym_info_size
+= nsyms
* sizeof(struct nlist_64
);
1376 object
->output_symbols64
= new_symbols64
;
1377 object
->output_sym_info_size
+=
1378 new_nsyms
* sizeof(struct nlist_64
);
1380 object
->output_nsymbols
= new_nsyms
;
1381 object
->st
->nsyms
= new_nsyms
;
1383 if(object
->hints_cmd
!= NULL
){
1384 object
->input_sym_info_size
+=
1385 object
->hints_cmd
->nhints
*
1386 sizeof(struct twolevel_hint
);
1387 object
->output_sym_info_size
+=
1388 object
->hints_cmd
->nhints
*
1389 sizeof(struct twolevel_hint
);
1392 if(object
->dyst
!= NULL
){
1395 * When stripping out the section contents to create a
1396 * dynamic library stub the relocation info also gets
1400 #endif /* !(NMEDIT) */
1402 object
->output_sym_info_size
+=
1403 object
->dyst
->nextrel
* sizeof(struct relocation_info
);
1405 object
->input_sym_info_size
+=
1406 object
->dyst
->nextrel
* sizeof(struct relocation_info
);
1409 if(object
->dyst
!= NULL
){
1410 object
->output_sym_info_size
+=
1411 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1412 object
->input_indirectsym_pad
;
1413 if(object
->mh
!= NULL
){
1414 object
->input_sym_info_size
+=
1415 object
->dyst
->nindirectsyms
* sizeof(uint32_t);
1418 object
->input_sym_info_size
+=
1419 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1420 object
->input_indirectsym_pad
;
1424 if(object
->dyst
!= NULL
){
1425 object
->output_sym_info_size
+=
1426 new_ntoc
* sizeof(struct dylib_table_of_contents
);
1427 object
->input_sym_info_size
+=
1428 object
->dyst
->ntoc
* sizeof(struct dylib_table_of_contents
);
1431 if(object
->dyst
!= NULL
){
1432 if(object
->mh
!= NULL
){
1433 object
->output_sym_info_size
+=
1434 object
->dyst
->nmodtab
* sizeof(struct dylib_module
);
1435 object
->input_sym_info_size
+=
1436 object
->dyst
->nmodtab
* sizeof(struct dylib_module
);
1439 object
->output_sym_info_size
+=
1440 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
);
1441 object
->input_sym_info_size
+=
1442 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
);
1446 if(object
->dyst
!= NULL
){
1447 object
->output_sym_info_size
+=
1448 new_nextrefsyms
* sizeof(struct dylib_reference
);
1449 object
->input_sym_info_size
+=
1450 object
->dyst
->nextrefsyms
* sizeof(struct dylib_reference
);
1453 object
->output_strings
= new_strings
;
1454 object
->output_strings_size
= new_strsize
;
1455 object
->output_sym_info_size
+= new_strsize
;
1456 object
->input_sym_info_size
+= strsize
;
1457 object
->st
->strsize
= new_strsize
;
1459 if(object
->code_sig_cmd
!= NULL
){
1462 #endif /* !(NMEDIT) */
1464 object
->output_code_sig_data
= object
->object_addr
+
1465 object
->code_sig_cmd
->dataoff
;
1466 object
->output_code_sig_data_size
=
1467 object
->code_sig_cmd
->datasize
;
1469 object
->input_sym_info_size
=
1470 rnd(object
->input_sym_info_size
, 16);
1471 object
->input_sym_info_size
+=
1472 object
->code_sig_cmd
->datasize
;
1475 strip_LC_CODE_SIGNATURE_commands(arch
, member
, object
);
1478 #endif /* !(NMEDIT) */
1480 object
->output_sym_info_size
=
1481 rnd(object
->output_sym_info_size
, 16);
1482 object
->output_sym_info_size
+=
1483 object
->code_sig_cmd
->datasize
;
1487 if(object
->dyst
!= NULL
){
1488 object
->dyst
->ilocalsym
= 0;
1489 object
->dyst
->nlocalsym
= new_nlocalsym
;
1490 object
->dyst
->iextdefsym
= new_nlocalsym
;
1491 object
->dyst
->nextdefsym
= new_nextdefsym
;
1492 object
->dyst
->iundefsym
= new_nlocalsym
+ new_nextdefsym
;
1493 object
->dyst
->nundefsym
= new_nundefsym
;
1494 if(object
->dyst
->nindirectsyms
!= 0){
1495 object
->output_indirect_symtab
= indirectsyms
;
1496 if(object
->object_byte_sex
!= host_byte_sex
)
1497 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
1498 object
->object_byte_sex
);
1502 * If the -c option is specified the object's filetype will
1503 * have been changed from MH_DYLIB to MH_DYLIB_STUB above.
1505 if(object
->mh_filetype
== MH_DYLIB
||
1506 object
->mh_filetype
== MH_DYLIB_STUB
){
1507 object
->output_tocs
= new_tocs
;
1508 object
->output_ntoc
= new_ntoc
;
1510 if(object
->mh
!= NULL
)
1511 object
->output_mods
= new_mods
;
1513 object
->output_mods64
= new_mods64
;
1514 object
->output_nmodtab
= new_nmodtab
;
1516 object
->output_mods
= mods
;
1517 object
->output_nmodtab
= nmodtab
;
1519 object
->output_refs
= new_refs
;
1520 object
->output_nextrefsyms
= new_nextrefsyms
;
1521 if(object
->object_byte_sex
!= host_byte_sex
){
1522 swap_dylib_table_of_contents(new_tocs
, new_ntoc
,
1523 object
->object_byte_sex
);
1525 if(object
->mh
!= NULL
)
1526 swap_dylib_module(new_mods
, new_nmodtab
,
1527 object
->object_byte_sex
);
1529 swap_dylib_module_64(new_mods64
, new_nmodtab
,
1530 object
->object_byte_sex
);
1532 if(object
->mh
!= NULL
)
1533 swap_dylib_module(mods
, nmodtab
,
1534 object
->object_byte_sex
);
1536 swap_dylib_module_64(mods64
, nmodtab
,
1537 object
->object_byte_sex
);
1539 swap_dylib_reference(new_refs
, new_nextrefsyms
,
1540 object
->object_byte_sex
);
1543 object
->dyst
->ntoc
= new_ntoc
;
1544 object
->dyst
->nextrefsyms
= new_nextrefsyms
;
1546 offset
= get_starting_syminfo_offset(object
);
1548 if(object
->dyld_info
!= 0){
1549 if (object
->dyld_info
->rebase_off
!= 0){
1550 object
->dyld_info
->rebase_off
= offset
;
1551 offset
+= object
->dyld_info
->rebase_size
;
1553 if (object
->dyld_info
->bind_off
!= 0){
1554 object
->dyld_info
->bind_off
= offset
;
1555 offset
+= object
->dyld_info
->bind_size
;
1557 if (object
->dyld_info
->weak_bind_off
!= 0){
1558 object
->dyld_info
->weak_bind_off
= offset
;
1559 offset
+= object
->dyld_info
->weak_bind_size
;
1561 if (object
->dyld_info
->lazy_bind_off
!= 0){
1562 object
->dyld_info
->lazy_bind_off
= offset
;
1563 offset
+= object
->dyld_info
->lazy_bind_size
;
1565 if (object
->dyld_info
->export_off
!= 0){
1566 object
->dyld_info
->export_off
= offset
;
1567 offset
+= object
->dyld_info
->export_size
;
1571 if(object
->dyst
->nlocrel
!= 0){
1572 object
->output_loc_relocs
= (struct relocation_info
*)
1573 (object
->object_addr
+ object
->dyst
->locreloff
);
1576 * When stripping out the section contents to create a
1577 * dynamic library stub the relocation info also gets
1581 object
->dyst
->nlocrel
= 0;
1582 object
->dyst
->locreloff
= 0;
1585 #endif /* defined(NMEDIT) */
1587 object
->dyst
->locreloff
= offset
;
1588 offset
+= object
->dyst
->nlocrel
*
1589 sizeof(struct relocation_info
);
1593 object
->dyst
->locreloff
= 0;
1595 if(object
->split_info_cmd
!= NULL
){
1596 object
->split_info_cmd
->dataoff
= offset
;
1597 offset
+= object
->split_info_cmd
->datasize
;
1600 if(object
->func_starts_info_cmd
!= NULL
){
1601 object
->func_starts_info_cmd
->dataoff
= offset
;
1602 offset
+= object
->func_starts_info_cmd
->datasize
;
1605 if(object
->data_in_code_cmd
!= NULL
){
1606 object
->data_in_code_cmd
->dataoff
= offset
;
1607 offset
+= object
->data_in_code_cmd
->datasize
;
1610 if(object
->code_sign_drs_cmd
!= NULL
){
1611 object
->code_sign_drs_cmd
->dataoff
= offset
;
1612 offset
+= object
->code_sign_drs_cmd
->datasize
;
1615 if(object
->st
->nsyms
!= 0){
1616 object
->st
->symoff
= offset
;
1617 if(object
->mh
!= NULL
)
1618 offset
+= object
->st
->nsyms
* sizeof(struct nlist
);
1620 offset
+= object
->st
->nsyms
* sizeof(struct nlist_64
);
1623 object
->st
->symoff
= 0;
1625 if(object
->hints_cmd
!= NULL
){
1626 if(object
->hints_cmd
->nhints
!= 0){
1627 object
->output_hints
= (struct twolevel_hint
*)
1628 (object
->object_addr
+ object
->hints_cmd
->offset
);
1629 object
->hints_cmd
->offset
= offset
;
1630 offset
+= object
->hints_cmd
->nhints
*
1631 sizeof(struct twolevel_hint
);
1634 object
->hints_cmd
->offset
= 0;
1637 if(object
->dyst
->nextrel
!= 0){
1638 object
->output_ext_relocs
= (struct relocation_info
*)
1639 (object
->object_addr
+ object
->dyst
->extreloff
);
1642 * When stripping out the section contents to create a
1643 * dynamic library stub the relocation info also gets
1647 object
->dyst
->nextrel
= 0;
1648 object
->dyst
->extreloff
= 0;
1651 #endif /* defined(NMEDIT) */
1653 object
->dyst
->extreloff
= offset
;
1654 offset
+= object
->dyst
->nextrel
*
1655 sizeof(struct relocation_info
);
1659 object
->dyst
->extreloff
= 0;
1661 if(object
->dyst
->nindirectsyms
!= 0){
1662 object
->dyst
->indirectsymoff
= offset
;
1663 offset
+= object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1664 object
->input_indirectsym_pad
;
1667 object
->dyst
->indirectsymoff
= 0;;
1669 if(object
->dyst
->ntoc
!= 0){
1670 object
->dyst
->tocoff
= offset
;
1671 offset
+= object
->dyst
->ntoc
*
1672 sizeof(struct dylib_table_of_contents
);
1675 object
->dyst
->tocoff
= 0;
1677 if(object
->dyst
->nmodtab
!= 0){
1680 * When stripping out the section contents to create a
1681 * dynamic library stub zero out the fields in the module
1682 * table for the sections and relocation information and
1683 * clear Objective-C address and size from modules.
1686 if(object
->mh
!= NULL
){
1687 for(k
= 0; k
< object
->dyst
->nmodtab
; k
++){
1688 mods
[k
].iinit_iterm
= 0;
1689 mods
[k
].ninit_nterm
= 0;
1690 mods
[k
].iextrel
= 0;
1691 mods
[k
].nextrel
= 0;
1692 mods
[k
].objc_module_info_addr
= 0;
1693 mods
[k
].objc_module_info_size
= 0;
1697 for(k
= 0; k
< object
->dyst
->nmodtab
; k
++){
1698 mods64
[k
].iinit_iterm
= 0;
1699 mods64
[k
].ninit_nterm
= 0;
1700 mods64
[k
].iextrel
= 0;
1701 mods64
[k
].nextrel
= 0;
1702 mods64
[k
].objc_module_info_addr
= 0;
1703 mods64
[k
].objc_module_info_size
= 0;
1707 #endif /* !(NMEDIT) */
1708 object
->dyst
->modtaboff
= offset
;
1709 if(object
->mh
!= NULL
)
1710 offset
+= object
->dyst
->nmodtab
*
1711 sizeof(struct dylib_module
);
1713 offset
+= object
->dyst
->nmodtab
*
1714 sizeof(struct dylib_module_64
);
1717 object
->dyst
->modtaboff
= 0;
1719 if(object
->dyst
->nextrefsyms
!= 0){
1720 object
->dyst
->extrefsymoff
= offset
;
1721 offset
+= object
->dyst
->nextrefsyms
*
1722 sizeof(struct dylib_reference
);
1725 object
->dyst
->extrefsymoff
= 0;
1727 if(object
->st
->strsize
!= 0){
1728 object
->st
->stroff
= offset
;
1729 offset
+= object
->st
->strsize
;
1732 object
->st
->stroff
= 0;
1734 if(object
->code_sig_cmd
!= NULL
){
1735 offset
= rnd(offset
, 16);
1736 object
->code_sig_cmd
->dataoff
= offset
;
1737 offset
+= object
->code_sig_cmd
->datasize
;
1741 if(new_strsize
!= 0){
1742 if(object
->mh
!= NULL
)
1743 object
->st
->stroff
= object
->st
->symoff
+
1744 new_nsyms
* sizeof(struct nlist
);
1746 object
->st
->stroff
= object
->st
->symoff
+
1747 new_nsyms
* sizeof(struct nlist_64
);
1750 object
->st
->stroff
= 0;
1752 object
->st
->symoff
= 0;
1758 * Here we are doing a full symbol strip. In some cases it may
1759 * leave the local relocation entries as well as LOCAL indirect
1760 * symbol table entries.
1764 saves
= (int32_t *)allocate(object
->st
->nsyms
* sizeof(int32_t));
1765 bzero(saves
, object
->st
->nsyms
* sizeof(int32_t));
1768 * Account for the symbolic info in the input file.
1770 if(object
->dyst
!= NULL
){
1771 object
->input_sym_info_size
+=
1772 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1773 object
->dyst
->nextrel
* sizeof(struct relocation_info
) +
1774 object
->dyst
->ntoc
* sizeof(struct dylib_table_of_contents
)+
1775 object
->dyst
->nextrefsyms
* sizeof(struct dylib_reference
);
1776 if(object
->mh
!= NULL
){
1777 object
->input_sym_info_size
+=
1778 object
->dyst
->nmodtab
* sizeof(struct dylib_module
) +
1779 object
->dyst
->nindirectsyms
* sizeof(uint32_t);
1782 object
->input_sym_info_size
+=
1783 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
) +
1784 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1785 object
->input_indirectsym_pad
;
1790 * Determine the offset where the remaining symbolic info will start
1791 * in the output file (if any).
1793 offset
= get_starting_syminfo_offset(object
);
1796 * For a full symbol strip all these values in the output file are
1799 object
->st
->symoff
= 0;
1800 object
->st
->nsyms
= 0;
1801 object
->st
->stroff
= 0;
1802 object
->st
->strsize
= 0;
1803 if(object
->dyst
!= NULL
){
1804 object
->dyst
->ilocalsym
= 0;
1805 object
->dyst
->nlocalsym
= 0;
1806 object
->dyst
->iextdefsym
= 0;
1807 object
->dyst
->nextdefsym
= 0;
1808 object
->dyst
->iundefsym
= 0;
1809 object
->dyst
->nundefsym
= 0;
1813 * This will accumulate any remaining symbolic info size in the
1816 object
->output_sym_info_size
= 0;
1819 * We set these so that checking can be done below to report the
1820 * symbols that can't be stripped because of relocation entries
1821 * or indirect symbol table entries. Normally if these table have a
1822 * non-zero number of entries it will be an error as we are trying
1823 * to strip everything. But it maybe that there are only LOCAL
1824 * indirect entries which is odd but will be OK.
1826 if(object
->dyst
!= NULL
){
1827 if(object
->dyst
->nextrel
!= 0){
1828 object
->output_ext_relocs
= (struct relocation_info
*)
1829 (object
->object_addr
+ object
->dyst
->extreloff
);
1832 * Since this file has a dynamic symbol table and if this file
1833 * has local relocation entries on input make sure they are
1834 * there on output. This is a rare case that it will not have
1835 * external relocs or indirect symbols but can happen as is the
1836 * case with the dynamic linker itself.
1838 if(object
->dyst
->nlocrel
!= 0){
1839 object
->output_loc_relocs
= (struct relocation_info
*)
1840 (object
->object_addr
+ object
->dyst
->locreloff
);
1841 object
->output_sym_info_size
+=
1842 object
->dyst
->nlocrel
* sizeof(struct relocation_info
);
1844 object
->dyst
->locreloff
= offset
;
1845 offset
+= object
->dyst
->nlocrel
*
1846 sizeof(struct relocation_info
);
1849 if(object
->dyst
->nindirectsyms
!= 0){
1850 object
->output_indirect_symtab
= (uint32_t *)
1851 (object
->object_addr
+
1852 object
->dyst
->indirectsymoff
);
1853 if(object
->object_byte_sex
!= host_byte_sex
)
1854 swap_indirect_symbols(
1855 object
->output_indirect_symtab
,
1856 object
->dyst
->nindirectsyms
,
1857 object
->object_byte_sex
);
1859 object
->output_sym_info_size
+=
1860 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1861 object
->input_indirectsym_pad
;
1863 object
->dyst
->indirectsymoff
= offset
;
1864 offset
+= object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1865 object
->input_indirectsym_pad
;
1869 #endif /* !defined(NMEDIT) */
1872 * Always clear the prebind checksum if any when creating a new file.
1874 if(object
->cs
!= NULL
)
1875 object
->cs
->cksum
= 0;
1877 if(object
->seg_linkedit
!= NULL
){
1878 object
->seg_linkedit
->filesize
+= object
->output_sym_info_size
-
1879 object
->input_sym_info_size
;
1880 object
->seg_linkedit
->vmsize
= object
->seg_linkedit
->filesize
;
1882 else if(object
->seg_linkedit64
!= NULL
){
1883 /* Do this in two steps to avoid 32/64-bit casting problems. */
1884 object
->seg_linkedit64
->filesize
-= object
->input_sym_info_size
;
1885 object
->seg_linkedit64
->filesize
+= object
->output_sym_info_size
;
1886 object
->seg_linkedit64
->vmsize
= object
->seg_linkedit64
->filesize
;
1890 * Check and update the external relocation entries to make sure
1891 * referenced symbols are not stripped and refer to the new symbol
1894 * The external relocation entries can be located in one of two places,
1895 * first off of the sections or second off of the dynamic symtab.
1897 missing_reloc_symbols
= 0;
1898 lc
= object
->load_commands
;
1899 if(object
->mh
!= NULL
)
1900 ncmds
= object
->mh
->ncmds
;
1902 ncmds
= object
->mh64
->ncmds
;
1903 for(i
= 0; i
< ncmds
; i
++){
1904 if(lc
->cmd
== LC_SEGMENT
&&
1905 object
->seg_linkedit
!= (struct segment_command
*)lc
){
1906 sg
= (struct segment_command
*)lc
;
1907 s
= (struct section
*)((char *)sg
+
1908 sizeof(struct segment_command
));
1909 for(j
= 0; j
< sg
->nsects
; j
++){
1911 if(s
->reloff
+ s
->nreloc
*
1912 sizeof(struct relocation_info
) >
1913 object
->object_size
){
1914 fatal_arch(arch
, member
, "truncated or malformed "
1915 "object (relocation entries for section (%.16s,"
1916 "%.16s) extends past the end of the file)",
1917 s
->segname
, s
->sectname
);
1919 relocs
= (struct relocation_info
*)
1920 (object
->object_addr
+ s
->reloff
);
1921 if(object
->object_byte_sex
!= host_byte_sex
)
1922 swap_relocation_info(relocs
, s
->nreloc
,
1924 if(s
->offset
+ s
->size
> object
->object_size
){
1925 fatal_arch(arch
, member
, "truncated or malformed "
1926 "object (contents of section (%.16s,"
1927 "%.16s) extends past the end of the file)",
1928 s
->segname
, s
->sectname
);
1930 contents
= object
->object_addr
+ s
->offset
;
1931 check_object_relocs(arch
, member
, object
, s
->segname
,
1932 s
->sectname
, s
->size
, contents
, relocs
, s
->nreloc
,
1933 symbols
, symbols64
, nsyms
, strings
,
1934 &missing_reloc_symbols
, host_byte_sex
);
1935 if(object
->object_byte_sex
!= host_byte_sex
)
1936 swap_relocation_info(relocs
, s
->nreloc
,
1937 object
->object_byte_sex
);
1942 else if(lc
->cmd
== LC_SEGMENT_64
&&
1943 object
->seg_linkedit64
!= (struct segment_command_64
*)lc
){
1944 sg64
= (struct segment_command_64
*)lc
;
1945 s64
= (struct section_64
*)((char *)sg64
+
1946 sizeof(struct segment_command_64
));
1947 for(j
= 0; j
< sg64
->nsects
; j
++){
1948 if(s64
->nreloc
!= 0){
1949 if(s64
->reloff
+ s64
->nreloc
*
1950 sizeof(struct relocation_info
) >
1951 object
->object_size
){
1952 fatal_arch(arch
, member
, "truncated or malformed "
1953 "object (relocation entries for section (%.16s,"
1954 "%.16s) extends past the end of the file)",
1955 s64
->segname
, s64
->sectname
);
1957 relocs
= (struct relocation_info
*)
1958 (object
->object_addr
+ s64
->reloff
);
1959 if(object
->object_byte_sex
!= host_byte_sex
)
1960 swap_relocation_info(relocs
, s64
->nreloc
,
1962 if(s64
->offset
+ s64
->size
> object
->object_size
){
1963 fatal_arch(arch
, member
, "truncated or malformed "
1964 "object (contents of section (%.16s,"
1965 "%.16s) extends past the end of the file)",
1966 s64
->segname
, s64
->sectname
);
1968 contents
= object
->object_addr
+ s64
->offset
;
1969 check_object_relocs(arch
, member
, object
, s64
->segname
,
1970 s64
->sectname
, s64
->size
, contents
, relocs
,
1971 s64
->nreloc
, symbols
, symbols64
, nsyms
, strings
,
1972 &missing_reloc_symbols
, host_byte_sex
);
1973 if(object
->object_byte_sex
!= host_byte_sex
)
1974 swap_relocation_info(relocs
, s64
->nreloc
,
1975 object
->object_byte_sex
);
1980 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1982 if(object
->dyst
!= NULL
&& object
->dyst
->nextrel
!= 0){
1983 relocs
= object
->output_ext_relocs
;
1984 if(object
->object_byte_sex
!= host_byte_sex
)
1985 swap_relocation_info(relocs
, object
->dyst
->nextrel
,
1988 for(i
= 0; i
< object
->dyst
->nextrel
; i
++){
1989 if((relocs
[i
].r_address
& R_SCATTERED
) == 0 &&
1990 relocs
[i
].r_extern
== 1){
1991 if(relocs
[i
].r_symbolnum
> nsyms
){
1992 fatal_arch(arch
, member
, "bad r_symbolnum for external "
1993 "relocation entry %d in: ", i
);
1995 if(saves
[relocs
[i
].r_symbolnum
] == 0){
1996 if(missing_reloc_symbols
== 0){
1997 error_arch(arch
, member
, "symbols referenced by "
1998 "relocation entries that can't be stripped in: ");
1999 missing_reloc_symbols
= 1;
2001 if(object
->mh
!= NULL
){
2002 fprintf(stderr
, "%s\n", strings
+ symbols
2003 [relocs
[i
].r_symbolnum
].n_un
.n_strx
);
2006 fprintf(stderr
, "%s\n", strings
+ symbols64
2007 [relocs
[i
].r_symbolnum
].n_un
.n_strx
);
2009 saves
[relocs
[i
].r_symbolnum
] = -1;
2011 if(saves
[relocs
[i
].r_symbolnum
] != -1){
2012 relocs
[i
].r_symbolnum
=
2013 saves
[relocs
[i
].r_symbolnum
] - 1;
2017 fatal_arch(arch
, member
, "bad external relocation entry "
2018 "%d (not external) in: ", i
);
2020 if((relocs
[i
].r_address
& R_SCATTERED
) == 0){
2021 if(reloc_has_pair(object
->mh_cputype
, relocs
[i
].r_type
))
2025 sreloc
= (struct scattered_relocation_info
*)relocs
+ i
;
2026 if(reloc_has_pair(object
->mh_cputype
, sreloc
->r_type
))
2030 if(object
->object_byte_sex
!= host_byte_sex
)
2031 swap_relocation_info(relocs
, object
->dyst
->nextrel
,
2032 object
->object_byte_sex
);
2036 * Check and update the indirect symbol table entries to make sure
2037 * referenced symbols are not stripped and refer to the new symbol
2040 if(object
->dyst
!= NULL
&& object
->dyst
->nindirectsyms
!= 0){
2041 if(object
->object_byte_sex
!= host_byte_sex
)
2042 swap_indirect_symbols(object
->output_indirect_symtab
,
2043 object
->dyst
->nindirectsyms
, host_byte_sex
);
2045 lc
= object
->load_commands
;
2046 if(object
->mh
!= NULL
)
2047 ncmds
= object
->mh
->ncmds
;
2049 ncmds
= object
->mh64
->ncmds
;
2050 for(i
= 0; i
< ncmds
; i
++){
2051 if(lc
->cmd
== LC_SEGMENT
&&
2052 object
->seg_linkedit
!= (struct segment_command
*)lc
){
2053 sg
= (struct segment_command
*)lc
;
2054 s
= (struct section
*)((char *)sg
+
2055 sizeof(struct segment_command
));
2056 for(j
= 0; j
< sg
->nsects
; j
++){
2057 section_type
= s
->flags
& SECTION_TYPE
;
2058 if(section_type
== S_LAZY_SYMBOL_POINTERS
||
2059 section_type
== S_LAZY_DYLIB_SYMBOL_POINTERS
||
2060 section_type
== S_NON_LAZY_SYMBOL_POINTERS
)
2062 else if(section_type
== S_SYMBOL_STUBS
)
2063 stride
= s
->reserved2
;
2068 nitems
= s
->size
/ stride
;
2069 contents
= object
->object_addr
+ s
->offset
;
2070 check_indirect_symtab(arch
, member
, object
, nitems
,
2071 s
->reserved1
, section_type
, contents
, symbols
,
2072 symbols64
, nsyms
, strings
, &missing_reloc_symbols
,
2077 else if(lc
->cmd
== LC_SEGMENT_64
&&
2078 object
->seg_linkedit64
!= (struct segment_command_64
*)lc
){
2079 sg64
= (struct segment_command_64
*)lc
;
2080 s64
= (struct section_64
*)((char *)sg64
+
2081 sizeof(struct segment_command_64
));
2082 for(j
= 0; j
< sg64
->nsects
; j
++){
2083 section_type
= s64
->flags
& SECTION_TYPE
;
2084 if(section_type
== S_LAZY_SYMBOL_POINTERS
||
2085 section_type
== S_LAZY_DYLIB_SYMBOL_POINTERS
||
2086 section_type
== S_NON_LAZY_SYMBOL_POINTERS
)
2088 else if(section_type
== S_SYMBOL_STUBS
)
2089 stride
= s64
->reserved2
;
2094 nitems
= s64
->size
/ stride
;
2095 contents
= object
->object_addr
+ s64
->offset
;
2096 check_indirect_symtab(arch
, member
, object
, nitems
,
2097 s64
->reserved1
, section_type
, contents
, symbols
,
2098 symbols64
, nsyms
, strings
, &missing_reloc_symbols
,
2103 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2106 if(object
->object_byte_sex
!= host_byte_sex
)
2107 swap_indirect_symbols(object
->output_indirect_symtab
,
2108 object
->dyst
->nindirectsyms
, object
->object_byte_sex
);
2112 * Issue a warning if object file has a code signature that the
2113 * operation will invalidate it.
2115 if(object
->code_sig_cmd
!= NULL
)
2116 warning_arch(arch
, member
, "changes being made to the file will "
2117 "invalidate the code signature in: ");
2121 * get_starting_syminfo_offset() returns the starting offset of the symbolic
2122 * info in the object file.
2126 get_starting_syminfo_offset(
2127 struct object
*object
)
2131 if(object
->seg_linkedit
!= NULL
||
2132 object
->seg_linkedit64
!= NULL
){
2133 if(object
->mh
!= NULL
)
2134 offset
= object
->seg_linkedit
->fileoff
;
2136 offset
= object
->seg_linkedit64
->fileoff
;
2140 if(object
->dyst
!= NULL
&&
2141 object
->dyst
->nlocrel
!= 0 &&
2142 object
->dyst
->locreloff
< offset
)
2143 offset
= object
->dyst
->locreloff
;
2144 if(object
->st
->nsyms
!= 0 &&
2145 object
->st
->symoff
< offset
)
2146 offset
= object
->st
->symoff
;
2147 if(object
->dyst
!= NULL
&&
2148 object
->dyst
->nextrel
!= 0 &&
2149 object
->dyst
->extreloff
< offset
)
2150 offset
= object
->dyst
->extreloff
;
2151 if(object
->dyst
!= NULL
&&
2152 object
->dyst
->nindirectsyms
!= 0 &&
2153 object
->dyst
->indirectsymoff
< offset
)
2154 offset
= object
->dyst
->indirectsymoff
;
2155 if(object
->dyst
!= NULL
&&
2156 object
->dyst
->ntoc
!= 0 &&
2157 object
->dyst
->tocoff
< offset
)
2158 offset
= object
->dyst
->tocoff
;
2159 if(object
->dyst
!= NULL
&&
2160 object
->dyst
->nmodtab
!= 0 &&
2161 object
->dyst
->modtaboff
< offset
)
2162 offset
= object
->dyst
->modtaboff
;
2163 if(object
->dyst
!= NULL
&&
2164 object
->dyst
->nextrefsyms
!= 0 &&
2165 object
->dyst
->extrefsymoff
< offset
)
2166 offset
= object
->dyst
->extrefsymoff
;
2167 if(object
->st
->strsize
!= 0 &&
2168 object
->st
->stroff
< offset
)
2169 offset
= object
->st
->stroff
;
2175 * check_object_relocs() is used to check and update the external relocation
2176 * entries from a section in an object file, to make sure referenced symbols
2177 * are not stripped and are changed to refer to the new symbol table indexes.
2181 check_object_relocs(
2183 struct member
*member
,
2184 struct object
*object
,
2189 struct relocation_info
*relocs
,
2191 struct nlist
*symbols
,
2192 struct nlist_64
*symbols64
,
2195 int32_t *missing_reloc_symbols
,
2196 enum byte_sex host_byte_sex
)
2201 uint32_t value
, n_ext
;
2204 struct scattered_relocation_info
*sreloc
;
2206 for(k
= 0; k
< nreloc
; k
++){
2207 if((relocs
[k
].r_address
& R_SCATTERED
) == 0 &&
2208 relocs
[k
].r_extern
== 1){
2209 if(relocs
[k
].r_symbolnum
> nsyms
){
2210 fatal_arch(arch
, member
, "bad r_symbolnum for relocation "
2211 "entry %d in section (%.16s,%.16s) in: ", k
, segname
,
2214 if(object
->mh
!= NULL
){
2215 n_strx
= symbols
[relocs
[k
].r_symbolnum
].n_un
.n_strx
;
2216 n_value
= symbols
[relocs
[k
].r_symbolnum
].n_value
;
2219 n_strx
= symbols64
[relocs
[k
].r_symbolnum
].n_un
.n_strx
;
2220 n_value
= symbols64
[relocs
[k
].r_symbolnum
].n_value
;
2223 if(saves
[relocs
[k
].r_symbolnum
] == 0){
2224 if(*missing_reloc_symbols
== 0){
2225 error_arch(arch
, member
, "symbols referenced by "
2226 "relocation entries that can't be stripped in: ");
2227 *missing_reloc_symbols
= 1;
2229 fprintf(stderr
, "%s\n", strings
+ n_strx
);
2230 saves
[relocs
[k
].r_symbolnum
] = -1;
2232 #else /* defined(NMEDIT) */
2234 * We are letting nmedit change global coalesed symbols into
2235 * statics in MH_OBJECT file types only. Relocation entries to
2236 * global coalesced symbols are external relocs.
2238 if(object
->mh
!= NULL
)
2239 n_ext
= new_symbols
[saves
[relocs
[k
].r_symbolnum
] - 1].
2242 n_ext
= new_symbols64
[saves
[relocs
[k
].r_symbolnum
] - 1].
2244 if(n_ext
!= N_EXT
&&
2245 object
->mh_cputype
!= CPU_TYPE_X86_64
){
2247 * We need to do the relocation for this external relocation
2248 * entry so the item to be relocated is correct for a local
2249 * relocation entry. We don't need to do this for x86-64.
2251 if(relocs
[k
].r_address
+ sizeof(int32_t) > sectsize
){
2252 fatal_arch(arch
, member
, "truncated or malformed "
2253 "object (r_address of relocation entry %u of "
2254 "section (%.16s,%.16s) extends past the end "
2255 "of the section)", k
, segname
, sectname
);
2257 if(object
->mh
!= NULL
){
2258 value
= *(uint32_t *)
2259 (contents
+ relocs
[k
].r_address
);
2260 if(object
->object_byte_sex
!= host_byte_sex
)
2261 value
= SWAP_INT(value
);
2263 * We handle a very limited form here. Only VANILLA
2264 * (r_type == 0) long (r_length==2) absolute or pcrel
2265 * that won't need a scattered relocation entry.
2267 if(relocs
[k
].r_type
!= 0 ||
2268 relocs
[k
].r_length
!= 2){
2269 fatal_arch(arch
, member
, "don't have "
2270 "code to convert external relocation "
2271 "entry %d in section (%.16s,%.16s) "
2272 "for global coalesced symbol: %s "
2273 "in: ", k
, segname
, sectname
,
2277 if(object
->object_byte_sex
!= host_byte_sex
)
2278 value
= SWAP_INT(value
);
2279 *(uint32_t *)(contents
+ relocs
[k
].r_address
) =
2283 value64
= *(uint64_t *)(contents
+ relocs
[k
].r_address
);
2284 if(object
->object_byte_sex
!= host_byte_sex
)
2285 value64
= SWAP_LONG_LONG(value64
);
2287 * We handle a very limited form here. Only VANILLA
2288 * (r_type == 0) quad (r_length==3) absolute or pcrel
2289 * that won't need a scattered relocation entry.
2291 if(relocs
[k
].r_type
!= 0 ||
2292 relocs
[k
].r_length
!= 3){
2293 fatal_arch(arch
, member
, "don't have "
2294 "code to convert external relocation "
2295 "entry %d in section (%.16s,%.16s) "
2296 "for global coalesced symbol: %s "
2297 "in: ", k
, segname
, sectname
,
2301 if(object
->object_byte_sex
!= host_byte_sex
)
2302 value64
= SWAP_LONG_LONG(value64
);
2303 *(uint64_t *)(contents
+ relocs
[k
].r_address
) = value64
;
2306 * Turn the extern reloc into a local.
2308 if(object
->mh
!= NULL
)
2309 relocs
[k
].r_symbolnum
=
2310 new_symbols
[saves
[relocs
[k
].r_symbolnum
] - 1].n_sect
;
2312 relocs
[k
].r_symbolnum
=
2313 new_symbols64
[saves
[relocs
[k
].r_symbolnum
] - 1].n_sect
;
2314 relocs
[k
].r_extern
= 0;
2317 if(relocs
[k
].r_extern
== 1 &&
2318 saves
[relocs
[k
].r_symbolnum
] != -1){
2319 relocs
[k
].r_symbolnum
= saves
[relocs
[k
].r_symbolnum
] - 1;
2322 if((relocs
[k
].r_address
& R_SCATTERED
) == 0){
2323 if(reloc_has_pair(object
->mh_cputype
, relocs
[k
].r_type
) == TRUE
)
2327 sreloc
= (struct scattered_relocation_info
*)relocs
+ k
;
2328 if(reloc_has_pair(object
->mh_cputype
, sreloc
->r_type
) == TRUE
)
2335 * check_indirect_symtab() checks and updates the indirect symbol table entries
2336 * to make sure referenced symbols are not stripped and refer to the new symbol
2341 check_indirect_symtab(
2343 struct member
*member
,
2344 struct object
*object
,
2347 uint32_t section_type
,
2349 struct nlist
*symbols
,
2350 struct nlist_64
*symbols64
,
2353 int32_t *missing_reloc_symbols
,
2354 enum byte_sex host_byte_sex
)
2358 uint32_t n_strx
, value
;
2360 enum bool made_local
;
2362 for(k
= 0; k
< nitems
; k
++){
2364 index
= object
->output_indirect_symtab
[reserved1
+ k
];
2365 if(index
== INDIRECT_SYMBOL_LOCAL
||
2366 index
== INDIRECT_SYMBOL_ABS
||
2367 index
== (INDIRECT_SYMBOL_LOCAL
| INDIRECT_SYMBOL_ABS
))
2370 fatal_arch(arch
, member
,"indirect symbol table entry %d (past " "the end of the symbol table) in: ", reserved1
+ k
);
2372 if(pflag
== 0 && nmedits
[index
] == TRUE
&& saves
[index
] != -1)
2374 if(saves
[index
] == 0)
2378 * Indirect symbol table entries for defined symbols in a
2379 * non-lazy pointer section that are not saved are changed to
2380 * INDIRECT_SYMBOL_LOCAL which their values just have to be
2381 * slid if the are not absolute symbols.
2383 if(object
->mh
!= NULL
){
2384 n_type
= symbols
[index
].n_type
;
2385 n_strx
= symbols
[index
].n_un
.n_strx
;
2388 n_type
= symbols64
[index
].n_type
;
2389 n_strx
= symbols64
[index
].n_un
.n_strx
;
2391 if((n_type
& N_TYPE
) != N_UNDF
&&
2392 (n_type
& N_TYPE
) != N_PBUD
&&
2393 section_type
== S_NON_LAZY_SYMBOL_POINTERS
){
2394 object
->output_indirect_symtab
[reserved1
+ k
] =
2395 INDIRECT_SYMBOL_LOCAL
;
2396 if((n_type
& N_TYPE
) == N_ABS
)
2397 object
->output_indirect_symtab
[reserved1
+ k
] |=
2398 INDIRECT_SYMBOL_ABS
;
2401 * When creating a stub shared library the section contents
2402 * are not updated since they will be stripped.
2404 if(object
->mh_filetype
!= MH_DYLIB_STUB
){
2405 if(object
->mh
!= NULL
){
2406 value
= symbols
[index
].n_value
;
2407 if (symbols
[index
].n_desc
& N_ARM_THUMB_DEF
)
2409 if(object
->object_byte_sex
!= host_byte_sex
)
2410 value
= SWAP_INT(value
);
2411 *(uint32_t *)(contents
+ k
* 4) = value
;
2414 value64
= symbols64
[index
].n_value
;
2415 if(object
->object_byte_sex
!= host_byte_sex
)
2416 value64
= SWAP_LONG_LONG(value64
);
2417 *(uint64_t *)(contents
+ k
* 8) = value64
;
2423 object
->output_indirect_symtab
[reserved1
+ k
] =
2426 #else /* !defined(NMEDIT) */
2428 if(*missing_reloc_symbols
== 0){
2429 error_arch(arch
, member
, "symbols referenced by "
2430 "indirect symbol table entries that can't be "
2432 *missing_reloc_symbols
= 1;
2434 fprintf(stderr
, "%s\n", strings
+ n_strx
);
2437 #endif /* !defined(NMEDIT) */
2441 #else /* !defined(NMEDIT) */
2442 if(made_local
== FALSE
&& saves
[index
] != -1)
2443 #endif /* !defined(NMEDIT) */
2445 object
->output_indirect_symtab
[reserved1
+k
] = saves
[index
] - 1;
2452 * This is called if there is a -d option specified. It reads the file with
2453 * the strings in it and places them in the array debug_filenames and sorts
2454 * them by name. The file that contains the file names must have names one
2455 * per line with no white space (except the newlines).
2459 setup_debug_filenames(
2462 int fd
, i
, strings_size
;
2463 struct stat stat_buf
;
2466 if((fd
= open(dfile
, O_RDONLY
)) < 0){
2467 system_error("can't open: %s", dfile
);
2470 if(fstat(fd
, &stat_buf
) == -1){
2471 system_error("can't stat: %s", dfile
);
2475 strings_size
= stat_buf
.st_size
;
2476 strings
= (char *)allocate(strings_size
+ 1);
2477 strings
[strings_size
] = '\0';
2478 if(read(fd
, strings
, strings_size
) != strings_size
){
2479 system_error("can't read: %s", dfile
);
2484 for(i
= 0; i
< strings_size
; i
++){
2491 debug_filenames
= (char **)allocate(ndebug_filenames
* sizeof(char *));
2493 for(i
= 0; i
< ndebug_filenames
; i
++){
2494 debug_filenames
[i
] = p
;
2497 qsort(debug_filenames
, ndebug_filenames
, sizeof(char *),
2498 (int (*)(const void *, const void *))cmp_qsort_filename
);
2501 printf("Debug filenames:\n");
2502 for(i
= 0; i
< ndebug_filenames
; i
++){
2503 printf("filename = %s\n", debug_filenames
[i
]);
2509 * Strip the symbol table to the level specified by the command line arguments.
2510 * The new symbol table is built and new_symbols is left pointing to it. The
2511 * number of new symbols is left in new_nsyms, the new string table is built
2512 * and new_stings is left pointing to it and new_strsize is left containing it.
2513 * This routine returns zero if successfull and non-zero otherwise.
2519 struct member
*member
,
2520 struct object
*object
,
2521 struct dylib_table_of_contents
*tocs
,
2523 struct dylib_module
*mods
,
2524 struct dylib_module_64
*mods64
,
2526 struct dylib_reference
*refs
,
2527 uint32_t nextrefsyms
)
2529 uint32_t i
, j
, k
, n
, inew_syms
, save_debug
, missing_syms
;
2530 uint32_t missing_symbols
;
2531 char *p
, *q
, **pp
, *basename
;
2532 struct symbol_list
*sp
;
2533 uint32_t new_ext_strsize
, len
, *changes
, inew_undefsyms
;
2534 unsigned char nsects
;
2535 struct load_command
*lc
;
2536 struct segment_command
*sg
;
2537 struct segment_command_64
*sg64
;
2538 struct section
*s
, **sections
;
2539 struct section_64
*s64
, **sections64
;
2540 uint32_t ncmds
, mh_flags
, s_flags
, n_strx
;
2542 struct undef_map
*undef_map
;
2543 struct undef_map64
*undef_map64
;
2544 uint8_t n_type
, n_sect
;
2547 uint32_t module_name
, iextdefsym
, nextdefsym
, ilocalsym
, nlocalsym
;
2548 uint32_t irefsym
, nrefsym
;
2549 enum bool has_dwarf
, hack_5614542
;
2555 for(i
= 0; i
< nsave_symbols
; i
++)
2556 save_symbols
[i
].sym
= NULL
;
2557 for(i
= 0; i
< nremove_symbols
; i
++)
2558 remove_symbols
[i
].sym
= NULL
;
2560 for(i
= 0; i
< nsave_symbols
; i
++)
2561 save_symbols
[i
].seen
= FALSE
;
2562 for(i
= 0; i
< nremove_symbols
; i
++)
2563 remove_symbols
[i
].seen
= FALSE
;
2567 if(object
->mh
!= NULL
)
2568 new_strsize
= sizeof(int32_t);
2570 new_strsize
= sizeof(int64_t);
2574 new_ext_strsize
= 0;
2577 * If this an object file that has DWARF debugging sections to strip
2578 * then we have to run ld -r on it.
2580 if(object
->mh_filetype
== MH_OBJECT
&& (Sflag
|| xflag
)){
2582 lc
= object
->load_commands
;
2583 if(object
->mh
!= NULL
)
2584 ncmds
= object
->mh
->ncmds
;
2586 ncmds
= object
->mh64
->ncmds
;
2587 for(i
= 0; i
< ncmds
&& has_dwarf
== FALSE
; i
++){
2588 if(lc
->cmd
== LC_SEGMENT
){
2589 sg
= (struct segment_command
*)lc
;
2590 s
= (struct section
*)((char *)sg
+
2591 sizeof(struct segment_command
));
2592 for(j
= 0; j
< sg
->nsects
; j
++){
2593 if(s
->flags
& S_ATTR_DEBUG
){
2600 else if(lc
->cmd
== LC_SEGMENT_64
){
2601 sg64
= (struct segment_command_64
*)lc
;
2602 s64
= (struct section_64
*)((char *)sg64
+
2603 sizeof(struct segment_command_64
));
2604 for(j
= 0; j
< sg64
->nsects
; j
++){
2605 if(s64
->flags
& S_ATTR_DEBUG
){
2612 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2614 if(has_dwarf
== TRUE
)
2615 make_ld_r_object(arch
, member
, object
);
2618 * Because of the "design" of 64-bit object files and the lack of
2619 * local relocation entries it is not possible for strip(1) to do its
2620 * job without becoming a static link editor. The "design" does not
2621 * actually strip the symbols it simply renames them to things like
2622 * "l1000". And they become static symbols but still have external
2623 * relocation entries. Thus can never actually be stripped. Also some
2624 * symbols, *.eh, symbols are not even changed to these names if there
2625 * corresponding global symbol is not stripped. So strip(1) only
2626 * recourse is to use the unified linker to create an ld -r object then
2627 * save all resulting symbols (both static and global) and hope the user
2628 * does not notice the stripping is not what they asked for.
2630 if(object
->mh_filetype
== MH_OBJECT
&&
2631 (object
->mh64
!= NULL
&& object
->ld_r_ofile
== NULL
))
2632 make_ld_r_object(arch
, member
, object
);
2635 * Since make_ld_r_object() may create an object with more symbols
2636 * this has to be done after make_ld_r_object() and nsyms is updated.
2638 saves
= (int32_t *)allocate(nsyms
* sizeof(int32_t));
2639 bzero(saves
, nsyms
* sizeof(int32_t));
2642 * Gather an array of section struct pointers so we can later determine
2643 * if we run into a global symbol in a coalesced section and not strip
2648 lc
= object
->load_commands
;
2649 if(object
->mh
!= NULL
)
2650 ncmds
= object
->mh
->ncmds
;
2652 ncmds
= object
->mh64
->ncmds
;
2653 for(i
= 0; i
< ncmds
; i
++){
2654 if(lc
->cmd
== LC_SEGMENT
){
2655 sg
= (struct segment_command
*)lc
;
2656 nsects
+= sg
->nsects
;
2658 else if(lc
->cmd
== LC_SEGMENT_64
){
2659 sg64
= (struct segment_command_64
*)lc
;
2660 nsects
+= sg64
->nsects
;
2662 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2664 if(object
->mh
!= NULL
){
2665 sections
= allocate(nsects
* sizeof(struct section
*));
2670 sections64
= allocate(nsects
* sizeof(struct section_64
*));
2673 lc
= object
->load_commands
;
2674 for(i
= 0; i
< ncmds
; i
++){
2675 if(lc
->cmd
== LC_SEGMENT
){
2676 sg
= (struct segment_command
*)lc
;
2677 s
= (struct section
*)((char *)sg
+
2678 sizeof(struct segment_command
));
2679 for(j
= 0; j
< sg
->nsects
; j
++)
2680 sections
[nsects
++] = s
++;
2682 else if(lc
->cmd
== LC_SEGMENT_64
){
2683 sg64
= (struct segment_command_64
*)lc
;
2684 s64
= (struct section_64
*)((char *)sg64
+
2685 sizeof(struct segment_command_64
));
2686 for(j
= 0; j
< sg64
->nsects
; j
++)
2687 sections64
[nsects
++] = s64
++;
2689 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2692 for(i
= 0; i
< nsyms
; i
++){
2694 if(object
->mh
!= NULL
){
2695 mh_flags
= object
->mh
->flags
;
2696 n_strx
= symbols
[i
].n_un
.n_strx
;
2697 n_type
= symbols
[i
].n_type
;
2698 n_sect
= symbols
[i
].n_sect
;
2699 if((n_type
& N_TYPE
) == N_SECT
){
2700 if(n_sect
== 0 || n_sect
> nsects
){
2701 error_arch(arch
, member
, "bad n_sect for symbol "
2702 "table entry %d in: ", i
);
2705 s_flags
= sections
[n_sect
- 1]->flags
;
2707 n_desc
= symbols
[i
].n_desc
;
2708 n_value
= symbols
[i
].n_value
;
2711 mh_flags
= object
->mh64
->flags
;
2712 n_strx
= symbols64
[i
].n_un
.n_strx
;
2713 n_type
= symbols64
[i
].n_type
;
2714 n_sect
= symbols64
[i
].n_sect
;
2715 if((n_type
& N_TYPE
) == N_SECT
){
2716 if(n_sect
== 0 || n_sect
> nsects
){
2717 error_arch(arch
, member
, "bad n_sect for symbol "
2718 "table entry %d in: ", i
);
2721 s_flags
= sections64
[n_sect
- 1]->flags
;
2723 n_desc
= symbols64
[i
].n_desc
;
2724 n_value
= symbols64
[i
].n_value
;
2727 if(n_strx
> strsize
){
2728 error_arch(arch
, member
, "bad string index for symbol "
2729 "table entry %d in: ", i
);
2733 if((n_type
& N_TYPE
) == N_INDR
){
2735 if(n_value
> strsize
){
2736 error_arch(arch
, member
, "bad string index for "
2737 "indirect symbol table entry %d in: ", i
);
2742 if((n_type
& N_EXT
) == 0){ /* local symbol */
2744 * For x86_64 .o files we have run ld -r on them and are stuck
2745 * keeping all resulting symbols.
2747 if(object
->mh
== NULL
&& (
2748 object
->mh64
->cputype
== CPU_TYPE_X86_64
) &&
2749 object
->mh64
->filetype
== MH_OBJECT
){
2751 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2754 saves
[i
] = new_nsyms
;
2757 * The cases a local symbol might be saved is with -X -S or
2760 else if((!strip_all
&& (Xflag
|| Sflag
)) || dfile
){
2761 if(n_type
& N_STAB
){ /* debug symbol */
2762 if(dfile
&& n_type
== N_SO
){
2764 basename
= strrchr(strings
+ n_strx
, '/');
2765 if(basename
!= NULL
)
2768 basename
= strings
+ n_strx
;
2769 pp
= bsearch(basename
, debug_filenames
,
2770 ndebug_filenames
, sizeof(char *),
2771 (int (*)(const void *, const void *)
2772 )cmp_bsearch_filename
);
2774 * Save the bracketing N_SO. For each N_SO that
2775 * has a filename there is an N_SO that has a
2776 * name of "" which ends the stabs for that file
2778 if(*basename
!= '\0'){
2786 * This is a bracketing SO so if we are
2787 * currently saving debug symbols save this
2788 * last one and turn off saving debug syms.
2792 new_strsize
+= strlen(strings
+
2796 saves
[i
] = new_nsyms
;
2805 if(saves
[i
] == 0 && (!Sflag
|| save_debug
)){
2807 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2810 saves
[i
] = new_nsyms
;
2813 else{ /* non-debug local symbol */
2814 if(xflag
== 0 && (Sflag
|| Xflag
)){
2817 strings
[n_strx
] != 'L')){
2819 * If this file is a for the dynamic linker and
2820 * this symbol is in a section marked so that
2821 * static symbols are stripped then don't
2824 if((mh_flags
& MH_DYLDLINK
) != MH_DYLDLINK
||
2825 (n_type
& N_TYPE
) != N_SECT
||
2826 (s_flags
& S_ATTR_STRIP_STATIC_SYMS
) !=
2827 S_ATTR_STRIP_STATIC_SYMS
){
2828 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2831 saves
[i
] = new_nsyms
;
2836 * Treat a local symbol that was a private extern as if
2837 * were global if it is referenced by a module and save
2840 if((n_type
& N_PEXT
) == N_PEXT
){
2842 private_extern_reference_by_module(
2843 i
, refs
,nextrefsyms
) == TRUE
){
2845 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2848 saves
[i
] = new_nsyms
;
2851 * We need to save symbols that were private externs
2852 * that are used with indirect symbols.
2855 symbol_pointer_used(i
, indirectsyms
,
2856 nindirectsyms
) == TRUE
){
2858 len
= strlen(strings
+ n_strx
) + 1;
2863 saves
[i
] = new_nsyms
;
2869 * Treat a local symbol that was a private extern as if were
2870 * global if it is not referenced by a module.
2872 else if((n_type
& N_PEXT
) == N_PEXT
){
2873 if(saves
[i
] == 0 && sfile
){
2874 sp
= bsearch(strings
+ n_strx
,
2875 save_symbols
, nsave_symbols
,
2876 sizeof(struct symbol_list
),
2877 (int (*)(const void *, const void *))
2878 symbol_list_bsearch
);
2880 if(sp
->sym
== NULL
){
2881 if(object
->mh
!= NULL
)
2882 sp
->sym
= &(symbols
[i
]);
2884 sp
->sym
= &(symbols64
[i
]);
2888 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2891 saves
[i
] = new_nsyms
;
2895 private_extern_reference_by_module(
2896 i
, refs
,nextrefsyms
) == TRUE
){
2898 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2901 saves
[i
] = new_nsyms
;
2904 * We need to save symbols that were private externs that
2905 * are used with indirect symbols.
2908 symbol_pointer_used(i
, indirectsyms
, nindirectsyms
) ==
2911 len
= strlen(strings
+ n_strx
) + 1;
2916 saves
[i
] = new_nsyms
;
2920 else{ /* global symbol */
2922 * strip -R on an x86_64 .o file should do nothing.
2925 (object
->mh
!= NULL
||
2926 object
->mh64
->cputype
!= CPU_TYPE_X86_64
||
2927 object
->mh64
->filetype
!= MH_OBJECT
)){
2928 sp
= bsearch(strings
+ n_strx
,
2929 remove_symbols
, nremove_symbols
,
2930 sizeof(struct symbol_list
),
2931 (int (*)(const void *, const void *))
2932 symbol_list_bsearch
);
2934 if((n_type
& N_TYPE
) == N_UNDF
||
2935 (n_type
& N_TYPE
) == N_PBUD
){
2936 error_arch(arch
, member
, "symbol: %s undefined"
2937 " and can't be stripped from: ",
2940 else if(sp
->sym
!= NULL
){
2941 sym
= (struct nlist
*)sp
->sym
;
2942 if((sym
->n_type
& N_PEXT
) != N_PEXT
)
2943 error_arch(arch
, member
, "more than one symbol "
2944 "for: %s found in: ", sp
->name
);
2947 if(object
->mh
!= NULL
)
2948 sp
->sym
= &(symbols
[i
]);
2950 sp
->sym
= &(symbols64
[i
]);
2953 if(n_desc
& REFERENCED_DYNAMICALLY
){
2954 error_arch(arch
, member
, "symbol: %s is dynamically"
2955 " referenced and can't be stripped "
2956 "from: ", sp
->name
);
2958 if((n_type
& N_TYPE
) == N_SECT
&&
2959 (s_flags
& SECTION_TYPE
) == S_COALESCED
){
2960 error_arch(arch
, member
, "symbol: %s is a global "
2961 "coalesced symbol and can't be "
2962 "stripped from: ", sp
->name
);
2964 /* don't save this symbol */
2968 if(Aflag
&& (n_type
& N_TYPE
) == N_ABS
&&
2971 strncmp(strings
+ n_strx
,
2972 ".objc_class_name_",
2973 sizeof(".objc_class_name_") - 1) == 0))){
2974 len
= strlen(strings
+ n_strx
) + 1;
2976 new_ext_strsize
+= len
;
2979 saves
[i
] = new_nsyms
;
2981 if(saves
[i
] == 0 && (uflag
|| default_dyld_executable
) &&
2982 ((((n_type
& N_TYPE
) == N_UNDF
) &&
2984 (n_type
& N_TYPE
) == N_PBUD
)){
2986 len
= strlen(strings
+ n_strx
) + 1;
2988 new_ext_strsize
+= len
;
2992 saves
[i
] = new_nsyms
;
2994 if(saves
[i
] == 0 && nflag
&&
2995 (n_type
& N_TYPE
) == N_SECT
){
2997 len
= strlen(strings
+ n_strx
) + 1;
2999 new_ext_strsize
+= len
;
3003 saves
[i
] = new_nsyms
;
3005 if(saves
[i
] == 0 && sfile
){
3006 sp
= bsearch(strings
+ n_strx
,
3007 save_symbols
, nsave_symbols
,
3008 sizeof(struct symbol_list
),
3009 (int (*)(const void *, const void *))
3010 symbol_list_bsearch
);
3012 if(sp
->sym
!= NULL
){
3013 sym
= (struct nlist
*)sp
->sym
;
3014 if((sym
->n_type
& N_PEXT
) != N_PEXT
)
3015 error_arch(arch
, member
, "more than one symbol "
3016 "for: %s found in: ", sp
->name
);
3019 if(object
->mh
!= NULL
)
3020 sp
->sym
= &(symbols
[i
]);
3022 sp
->sym
= &(symbols64
[i
]);
3024 len
= strlen(strings
+ n_strx
) + 1;
3026 new_ext_strsize
+= len
;
3027 if((n_type
& N_TYPE
) == N_UNDF
||
3028 (n_type
& N_TYPE
) == N_PBUD
)
3033 saves
[i
] = new_nsyms
;
3038 * We only need to save coalesced symbols that are used as
3039 * indirect symbols in 32-bit applications.
3041 * In 64-bit applications, we only need to save coalesced
3042 * symbols that are used as weak definitions.
3044 if(object
->mh
!= NULL
&&
3046 (n_type
& N_TYPE
) == N_SECT
&&
3047 (s_flags
& SECTION_TYPE
) == S_COALESCED
&&
3048 symbol_pointer_used(i
, indirectsyms
, nindirectsyms
) == TRUE
){
3050 len
= strlen(strings
+ n_strx
) + 1;
3052 new_ext_strsize
+= len
;
3056 saves
[i
] = new_nsyms
;
3059 (n_type
& N_TYPE
) == N_SECT
&&
3060 (n_desc
& N_WEAK_DEF
) != 0){
3062 len
= strlen(strings
+ n_strx
) + 1;
3064 new_ext_strsize
+= len
;
3068 saves
[i
] = new_nsyms
;
3070 if(saves
[i
] == 0 && ((Xflag
|| Sflag
|| xflag
) ||
3071 ((rflag
|| default_dyld_executable
) &&
3072 n_desc
& REFERENCED_DYNAMICALLY
))){
3073 len
= strlen(strings
+ n_strx
) + 1;
3075 new_ext_strsize
+= len
;
3076 if((n_type
& N_TYPE
) == N_INDR
){
3077 len
= strlen(strings
+ n_value
) + 1;
3079 new_ext_strsize
+= len
;
3081 if((n_type
& N_TYPE
) == N_UNDF
||
3082 (n_type
& N_TYPE
) == N_PBUD
)
3087 saves
[i
] = new_nsyms
;
3090 * For x86_64 .o files we have run ld -r on them and are stuck
3091 * keeping all resulting symbols.
3094 object
->mh
== NULL
&&
3095 object
->mh64
->cputype
== CPU_TYPE_X86_64
&&
3096 object
->mh64
->filetype
== MH_OBJECT
){
3097 len
= strlen(strings
+ n_strx
) + 1;
3099 new_ext_strsize
+= len
;
3100 if((n_type
& N_TYPE
) == N_INDR
){
3101 len
= strlen(strings
+ n_value
) + 1;
3103 new_ext_strsize
+= len
;
3105 if((n_type
& N_TYPE
) == N_UNDF
||
3106 (n_type
& N_TYPE
) == N_PBUD
)
3111 saves
[i
] = new_nsyms
;
3116 * The module table's module names are placed with the external strings.
3117 * So size them and add this to the external string size.
3119 for(i
= 0; i
< nmodtab
; i
++){
3120 if(object
->mh
!= NULL
)
3121 module_name
= mods
[i
].module_name
;
3123 module_name
= mods64
[i
].module_name
;
3124 if(module_name
== 0 || module_name
> strsize
){
3125 error_arch(arch
, member
, "bad string index for module_name "
3126 "of module table entry %d in: ", i
);
3129 len
= strlen(strings
+ module_name
) + 1;
3131 new_ext_strsize
+= len
;
3135 * Updating the reference table may require a symbol not yet listed as
3136 * as saved to be present in the output file. If a defined external
3137 * symbol is removed and there is a undefined reference to it in the
3138 * reference table an undefined symbol needs to be created for it in
3139 * the output file. If this happens the number of new symbols and size
3140 * of the new strings are adjusted. And the array changes[] is set to
3141 * map the old symbol index to the new symbol index for the symbol that
3142 * is changed to an undefined symbol.
3144 missing_symbols
= 0;
3145 if(ref_saves
!= NULL
)
3147 ref_saves
= (int32_t *)allocate(nextrefsyms
* sizeof(int32_t));
3148 bzero(ref_saves
, nextrefsyms
* sizeof(int32_t));
3149 changes
= (uint32_t *)allocate(nsyms
* sizeof(int32_t));
3150 bzero(changes
, nsyms
* sizeof(int32_t));
3151 new_nextrefsyms
= 0;
3152 for(i
= 0; i
< nextrefsyms
; i
++){
3153 if(refs
[i
].isym
> nsyms
){
3154 error_arch(arch
, member
, "bad symbol table index for "
3155 "reference table entry %d in: ", i
);
3158 if(saves
[refs
[i
].isym
]){
3160 ref_saves
[i
] = new_nextrefsyms
;
3163 if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
||
3164 refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
){
3165 if(changes
[refs
[i
].isym
] == 0){
3166 if(object
->mh
!= NULL
)
3167 n_strx
= symbols
[refs
[i
].isym
].n_un
.n_strx
;
3169 n_strx
= symbols64
[refs
[i
].isym
].n_un
.n_strx
;
3170 len
= strlen(strings
+ n_strx
) + 1;
3172 new_ext_strsize
+= len
;
3175 changes
[refs
[i
].isym
] = new_nsyms
;
3177 ref_saves
[i
] = new_nextrefsyms
;
3182 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
||
3183 refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
){
3184 if(missing_symbols
== 0){
3185 error_arch(arch
, member
, "private extern symbols "
3186 "referenced by modules can't be stripped in: ");
3187 missing_symbols
= 1;
3189 if(object
->mh
!= NULL
)
3190 n_strx
= symbols
[refs
[i
].isym
].n_un
.n_strx
;
3192 n_strx
= symbols64
[refs
[i
].isym
].n_un
.n_strx
;
3193 fprintf(stderr
, "%s\n", strings
+ n_strx
);
3194 saves
[refs
[i
].isym
] = -1;
3199 if(missing_symbols
== 1)
3205 for(i
= 0; i
< nsave_symbols
; i
++){
3206 if(save_symbols
[i
].sym
== NULL
){
3207 if(missing_syms
== 0){
3208 error_arch(arch
, member
, "symbols names listed "
3209 "in: %s not in: ", sfile
);
3212 fprintf(stderr
, "%s\n", save_symbols
[i
].name
);
3218 * strip -R on an x86_64 .o file should do nothing.
3221 (object
->mh
!= NULL
||
3222 object
->mh64
->cputype
!= CPU_TYPE_X86_64
||
3223 object
->mh64
->filetype
!= MH_OBJECT
)){
3224 for(i
= 0; i
< nremove_symbols
; i
++){
3225 if(remove_symbols
[i
].sym
== NULL
){
3226 if(missing_syms
== 0){
3227 error_arch(arch
, member
, "symbols names listed "
3228 "in: %s not in: ", Rfile
);
3231 fprintf(stderr
, "%s\n", remove_symbols
[i
].name
);
3238 * If there is a chance that we could end up with an indirect symbol
3239 * with an index of zero we need to avoid that due to a work around
3240 * in the dynamic linker for a bug it is working around that was in
3241 * the old classic static linker. See radar bug 5614542 and the
3242 * related bugs 3685312 and 3534709.
3244 * A reasonable way to do this to know that local symbols are first in
3245 * the symbol table. So if we have any local symbols this won't happen
3246 * and if there are no indirect symbols it will also not happen. Past
3247 * that we'll just add a local symbol so it will end up at symbol index
3248 * zero and avoid any indirect symbol having that index.
3250 * If one really wanted they could build up the new symbol table then
3251 * look at all the indirect symbol table entries to see if any of them
3252 * have an index of zero then in that case throw that new symbol table
3253 * away and rebuild the symbol and string table once again after adding
3254 * a local symbol. This seems not all that resonable to save one symbol
3255 * table entry and a few bytes in the string table for the complexity it
3256 * would add and what it would save.
3258 if(new_nlocalsym
== 0 && nindirectsyms
!= 0){
3259 len
= strlen("radr://5614542") + 1;
3263 hack_5614542
= TRUE
;
3266 hack_5614542
= FALSE
;
3269 if(object
->mh
!= NULL
){
3270 new_symbols
= (struct nlist
*)
3271 allocate(new_nsyms
* sizeof(struct nlist
));
3272 new_symbols64
= NULL
;
3276 new_symbols64
= (struct nlist_64
*)
3277 allocate(new_nsyms
* sizeof(struct nlist_64
));
3279 if(object
->mh
!= NULL
)
3280 new_strsize
= rnd(new_strsize
, sizeof(int32_t));
3282 new_strsize
= rnd(new_strsize
, sizeof(int64_t));
3283 new_strings
= (char *)allocate(new_strsize
);
3284 if(object
->mh
!= NULL
){
3285 new_strings
[new_strsize
- 3] = '\0';
3286 new_strings
[new_strsize
- 2] = '\0';
3287 new_strings
[new_strsize
- 1] = '\0';
3290 new_strings
[new_strsize
- 7] = '\0';
3291 new_strings
[new_strsize
- 6] = '\0';
3292 new_strings
[new_strsize
- 5] = '\0';
3293 new_strings
[new_strsize
- 4] = '\0';
3294 new_strings
[new_strsize
- 3] = '\0';
3295 new_strings
[new_strsize
- 2] = '\0';
3296 new_strings
[new_strsize
- 1] = '\0';
3299 memset(new_strings
, '\0', sizeof(int32_t));
3300 p
= new_strings
+ sizeof(int32_t);
3301 q
= p
+ new_ext_strsize
;
3304 * If all strings were stripped set the size to zero but only for 32-bit
3305 * because the unified linker seems to set the filesize of empty .o
3306 * files to include the string table.
3308 if(object
->mh
!= NULL
&& new_strsize
== sizeof(int32_t))
3312 * Now create a symbol table and string table in this order
3315 * external defined symbols
3324 * If we are doing the hack for radar bug 5614542 (see above) add the
3325 * one local symbol and string.
3327 * We use an N_OPT stab which should be safe to use and not mess any
3328 * thing up. In Mac OS X, gcc(1) writes one N_OPT stab saying the file
3329 * is compiled with gcc(1). Then gdb(1) looks for that stab, but it
3330 * also looks at the name. If the name string is "gcc_compiled" or
3331 * "gcc2_compiled" gdb(1) sets its "compiled by gcc flag. If the N_OPT
3332 * is emitted INSIDE an N_SO section, then gdb(1) thinks that object
3333 * module was compiled by Sun's compiler, which apparently sticks one
3334 * outermost N_LBRAC/N_RBRAC pair, which gdb(1) strips off. But if the
3335 * N_OPT comes before any N_SO stabs, then gdb(1) will just ignore it.
3336 * Since this N_OPT is the first local symbol, it will always come
3337 * before any N_SO stabs that might be around and should be fine.
3339 if(hack_5614542
== TRUE
){
3340 if(object
->mh
!= NULL
){
3341 new_symbols
[inew_syms
].n_type
= N_OPT
;
3342 new_symbols
[inew_syms
].n_sect
= NO_SECT
;
3343 new_symbols
[inew_syms
].n_desc
= 0;
3344 new_symbols
[inew_syms
].n_value
= 0x05614542;
3347 new_symbols64
[inew_syms
].n_type
= N_OPT
;
3348 new_symbols64
[inew_syms
].n_sect
= NO_SECT
;
3349 new_symbols64
[inew_syms
].n_desc
= 0;
3350 new_symbols64
[inew_syms
].n_value
= 0x05614542;
3352 strcpy(q
, "radr://5614542");
3353 if(object
->mh
!= NULL
)
3354 new_symbols
[inew_syms
].n_un
.n_strx
=
3357 new_symbols64
[inew_syms
].n_un
.n_strx
=
3363 for(i
= 0; i
< nsyms
; i
++){
3365 if(object
->mh
!= NULL
){
3366 n_strx
= symbols
[i
].n_un
.n_strx
;
3367 n_type
= symbols
[i
].n_type
;
3370 n_strx
= symbols64
[i
].n_un
.n_strx
;
3371 n_type
= symbols64
[i
].n_type
;
3373 if((n_type
& N_EXT
) == 0){
3374 if(object
->mh
!= NULL
)
3375 new_symbols
[inew_syms
] = symbols
[i
];
3377 new_symbols64
[inew_syms
] = symbols64
[i
];
3379 strcpy(q
, strings
+ n_strx
);
3380 if(object
->mh
!= NULL
)
3381 new_symbols
[inew_syms
].n_un
.n_strx
=
3384 new_symbols64
[inew_syms
].n_un
.n_strx
=
3389 saves
[i
] = inew_syms
;
3394 inew_nextdefsym
= inew_syms
;
3395 #endif /* TRIE_SUPPORT */
3396 for(i
= 0; i
< nsyms
; i
++){
3398 if(object
->mh
!= NULL
){
3399 n_strx
= symbols
[i
].n_un
.n_strx
;
3400 n_type
= symbols
[i
].n_type
;
3401 n_value
= symbols
[i
].n_value
;
3404 n_strx
= symbols64
[i
].n_un
.n_strx
;
3405 n_type
= symbols64
[i
].n_type
;
3406 n_value
= symbols64
[i
].n_value
;
3408 if((n_type
& N_EXT
) == N_EXT
&&
3409 ((n_type
& N_TYPE
) != N_UNDF
&&
3410 (n_type
& N_TYPE
) != N_PBUD
)){
3411 if(object
->mh
!= NULL
)
3412 new_symbols
[inew_syms
] = symbols
[i
];
3414 new_symbols64
[inew_syms
] = symbols64
[i
];
3416 strcpy(p
, strings
+ n_strx
);
3417 if(object
->mh
!= NULL
)
3418 new_symbols
[inew_syms
].n_un
.n_strx
=
3421 new_symbols64
[inew_syms
].n_un
.n_strx
=
3425 if((n_type
& N_TYPE
) == N_INDR
){
3427 strcpy(p
, strings
+ n_value
);
3428 if(object
->mh
!= NULL
)
3429 new_symbols
[inew_syms
].n_value
=
3432 new_symbols64
[inew_syms
].n_value
=
3438 saves
[i
] = inew_syms
;
3443 * Build the new undefined symbols into a map and sort it.
3446 if(object
->mh
!= NULL
){
3447 undef_map
= (struct undef_map
*)allocate(new_nundefsym
*
3448 sizeof(struct undef_map
));
3453 undef_map64
= (struct undef_map64
*)allocate(new_nundefsym
*
3454 sizeof(struct undef_map64
));
3456 for(i
= 0; i
< nsyms
; i
++){
3458 if(object
->mh
!= NULL
){
3459 n_strx
= symbols
[i
].n_un
.n_strx
;
3460 n_type
= symbols
[i
].n_type
;
3463 n_strx
= symbols64
[i
].n_un
.n_strx
;
3464 n_type
= symbols64
[i
].n_type
;
3466 if((n_type
& N_EXT
) == N_EXT
&&
3467 ((n_type
& N_TYPE
) == N_UNDF
||
3468 (n_type
& N_TYPE
) == N_PBUD
)){
3469 if(object
->mh
!= NULL
)
3470 undef_map
[inew_undefsyms
].symbol
= symbols
[i
];
3472 undef_map64
[inew_undefsyms
].symbol64
= symbols64
[i
];
3474 strcpy(p
, strings
+ n_strx
);
3475 if(object
->mh
!= NULL
)
3476 undef_map
[inew_undefsyms
].symbol
.n_un
.n_strx
=
3479 undef_map64
[inew_undefsyms
].symbol64
.n_un
.n_strx
=
3483 if(object
->mh
!= NULL
)
3484 undef_map
[inew_undefsyms
].index
= i
;
3486 undef_map64
[inew_undefsyms
].index
= i
;
3491 for(i
= 0; i
< nsyms
; i
++){
3493 if(object
->mh
!= NULL
)
3494 n_strx
= symbols
[i
].n_un
.n_strx
;
3496 n_strx
= symbols64
[i
].n_un
.n_strx
;
3498 strcpy(p
, strings
+ n_strx
);
3499 if(object
->mh
!= NULL
)
3500 undef_map
[inew_undefsyms
].symbol
.n_un
.n_strx
=
3503 undef_map64
[inew_undefsyms
].symbol64
.n_un
.n_strx
=
3507 if(object
->mh
!= NULL
){
3508 undef_map
[inew_undefsyms
].symbol
.n_type
= N_UNDF
| N_EXT
;
3509 undef_map
[inew_undefsyms
].symbol
.n_sect
= NO_SECT
;
3510 undef_map
[inew_undefsyms
].symbol
.n_desc
= 0;
3511 undef_map
[inew_undefsyms
].symbol
.n_value
= 0;
3512 undef_map
[inew_undefsyms
].index
= i
;
3515 undef_map64
[inew_undefsyms
].symbol64
.n_type
= N_UNDF
|N_EXT
;
3516 undef_map64
[inew_undefsyms
].symbol64
.n_sect
= NO_SECT
;
3517 undef_map64
[inew_undefsyms
].symbol64
.n_desc
= 0;
3518 undef_map64
[inew_undefsyms
].symbol64
.n_value
= 0;
3519 undef_map64
[inew_undefsyms
].index
= i
;
3524 /* Sort the undefined symbols by name */
3525 qsort_strings
= new_strings
;
3526 if(object
->mh
!= NULL
)
3527 qsort(undef_map
, new_nundefsym
, sizeof(struct undef_map
),
3528 (int (*)(const void *, const void *))cmp_qsort_undef_map
);
3530 qsort(undef_map64
, new_nundefsym
, sizeof(struct undef_map64
),
3531 (int (*)(const void *, const void *))cmp_qsort_undef_map_64
);
3532 /* Copy the symbols now in sorted order into new_symbols */
3533 for(i
= 0; i
< new_nundefsym
; i
++){
3534 if(object
->mh
!= NULL
){
3535 new_symbols
[inew_syms
] = undef_map
[i
].symbol
;
3537 saves
[undef_map
[i
].index
] = inew_syms
;
3540 new_symbols64
[inew_syms
] = undef_map64
[i
].symbol64
;
3542 saves
[undef_map64
[i
].index
] = inew_syms
;
3547 * Fixup the module table's module name strings adding them to the
3548 * string table. Also fix the indexes into the symbol table for
3549 * external and local symbols. And fix up the indexes into the
3552 for(i
= 0; i
< nmodtab
; i
++){
3553 if(object
->mh
!= NULL
){
3554 strcpy(p
, strings
+ mods
[i
].module_name
);
3555 mods
[i
].module_name
= p
- new_strings
;
3556 iextdefsym
= mods
[i
].iextdefsym
;
3557 nextdefsym
= mods
[i
].nextdefsym
;
3558 ilocalsym
= mods
[i
].ilocalsym
;
3559 nlocalsym
= mods
[i
].nlocalsym
;
3560 irefsym
= mods
[i
].irefsym
;
3561 nrefsym
= mods
[i
].nrefsym
;
3564 strcpy(p
, strings
+ mods64
[i
].module_name
);
3565 mods64
[i
].module_name
= p
- new_strings
;
3566 iextdefsym
= mods64
[i
].iextdefsym
;
3567 nextdefsym
= mods64
[i
].nextdefsym
;
3568 ilocalsym
= mods64
[i
].ilocalsym
;
3569 nlocalsym
= mods64
[i
].nlocalsym
;
3570 irefsym
= mods64
[i
].irefsym
;
3571 nrefsym
= mods64
[i
].nrefsym
;
3575 if(iextdefsym
> nsyms
){
3576 error_arch(arch
, member
, "bad index into externally defined "
3577 "symbols of module table entry %d in: ", i
);
3580 if(iextdefsym
+ nextdefsym
> nsyms
){
3581 error_arch(arch
, member
, "bad number of externally defined "
3582 "symbols of module table entry %d in: ", i
);
3585 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
3586 if(saves
[j
] != 0 && changes
[j
] == 0)
3590 for(k
= j
; k
< iextdefsym
+ nextdefsym
; k
++){
3591 if(saves
[k
] != 0 && changes
[k
] == 0)
3595 if(object
->mh
!= NULL
){
3596 mods
[i
].iextdefsym
= 0;
3597 mods
[i
].nextdefsym
= 0;
3600 mods64
[i
].iextdefsym
= 0;
3601 mods64
[i
].nextdefsym
= 0;
3605 if(object
->mh
!= NULL
){
3606 mods
[i
].iextdefsym
= saves
[j
] - 1;
3607 mods
[i
].nextdefsym
= n
;
3610 mods64
[i
].iextdefsym
= saves
[j
] - 1;
3611 mods64
[i
].nextdefsym
= n
;
3615 if(ilocalsym
> nsyms
){
3616 error_arch(arch
, member
, "bad index into symbols for local "
3617 "symbols of module table entry %d in: ", i
);
3620 if(ilocalsym
+ nlocalsym
> nsyms
){
3621 error_arch(arch
, member
, "bad number of local "
3622 "symbols of module table entry %d in: ", i
);
3625 for(j
= ilocalsym
; j
< ilocalsym
+ nlocalsym
; j
++){
3630 for(k
= j
; k
< ilocalsym
+ nlocalsym
; k
++){
3635 if(object
->mh
!= NULL
){
3636 mods
[i
].ilocalsym
= 0;
3637 mods
[i
].nlocalsym
= 0;
3640 mods64
[i
].ilocalsym
= 0;
3641 mods64
[i
].nlocalsym
= 0;
3645 if(object
->mh
!= NULL
){
3646 mods
[i
].ilocalsym
= saves
[j
] - 1;
3647 mods
[i
].nlocalsym
= n
;
3650 mods64
[i
].ilocalsym
= saves
[j
] - 1;
3651 mods64
[i
].nlocalsym
= n
;
3655 if(irefsym
> nextrefsyms
){
3656 error_arch(arch
, member
, "bad index into reference table "
3657 "of module table entry %d in: ", i
);
3660 if(irefsym
+ nrefsym
> nextrefsyms
){
3661 error_arch(arch
, member
, "bad number of reference table "
3662 "entries of module table entry %d in: ", i
);
3665 for(j
= irefsym
; j
< irefsym
+ nrefsym
; j
++){
3666 if(ref_saves
[j
] != 0)
3670 for(k
= j
; k
< irefsym
+ nrefsym
; k
++){
3671 if(ref_saves
[k
] != 0)
3675 if(object
->mh
!= NULL
){
3676 mods
[i
].irefsym
= 0;
3677 mods
[i
].nrefsym
= 0;
3680 mods64
[i
].irefsym
= 0;
3681 mods64
[i
].nrefsym
= 0;
3685 if(object
->mh
!= NULL
){
3686 mods
[i
].irefsym
= ref_saves
[j
] - 1;
3687 mods
[i
].nrefsym
= n
;
3690 mods64
[i
].irefsym
= ref_saves
[j
] - 1;
3691 mods64
[i
].nrefsym
= n
;
3697 * Create a new reference table.
3699 new_refs
= allocate(new_nextrefsyms
* sizeof(struct dylib_reference
));
3701 for(i
= 0; i
< nextrefsyms
; i
++){
3703 if(saves
[refs
[i
].isym
]){
3704 new_refs
[j
].isym
= saves
[refs
[i
].isym
] - 1;
3705 new_refs
[j
].flags
= refs
[i
].flags
;
3708 if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
||
3709 refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
){
3710 new_refs
[j
].isym
= changes
[refs
[i
].isym
] - 1;
3711 new_refs
[j
].flags
= refs
[i
].flags
;
3719 * Create a new dylib table of contents.
3722 for(i
= 0; i
< ntoc
; i
++){
3723 if(tocs
[i
].symbol_index
>= nsyms
){
3724 error_arch(arch
, member
, "bad symbol index for table of "
3725 "contents table entry %d in: ", i
);
3728 if(saves
[tocs
[i
].symbol_index
] != 0 &&
3729 changes
[tocs
[i
].symbol_index
] == 0)
3732 new_tocs
= allocate(new_ntoc
* sizeof(struct dylib_table_of_contents
));
3734 for(i
= 0; i
< ntoc
; i
++){
3735 if(saves
[tocs
[i
].symbol_index
] != 0 &&
3736 changes
[tocs
[i
].symbol_index
] == 0){
3737 new_tocs
[j
].symbol_index
= saves
[tocs
[i
].symbol_index
] - 1;
3738 new_tocs
[j
].module_index
= tocs
[i
].module_index
;
3744 * Update the export trie if it has one but only call the the
3745 * prune_trie() routine when we are removing global symbols as is
3746 * done with default stripping of a dyld executable or with the -s
3749 if(object
->dyld_info
!= NULL
&&
3750 object
->dyld_info
->export_size
!= 0 &&
3751 (default_dyld_executable
|| sfile
!= NULL
|| Rfile
!= NULL
)){
3752 const char *error_string
;
3753 uint32_t trie_new_size
;
3755 error_string
= prune_trie((uint8_t *)(object
->object_addr
+
3756 object
->dyld_info
->export_off
),
3757 object
->dyld_info
->export_size
,
3760 if(error_string
!= NULL
){
3761 error_arch(arch
, member
, "%s", error_string
);
3765 #endif /* TRIE_SUPPORT */
3767 if(undef_map
!= NULL
)
3769 if(undef_map64
!= NULL
)
3773 if(sections
!= NULL
)
3775 if(sections64
!= NULL
)
3786 * prune() is called by prune_trie() and passed a name of an external symbol
3787 * in the trie. It returns 1 if the symbols is to be pruned out and 0 if the
3788 * symbol is to be kept.
3790 * Note that it may seem like a linear search of the new symbols would not be
3791 * the best approach but in 10.6 the only defined global symbol left in a
3792 * stripped executable is __mh_execute_header and new_nextdefsym is usually 1
3793 * so this never actually loops in practice.
3802 for(i
= 0; i
< new_nextdefsym
; i
++){
3803 if(new_symbols
!= NULL
){
3804 if(strcmp(name
, new_strings
+ new_symbols
[inew_nextdefsym
+ i
]
3809 if(strcmp(name
, new_strings
+ new_symbols64
[inew_nextdefsym
+ i
]
3816 #endif /* TRIE_SUPPORT */
3819 * make_ld_r_object() takes the object file contents referenced by the passed
3820 * data structures, writes that to a temporary file, runs "ld -r" plus the
3821 * specified stripping option creating a second temporary file, reads that file
3822 * in and replaces the object file contents with that and resets the variables
3823 * pointing to the symbol, string and indirect tables.
3829 struct member
*member
,
3830 struct object
*object
)
3832 enum byte_sex host_byte_sex
;
3833 char *input_file
, *output_file
;
3835 struct ofile
*ld_r_ofile
;
3836 struct arch
*ld_r_archs
;
3837 uint32_t ld_r_narchs
, save_errors
;
3839 host_byte_sex
= get_host_byte_sex();
3842 * Swap the object file back into its bytesex before writing it to the
3843 * temporary file if needed.
3845 if(object
->object_byte_sex
!= host_byte_sex
){
3846 if(object
->mh
!= NULL
){
3847 if(swap_object_headers(object
->mh
, object
->load_commands
) ==
3849 fatal("internal error: swap_object_headers() failed");
3850 swap_nlist(symbols
, nsyms
, object
->object_byte_sex
);
3853 if(swap_object_headers(object
->mh64
, object
->load_commands
) ==
3855 fatal("internal error: swap_object_headers() failed");
3856 swap_nlist_64(symbols64
, nsyms
, object
->object_byte_sex
);
3858 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
3859 object
->object_byte_sex
);
3863 * Create an input object file for the ld -r command from the bytes
3864 * of this arch's object file.
3866 input_file
= makestr("/tmp/strip.XXXXXX", NULL
);
3867 input_file
= mktemp(input_file
);
3869 if((fd
= open(input_file
, O_WRONLY
|O_CREAT
, 0600)) < 0)
3870 system_fatal("can't open temporary file: %s", input_file
);
3872 if(write(fd
, object
->object_addr
, object
->object_size
) !=
3873 object
->object_size
)
3874 system_fatal("can't write temporary file: %s", input_file
);
3877 system_fatal("can't close temporary file: %s", input_file
);
3880 * Create a temporary name for the output file of the ld -r
3882 output_file
= makestr("/tmp/strip.XXXXXX", NULL
);
3883 output_file
= mktemp(output_file
);
3886 * Create the ld -r command line and execute it.
3888 reset_execute_list();
3889 add_execute_list_with_prefix("ld");
3890 add_execute_list("-keep_private_externs");
3891 add_execute_list("-r");
3893 add_execute_list("-S");
3895 add_execute_list("-x");
3896 add_execute_list(input_file
);
3897 add_execute_list("-o");
3898 add_execute_list(output_file
);
3900 add_execute_list("-x");
3901 add_execute_list("-exported_symbols_list");
3902 add_execute_list(sfile
);
3905 add_execute_list("-unexported_symbols_list");
3906 add_execute_list(Rfile
);
3908 if(execute_list(vflag
) == 0)
3909 fatal("internal link edit command failed");
3911 save_errors
= errors
;
3913 /* breakout the output file of the ld -f for processing */
3914 ld_r_ofile
= breakout(output_file
, &ld_r_archs
, &ld_r_narchs
, FALSE
);
3916 goto make_ld_r_object_cleanup
;
3918 /* checkout the file for symbol table replacement processing */
3919 checkout(ld_r_archs
, ld_r_narchs
);
3922 * Make sure the output of the ld -r is an object file with one arch.
3924 if(ld_r_narchs
!= 1 ||
3925 ld_r_archs
->type
!= OFILE_Mach_O
||
3926 ld_r_archs
->object
== NULL
||
3927 ld_r_archs
->object
->mh_filetype
!= MH_OBJECT
)
3928 fatal("internal link edit command failed to produce a thin Mach-O "
3932 * Now reset all the data of the input object with the ld -r output
3935 nsyms
= ld_r_archs
->object
->st
->nsyms
;
3936 if(ld_r_archs
->object
->mh
!= NULL
){
3937 symbols
= (struct nlist
*)
3938 (ld_r_archs
->object
->object_addr
+
3939 ld_r_archs
->object
->st
->symoff
);
3940 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3941 swap_nlist(symbols
, nsyms
, host_byte_sex
);
3946 symbols64
= (struct nlist_64
*)
3947 (ld_r_archs
->object
->object_addr
+
3948 ld_r_archs
->object
->st
->symoff
);
3949 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3950 swap_nlist_64(symbols64
, nsyms
, host_byte_sex
);
3952 strings
= ld_r_archs
->object
->object_addr
+
3953 ld_r_archs
->object
->st
->stroff
;
3954 strsize
= ld_r_archs
->object
->st
->strsize
;
3956 if(ld_r_archs
->object
->dyst
!= NULL
&&
3957 ld_r_archs
->object
->dyst
->nindirectsyms
!= 0){
3958 nindirectsyms
= ld_r_archs
->object
->dyst
->nindirectsyms
;
3959 indirectsyms
= (uint32_t *)
3960 (ld_r_archs
->object
->object_addr
+
3961 ld_r_archs
->object
->dyst
->indirectsymoff
);
3962 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3963 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
3967 indirectsyms
= NULL
;
3971 if(ld_r_archs
->object
->mh
!= NULL
)
3972 ld_r_archs
->object
->input_sym_info_size
=
3973 nsyms
* sizeof(struct nlist
) +
3976 ld_r_archs
->object
->input_sym_info_size
=
3977 nsyms
* sizeof(struct nlist_64
) +
3981 * Copy over the object struct from the ld -r object file onto the
3982 * input object file.
3984 *object
= *ld_r_archs
->object
;
3987 * Save the ofile struct for the ld -r output so it can be umapped when
3988 * we are done. And free up the ld_r_archs now that we are done with
3991 object
->ld_r_ofile
= ld_r_ofile
;
3992 free_archs(ld_r_archs
, ld_r_narchs
);
3994 make_ld_r_object_cleanup
:
3995 errors
+= save_errors
;
3997 * Remove the input and output files and clean up.
3999 if(unlink(input_file
) == -1)
4000 system_fatal("can't remove temporary file: %s", input_file
);
4001 if(unlink(output_file
) == -1)
4002 system_fatal("can't remove temporary file: %s", output_file
);
4008 * strip_LC_UUID_commands() is called when -no_uuid is specified to remove any
4009 * LC_UUID load commands from the object's load commands.
4013 strip_LC_UUID_commands(
4015 struct member
*member
,
4016 struct object
*object
)
4018 uint32_t i
, ncmds
, nuuids
, mh_sizeofcmds
, sizeofcmds
;
4019 struct load_command
*lc1
, *lc2
, *new_load_commands
;
4020 struct segment_command
*sg
;
4023 * See if there are any LC_UUID load commands.
4026 lc1
= arch
->object
->load_commands
;
4027 if(arch
->object
->mh
!= NULL
){
4028 ncmds
= arch
->object
->mh
->ncmds
;
4029 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
4032 ncmds
= arch
->object
->mh64
->ncmds
;
4033 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
4035 for(i
= 0; i
< ncmds
; i
++){
4036 if(lc1
->cmd
== LC_UUID
){
4039 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4041 /* if no LC_UUID load commands just return */
4046 * Allocate space for the new load commands as zero it out so any holes
4047 * will be zero bytes.
4049 new_load_commands
= allocate(mh_sizeofcmds
);
4050 memset(new_load_commands
, '\0', mh_sizeofcmds
);
4053 * Copy all the load commands except the LC_UUID load commands into the
4054 * allocated space for the new load commands.
4056 lc1
= arch
->object
->load_commands
;
4057 lc2
= new_load_commands
;
4059 for(i
= 0; i
< ncmds
; i
++){
4060 if(lc1
->cmd
!= LC_UUID
){
4061 memcpy(lc2
, lc1
, lc1
->cmdsize
);
4062 sizeofcmds
+= lc2
->cmdsize
;
4063 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
4065 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4069 * Finally copy the updated load commands over the existing load
4072 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
4073 if(mh_sizeofcmds
> sizeofcmds
){
4074 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
4075 (mh_sizeofcmds
- sizeofcmds
));
4078 if(arch
->object
->mh
!= NULL
) {
4079 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
4080 arch
->object
->mh
->ncmds
= ncmds
;
4082 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
4083 arch
->object
->mh64
->ncmds
= ncmds
;
4085 free(new_load_commands
);
4087 /* reset the pointers into the load commands */
4088 lc1
= arch
->object
->load_commands
;
4089 for(i
= 0; i
< ncmds
; i
++){
4092 arch
->object
->st
= (struct symtab_command
*)lc1
;
4095 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
4097 case LC_TWOLEVEL_HINTS
:
4098 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
4100 case LC_PREBIND_CKSUM
:
4101 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
4104 sg
= (struct segment_command
*)lc1
;
4105 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
4106 arch
->object
->seg_linkedit
= sg
;
4108 case LC_SEGMENT_SPLIT_INFO
:
4109 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
4111 case LC_FUNCTION_STARTS
:
4112 object
->func_starts_info_cmd
=
4113 (struct linkedit_data_command
*)lc1
;
4115 case LC_DATA_IN_CODE
:
4116 object
->data_in_code_cmd
=
4117 (struct linkedit_data_command
*)lc1
;
4119 case LC_DYLIB_CODE_SIGN_DRS
:
4120 object
->code_sign_drs_cmd
=
4121 (struct linkedit_data_command
*)lc1
;
4123 case LC_CODE_SIGNATURE
:
4124 object
->code_sig_cmd
= (struct linkedit_data_command
*)lc1
;
4126 case LC_DYLD_INFO_ONLY
:
4128 object
->dyld_info
= (struct dyld_info_command
*)lc1
;
4130 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4136 * strip_LC_CODE_SIGNATURE_commands() is called when -c is specified to remove
4137 * any LC_CODE_SIGNATURE load commands from the object's load commands.
4141 strip_LC_CODE_SIGNATURE_commands(
4143 struct member
*member
,
4144 struct object
*object
)
4146 uint32_t i
, ncmds
, mh_sizeofcmds
, sizeofcmds
;
4147 struct load_command
*lc1
, *lc2
, *new_load_commands
;
4148 struct segment_command
*sg
;
4151 * See if there is an LC_CODE_SIGNATURE load command and if no command
4154 if(object
->code_sig_cmd
== NULL
)
4158 * Allocate space for the new load commands and zero it out so any holes
4159 * will be zero bytes.
4161 if(arch
->object
->mh
!= NULL
){
4162 ncmds
= arch
->object
->mh
->ncmds
;
4163 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
4166 ncmds
= arch
->object
->mh64
->ncmds
;
4167 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
4169 new_load_commands
= allocate(mh_sizeofcmds
);
4170 memset(new_load_commands
, '\0', mh_sizeofcmds
);
4173 * Copy all the load commands except the LC_CODE_SIGNATURE load commands
4174 * into the allocated space for the new load commands.
4176 lc1
= arch
->object
->load_commands
;
4177 lc2
= new_load_commands
;
4179 for(i
= 0; i
< ncmds
; i
++){
4180 if(lc1
->cmd
!= LC_CODE_SIGNATURE
){
4181 memcpy(lc2
, lc1
, lc1
->cmdsize
);
4182 sizeofcmds
+= lc2
->cmdsize
;
4183 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
4185 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4189 * Finally copy the updated load commands over the existing load
4192 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
4193 if(mh_sizeofcmds
> sizeofcmds
){
4194 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
4195 (mh_sizeofcmds
- sizeofcmds
));
4198 if(arch
->object
->mh
!= NULL
) {
4199 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
4200 arch
->object
->mh
->ncmds
= ncmds
;
4202 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
4203 arch
->object
->mh64
->ncmds
= ncmds
;
4205 free(new_load_commands
);
4207 /* reset the pointers into the load commands */
4208 object
->code_sig_cmd
= NULL
;
4209 lc1
= arch
->object
->load_commands
;
4210 for(i
= 0; i
< ncmds
; i
++){
4213 arch
->object
->st
= (struct symtab_command
*)lc1
;
4216 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
4218 case LC_TWOLEVEL_HINTS
:
4219 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
4221 case LC_PREBIND_CKSUM
:
4222 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
4225 sg
= (struct segment_command
*)lc1
;
4226 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
4227 arch
->object
->seg_linkedit
= sg
;
4229 case LC_SEGMENT_SPLIT_INFO
:
4230 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
4232 case LC_FUNCTION_STARTS
:
4233 object
->func_starts_info_cmd
=
4234 (struct linkedit_data_command
*)lc1
;
4236 case LC_DATA_IN_CODE
:
4237 object
->data_in_code_cmd
=
4238 (struct linkedit_data_command
*)lc1
;
4240 case LC_DYLIB_CODE_SIGN_DRS
:
4241 object
->code_sign_drs_cmd
=
4242 (struct linkedit_data_command
*)lc1
;
4245 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4249 * To get the right amount of the file copied out by writeout() for the
4250 * case when we are stripping out the section contents we already reduce
4251 * the object size by the size of the section contents including the
4252 * padding after the load commands. So here we need to further reduce
4253 * it by the load command for the LC_CODE_SIGNATURE (a struct
4254 * linkedit_data_command) we are removing.
4256 object
->object_size
-= sizeof(struct linkedit_data_command
);
4258 * Then this size minus the size of the input symbolic information is
4259 * what is copied out from the file by writeout(). Which in this case
4260 * is just the new headers.
4264 * Finally for -c the file offset to the link edit information is to be
4265 * right after the load commands. So reset this for the updated size
4266 * of the load commands without the LC_CODE_SIGNATURE.
4268 if(object
->mh
!= NULL
)
4269 object
->seg_linkedit
->fileoff
= sizeof(struct mach_header
) +
4272 object
->seg_linkedit64
->fileoff
= sizeof(struct mach_header_64
) +
4275 #endif /* !(NMEDIT) */
4278 * private_extern_reference_by_module() is passed a symbol_index of a private
4279 * extern symbol and the module table. If the symbol_index appears in the
4280 * module symbol table this returns TRUE else it returns FALSE.
4284 private_extern_reference_by_module(
4285 uint32_t symbol_index
,
4286 struct dylib_reference
*refs
,
4287 uint32_t nextrefsyms
)
4291 for(i
= 0; i
< nextrefsyms
; i
++){
4292 if(refs
[i
].isym
== symbol_index
){
4293 if(refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
||
4294 refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
){
4303 * symbol_pointer_used() is passed a symbol_index and the indirect table. If
4304 * the symbol_index appears in the indirect symbol table this returns TRUE else
4309 symbol_pointer_used(
4310 uint32_t symbol_index
,
4311 uint32_t *indirectsyms
,
4312 uint32_t nindirectsyms
)
4316 for(i
= 0; i
< nindirectsyms
; i
++){
4317 if(indirectsyms
[i
] == symbol_index
)
4324 * Function for qsort for comparing undefined map entries.
4328 cmp_qsort_undef_map(
4329 const struct undef_map
*sym1
,
4330 const struct undef_map
*sym2
)
4332 return(strcmp(qsort_strings
+ sym1
->symbol
.n_un
.n_strx
,
4333 qsort_strings
+ sym2
->symbol
.n_un
.n_strx
));
4338 cmp_qsort_undef_map_64(
4339 const struct undef_map64
*sym1
,
4340 const struct undef_map64
*sym2
)
4342 return(strcmp(qsort_strings
+ sym1
->symbol64
.n_un
.n_strx
,
4343 qsort_strings
+ sym2
->symbol64
.n_un
.n_strx
));
4345 #endif /* !defined(NMEDIT) */
4349 * Function for qsort for comparing object names.
4357 return(strcmp(*name1
, *name2
));
4361 * Function for bsearch for finding a object name.
4365 cmp_bsearch_filename(
4369 return(strcmp(name1
, *name2
));
4371 #endif /* !defined(NMEDIT) */
4378 struct member
*member
,
4379 struct object
*object
,
4380 struct nlist
*symbols
,
4381 struct nlist_64
*symbols64
,
4385 struct dylib_table_of_contents
*tocs
,
4387 struct dylib_module
*mods
,
4388 struct dylib_module_64
*mods64
,
4390 struct dylib_reference
*refs
,
4391 uint32_t nextrefsyms
)
4394 unsigned char data_n_sect
, nsects
;
4395 struct load_command
*lc
;
4396 struct segment_command
*sg
;
4397 struct segment_command_64
*sg64
;
4398 struct section
*s
, **sections
;
4399 struct section_64
*s64
, **sections64
;
4401 uint32_t missing_syms
;
4402 struct symbol_list
*sp
;
4403 struct nlist
**global_symbol
;
4404 struct nlist_64
**global_symbol64
;
4405 enum bool global_symbol_found
;
4406 char *global_name
, save_char
;
4407 enum bool dwarf_debug_map
;
4408 enum byte_sex host_byte_sex
;
4409 int32_t missing_reloc_symbols
;
4410 enum bool edit_symtab_return
;
4413 uint32_t new_ext_strsize
, len
, inew_syms
;
4415 struct nlist
**changed_globals
;
4416 struct nlist_64
**changed_globals64
;
4417 uint32_t nchanged_globals
;
4418 uint32_t ncmds
, s_flags
, n_strx
, module_name
, ilocalsym
, nlocalsym
;
4419 uint32_t iextdefsym
, nextdefsym
;
4420 uint8_t n_type
, n_sect
, global_symbol_n_sect
;
4422 enum bool warned_about_global_coalesced_symbols
;
4424 edit_symtab_return
= TRUE
;
4425 host_byte_sex
= get_host_byte_sex();
4426 missing_reloc_symbols
= 0;
4427 warned_about_global_coalesced_symbols
= FALSE
;
4431 nmedits
= allocate(nsyms
* sizeof(enum bool));
4432 for(i
= 0; i
< nsyms
; i
++)
4436 * If nmedit is operating on a dynamic library then symbols are turned
4437 * into private externs with the extern bit off not into static symbols.
4439 if(object
->mh_filetype
== MH_DYLIB
&& pflag
== TRUE
){
4440 error_arch(arch
, member
, "can't use -p with dynamic libraries");
4445 * As part of the MAJOR guess for the second pass to fix stabs for the
4446 * globals symbols that get turned into non-global symbols. We need to
4447 * change the stabs. To do this we to know if a N_GSYM is for a data
4448 * symbol or not to know to turn it into an N_STSYM or a N_FUN.
4449 * This logic as determined by compiling test cases with and without
4450 * the key word 'static' and looking at the difference between the STABS
4451 * the compiler generates and trying to match that here.
4453 * We also use this loop and the next to gather an array of section
4454 * struct pointers so we can later determine if we run into a global
4455 * symbol in a coalesced section and not turn those symbols into
4461 data_n_sect
= NO_SECT
;
4462 lc
= object
->load_commands
;
4463 if(object
->mh
!= NULL
)
4464 ncmds
= object
->mh
->ncmds
;
4466 ncmds
= object
->mh64
->ncmds
;
4467 for(i
= 0; i
< ncmds
; i
++){
4468 if(lc
->cmd
== LC_SEGMENT
){
4469 sg
= (struct segment_command
*)lc
;
4470 s
= (struct section
*)((char *)sg
+
4471 sizeof(struct segment_command
));
4472 nsects
+= sg
->nsects
;
4473 for(j
= 0; j
< sg
->nsects
; j
++){
4474 if(strcmp(s
->segname
, SEG_DATA
) == 0 &&
4475 strcmp(s
->sectname
, SECT_DATA
) == 0 &&
4476 data_n_sect
== NO_SECT
){
4477 data_n_sect
= n_sect
;
4484 else if(lc
->cmd
== LC_SEGMENT_64
){
4485 sg64
= (struct segment_command_64
*)lc
;
4486 s64
= (struct section_64
*)((char *)sg64
+
4487 sizeof(struct segment_command_64
));
4488 nsects
+= sg64
->nsects
;
4489 for(j
= 0; j
< sg64
->nsects
; j
++){
4490 if(strcmp(s64
->segname
, SEG_DATA
) == 0 &&
4491 strcmp(s64
->sectname
, SECT_DATA
) == 0 &&
4492 data_n_sect
== NO_SECT
){
4493 data_n_sect
= n_sect
;
4500 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
4502 if(object
->mh
!= NULL
){
4503 sections
= allocate(nsects
* sizeof(struct section
*));
4508 sections64
= allocate(nsects
* sizeof(struct section_64
*));
4511 lc
= object
->load_commands
;
4512 for(i
= 0; i
< ncmds
; i
++){
4513 if(lc
->cmd
== LC_SEGMENT
){
4514 sg
= (struct segment_command
*)lc
;
4515 s
= (struct section
*)((char *)sg
+
4516 sizeof(struct segment_command
));
4517 for(j
= 0; j
< sg
->nsects
; j
++){
4518 sections
[nsects
++] = s
++;
4521 else if(lc
->cmd
== LC_SEGMENT_64
){
4522 sg64
= (struct segment_command_64
*)lc
;
4523 s64
= (struct section_64
*)((char *)sg64
+
4524 sizeof(struct segment_command_64
));
4525 for(j
= 0; j
< sg64
->nsects
; j
++){
4526 sections64
[nsects
++] = s64
++;
4529 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
4533 * Zero out the saved symbols so they can be recorded for this file.
4535 for(i
= 0; i
< nsave_symbols
; i
++)
4536 save_symbols
[i
].sym
= NULL
;
4537 for(i
= 0; i
< nremove_symbols
; i
++)
4538 remove_symbols
[i
].sym
= NULL
;
4540 for(i
= 0; i
< nsave_symbols
; i
++)
4541 save_symbols
[i
].seen
= FALSE
;
4542 for(i
= 0; i
< nremove_symbols
; i
++)
4543 remove_symbols
[i
].seen
= FALSE
;
4546 nchanged_globals
= 0;
4547 if(object
->mh
!= NULL
){
4548 changed_globals
= allocate(nsyms
* sizeof(struct nlist
*));
4549 changed_globals64
= NULL
;
4550 for(i
= 0; i
< nsyms
; i
++)
4551 changed_globals
[i
] = NULL
;
4554 changed_globals
= NULL
;
4555 changed_globals64
= allocate(nsyms
* sizeof(struct nlist_64
*));
4556 for(i
= 0; i
< nsyms
; i
++)
4557 changed_globals64
[i
] = NULL
;
4561 * These are the variables for the new symbol table and new string
4562 * table. Since this routine only turns globals into non-globals the
4563 * number of symbols does not change. But the count of local, defined
4564 * external symbols does change.
4571 new_strsize
= sizeof(int32_t);
4572 new_ext_strsize
= 0;
4575 * First pass: turn the globals symbols into non-global symbols.
4577 for(i
= 0; i
< nsyms
; i
++){
4580 if(object
->mh
!= NULL
){
4581 n_strx
= symbols
[i
].n_un
.n_strx
;
4582 n_type
= symbols
[i
].n_type
;
4583 n_sect
= symbols
[i
].n_sect
;
4584 if((n_type
& N_TYPE
) == N_SECT
)
4585 s_flags
= sections
[n_sect
- 1]->flags
;
4586 n_value
= symbols
[i
].n_value
;
4589 n_strx
= symbols64
[i
].n_un
.n_strx
;
4590 n_type
= symbols64
[i
].n_type
;
4591 n_sect
= symbols64
[i
].n_sect
;
4592 if((n_type
& N_TYPE
) == N_SECT
)
4593 s_flags
= sections64
[n_sect
- 1]->flags
;
4594 n_value
= symbols64
[i
].n_value
;
4597 if(n_strx
> strsize
){
4598 error_arch(arch
, member
, "bad string index for symbol "
4599 "table entry %u in: ", i
);
4602 len
= strlen(strings
+ n_strx
) + 1;
4605 if((n_type
& N_TYPE
) != N_UNDF
&&
4606 (n_type
& N_TYPE
) != N_PBUD
){
4607 if((n_type
& N_TYPE
) == N_SECT
){
4608 if(n_sect
> nsects
){
4609 error_arch(arch
, member
, "bad n_sect for symbol "
4610 "table entry %u in: ", i
);
4613 if(((s_flags
& SECTION_TYPE
) == S_COALESCED
) &&
4615 object
->mh_filetype
!= MH_OBJECT
){
4616 /* this remains a global defined symbol */
4617 if(warned_about_global_coalesced_symbols
== FALSE
){
4618 warning_arch(arch
, member
, "can't make global "
4619 "coalesced symbols (like %s) into static "
4620 "symbols (use ld(1)'s "
4621 "-exported_symbols_list option) in a final "
4622 "linked image: ", strings
+ n_strx
);
4623 warned_about_global_coalesced_symbols
= TRUE
;
4626 new_ext_strsize
+= len
;
4628 sp
= bsearch(strings
+ n_strx
,
4629 remove_symbols
, nremove_symbols
,
4630 sizeof(struct symbol_list
),
4631 (int (*)(const void *, const void *))
4632 symbol_list_bsearch
);
4634 if(sp
->sym
!= NULL
){
4635 error_arch(arch
, member
, "more than one "
4636 "symbol for: %s found in: ", sp
->name
);
4640 if(object
->mh
!= NULL
)
4641 sp
->sym
= &(symbols
[i
]);
4643 sp
->sym
= &(symbols64
[i
]);
4645 warning_arch(arch
, member
, "can't make "
4646 "global coalesced symbol: %s into a "
4647 "static symbol in: ", sp
->name
);
4651 * In case the user has listed this coalesced
4652 * symbol in the save list look for it and mark it
4653 * as seen so we don't complain about not seeing it.
4655 sp
= bsearch(strings
+ n_strx
,
4656 save_symbols
, nsave_symbols
,
4657 sizeof(struct symbol_list
),
4658 (int (*)(const void *, const void *))
4659 symbol_list_bsearch
);
4661 if(sp
->sym
!= NULL
){
4662 error_arch(arch
, member
, "more than one "
4663 "symbol for: %s found in: ", sp
->name
);
4667 if(object
->mh
!= NULL
)
4668 sp
->sym
= &(symbols
[i
]);
4670 sp
->sym
= &(symbols64
[i
]);
4674 continue; /* leave this symbol unchanged */
4677 sp
= bsearch(strings
+ n_strx
,
4678 remove_symbols
, nremove_symbols
,
4679 sizeof(struct symbol_list
),
4680 (int (*)(const void *, const void *))
4681 symbol_list_bsearch
);
4683 if(sp
->sym
!= NULL
){
4684 error_arch(arch
, member
, "more than one symbol "
4685 "for: %s found in: ", sp
->name
);
4689 if(object
->mh
!= NULL
)
4690 sp
->sym
= &(symbols
[i
]);
4692 sp
->sym
= &(symbols64
[i
]);
4699 * If there is no list of saved symbols, then all
4700 * symbols will be saved unless listed in the remove
4705 * There is no save list, so if there is also no
4706 * remove list but the -p flag is specified or it is
4707 * a dynamic library then change all symbols.
4709 if((pflag
|| object
->mh_filetype
== MH_DYLIB
)
4710 && nremove_symbols
== 0)
4712 /* this remains a global defined symbol */
4714 new_ext_strsize
+= len
;
4716 continue; /* leave this symbol unchanged */
4719 sp
= bsearch(strings
+ n_strx
,
4720 save_symbols
, nsave_symbols
,
4721 sizeof(struct symbol_list
),
4722 (int (*)(const void *, const void *))
4723 symbol_list_bsearch
);
4725 if(sp
->sym
!= NULL
){
4726 error_arch(arch
, member
, "more than one symbol "
4727 "for: %s found in: ", sp
->name
);
4731 if(object
->mh
!= NULL
)
4732 sp
->sym
= &(symbols
[i
]);
4734 sp
->sym
= &(symbols64
[i
]);
4736 /* this remains a global defined symbol */
4738 new_ext_strsize
+= len
;
4743 if(Aflag
&& n_type
== (N_EXT
| N_ABS
) &&
4746 strncmp(strings
+ n_strx
,
4747 ".objc_class_name_",
4748 sizeof(".objc_class_name_") - 1) == 0))){
4749 /* this remains a global defined symbol */
4751 new_ext_strsize
+= len
;
4756 if((n_type
& N_TYPE
) != N_INDR
){
4758 if(object
->mh
!= NULL
)
4759 changed_globals
[nchanged_globals
++] =
4762 changed_globals64
[nchanged_globals
++] =
4765 /* this remains a global defined symbol */
4767 new_ext_strsize
+= len
;
4771 /* this will become a non-global symbol */
4777 /* this remains a global defined symbol */
4779 new_ext_strsize
+= len
;
4786 /* this is an undefined symbol */
4788 new_ext_strsize
+= len
;
4793 /* this is a local symbol */
4800 * The module table's module names are placed with the external
4801 * strings. So size them and add this to the external string size.
4803 for(i
= 0; i
< nmodtab
; i
++){
4804 if(object
->mh
!= NULL
)
4805 module_name
= mods
[i
].module_name
;
4807 module_name
= mods64
[i
].module_name
;
4808 if(module_name
== 0 || module_name
> strsize
){
4809 error_arch(arch
, member
, "bad string index for module_name "
4810 "of module table entry %d in: ", i
);
4813 len
= strlen(strings
+ module_name
) + 1;
4815 new_ext_strsize
+= len
;
4819 * Warn about symbols to be saved that were missing.
4824 for(i
= 0; i
< nsave_symbols
; i
++){
4825 if(save_symbols
[i
].sym
== NULL
){
4826 if(missing_syms
== 0){
4827 error_arch(arch
, member
, "symbols names listed "
4828 "in: %s not in: ", sfile
);
4831 fprintf(stderr
, "%s\n", save_symbols
[i
].name
);
4834 for(i
= 0; i
< nremove_symbols
; i
++){
4835 if(remove_symbols
[i
].sym
== NULL
){
4836 if(missing_syms
== 0){
4837 error_arch(arch
, member
, "symbols names listed "
4838 "in: %s not in: ", Rfile
);
4841 fprintf(stderr
, "%s\n", remove_symbols
[i
].name
);
4848 * Second pass: fix stabs for the globals symbols that got turned into
4849 * non-global symbols. This is a MAJOR guess. The specific changes
4850 * to do here were determined by compiling test cases with and without
4851 * the key word 'static' and looking at the difference between the STABS
4852 * the compiler generates and trying to match that here.
4854 global_strings
= strings
;
4855 if(object
->mh
!= NULL
)
4856 qsort(changed_globals
, nchanged_globals
, sizeof(struct nlist
*),
4857 (int (*)(const void *, const void *))cmp_qsort_global
);
4859 qsort(changed_globals64
, nchanged_globals
,sizeof(struct nlist_64
*),
4860 (int (*)(const void *, const void *))cmp_qsort_global_64
);
4861 dwarf_debug_map
= FALSE
;
4862 for(i
= 0; i
< nsyms
; i
++){
4864 if(object
->mh
!= NULL
){
4865 n_strx
= symbols
[i
].n_un
.n_strx
;
4866 n_type
= symbols
[i
].n_type
;
4867 n_desc
= symbols
[i
].n_desc
;
4870 n_strx
= symbols64
[i
].n_un
.n_strx
;
4871 n_type
= symbols64
[i
].n_type
;
4872 n_desc
= symbols64
[i
].n_desc
;
4875 dwarf_debug_map
= FALSE
;
4876 else if (n_type
== N_OSO
)
4877 dwarf_debug_map
= n_desc
!= 0;
4878 else if (dwarf_debug_map
&& n_type
== N_GSYM
){
4879 global_name
= strings
+ n_strx
;
4880 if(object
->mh
!= NULL
){
4881 global_symbol
= bsearch(global_name
, changed_globals
,
4882 nchanged_globals
,sizeof(struct nlist
*),
4883 (int (*)(const void *, const void *))
4884 cmp_bsearch_global
);
4885 if(global_symbol
!= NULL
){
4886 symbols
[i
].n_type
= N_STSYM
;
4887 symbols
[i
].n_sect
= (*global_symbol
)->n_sect
;
4888 symbols
[i
].n_value
= (*global_symbol
)->n_value
;
4892 global_symbol64
= bsearch(global_name
, changed_globals64
,
4894 sizeof(struct nlist_64
*),
4895 (int (*)(const void *, const void *))
4896 cmp_bsearch_global_64
);
4897 if(global_symbol64
!= NULL
){
4898 symbols64
[i
].n_type
= N_STSYM
;
4899 symbols64
[i
].n_sect
= (*global_symbol64
)->n_sect
;
4900 symbols64
[i
].n_value
= (*global_symbol64
)->n_value
;
4904 else if(! dwarf_debug_map
&&
4905 (n_type
== N_GSYM
|| n_type
== N_FUN
) &&
4906 (n_strx
!= 0 && strings
[n_strx
] != '\0')){
4907 global_name
= strings
+ n_strx
;
4908 if((global_name
[0] == '+' || global_name
[0] == '-') &&
4909 global_name
[1] == '['){
4911 while(j
+ n_strx
< strsize
&& global_name
[j
] != ']')
4913 if(j
+ n_strx
< strsize
&& global_name
[j
] == ']')
4918 while(j
+ n_strx
< strsize
&& global_name
[j
] != ':')
4920 if(j
+ n_strx
>= strsize
){
4921 error_arch(arch
, member
, "bad N_STAB symbol name for entry "
4922 "%u (does not contain ':' separating name from type) "
4926 save_char
= global_name
[j
];
4927 global_name
[j
] = '\0';
4929 global_symbol_found
= FALSE
;
4930 global_symbol_n_sect
= 0;
4931 if(object
->mh
!= NULL
){
4932 global_symbol
= bsearch(global_name
, changed_globals
,
4933 nchanged_globals
,sizeof(struct nlist
*),
4934 (int (*)(const void *, const void *))
4935 cmp_bsearch_global_stab
);
4936 global_symbol64
= NULL
;
4937 if(global_symbol
!= NULL
){
4938 global_symbol_found
= TRUE
;
4939 global_symbol_n_sect
= (*global_symbol
)->n_sect
;
4943 global_symbol64
= bsearch(global_name
, changed_globals64
,
4945 sizeof(struct nlist_64
*),
4946 (int (*)(const void *, const void *))
4947 cmp_bsearch_global_stab_64
);
4948 global_symbol
= NULL
;
4949 if(global_symbol64
!= NULL
){
4950 global_symbol_found
= TRUE
;
4951 global_symbol_n_sect
= (*global_symbol64
)->n_sect
;
4954 global_name
[j
] = save_char
;
4955 if(global_symbol_found
== TRUE
){
4956 if(n_type
== N_GSYM
){
4957 if(global_symbol_n_sect
== data_n_sect
){
4958 if(object
->mh
!= NULL
)
4959 symbols
[i
].n_type
= N_STSYM
;
4961 symbols64
[i
].n_type
= N_STSYM
;
4964 if(object
->mh
!= NULL
)
4965 symbols
[i
].n_type
= N_FUN
;
4967 symbols64
[i
].n_type
= N_FUN
;
4969 if(object
->mh
!= NULL
){
4970 symbols
[i
].n_sect
= (*global_symbol
)->n_sect
;
4971 symbols
[i
].n_value
= (*global_symbol
)->n_value
;
4972 symbols
[i
].n_desc
= (*global_symbol
)->n_desc
;
4975 symbols64
[i
].n_sect
= (*global_symbol64
)->n_sect
;
4976 symbols64
[i
].n_value
= (*global_symbol64
)->n_value
;
4977 symbols64
[i
].n_desc
= (*global_symbol64
)->n_desc
;
4979 if(j
+ 1 + n_strx
>= strsize
||
4980 global_name
[j
+1] != 'G'){
4981 error_arch(arch
, member
, "bad N_GSYM symbol name "
4982 "for entry %u (does not have type 'G' after "
4983 "':' in name) in: ", i
);
4986 global_name
[j
+1] = 'S';
4988 else{ /* n_type == N_FUN */
4989 if(j
+ 1 + n_strx
>= strsize
||
4990 global_name
[j
+1] == 'F'){
4991 global_name
[j
+1] = 'f';
4997 global_strings
= NULL
;
5000 * Now what needs to be done is to create the new symbol table moving
5001 * those global symbols being changed into non-globals into the areas
5002 * in the symbol table for local symbols. The symbol table and string
5003 * table must be in this order:
5007 * external defined symbols
5015 saves
= (int32_t *)allocate(nsyms
* sizeof(int32_t));
5016 bzero(saves
, nsyms
* sizeof(int32_t));
5018 if(object
->mh
!= NULL
){
5019 new_symbols
= (struct nlist
*)
5020 allocate(new_nsyms
* sizeof(struct nlist
));
5021 new_symbols64
= NULL
;
5025 new_symbols64
= (struct nlist_64
*)
5026 allocate(new_nsyms
* sizeof(struct nlist_64
));
5028 new_strsize
= rnd(new_strsize
, sizeof(int32_t));
5029 new_strings
= (char *)allocate(new_strsize
);
5030 new_strings
[new_strsize
- 3] = '\0';
5031 new_strings
[new_strsize
- 2] = '\0';
5032 new_strings
[new_strsize
- 1] = '\0';
5034 memset(new_strings
, '\0', sizeof(int32_t));
5035 p
= new_strings
+ sizeof(int32_t);
5036 q
= p
+ new_ext_strsize
;
5039 * If this is a dynamic library the movement of the symbols has to be
5040 * done with respect to the modules. As the local symbols, and external
5041 * defined symbols are grouped together for each module. Then a new
5042 * module table needs to be created with the new indexes into the symbol
5043 * table for each module.
5045 new_nmodtab
= nmodtab
;
5047 new_nextrefsyms
= nextrefsyms
;
5048 if(object
->mh_filetype
== MH_DYLIB
&& nmodtab
!= 0){
5049 if(object
->mh
!= NULL
){
5050 new_mods
= allocate(nmodtab
* sizeof(struct dylib_module
));
5055 new_mods64
= allocate(nmodtab
* sizeof(struct dylib_module_64
));
5060 * This first loop through the module table sets the index and
5061 * counts of the local symbols for each module.
5063 for(i
= 0; i
< nmodtab
; i
++){
5065 * First put the existing local symbols into the new symbol
5068 if(object
->mh
!= NULL
){
5069 new_mods
[i
].ilocalsym
= inew_syms
;
5070 new_mods
[i
].nlocalsym
= 0;
5071 ilocalsym
= mods
[i
].ilocalsym
;
5072 nlocalsym
= mods
[i
].nlocalsym
;
5075 new_mods64
[i
].ilocalsym
= inew_syms
;
5076 new_mods64
[i
].nlocalsym
= 0;
5077 ilocalsym
= mods64
[i
].ilocalsym
;
5078 nlocalsym
= mods64
[i
].nlocalsym
;
5080 for(j
= ilocalsym
; j
< ilocalsym
+ nlocalsym
; j
++){
5081 if(object
->mh
!= NULL
){
5082 n_strx
= symbols
[j
].n_un
.n_strx
;
5083 n_type
= symbols
[j
].n_type
;
5086 n_strx
= symbols64
[j
].n_un
.n_strx
;
5087 n_type
= symbols64
[j
].n_type
;
5089 if((n_type
& N_EXT
) == 0){
5090 if(object
->mh
!= NULL
)
5091 new_symbols
[inew_syms
] = symbols
[j
];
5093 new_symbols64
[inew_syms
] = symbols64
[j
];
5095 strcpy(q
, strings
+ n_strx
);
5096 if(object
->mh
!= NULL
)
5097 new_symbols
[inew_syms
].n_un
.n_strx
=
5100 new_symbols64
[inew_syms
].n_un
.n_strx
=
5105 saves
[j
] = inew_syms
;
5106 if(object
->mh
!= NULL
)
5107 new_mods
[i
].nlocalsym
++;
5109 new_mods64
[i
].nlocalsym
++;
5113 * Next put the global symbols that were changed into
5114 * non-global symbols into the new symbol table and moved their
5115 * counts to the local symbol counts.
5117 if(object
->mh
!= NULL
){
5118 iextdefsym
= mods
[i
].iextdefsym
;
5119 nextdefsym
= mods
[i
].nextdefsym
;
5122 iextdefsym
= mods64
[i
].iextdefsym
;
5123 nextdefsym
= mods64
[i
].nextdefsym
;
5125 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
5126 if(object
->mh
!= NULL
){
5127 n_strx
= symbols
[j
].n_un
.n_strx
;
5128 n_type
= symbols
[j
].n_type
;
5131 n_strx
= symbols64
[j
].n_un
.n_strx
;
5132 n_type
= symbols64
[j
].n_type
;
5134 if((n_type
& N_EXT
) != 0){
5135 if(nmedits
[j
] == TRUE
){
5137 * Change the new symbol to a private extern symbol
5138 * with the extern bit off.
5140 if(object
->mh
!= NULL
){
5141 new_symbols
[inew_syms
] = symbols
[j
];
5142 new_symbols
[inew_syms
].n_type
|= N_PEXT
;
5143 new_symbols
[inew_syms
].n_type
&= ~N_EXT
;
5146 new_symbols64
[inew_syms
] = symbols64
[j
];
5147 new_symbols64
[inew_syms
].n_type
|= N_PEXT
;
5148 new_symbols64
[inew_syms
].n_type
&= ~N_EXT
;
5151 strcpy(q
, strings
+ n_strx
);
5152 if(object
->mh
!= NULL
)
5153 new_symbols
[inew_syms
].n_un
.n_strx
=
5156 new_symbols64
[inew_syms
].n_un
.n_strx
=
5161 saves
[j
] = inew_syms
;
5162 if(object
->mh
!= NULL
)
5163 new_mods
[i
].nlocalsym
++;
5165 new_mods64
[i
].nlocalsym
++;
5171 * Next put the unchanged defined global symbols into the new
5174 for(i
= 0; i
< nmodtab
; i
++){
5175 if(object
->mh
!= NULL
){
5176 new_mods
[i
].iextdefsym
= inew_syms
;
5177 new_mods
[i
].nextdefsym
= 0;
5178 iextdefsym
= mods
[i
].iextdefsym
;
5179 nextdefsym
= mods
[i
].nextdefsym
;
5182 new_mods64
[i
].iextdefsym
= inew_syms
;
5183 new_mods64
[i
].nextdefsym
= 0;
5184 iextdefsym
= mods64
[i
].iextdefsym
;
5185 nextdefsym
= mods64
[i
].nextdefsym
;
5187 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
5188 if(object
->mh
!= NULL
){
5189 n_strx
= symbols
[j
].n_un
.n_strx
;
5190 n_type
= symbols
[j
].n_type
;
5193 n_strx
= symbols64
[j
].n_un
.n_strx
;
5194 n_type
= symbols64
[j
].n_type
;
5196 if((n_type
& N_EXT
) != 0){
5197 if(nmedits
[j
] == FALSE
){
5198 if(object
->mh
!= NULL
)
5199 new_symbols
[inew_syms
] = symbols
[j
];
5201 new_symbols64
[inew_syms
] = symbols64
[j
];
5203 strcpy(p
, strings
+ n_strx
);
5204 if(object
->mh
!= NULL
)
5205 new_symbols
[inew_syms
].n_un
.n_strx
=
5208 new_symbols64
[inew_syms
].n_un
.n_strx
=
5213 saves
[j
] = inew_syms
;
5214 if(object
->mh
!= NULL
)
5215 new_mods
[i
].nextdefsym
++;
5217 new_mods64
[i
].nextdefsym
++;
5223 * Last put the undefined symbols into the new symbol table.
5225 for(i
= 0; i
< nsyms
; i
++){
5226 if(object
->mh
!= NULL
){
5227 n_strx
= symbols
[i
].n_un
.n_strx
;
5228 n_type
= symbols
[i
].n_type
;
5231 n_strx
= symbols64
[i
].n_un
.n_strx
;
5232 n_type
= symbols64
[i
].n_type
;
5234 if((n_type
& N_EXT
) != 0 &&
5235 ((n_type
& N_TYPE
) == N_UNDF
||
5236 (n_type
& N_TYPE
) == N_PBUD
)){
5237 if(object
->mh
!= NULL
)
5238 new_symbols
[inew_syms
] = symbols
[i
];
5240 new_symbols64
[inew_syms
] = symbols64
[i
];
5242 strcpy(p
, strings
+ n_strx
);
5243 if(object
->mh
!= NULL
)
5244 new_symbols
[inew_syms
].n_un
.n_strx
=
5247 new_symbols64
[inew_syms
].n_un
.n_strx
=
5252 saves
[i
] = inew_syms
;
5257 * Place the module table's module names with the external strings
5258 * and set the names in the new module table. And then copy the
5259 * other unchanged fields.
5261 for(i
= 0; i
< nmodtab
; i
++){
5262 if(object
->mh
!= NULL
){
5263 strcpy(p
, strings
+ mods
[i
].module_name
);
5264 new_mods
[i
].module_name
= p
- new_strings
;
5267 new_mods
[i
].irefsym
= mods
[i
].irefsym
;
5268 new_mods
[i
].nrefsym
= mods
[i
].nrefsym
;
5269 new_mods
[i
].iextrel
= mods
[i
].iextrel
;
5270 new_mods
[i
].nextrel
= mods
[i
].nextrel
;
5271 new_mods
[i
].iinit_iterm
= mods
[i
].iinit_iterm
;
5272 new_mods
[i
].ninit_nterm
= mods
[i
].ninit_nterm
;
5273 new_mods
[i
].objc_module_info_addr
=
5274 mods
[i
].objc_module_info_addr
;
5275 new_mods
[i
].objc_module_info_size
=
5276 mods
[i
].objc_module_info_size
;
5279 strcpy(p
, strings
+ mods64
[i
].module_name
);
5280 new_mods64
[i
].module_name
= p
- new_strings
;
5283 new_mods64
[i
].irefsym
= mods64
[i
].irefsym
;
5284 new_mods64
[i
].nrefsym
= mods64
[i
].nrefsym
;
5285 new_mods64
[i
].iextrel
= mods64
[i
].iextrel
;
5286 new_mods64
[i
].nextrel
= mods64
[i
].nextrel
;
5287 new_mods64
[i
].iinit_iterm
= mods64
[i
].iinit_iterm
;
5288 new_mods64
[i
].ninit_nterm
= mods64
[i
].ninit_nterm
;
5289 new_mods64
[i
].objc_module_info_addr
=
5290 mods64
[i
].objc_module_info_addr
;
5291 new_mods64
[i
].objc_module_info_size
=
5292 mods64
[i
].objc_module_info_size
;
5297 * Update the reference table with the new symbol indexes for all
5298 * entries and change type of reference (the flags field) for those
5299 * symbols that got changed from globals to non-globals.
5301 new_nextrefsyms
= nextrefsyms
;
5302 new_refs
= allocate(new_nextrefsyms
*
5303 sizeof(struct dylib_reference
));
5305 for(i
= 0; i
< nextrefsyms
; i
++){
5306 if(nmedits
[refs
[i
].isym
] == TRUE
){
5307 if(refs
[i
].flags
== REFERENCE_FLAG_DEFINED
)
5309 REFERENCE_FLAG_PRIVATE_DEFINED
;
5310 else if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
)
5312 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
;
5313 else if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
)
5315 REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
;
5317 new_refs
[i
].flags
= refs
[i
].flags
;
5320 new_refs
[i
].flags
= refs
[i
].flags
;
5322 new_refs
[i
].isym
= saves
[refs
[i
].isym
] - 1;
5326 * Create a new dylib table of contents without the global symbols
5327 * that got turned into non-globals.
5329 new_ntoc
= ntoc
- nchanged_globals
;
5330 new_tocs
= allocate(new_ntoc
*
5331 sizeof(struct dylib_table_of_contents
));
5333 for(i
= 0; i
< ntoc
; i
++){
5334 if(tocs
[i
].symbol_index
>= nsyms
){
5335 error_arch(arch
, member
, "bad symbol index for table of "
5336 "contents table entry %d in: ", i
);
5339 if(nmedits
[tocs
[i
].symbol_index
] == FALSE
){
5340 new_tocs
[k
].symbol_index
= saves
[tocs
[i
].symbol_index
] - 1;
5341 new_tocs
[k
].module_index
= tocs
[i
].module_index
;
5347 * If is not a dynamic library so all global symbols changed into
5348 * statics can be moved to the end of the local symbols. If the pflag
5349 * is set then the changed symbols remain global and just get the
5350 * private extern bit set.
5354 * First put the existing local symbols into the new symbol table.
5357 for(i
= 0; i
< nsyms
; i
++){
5358 if(object
->mh
!= NULL
){
5359 n_strx
= symbols
[i
].n_un
.n_strx
;
5360 n_type
= symbols
[i
].n_type
;
5363 n_strx
= symbols64
[i
].n_un
.n_strx
;
5364 n_type
= symbols64
[i
].n_type
;
5366 if((n_type
& N_EXT
) == 0){
5367 if(object
->mh
!= NULL
)
5368 new_symbols
[inew_syms
] = symbols
[i
];
5370 new_symbols64
[inew_syms
] = symbols64
[i
];
5372 strcpy(q
, strings
+ n_strx
);
5373 if(object
->mh
!= NULL
)
5374 new_symbols
[inew_syms
].n_un
.n_strx
=
5377 new_symbols64
[inew_syms
].n_un
.n_strx
=
5382 saves
[i
] = inew_syms
;
5386 * Next put the global symbols that were changed into statics
5387 * symbols into the new symbol table.
5390 for(i
= 0; i
< nsyms
; i
++){
5391 if(object
->mh
!= NULL
){
5392 n_strx
= symbols
[i
].n_un
.n_strx
;
5393 n_type
= symbols
[i
].n_type
;
5396 n_strx
= symbols64
[i
].n_un
.n_strx
;
5397 n_type
= symbols64
[i
].n_type
;
5399 if((n_type
& N_EXT
) != 0){
5400 if(nmedits
[i
] == TRUE
){
5402 * Change the new symbol to not be an extern symbol
5403 * by turning off the extern bit.
5405 if(object
->mh
!= NULL
){
5406 new_symbols
[inew_syms
] = symbols
[i
];
5407 new_symbols
[inew_syms
].n_type
&= ~N_EXT
;
5408 new_symbols
[inew_syms
].n_desc
&= ~N_WEAK_DEF
;
5411 new_symbols64
[inew_syms
] = symbols64
[i
];
5412 new_symbols64
[inew_syms
].n_type
&= ~N_EXT
;
5413 new_symbols64
[inew_syms
].n_desc
&= ~N_WEAK_DEF
;
5416 strcpy(q
, strings
+ n_strx
);
5417 if(object
->mh
!= NULL
)
5418 new_symbols
[inew_syms
].n_un
.n_strx
=
5421 new_symbols64
[inew_syms
].n_un
.n_strx
=
5426 saves
[i
] = inew_syms
;
5432 * Last put the unchanged global symbols into the new symbol table
5433 * and symbols changed into private externs.
5435 for(i
= 0; i
< nsyms
; i
++){
5436 if(object
->mh
!= NULL
){
5437 n_strx
= symbols
[i
].n_un
.n_strx
;
5438 n_type
= symbols
[i
].n_type
;
5441 n_strx
= symbols64
[i
].n_un
.n_strx
;
5442 n_type
= symbols64
[i
].n_type
;
5444 if((n_type
& N_EXT
) != 0){
5445 if(nmedits
[i
] == FALSE
|| pflag
== TRUE
){
5446 if(object
->mh
!= NULL
)
5447 new_symbols
[inew_syms
] = symbols
[i
];
5449 new_symbols64
[inew_syms
] = symbols64
[i
];
5450 if(nmedits
[i
] == TRUE
&& pflag
== TRUE
){
5452 * Change the new symbol to be a private extern
5453 * symbol by turning on the private extern bit.
5455 if(object
->mh
!= NULL
)
5456 new_symbols
[inew_syms
].n_type
|= N_PEXT
;
5458 new_symbols64
[inew_syms
].n_type
|= N_PEXT
;
5461 strcpy(p
, strings
+ n_strx
);
5462 if(object
->mh
!= NULL
)
5463 new_symbols
[inew_syms
].n_un
.n_strx
=
5466 new_symbols64
[inew_syms
].n_un
.n_strx
=
5471 saves
[i
] = inew_syms
;
5477 if(sections
!= NULL
)
5479 if(sections64
!= NULL
)
5489 * Function for qsort for comparing global symbol names.
5494 const struct nlist
**sym1
,
5495 const struct nlist
**sym2
)
5497 return(strcmp(global_strings
+ (*sym1
)->n_un
.n_strx
,
5498 global_strings
+ (*sym2
)->n_un
.n_strx
));
5503 cmp_qsort_global_64(
5504 const struct nlist_64
**sym1
,
5505 const struct nlist_64
**sym2
)
5507 return(strcmp(global_strings
+ (*sym1
)->n_un
.n_strx
,
5508 global_strings
+ (*sym2
)->n_un
.n_strx
));
5512 * Function for bsearch for finding a global symbol that matches a stab name.
5516 cmp_bsearch_global_stab(
5518 const struct nlist
**sym
)
5521 * The +1 is for the '_' on the global symbol that is not on the
5522 * stab string that is trying to be matched.
5524 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
+ 1));
5529 cmp_bsearch_global_stab_64(
5531 const struct nlist_64
**sym
)
5534 * The +1 is for the '_' on the global symbol that is not on the
5535 * stab string that is trying to be matched.
5537 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
+ 1));
5541 * Function for bsearch for finding a global symbol that matches a stab name
5548 const struct nlist
**sym
)
5550 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
));
5555 cmp_bsearch_global_64(
5557 const struct nlist_64
**sym
)
5559 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
));
5561 #endif /* defined(NMEDIT) */