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 aflag
; /* -a save all symbols, just regenerate symbol table */
62 static uint32_t iflag
; /* -i ignore symbols in -s file not in object */
64 static uint32_t pflag
; /* make all defined global symbols private extern */
65 #else /* !defined(NMEDIT) */
66 static char *dfile
; /* filename of filenames of debugger symbols to keep */
67 static uint32_t uflag
; /* save undefined symbols */
68 static uint32_t rflag
; /* save symbols referenced dynamically */
69 static uint32_t nflag
; /* save N_SECT global symbols */
70 static uint32_t Sflag
; /* -S strip only debugger symbols N_STAB */
71 static uint32_t xflag
; /* -x strip non-globals */
72 static uint32_t Xflag
; /* -X strip local symbols with 'L' names */
73 static uint32_t tflag
; /* -t strip local symbols except those in the text
74 section with names that don't begin with 'L' */
75 static uint32_t cflag
; /* -c strip section contents from dynamic libraries
76 files to create stub libraries */
77 static uint32_t no_uuid
;/* -no_uuid strip LC_UUID load commands */
78 static uint32_t no_code_signature
;
79 /* -no_code_signature strip LC_CODE_SIGNATURE cmds */
80 static uint32_t vflag
; /* -v for verbose debugging ld -r executions */
81 static uint32_t lflag
; /* -l do ld -r executions even if it has bugs */
82 static uint32_t strip_all
= 1;
84 * This is set on an object by object basis if the strip_all flag is still set
85 * and the object is an executable that is for use with the dynamic linker.
86 * This has the same effect as -r and -u.
88 static enum bool default_dyld_executable
= FALSE
;
92 * Data structures to perform selective stripping of symbol table entries.
93 * save_symbols is the names of the symbols from the -s <file> argument.
94 * remove_symbols is the names of the symbols from the -R <file> argument.
96 static struct symbol_list
*save_symbols
= NULL
;
97 static uint32_t nsave_symbols
= 0;
98 static struct symbol_list
*remove_symbols
= NULL
;
99 static uint32_t nremove_symbols
= 0;
102 * saves points to an array of uint32_t's that is allocated. This array is a
103 * map of old symbol indexes to new symbol indexes. The new symbol indexes are
104 * plus 1 and zero value means that old symbol is not in the new symbol table.
105 * ref_saves is used in the same way but for the reference table.
106 * nmedits is an array and indexed by the symbol index the value indicates if
107 * the symbol was edited and turned into a non-global.
109 static int32_t *saves
= NULL
;
111 static int32_t *ref_saves
= NULL
;
113 static enum bool *nmedits
= NULL
;
117 * These hold pointers to the symbol, string and indirect tables being worked on
118 * by strip_object and strip_symtab() from an input object file or possiblity
119 * changed to an ld -r (-S or -x) file by make_ld_r_object().
121 static struct nlist
*symbols
= NULL
;
122 static struct nlist_64
*symbols64
= NULL
;
123 static uint32_t nsyms
= 0;
124 static char *strings
= NULL
;
125 static uint32_t strsize
= 0;
126 static uint32_t *indirectsyms
= NULL
;
127 static uint32_t nindirectsyms
= 0;
130 * These hold the new symbol and string table created by strip_symtab()
131 * and the new counts of local, defined external and undefined symbols.
133 static struct nlist
*new_symbols
= NULL
;
134 static struct nlist_64
*new_symbols64
= NULL
;
135 static uint32_t new_nsyms
= 0;
136 static char *new_strings
= NULL
;
137 static uint32_t new_strsize
= 0;
138 static uint32_t new_nlocalsym
= 0;
139 static uint32_t new_nextdefsym
= 0;
140 static uint32_t new_nundefsym
= 0;
141 #if defined(TRIE_SUPPORT) && !defined(NMEDIT)
143 * The index into the new symbols where the defined external start.
145 static uint32_t inew_nextdefsym
= 0;
149 * These hold the new table of contents, reference table and module table for
152 static struct dylib_table_of_contents
*new_tocs
= NULL
;
153 static uint32_t new_ntoc
= 0;
154 static struct dylib_reference
*new_refs
= NULL
;
155 static uint32_t new_nextrefsyms
= 0;
157 static struct dylib_module
*new_mods
= NULL
;
158 static struct dylib_module_64
*new_mods64
= NULL
;
159 static uint32_t new_nmodtab
= 0;
164 * The list of file names to save debugging symbols from.
166 static char **debug_filenames
= NULL
;
167 static uint32_t ndebug_filenames
= 0;
174 struct nlist_64 symbol64
;
176 static char *qsort_strings
= NULL
;
177 #endif /* !defined(NMEDIT) */
180 /* Internal routines */
184 static void strip_file(
186 struct arch_flag
*arch_flags
,
187 uint32_t narch_flags
,
188 enum bool all_archs
);
190 static void strip_arch(
193 struct arch_flag
*arch_flags
,
194 uint32_t narch_flags
,
195 enum bool all_archs
);
197 static void strip_object(
199 struct member
*member
,
200 struct object
*object
);
202 static uint32_t get_starting_syminfo_offset(
203 struct object
*object
);
205 static void check_object_relocs(
207 struct member
*member
,
208 struct object
*object
,
213 struct relocation_info
*relocs
,
215 struct nlist
*symbols
,
216 struct nlist_64
*symbols64
,
219 int32_t *missing_reloc_symbols
,
220 enum byte_sex host_byte_sex
);
222 static void check_indirect_symtab(
224 struct member
*member
,
225 struct object
*object
,
228 uint32_t section_type
,
230 struct nlist
*symbols
,
231 struct nlist_64
*symbols64
,
234 int32_t *missing_reloc_symbols
,
235 enum byte_sex host_byte_sex
);
238 static enum bool strip_symtab(
240 struct member
*member
,
241 struct object
*object
,
242 struct dylib_table_of_contents
*tocs
,
244 struct dylib_module
*mods
,
245 struct dylib_module_64
*mods64
,
247 struct dylib_reference
*refs
,
248 uint32_t nextrefsyms
);
253 #endif /* TRIE_SUPPORT */
255 static void make_ld_r_object(
257 struct member
*member
,
258 struct object
*object
);
260 static void strip_LC_UUID_commands(
262 struct member
*member
,
263 struct object
*object
);
266 static void strip_LC_CODE_SIGNATURE_commands(
268 struct member
*member
,
269 struct object
*object
);
270 #endif /* !(NMEDIT) */
272 static enum bool private_extern_reference_by_module(
273 uint32_t symbol_index
,
274 struct dylib_reference
*refs
,
275 uint32_t nextrefsyms
);
277 static enum bool symbol_pointer_used(
278 uint32_t symbol_index
,
279 uint32_t *indirectsyms
,
280 uint32_t nindirectsyms
);
282 static int cmp_qsort_undef_map(
283 const struct undef_map
*sym1
,
284 const struct undef_map
*sym2
);
286 static int cmp_qsort_undef_map_64(
287 const struct undef_map64
*sym1
,
288 const struct undef_map64
*sym2
);
289 #endif /* !defined(NMEDIT) */
292 static enum bool edit_symtab(
294 struct member
*member
,
295 struct object
*object
,
296 struct nlist
*symbols
,
297 struct nlist_64
*symbols64
,
301 struct dylib_table_of_contents
*tocs
,
303 struct dylib_module
*mods
,
304 struct dylib_module_64
*mods64
,
306 struct dylib_reference
*refs
,
307 uint32_t nextrefsyms
);
311 static void setup_debug_filenames(
314 static int cmp_qsort_filename(
318 static int cmp_bsearch_filename(
325 * This variable and routines are used for nmedit(1) only.
327 static char *global_strings
= NULL
;
329 static int cmp_qsort_global(
330 const struct nlist
**sym1
,
331 const struct nlist
**sym2
);
333 static int cmp_qsort_global_64(
334 const struct nlist_64
**sym1
,
335 const struct nlist_64
**sym2
);
337 static int cmp_bsearch_global_stab(
339 const struct nlist
**sym
);
341 static int cmp_bsearch_global_stab_64(
343 const struct nlist_64
**sym
);
345 static int cmp_bsearch_global(
347 const struct nlist
**sym
);
349 static int cmp_bsearch_global_64(
351 const struct nlist_64
**sym
);
361 uint32_t j
, args_left
, files_specified
;
362 struct arch_flag
*arch_flags
;
363 uint32_t narch_flags
;
365 struct symbol_list
*sp
;
375 for (i
= 1; i
< argc
; i
++){
376 if(argv
[i
][0] == '-'){
377 if(argv
[i
][1] == '\0'){
381 if(strcmp(argv
[i
], "-o") == 0){
383 fatal("-o requires an argument");
384 if(output_file
!= NULL
)
385 fatal("only one -o option allowed");
386 output_file
= argv
[i
+ 1];
389 else if(strcmp(argv
[i
], "-s") == 0){
391 fatal("-s requires an argument");
393 fatal("only one -s option allowed");
397 else if(strcmp(argv
[i
], "-R") == 0){
399 fatal("-R requires an argument");
401 fatal("only one -R option allowed");
406 else if(strcmp(argv
[i
], "-d") == 0){
408 fatal("-d requires an argument");
410 fatal("only one -d option allowed");
414 else if(strcmp(argv
[i
], "-no_uuid") == 0){
417 else if(strcmp(argv
[i
], "-no_code_signature") == 0){
418 no_code_signature
= 1;
420 #endif /* !defined(NMEDIT) */
421 else if(strcmp(argv
[i
], "-arch") == 0){
423 error("missing argument(s) to %s option", argv
[i
]);
426 if(strcmp("all", argv
[i
+1]) == 0){
430 arch_flags
= reallocate(arch_flags
,
431 (narch_flags
+ 1) * sizeof(struct arch_flag
));
432 if(get_arch_from_flag(argv
[i
+1],
433 arch_flags
+ narch_flags
) == 0){
434 error("unknown architecture specification flag: "
435 "%s %s", argv
[i
], argv
[i
+1]);
439 for(j
= 0; j
< narch_flags
; j
++){
440 if(arch_flags
[j
].cputype
==
441 arch_flags
[narch_flags
].cputype
&&
442 (arch_flags
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
443 (arch_flags
[narch_flags
].cpusubtype
&
444 ~CPU_SUBTYPE_MASK
) &&
445 strcmp(arch_flags
[j
].name
,
446 arch_flags
[narch_flags
].name
) == 0)
455 for(j
= 1; argv
[i
][j
] != '\0'; j
++){
461 #else /* !defined(NMEDIT) */
493 #endif /* !defined(NMEDIT) */
498 #endif /* !defined(NMEDIT) */
517 error("unrecognized option: %s", argv
[i
]);
527 files_specified
+= argc
- (i
+ 1);
529 if(files_specified
> 1 && output_file
!= NULL
){
530 error("-o <filename> can only be used when one file is specified");
535 setup_symbol_list(sfile
, &save_symbols
, &nsave_symbols
);
539 if(Rfile
== NULL
&& pflag
== 0){
540 error("-s <filename>, -R <filename> or -p argument required");
547 setup_symbol_list(Rfile
, &remove_symbols
, &nremove_symbols
);
549 for(j
= 0; j
< nremove_symbols
; j
++){
550 sp
= bsearch(remove_symbols
[j
].name
,
551 save_symbols
, nsave_symbols
,
552 sizeof(struct symbol_list
),
553 (int (*)(const void *, const void *))
554 symbol_list_bsearch
);
556 error("symbol name: %s is listed in both -s %s and -R "
557 "%s files (can't be both saved and removed)",
558 remove_symbols
[j
].name
, sfile
, Rfile
);
566 /* the default when no -arch flags is present is to strip all archs */
572 setup_debug_filenames(dfile
);
574 #endif /* !defined(NMEDIT) */
578 for (i
= 1; i
< argc
; i
++) {
579 if(args_left
&& argv
[i
][0] == '-'){
580 if(argv
[i
][1] == '\0')
582 else if(strcmp(argv
[i
], "-o") == 0 ||
583 strcmp(argv
[i
], "-s") == 0 ||
584 strcmp(argv
[i
], "-R") == 0 ||
586 strcmp(argv
[i
], "-d") == 0 ||
587 #endif /* !defined(NMEDIT) */
588 strcmp(argv
[i
], "-arch") == 0)
592 char resolved_path
[PATH_MAX
+ 1];
594 if(realpath(argv
[i
], resolved_path
) == NULL
)
595 strip_file(argv
[i
], arch_flags
, narch_flags
, all_archs
);
597 strip_file(resolved_path
, arch_flags
,narch_flags
,all_archs
);
601 if(files_specified
== 0)
602 fatal("no files specified");
605 return(EXIT_FAILURE
);
607 return(EXIT_SUCCESS
);
616 fprintf(stderr
, "Usage: %s [-AanuStXx] [-no_uuid] [-no_code_signature] "
617 "[-] [-d filename] [-s filename] [-R filename] [-o output] "
618 "file [...]\n", progname
);
619 #else /* defined(NMEDIT) */
620 fprintf(stderr
, "Usage: %s -s filename [-R filename] [-p] [-A] [-] "
621 "[-o output] file [...] \n",
631 struct arch_flag
*arch_flags
,
632 uint32_t narch_flags
,
638 struct stat stat_buf
;
639 uint32_t previous_errors
;
640 enum bool unix_standard_mode
;
649 previous_errors
= errors
;
652 /* breakout the file for processing */
653 ofile
= breakout(input_file
, &archs
, &narchs
, FALSE
);
657 /* checkout the file for symbol table replacement processing */
658 checkout(archs
, narchs
);
660 /* process the symbols in the input file */
661 strip_arch(archs
, narchs
, arch_flags
, narch_flags
, all_archs
);
663 free_archs(archs
, narchs
);
668 /* create the output file */
669 if(stat(input_file
, &stat_buf
) == -1)
670 system_error("can't stat input file: %s", input_file
);
671 if(output_file
!= NULL
){
672 writeout(archs
, narchs
, output_file
, stat_buf
.st_mode
& 0777,
673 TRUE
, FALSE
, FALSE
, NULL
);
676 unix_standard_mode
= get_unix_standard_mode();
680 output_file
= makestr(input_file
, ".nmedit", NULL
);
681 #else /* !defined(NMEDIT) */
683 * In UNIX standard conformance mode we are not allowed to replace
684 * a file that is not writeable.
686 if(unix_standard_mode
== TRUE
&&
687 access(input_file
, W_OK
) == -1){
688 system_error("file: %s is not writable", input_file
);
689 goto strip_file_return
;
691 output_file
= makestr(input_file
, ".strip", NULL
);
694 * The UNIX standard conformance test suite expects files of
695 * MAXPATHLEN to work.
697 if(strlen(output_file
) >= MAXPATHLEN
){
699 * If there is a directory path in the name try to change
700 * the current working directory to that path.
702 if((p
= rindex(output_file
, '/')) != NULL
){
703 if((cwd_fd
= open(".", O_RDONLY
, 0)) == -1){
704 system_error("can't open current working directory");
705 goto strip_file_return
;
708 if(chdir(output_file
) == -1){
709 system_error("can't change current working directory "
710 "to: %s", output_file
);
711 goto strip_file_return
;
713 p
= rindex(input_file
, '/');
714 rename_file
= makestr(p
+ 1, NULL
);
717 * Create what might be a short enough name.
720 output_file
= makestr("strip.XXXXXX", NULL
);
721 output_file
= mktemp(output_file
);
724 writeout(archs
, narchs
, output_file
, stat_buf
.st_mode
& 0777,
725 TRUE
, FALSE
, FALSE
, NULL
);
726 if(rename_file
!= NULL
){
727 if(rename(output_file
, rename_file
) == -1)
728 system_error("can't move temporary file: %s to file: %s",
729 output_file
, rename_file
);
733 if(rename(output_file
, input_file
) == -1)
734 system_error("can't move temporary file: %s to input "
735 "file: %s", output_file
, input_file
);
741 * If we changed the current working directory change back to
742 * the previous working directory.
745 if(fchdir(cwd_fd
) == -1)
746 system_error("can't change back to previous working "
748 if(close(cwd_fd
) == -1)
749 system_error("can't close previous working directory");
755 #endif /* !defined(NMEDIT) */
756 /* clean-up data structures */
757 free_archs(archs
, narchs
);
760 errors
+= previous_errors
;
768 struct arch_flag
*arch_flags
,
769 uint32_t narch_flags
,
772 uint32_t i
, j
, k
, offset
, size
, missing_syms
;
774 cpu_subtype_t cpusubtype
;
775 struct arch_flag host_arch_flag
;
776 enum bool arch_process
, any_processing
, *arch_flag_processed
, family
;
777 const struct arch_flag
*family_arch_flag
;
780 * Using the specified arch_flags process specified objects for those
783 any_processing
= FALSE
;
784 arch_flag_processed
= NULL
;
786 arch_flag_processed
= allocate(narch_flags
* sizeof(enum bool));
787 memset(arch_flag_processed
, '\0', narch_flags
* sizeof(enum bool));
788 for(i
= 0; i
< narchs
; i
++){
790 * Determine the architecture (cputype and cpusubtype) of arch[i]
794 if(archs
[i
].type
== OFILE_ARCHIVE
){
795 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
796 if(archs
[i
].members
[j
].type
== OFILE_Mach_O
){
797 cputype
= archs
[i
].members
[j
].object
->mh_cputype
;
798 cpusubtype
= archs
[i
].members
[j
].object
->mh_cpusubtype
;
803 else if(archs
[i
].type
== OFILE_Mach_O
){
804 cputype
= archs
[i
].object
->mh_cputype
;
805 cpusubtype
= archs
[i
].object
->mh_cpusubtype
;
807 else if(archs
[i
].fat_arch
!= NULL
){
808 cputype
= archs
[i
].fat_arch
->cputype
;
809 cpusubtype
= archs
[i
].fat_arch
->cpusubtype
;
811 arch_process
= FALSE
;
812 if(all_archs
== TRUE
){
815 else if(narch_flags
!= 0){
817 if(narch_flags
== 1){
819 get_arch_family_from_cputype(arch_flags
[0].cputype
);
820 if(family_arch_flag
!= NULL
)
822 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
823 (arch_flags
[0].cpusubtype
& ~CPU_SUBTYPE_MASK
));
825 for(j
= 0; j
< narch_flags
; j
++){
826 if(arch_flags
[j
].cputype
== cputype
&&
827 ((arch_flags
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
828 (cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
831 arch_flag_processed
[j
] = TRUE
;
837 (void)get_arch_from_host(&host_arch_flag
, NULL
);
838 if(host_arch_flag
.cputype
== cputype
&&
839 (host_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
840 (cpusubtype
& ~CPU_SUBTYPE_MASK
))
843 if(narchs
!= 1 && arch_process
== FALSE
)
845 any_processing
= TRUE
;
848 * Now this arch[i] has been selected to be processed so process it
849 * according to its type.
851 if(archs
[i
].type
== OFILE_ARCHIVE
){
852 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
853 if(archs
[i
].members
[j
].type
== OFILE_Mach_O
){
854 strip_object(archs
+ i
, archs
[i
].members
+ j
,
855 archs
[i
].members
[j
].object
);
860 for(k
= 0; k
< nsave_symbols
; k
++){
861 if(save_symbols
[k
].seen
== FALSE
){
862 if(missing_syms
== 0){
863 error_arch(archs
+ i
, NULL
, "symbols names "
864 "listed in: %s not in: ", sfile
);
867 fprintf(stderr
, "%s\n", save_symbols
[k
].name
);
871 for(k
= 0; k
< nsave_symbols
; k
++){
872 save_symbols
[k
].seen
= FALSE
;
876 for(k
= 0; k
< nremove_symbols
; k
++){
877 if(remove_symbols
[k
].seen
== FALSE
){
878 if(missing_syms
== 0){
879 error_arch(archs
+ i
, NULL
, "symbols names "
880 "listed in: %s not defined in: ",
884 fprintf(stderr
, "%s\n", remove_symbols
[k
].name
);
888 for(k
= 0; k
< nremove_symbols
; k
++){
889 remove_symbols
[k
].seen
= FALSE
;
892 * Reset the library offsets and size.
895 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
896 archs
[i
].members
[j
].offset
= offset
;
898 if(archs
[i
].members
[j
].member_long_name
== TRUE
){
899 size
= rnd(archs
[i
].members
[j
].member_name_size
, 8) +
900 (rnd(sizeof(struct ar_hdr
), 8) -
901 sizeof(struct ar_hdr
));
902 archs
[i
].toc_long_name
= TRUE
;
904 if(archs
[i
].members
[j
].object
!= NULL
){
906 rnd(archs
[i
].members
[j
].object
->object_size
-
907 archs
[i
].members
[j
].object
->input_sym_info_size
+
908 archs
[i
].members
[j
].object
->output_sym_info_size
,
910 sprintf(archs
[i
].members
[j
].ar_hdr
->ar_size
, "%-*ld",
911 (int)sizeof(archs
[i
].members
[j
].ar_hdr
->ar_size
),
914 * This has to be done by hand because sprintf puts a
915 * null at the end of the buffer.
917 memcpy(archs
[i
].members
[j
].ar_hdr
->ar_fmag
, ARFMAG
,
918 (int)sizeof(archs
[i
].members
[j
].ar_hdr
->ar_fmag
));
921 size
+= archs
[i
].members
[j
].unknown_size
;
923 offset
+= sizeof(struct ar_hdr
) + size
;
925 archs
[i
].library_size
= offset
;
927 else if(archs
[i
].type
== OFILE_Mach_O
){
928 strip_object(archs
+ i
, NULL
, archs
[i
].object
);
931 warning_arch(archs
+ i
, NULL
, "can't process non-object and "
932 "non-archive file: ");
936 if(all_archs
== FALSE
&& narch_flags
!= 0){
937 for(i
= 0; i
< narch_flags
; i
++){
938 if(arch_flag_processed
[i
] == FALSE
)
939 error("file: %s does not contain architecture: %s",
940 archs
[0].file_name
, arch_flags
[i
].name
);
942 free(arch_flag_processed
);
944 if(any_processing
== FALSE
)
945 fatal("no processing done on input file: %s (specify a -arch flag)",
953 struct member
*member
,
954 struct object
*object
)
956 enum byte_sex host_byte_sex
;
958 struct dylib_table_of_contents
*tocs
;
960 struct dylib_module
*mods
;
961 struct dylib_module_64
*mods64
;
963 struct dylib_reference
*refs
;
964 uint32_t nextrefsyms
;
966 struct load_command
*lc
;
967 struct segment_command
*sg
;
968 struct segment_command_64
*sg64
;
970 struct section_64
*s64
;
971 struct relocation_info
*relocs
;
972 struct scattered_relocation_info
*sreloc
;
973 int32_t missing_reloc_symbols
;
974 uint32_t stride
, section_type
, nitems
;
976 uint32_t dyld_info_start
;
977 uint32_t dyld_info_end
;
984 host_byte_sex
= get_host_byte_sex();
986 /* Don't do anything to stub dylibs which have no load commands. */
987 if(object
->mh_filetype
== MH_DYLIB_STUB
){
988 if((object
->mh
!= NULL
&& object
->mh
->ncmds
== 0) ||
989 (object
->mh64
!= NULL
&& object
->mh64
->ncmds
== 0)){
993 if(object
->mh_filetype
== MH_DSYM
)
994 fatal_arch(arch
, member
, "can't process dSYM companion file: ");
995 if(object
->st
== NULL
|| object
->st
->nsyms
== 0){
996 warning_arch(arch
, member
, "input object file stripped: ");
1000 nsyms
= object
->st
->nsyms
;
1001 if(object
->mh
!= NULL
){
1002 symbols
= (struct nlist
*)
1003 (object
->object_addr
+ object
->st
->symoff
);
1004 if(object
->object_byte_sex
!= host_byte_sex
)
1005 swap_nlist(symbols
, nsyms
, host_byte_sex
);
1010 symbols64
= (struct nlist_64
*)
1011 (object
->object_addr
+ object
->st
->symoff
);
1012 if(object
->object_byte_sex
!= host_byte_sex
)
1013 swap_nlist_64(symbols64
, nsyms
, host_byte_sex
);
1015 strings
= object
->object_addr
+ object
->st
->stroff
;
1016 strsize
= object
->st
->strsize
;
1019 if(object
->mh
!= NULL
)
1020 flags
= object
->mh
->flags
;
1022 flags
= object
->mh64
->flags
;
1023 if(object
->mh_filetype
== MH_DYLIB
&&
1024 (flags
& MH_PREBOUND
) != MH_PREBOUND
){
1025 arch
->dont_update_LC_ID_DYLIB_timestamp
= TRUE
;
1027 if(object
->mh_filetype
!= MH_DYLIB
&& cflag
)
1028 fatal_arch(arch
, member
, "-c can't be used on non-dynamic "
1030 #endif /* !(NMEDIT) */
1031 if(object
->mh_filetype
== MH_DYLIB_STUB
)
1032 fatal_arch(arch
, member
, "dynamic stub library can't be changed "
1035 if(object
->mh_filetype
== MH_DYLIB
){
1036 tocs
= (struct dylib_table_of_contents
*)
1037 (object
->object_addr
+ object
->dyst
->tocoff
);
1038 ntoc
= object
->dyst
->ntoc
;
1039 nmodtab
= object
->dyst
->nmodtab
;
1040 if(object
->mh
!= NULL
){
1041 mods
= (struct dylib_module
*)
1042 (object
->object_addr
+ object
->dyst
->modtaboff
);
1043 if(object
->object_byte_sex
!= host_byte_sex
)
1044 swap_dylib_module(mods
, nmodtab
, host_byte_sex
);
1049 mods64
= (struct dylib_module_64
*)
1050 (object
->object_addr
+ object
->dyst
->modtaboff
);
1051 if(object
->object_byte_sex
!= host_byte_sex
)
1052 swap_dylib_module_64(mods64
, nmodtab
, host_byte_sex
);
1054 refs
= (struct dylib_reference
*)
1055 (object
->object_addr
+ object
->dyst
->extrefsymoff
);
1056 nextrefsyms
= object
->dyst
->nextrefsyms
;
1057 if(object
->object_byte_sex
!= host_byte_sex
){
1058 swap_dylib_table_of_contents(tocs
, ntoc
, host_byte_sex
);
1059 swap_dylib_reference(refs
, nextrefsyms
, host_byte_sex
);
1063 * In the -c flag is specified then strip the section contents of
1064 * this dynamic library and change it into a stub library. When
1065 * creating a stub library the timestamp is not changed.
1068 arch
->dont_update_LC_ID_DYLIB_timestamp
= TRUE
;
1070 lc
= object
->load_commands
;
1071 if(object
->mh
!= NULL
){
1072 ncmds
= object
->mh
->ncmds
;
1073 object
->mh_filetype
= MH_DYLIB_STUB
;
1074 object
->mh
->filetype
= MH_DYLIB_STUB
;
1077 ncmds
= object
->mh64
->ncmds
;
1078 object
->mh_filetype
= MH_DYLIB_STUB
;
1079 object
->mh64
->filetype
= MH_DYLIB_STUB
;
1081 for(i
= 0; i
< ncmds
; i
++){
1082 if(lc
->cmd
== LC_SEGMENT
){
1083 sg
= (struct segment_command
*)lc
;
1084 if(strcmp(sg
->segname
, SEG_LINKEDIT
) != 0){
1086 * Zero out the section offset, reloff, and size
1087 * fields as the section contents are being removed.
1089 s
= (struct section
*)
1090 ((char *)sg
+ sizeof(struct segment_command
));
1091 for(j
= 0; j
< sg
->nsects
; j
++){
1093 * For section types with indirect tables we
1094 * do not zero out the section size in a stub
1095 * library. As the section size is needed to
1096 * know now many indirect table entries the
1097 * section has. This is a bit odd but programs
1098 * dealing with MH_DYLIB_STUB filetypes special
1101 section_type
= s
[j
].flags
& SECTION_TYPE
;
1102 if(section_type
!= S_SYMBOL_STUBS
&&
1103 section_type
!= S_LAZY_SYMBOL_POINTERS
&&
1104 section_type
!= S_LAZY_DYLIB_SYMBOL_POINTERS
&&
1105 section_type
!= S_NON_LAZY_SYMBOL_POINTERS
){
1112 /* zero out file offset and size in the segment */
1117 else if(lc
->cmd
== LC_SEGMENT_64
){
1118 sg64
= (struct segment_command_64
*)lc
;
1119 if(strcmp(sg64
->segname
, SEG_LINKEDIT
) != 0){
1121 * Zero out the section offset, reloff, and size
1122 * fields as the section contents are being removed.
1124 s64
= (struct section_64
*)
1126 sizeof(struct segment_command_64
));
1127 for(j
= 0; j
< sg64
->nsects
; j
++){
1129 * For section types with indirect tables we
1130 * do not zero out the section size in a stub
1131 * library. As the section size is needed to
1132 * know now many indirect table entries the
1133 * section has. This is a bit odd but programs
1134 * dealing with MH_DYLIB_STUB filetypes special
1137 section_type
= s64
[j
].flags
& SECTION_TYPE
;
1138 if(section_type
!= S_SYMBOL_STUBS
&&
1139 section_type
!= S_LAZY_SYMBOL_POINTERS
&&
1140 section_type
!= S_LAZY_DYLIB_SYMBOL_POINTERS
&&
1141 section_type
!= S_NON_LAZY_SYMBOL_POINTERS
){
1148 /* zero out file offset and size in the segment */
1153 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1156 * To get the right amount of the file copied out by writeout()
1157 * for the case when we are stripping out the section contents
1158 * we reduce the object size by the size of the section contents
1159 * including the padding after the load commands. Then this
1160 * size minus the size of the input symbolic information is
1163 if(object
->mh
!= NULL
){
1164 object
->object_size
-= (object
->seg_linkedit
->fileoff
-
1165 (sizeof(struct mach_header
) +
1166 object
->mh
->sizeofcmds
));
1168 * Set the file offset to the link edit information to be
1169 * right after the load commands.
1171 object
->seg_linkedit
->fileoff
=
1172 sizeof(struct mach_header
) +
1173 object
->mh
->sizeofcmds
;
1176 object
->object_size
-= (object
->seg_linkedit64
->fileoff
-
1177 (sizeof(struct mach_header_64
) +
1178 object
->mh64
->sizeofcmds
));
1180 * Set the file offset to the link edit information to be
1181 * right after the load commands.
1183 object
->seg_linkedit64
->fileoff
=
1184 sizeof(struct mach_header_64
) +
1185 object
->mh64
->sizeofcmds
;
1188 #endif /* !(NMEDIT) */
1201 * coalesced symbols can be stripped only if they are not used via an
1202 * symbol pointer. So to know that strip_symtab() needs to be passed
1203 * the indirect symbol table.
1205 if(object
->dyst
!= NULL
&& object
->dyst
->nindirectsyms
!= 0){
1206 nindirectsyms
= object
->dyst
->nindirectsyms
;
1207 indirectsyms
= (uint32_t *)
1208 (object
->object_addr
+ object
->dyst
->indirectsymoff
);
1209 if(object
->object_byte_sex
!= host_byte_sex
)
1210 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
1214 indirectsyms
= NULL
;
1218 if(object
->mh
!= NULL
)
1219 object
->input_sym_info_size
=
1220 nsyms
* sizeof(struct nlist
) +
1223 object
->input_sym_info_size
=
1224 nsyms
* sizeof(struct nlist_64
) +
1227 if(object
->mh
!= NULL
)
1228 flags
= object
->mh
->flags
;
1230 flags
= object
->mh64
->flags
;
1232 (flags
& MH_DYLDLINK
) == MH_DYLDLINK
&&
1233 object
->mh_filetype
== MH_EXECUTE
)
1234 default_dyld_executable
= TRUE
;
1236 default_dyld_executable
= FALSE
;
1237 #endif /* !defined(NMEDIT) */
1240 if(sfile
!= NULL
|| Rfile
!= NULL
|| dfile
!= NULL
|| Aflag
|| aflag
||
1241 uflag
|| Sflag
|| xflag
|| Xflag
|| tflag
|| nflag
|| rflag
||
1242 default_dyld_executable
|| object
->mh_filetype
== MH_DYLIB
||
1243 object
->mh_filetype
== MH_DYLINKER
)
1244 #endif /* !defined(NMEDIT) */
1247 if(edit_symtab(arch
, member
, object
, symbols
, symbols64
, nsyms
,
1248 strings
, strsize
, tocs
, ntoc
, mods
, mods64
, nmodtab
, refs
,
1249 nextrefsyms
) == FALSE
)
1251 #else /* !defined(NMEDIT) */
1252 if(strip_symtab(arch
, member
, object
, tocs
, ntoc
, mods
, mods64
,
1253 nmodtab
, refs
, nextrefsyms
) == FALSE
)
1256 strip_LC_UUID_commands(arch
, member
, object
);
1257 #endif /* !defined(NMEDIT) */
1258 if(object
->mh
!= NULL
)
1259 object
->output_sym_info_size
=
1260 new_nsyms
* sizeof(struct nlist
) +
1263 object
->output_sym_info_size
=
1264 new_nsyms
* sizeof(struct nlist_64
) +
1267 object
->st
->nsyms
= new_nsyms
;
1268 object
->st
->strsize
= new_strsize
;
1270 if(object
->mh
!= NULL
)
1271 object
->output_symbols
= new_symbols
;
1273 object
->output_symbols64
= new_symbols64
;
1274 object
->output_nsymbols
= new_nsyms
;
1275 object
->output_strings
= new_strings
;
1276 object
->output_strings_size
= new_strsize
;
1278 if(object
->dyld_info
!= NULL
){
1279 /* there are five parts to the dyld info, but
1280 strip does not alter them, so copy as a block */
1281 dyld_info_start
= 0;
1282 if (object
->dyld_info
->rebase_off
!= 0)
1283 dyld_info_start
= object
->dyld_info
->rebase_off
;
1284 else if (object
->dyld_info
->bind_off
!= 0)
1285 dyld_info_start
= object
->dyld_info
->bind_off
;
1286 else if (object
->dyld_info
->weak_bind_off
!= 0)
1287 dyld_info_start
= object
->dyld_info
->weak_bind_off
;
1288 else if (object
->dyld_info
->lazy_bind_off
!= 0)
1289 dyld_info_start
= object
->dyld_info
->lazy_bind_off
;
1290 else if (object
->dyld_info
->export_off
!= 0)
1291 dyld_info_start
= object
->dyld_info
->export_off
;
1293 if (object
->dyld_info
->export_size
!= 0)
1294 dyld_info_end
= object
->dyld_info
->export_off
1295 + object
->dyld_info
->export_size
;
1296 else if (object
->dyld_info
->lazy_bind_size
!= 0)
1297 dyld_info_end
= object
->dyld_info
->lazy_bind_off
1298 + object
->dyld_info
->lazy_bind_size
;
1299 else if (object
->dyld_info
->weak_bind_size
!= 0)
1300 dyld_info_end
= object
->dyld_info
->weak_bind_off
1301 + object
->dyld_info
->weak_bind_size
;
1302 else if (object
->dyld_info
->bind_size
!= 0)
1303 dyld_info_end
= object
->dyld_info
->bind_off
1304 + object
->dyld_info
->bind_size
;
1305 else if (object
->dyld_info
->rebase_size
!= 0)
1306 dyld_info_end
= object
->dyld_info
->rebase_off
1307 + object
->dyld_info
->rebase_size
;
1308 object
->output_dyld_info
= object
->object_addr
+dyld_info_start
;
1309 object
->output_dyld_info_size
= dyld_info_end
- dyld_info_start
;
1310 object
->output_sym_info_size
+= object
->output_dyld_info_size
;
1312 * Warn about strip -s or -R on a final linked image with
1315 if(nsave_symbols
!= 0){
1316 warning_arch(arch
, NULL
, "removing global symbols from a "
1317 "final linked no longer supported. Use "
1318 "-exported_symbols_list at link time when "
1322 if(object
->split_info_cmd
!= NULL
){
1323 object
->output_split_info_data
= object
->object_addr
+
1324 object
->split_info_cmd
->dataoff
;
1325 object
->output_split_info_data_size
=
1326 object
->split_info_cmd
->datasize
;
1328 if(object
->func_starts_info_cmd
!= NULL
){
1329 object
->output_func_start_info_data
= object
->object_addr
+
1330 object
->func_starts_info_cmd
->dataoff
;
1331 object
->output_func_start_info_data_size
=
1332 object
->func_starts_info_cmd
->datasize
;
1334 if(object
->code_sig_cmd
!= NULL
){
1336 if(!cflag
&& !no_code_signature
)
1337 #endif /* !(NMEDIT) */
1339 object
->output_code_sig_data
= object
->object_addr
+
1340 object
->code_sig_cmd
->dataoff
;
1341 object
->output_code_sig_data_size
=
1342 object
->code_sig_cmd
->datasize
;
1346 if(object
->dyst
!= NULL
){
1347 object
->dyst
->ilocalsym
= 0;
1348 object
->dyst
->nlocalsym
= new_nlocalsym
;
1349 object
->dyst
->iextdefsym
= new_nlocalsym
;
1350 object
->dyst
->nextdefsym
= new_nextdefsym
;
1351 object
->dyst
->iundefsym
= new_nlocalsym
+ new_nextdefsym
;
1352 object
->dyst
->nundefsym
= new_nundefsym
;
1353 if(object
->dyst
->nindirectsyms
!= 0){
1354 object
->output_indirect_symtab
= indirectsyms
;
1355 if(object
->object_byte_sex
!= host_byte_sex
)
1356 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
1357 object
->object_byte_sex
);
1361 * If the -c option is specified the object's filetype will
1362 * have been changed from MH_DYLIB to MH_DYLIB_STUB above.
1364 if(object
->mh_filetype
== MH_DYLIB
||
1365 object
->mh_filetype
== MH_DYLIB_STUB
){
1366 object
->output_tocs
= new_tocs
;
1367 object
->output_ntoc
= new_ntoc
;
1369 if(object
->mh
!= NULL
)
1370 object
->output_mods
= new_mods
;
1372 object
->output_mods64
= new_mods64
;
1373 object
->output_nmodtab
= new_nmodtab
;
1375 object
->output_mods
= mods
;
1376 object
->output_nmodtab
= nmodtab
;
1378 object
->output_refs
= new_refs
;
1379 object
->output_nextrefsyms
= new_nextrefsyms
;
1380 if(object
->object_byte_sex
!= host_byte_sex
){
1381 swap_dylib_table_of_contents(new_tocs
, new_ntoc
,
1382 object
->object_byte_sex
);
1384 if(object
->mh
!= NULL
)
1385 swap_dylib_module(new_mods
, new_nmodtab
,
1386 object
->object_byte_sex
);
1388 swap_dylib_module_64(new_mods64
, new_nmodtab
,
1389 object
->object_byte_sex
);
1391 if(object
->mh
!= NULL
)
1392 swap_dylib_module(mods
, nmodtab
,
1393 object
->object_byte_sex
);
1395 swap_dylib_module_64(mods64
, nmodtab
,
1396 object
->object_byte_sex
);
1398 swap_dylib_reference(new_refs
, new_nextrefsyms
,
1399 object
->object_byte_sex
);
1402 if(object
->dyld_info
!= NULL
){
1403 object
->input_sym_info_size
+= object
->dyld_info
->rebase_size
1404 + object
->dyld_info
->bind_size
1405 + object
->dyld_info
->weak_bind_size
1406 + object
->dyld_info
->lazy_bind_size
1407 + object
->dyld_info
->export_size
;
1409 object
->input_sym_info_size
+=
1410 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1411 object
->dyst
->nextrel
* sizeof(struct relocation_info
) +
1412 object
->dyst
->ntoc
* sizeof(struct dylib_table_of_contents
)+
1413 object
->dyst
->nextrefsyms
* sizeof(struct dylib_reference
);
1414 if(object
->mh
!= NULL
){
1415 object
->input_sym_info_size
+=
1416 object
->dyst
->nmodtab
* sizeof(struct dylib_module
) +
1417 object
->dyst
->nindirectsyms
* sizeof(uint32_t);
1420 object
->input_sym_info_size
+=
1421 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
) +
1422 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1423 object
->input_indirectsym_pad
;
1427 * When stripping out the section contents to create a
1428 * dynamic library stub the relocation info also gets
1432 #endif /* !(NMEDIT) */
1434 object
->output_sym_info_size
+=
1435 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1436 object
->dyst
->nextrel
* sizeof(struct relocation_info
);
1438 object
->output_sym_info_size
+=
1439 new_ntoc
* sizeof(struct dylib_table_of_contents
)+
1440 new_nextrefsyms
* sizeof(struct dylib_reference
) +
1441 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1442 object
->input_indirectsym_pad
;
1443 if(object
->mh
!= NULL
){
1444 object
->output_sym_info_size
+=
1445 object
->dyst
->nmodtab
* sizeof(struct dylib_module
);
1448 object
->output_sym_info_size
+=
1449 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
);
1451 if(object
->hints_cmd
!= NULL
){
1452 object
->input_sym_info_size
+=
1453 object
->hints_cmd
->nhints
*
1454 sizeof(struct twolevel_hint
);
1455 object
->output_sym_info_size
+=
1456 object
->hints_cmd
->nhints
*
1457 sizeof(struct twolevel_hint
);
1459 if(object
->split_info_cmd
!= NULL
){
1460 object
->input_sym_info_size
+=
1461 object
->split_info_cmd
->datasize
;
1462 object
->output_sym_info_size
+=
1463 object
->split_info_cmd
->datasize
;
1465 if(object
->func_starts_info_cmd
!= NULL
){
1466 object
->input_sym_info_size
+=
1467 object
->func_starts_info_cmd
->datasize
;
1468 object
->output_sym_info_size
+=
1469 object
->func_starts_info_cmd
->datasize
;
1471 if(object
->code_sig_cmd
!= NULL
){
1472 object
->input_sym_info_size
=
1473 rnd(object
->input_sym_info_size
, 16);
1474 object
->input_sym_info_size
+=
1475 object
->code_sig_cmd
->datasize
;
1477 if(cflag
|| no_code_signature
){
1478 strip_LC_CODE_SIGNATURE_commands(arch
, member
, object
);
1481 #endif /* !(NMEDIT) */
1483 object
->output_sym_info_size
=
1484 rnd(object
->output_sym_info_size
, 16);
1485 object
->output_sym_info_size
+=
1486 object
->code_sig_cmd
->datasize
;
1490 object
->dyst
->ntoc
= new_ntoc
;
1491 object
->dyst
->nextrefsyms
= new_nextrefsyms
;
1493 offset
= get_starting_syminfo_offset(object
);
1495 if(object
->dyld_info
!= 0){
1496 if (object
->dyld_info
->rebase_off
!= 0){
1497 object
->dyld_info
->rebase_off
= offset
;
1498 offset
+= object
->dyld_info
->rebase_size
;
1500 if (object
->dyld_info
->bind_off
!= 0){
1501 object
->dyld_info
->bind_off
= offset
;
1502 offset
+= object
->dyld_info
->bind_size
;
1504 if (object
->dyld_info
->weak_bind_off
!= 0){
1505 object
->dyld_info
->weak_bind_off
= offset
;
1506 offset
+= object
->dyld_info
->weak_bind_size
;
1508 if (object
->dyld_info
->lazy_bind_off
!= 0){
1509 object
->dyld_info
->lazy_bind_off
= offset
;
1510 offset
+= object
->dyld_info
->lazy_bind_size
;
1512 if (object
->dyld_info
->export_off
!= 0){
1513 object
->dyld_info
->export_off
= offset
;
1514 offset
+= object
->dyld_info
->export_size
;
1518 if(object
->dyst
->nlocrel
!= 0){
1519 object
->output_loc_relocs
= (struct relocation_info
*)
1520 (object
->object_addr
+ object
->dyst
->locreloff
);
1523 * When stripping out the section contents to create a
1524 * dynamic library stub the relocation info also gets
1528 object
->dyst
->nlocrel
= 0;
1529 object
->dyst
->locreloff
= 0;
1532 #endif /* defined(NMEDIT) */
1534 object
->dyst
->locreloff
= offset
;
1535 offset
+= object
->dyst
->nlocrel
*
1536 sizeof(struct relocation_info
);
1540 object
->dyst
->locreloff
= 0;
1542 if(object
->split_info_cmd
!= NULL
){
1543 object
->split_info_cmd
->dataoff
= offset
;
1544 offset
+= object
->split_info_cmd
->datasize
;
1547 if(object
->func_starts_info_cmd
!= NULL
){
1548 object
->func_starts_info_cmd
->dataoff
= offset
;
1549 offset
+= object
->func_starts_info_cmd
->datasize
;
1552 if(object
->st
->nsyms
!= 0){
1553 object
->st
->symoff
= offset
;
1554 if(object
->mh
!= NULL
)
1555 offset
+= object
->st
->nsyms
* sizeof(struct nlist
);
1557 offset
+= object
->st
->nsyms
* sizeof(struct nlist_64
);
1560 object
->st
->symoff
= 0;
1562 if(object
->hints_cmd
!= NULL
){
1563 if(object
->hints_cmd
->nhints
!= 0){
1564 object
->output_hints
= (struct twolevel_hint
*)
1565 (object
->object_addr
+ object
->hints_cmd
->offset
);
1566 object
->hints_cmd
->offset
= offset
;
1567 offset
+= object
->hints_cmd
->nhints
*
1568 sizeof(struct twolevel_hint
);
1571 object
->hints_cmd
->offset
= 0;
1574 if(object
->dyst
->nextrel
!= 0){
1575 object
->output_ext_relocs
= (struct relocation_info
*)
1576 (object
->object_addr
+ object
->dyst
->extreloff
);
1579 * When stripping out the section contents to create a
1580 * dynamic library stub the relocation info also gets
1584 object
->dyst
->nextrel
= 0;
1585 object
->dyst
->extreloff
= 0;
1588 #endif /* defined(NMEDIT) */
1590 object
->dyst
->extreloff
= offset
;
1591 offset
+= object
->dyst
->nextrel
*
1592 sizeof(struct relocation_info
);
1596 object
->dyst
->extreloff
= 0;
1598 if(object
->dyst
->nindirectsyms
!= 0){
1599 object
->dyst
->indirectsymoff
= offset
;
1600 offset
+= object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1601 object
->input_indirectsym_pad
;
1604 object
->dyst
->indirectsymoff
= 0;;
1606 if(object
->dyst
->ntoc
!= 0){
1607 object
->dyst
->tocoff
= offset
;
1608 offset
+= object
->dyst
->ntoc
*
1609 sizeof(struct dylib_table_of_contents
);
1612 object
->dyst
->tocoff
= 0;
1614 if(object
->dyst
->nmodtab
!= 0){
1617 * When stripping out the section contents to create a
1618 * dynamic library stub zero out the fields in the module
1619 * table for the sections and relocation information and
1620 * clear Objective-C address and size from modules.
1623 if(object
->mh
!= NULL
){
1624 for(k
= 0; k
< object
->dyst
->nmodtab
; k
++){
1625 mods
[k
].iinit_iterm
= 0;
1626 mods
[k
].ninit_nterm
= 0;
1627 mods
[k
].iextrel
= 0;
1628 mods
[k
].nextrel
= 0;
1629 mods
[k
].objc_module_info_addr
= 0;
1630 mods
[k
].objc_module_info_size
= 0;
1634 for(k
= 0; k
< object
->dyst
->nmodtab
; k
++){
1635 mods64
[k
].iinit_iterm
= 0;
1636 mods64
[k
].ninit_nterm
= 0;
1637 mods64
[k
].iextrel
= 0;
1638 mods64
[k
].nextrel
= 0;
1639 mods64
[k
].objc_module_info_addr
= 0;
1640 mods64
[k
].objc_module_info_size
= 0;
1644 #endif /* !(NMEDIT) */
1645 object
->dyst
->modtaboff
= offset
;
1646 if(object
->mh
!= NULL
)
1647 offset
+= object
->dyst
->nmodtab
*
1648 sizeof(struct dylib_module
);
1650 offset
+= object
->dyst
->nmodtab
*
1651 sizeof(struct dylib_module_64
);
1654 object
->dyst
->modtaboff
= 0;
1656 if(object
->dyst
->nextrefsyms
!= 0){
1657 object
->dyst
->extrefsymoff
= offset
;
1658 offset
+= object
->dyst
->nextrefsyms
*
1659 sizeof(struct dylib_reference
);
1662 object
->dyst
->extrefsymoff
= 0;
1664 if(object
->st
->strsize
!= 0){
1665 object
->st
->stroff
= offset
;
1666 offset
+= object
->st
->strsize
;
1669 object
->st
->stroff
= 0;
1671 if(object
->code_sig_cmd
!= NULL
){
1672 offset
= rnd(offset
, 16);
1673 object
->code_sig_cmd
->dataoff
= offset
;
1674 offset
+= object
->code_sig_cmd
->datasize
;
1678 if(new_strsize
!= 0){
1679 if(object
->mh
!= NULL
)
1680 object
->st
->stroff
= object
->st
->symoff
+
1681 new_nsyms
* sizeof(struct nlist
);
1683 object
->st
->stroff
= object
->st
->symoff
+
1684 new_nsyms
* sizeof(struct nlist_64
);
1687 object
->st
->stroff
= 0;
1689 object
->st
->symoff
= 0;
1695 * Here we are doing a full symbol strip. In some cases it may
1696 * leave the local relocation entries as well as LOCAL indirect
1697 * symbol table entries.
1701 saves
= (int32_t *)allocate(object
->st
->nsyms
* sizeof(int32_t));
1702 bzero(saves
, object
->st
->nsyms
* sizeof(int32_t));
1705 * Account for the symbolic info in the input file.
1707 if(object
->dyst
!= NULL
){
1708 object
->input_sym_info_size
+=
1709 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1710 object
->dyst
->nextrel
* sizeof(struct relocation_info
) +
1711 object
->dyst
->ntoc
* sizeof(struct dylib_table_of_contents
)+
1712 object
->dyst
->nextrefsyms
* sizeof(struct dylib_reference
);
1713 if(object
->mh
!= NULL
){
1714 object
->input_sym_info_size
+=
1715 object
->dyst
->nmodtab
* sizeof(struct dylib_module
) +
1716 object
->dyst
->nindirectsyms
* sizeof(uint32_t);
1719 object
->input_sym_info_size
+=
1720 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
) +
1721 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1722 object
->input_indirectsym_pad
;
1727 * Determine the offset where the remaining symbolic info will start
1728 * in the output file (if any).
1730 offset
= get_starting_syminfo_offset(object
);
1733 * For a full symbol strip all these values in the output file are
1736 object
->st
->symoff
= 0;
1737 object
->st
->nsyms
= 0;
1738 object
->st
->stroff
= 0;
1739 object
->st
->strsize
= 0;
1740 if(object
->dyst
!= NULL
){
1741 object
->dyst
->ilocalsym
= 0;
1742 object
->dyst
->nlocalsym
= 0;
1743 object
->dyst
->iextdefsym
= 0;
1744 object
->dyst
->nextdefsym
= 0;
1745 object
->dyst
->iundefsym
= 0;
1746 object
->dyst
->nundefsym
= 0;
1750 * This will accumulate any remaining symbolic info size in the
1753 object
->output_sym_info_size
= 0;
1756 * We set these so that checking can be done below to report the
1757 * symbols that can't be stripped because of relocation entries
1758 * or indirect symbol table entries. Normally if these table have a
1759 * non-zero number of entries it will be an error as we are trying
1760 * to strip everything. But it maybe that there are only LOCAL
1761 * indirect entries which is odd but will be OK.
1763 if(object
->dyst
!= NULL
){
1764 if(object
->dyst
->nextrel
!= 0){
1765 object
->output_ext_relocs
= (struct relocation_info
*)
1766 (object
->object_addr
+ object
->dyst
->extreloff
);
1769 * Since this file has a dynamic symbol table and if this file
1770 * has local relocation entries on input make sure they are
1771 * there on output. This is a rare case that it will not have
1772 * external relocs or indirect symbols but can happen as is the
1773 * case with the dynamic linker itself.
1775 if(object
->dyst
->nlocrel
!= 0){
1776 object
->output_loc_relocs
= (struct relocation_info
*)
1777 (object
->object_addr
+ object
->dyst
->locreloff
);
1778 object
->output_sym_info_size
+=
1779 object
->dyst
->nlocrel
* sizeof(struct relocation_info
);
1781 object
->dyst
->locreloff
= offset
;
1782 offset
+= object
->dyst
->nlocrel
*
1783 sizeof(struct relocation_info
);
1786 if(object
->dyst
->nindirectsyms
!= 0){
1787 object
->output_indirect_symtab
= (uint32_t *)
1788 (object
->object_addr
+
1789 object
->dyst
->indirectsymoff
);
1790 if(object
->object_byte_sex
!= host_byte_sex
)
1791 swap_indirect_symbols(
1792 object
->output_indirect_symtab
,
1793 object
->dyst
->nindirectsyms
,
1794 object
->object_byte_sex
);
1796 object
->output_sym_info_size
+=
1797 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1798 object
->input_indirectsym_pad
;
1800 object
->dyst
->indirectsymoff
= offset
;
1801 offset
+= object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1802 object
->input_indirectsym_pad
;
1806 #endif /* !defined(NMEDIT) */
1809 * Always clear the prebind checksum if any when creating a new file.
1811 if(object
->cs
!= NULL
)
1812 object
->cs
->cksum
= 0;
1814 if(object
->seg_linkedit
!= NULL
){
1815 object
->seg_linkedit
->filesize
+= object
->output_sym_info_size
-
1816 object
->input_sym_info_size
;
1817 object
->seg_linkedit
->vmsize
= object
->seg_linkedit
->filesize
;
1819 else if(object
->seg_linkedit64
!= NULL
){
1820 /* Do this in two steps to avoid 32/64-bit casting problems. */
1821 object
->seg_linkedit64
->filesize
-= object
->input_sym_info_size
;
1822 object
->seg_linkedit64
->filesize
+= object
->output_sym_info_size
;
1823 object
->seg_linkedit64
->vmsize
= object
->seg_linkedit64
->filesize
;
1827 * Check and update the external relocation entries to make sure
1828 * referenced symbols are not stripped and refer to the new symbol
1831 * The external relocation entries can be located in one of two places,
1832 * first off of the sections or second off of the dynamic symtab.
1834 missing_reloc_symbols
= 0;
1835 lc
= object
->load_commands
;
1836 if(object
->mh
!= NULL
)
1837 ncmds
= object
->mh
->ncmds
;
1839 ncmds
= object
->mh64
->ncmds
;
1840 for(i
= 0; i
< ncmds
; i
++){
1841 if(lc
->cmd
== LC_SEGMENT
&&
1842 object
->seg_linkedit
!= (struct segment_command
*)lc
){
1843 sg
= (struct segment_command
*)lc
;
1844 s
= (struct section
*)((char *)sg
+
1845 sizeof(struct segment_command
));
1846 for(j
= 0; j
< sg
->nsects
; j
++){
1848 if(s
->reloff
+ s
->nreloc
*
1849 sizeof(struct relocation_info
) >
1850 object
->object_size
){
1851 fatal_arch(arch
, member
, "truncated or malformed "
1852 "object (relocation entries for section (%.16s,"
1853 "%.16s) extends past the end of the file)",
1854 s
->segname
, s
->sectname
);
1856 relocs
= (struct relocation_info
*)
1857 (object
->object_addr
+ s
->reloff
);
1858 if(object
->object_byte_sex
!= host_byte_sex
)
1859 swap_relocation_info(relocs
, s
->nreloc
,
1861 if(s
->offset
+ s
->size
> object
->object_size
){
1862 fatal_arch(arch
, member
, "truncated or malformed "
1863 "object (contents of section (%.16s,"
1864 "%.16s) extends past the end of the file)",
1865 s
->segname
, s
->sectname
);
1867 contents
= object
->object_addr
+ s
->offset
;
1868 check_object_relocs(arch
, member
, object
, s
->segname
,
1869 s
->sectname
, s
->size
, contents
, relocs
, s
->nreloc
,
1870 symbols
, symbols64
, nsyms
, strings
,
1871 &missing_reloc_symbols
, host_byte_sex
);
1872 if(object
->object_byte_sex
!= host_byte_sex
)
1873 swap_relocation_info(relocs
, s
->nreloc
,
1874 object
->object_byte_sex
);
1879 else if(lc
->cmd
== LC_SEGMENT_64
&&
1880 object
->seg_linkedit64
!= (struct segment_command_64
*)lc
){
1881 sg64
= (struct segment_command_64
*)lc
;
1882 s64
= (struct section_64
*)((char *)sg64
+
1883 sizeof(struct segment_command_64
));
1884 for(j
= 0; j
< sg64
->nsects
; j
++){
1885 if(s64
->nreloc
!= 0){
1886 if(s64
->reloff
+ s64
->nreloc
*
1887 sizeof(struct relocation_info
) >
1888 object
->object_size
){
1889 fatal_arch(arch
, member
, "truncated or malformed "
1890 "object (relocation entries for section (%.16s,"
1891 "%.16s) extends past the end of the file)",
1892 s64
->segname
, s64
->sectname
);
1894 relocs
= (struct relocation_info
*)
1895 (object
->object_addr
+ s64
->reloff
);
1896 if(object
->object_byte_sex
!= host_byte_sex
)
1897 swap_relocation_info(relocs
, s64
->nreloc
,
1899 if(s64
->offset
+ s64
->size
> object
->object_size
){
1900 fatal_arch(arch
, member
, "truncated or malformed "
1901 "object (contents of section (%.16s,"
1902 "%.16s) extends past the end of the file)",
1903 s64
->segname
, s64
->sectname
);
1905 contents
= object
->object_addr
+ s64
->offset
;
1906 check_object_relocs(arch
, member
, object
, s64
->segname
,
1907 s64
->sectname
, s64
->size
, contents
, relocs
,
1908 s64
->nreloc
, symbols
, symbols64
, nsyms
, strings
,
1909 &missing_reloc_symbols
, host_byte_sex
);
1910 if(object
->object_byte_sex
!= host_byte_sex
)
1911 swap_relocation_info(relocs
, s64
->nreloc
,
1912 object
->object_byte_sex
);
1917 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1919 if(object
->dyst
!= NULL
&& object
->dyst
->nextrel
!= 0){
1920 relocs
= object
->output_ext_relocs
;
1921 if(object
->object_byte_sex
!= host_byte_sex
)
1922 swap_relocation_info(relocs
, object
->dyst
->nextrel
,
1925 for(i
= 0; i
< object
->dyst
->nextrel
; i
++){
1926 if((relocs
[i
].r_address
& R_SCATTERED
) == 0 &&
1927 relocs
[i
].r_extern
== 1){
1928 if(relocs
[i
].r_symbolnum
> nsyms
){
1929 fatal_arch(arch
, member
, "bad r_symbolnum for external "
1930 "relocation entry %d in: ", i
);
1932 if(saves
[relocs
[i
].r_symbolnum
] == 0){
1933 if(missing_reloc_symbols
== 0){
1934 error_arch(arch
, member
, "symbols referenced by "
1935 "relocation entries that can't be stripped in: ");
1936 missing_reloc_symbols
= 1;
1938 if(object
->mh
!= NULL
){
1939 fprintf(stderr
, "%s\n", strings
+ symbols
1940 [relocs
[i
].r_symbolnum
].n_un
.n_strx
);
1943 fprintf(stderr
, "%s\n", strings
+ symbols64
1944 [relocs
[i
].r_symbolnum
].n_un
.n_strx
);
1946 saves
[relocs
[i
].r_symbolnum
] = -1;
1948 if(saves
[relocs
[i
].r_symbolnum
] != -1){
1949 relocs
[i
].r_symbolnum
=
1950 saves
[relocs
[i
].r_symbolnum
] - 1;
1954 fatal_arch(arch
, member
, "bad external relocation entry "
1955 "%d (not external) in: ", i
);
1957 if((relocs
[i
].r_address
& R_SCATTERED
) == 0){
1958 if(reloc_has_pair(object
->mh_cputype
, relocs
[i
].r_type
))
1962 sreloc
= (struct scattered_relocation_info
*)relocs
+ i
;
1963 if(reloc_has_pair(object
->mh_cputype
, sreloc
->r_type
))
1967 if(object
->object_byte_sex
!= host_byte_sex
)
1968 swap_relocation_info(relocs
, object
->dyst
->nextrel
,
1969 object
->object_byte_sex
);
1973 * Check and update the indirect symbol table entries to make sure
1974 * referenced symbols are not stripped and refer to the new symbol
1977 if(object
->dyst
!= NULL
&& object
->dyst
->nindirectsyms
!= 0){
1978 if(object
->object_byte_sex
!= host_byte_sex
)
1979 swap_indirect_symbols(object
->output_indirect_symtab
,
1980 object
->dyst
->nindirectsyms
, host_byte_sex
);
1982 lc
= object
->load_commands
;
1983 if(object
->mh
!= NULL
)
1984 ncmds
= object
->mh
->ncmds
;
1986 ncmds
= object
->mh64
->ncmds
;
1987 for(i
= 0; i
< ncmds
; i
++){
1988 if(lc
->cmd
== LC_SEGMENT
&&
1989 object
->seg_linkedit
!= (struct segment_command
*)lc
){
1990 sg
= (struct segment_command
*)lc
;
1991 s
= (struct section
*)((char *)sg
+
1992 sizeof(struct segment_command
));
1993 for(j
= 0; j
< sg
->nsects
; j
++){
1994 section_type
= s
->flags
& SECTION_TYPE
;
1995 if(section_type
== S_LAZY_SYMBOL_POINTERS
||
1996 section_type
== S_LAZY_DYLIB_SYMBOL_POINTERS
||
1997 section_type
== S_NON_LAZY_SYMBOL_POINTERS
)
1999 else if(section_type
== S_SYMBOL_STUBS
)
2000 stride
= s
->reserved2
;
2005 nitems
= s
->size
/ stride
;
2006 contents
= object
->object_addr
+ s
->offset
;
2007 check_indirect_symtab(arch
, member
, object
, nitems
,
2008 s
->reserved1
, section_type
, contents
, symbols
,
2009 symbols64
, nsyms
, strings
, &missing_reloc_symbols
,
2014 else if(lc
->cmd
== LC_SEGMENT_64
&&
2015 object
->seg_linkedit64
!= (struct segment_command_64
*)lc
){
2016 sg64
= (struct segment_command_64
*)lc
;
2017 s64
= (struct section_64
*)((char *)sg64
+
2018 sizeof(struct segment_command_64
));
2019 for(j
= 0; j
< sg64
->nsects
; j
++){
2020 section_type
= s64
->flags
& SECTION_TYPE
;
2021 if(section_type
== S_LAZY_SYMBOL_POINTERS
||
2022 section_type
== S_LAZY_DYLIB_SYMBOL_POINTERS
||
2023 section_type
== S_NON_LAZY_SYMBOL_POINTERS
)
2025 else if(section_type
== S_SYMBOL_STUBS
)
2026 stride
= s64
->reserved2
;
2031 nitems
= s64
->size
/ stride
;
2032 contents
= object
->object_addr
+ s64
->offset
;
2033 check_indirect_symtab(arch
, member
, object
, nitems
,
2034 s64
->reserved1
, section_type
, contents
, symbols
,
2035 symbols64
, nsyms
, strings
, &missing_reloc_symbols
,
2040 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2043 if(object
->object_byte_sex
!= host_byte_sex
)
2044 swap_indirect_symbols(object
->output_indirect_symtab
,
2045 object
->dyst
->nindirectsyms
, object
->object_byte_sex
);
2049 * Issue a warning if object file has a code signature that the
2050 * operation will invalidate it.
2052 if(object
->code_sig_cmd
!= NULL
)
2053 warning_arch(arch
, member
, "changes being made to the file will "
2054 "invalidate the code signature in: ");
2058 * get_starting_syminfo_offset() returns the starting offset of the symbolic
2059 * info in the object file.
2063 get_starting_syminfo_offset(
2064 struct object
*object
)
2068 if(object
->seg_linkedit
!= NULL
||
2069 object
->seg_linkedit64
!= NULL
){
2070 if(object
->mh
!= NULL
)
2071 offset
= object
->seg_linkedit
->fileoff
;
2073 offset
= object
->seg_linkedit64
->fileoff
;
2077 if(object
->dyst
!= NULL
&&
2078 object
->dyst
->nlocrel
!= 0 &&
2079 object
->dyst
->locreloff
< offset
)
2080 offset
= object
->dyst
->locreloff
;
2081 if(object
->st
->nsyms
!= 0 &&
2082 object
->st
->symoff
< offset
)
2083 offset
= object
->st
->symoff
;
2084 if(object
->dyst
!= NULL
&&
2085 object
->dyst
->nextrel
!= 0 &&
2086 object
->dyst
->extreloff
< offset
)
2087 offset
= object
->dyst
->extreloff
;
2088 if(object
->dyst
!= NULL
&&
2089 object
->dyst
->nindirectsyms
!= 0 &&
2090 object
->dyst
->indirectsymoff
< offset
)
2091 offset
= object
->dyst
->indirectsymoff
;
2092 if(object
->dyst
!= NULL
&&
2093 object
->dyst
->ntoc
!= 0 &&
2094 object
->dyst
->tocoff
< offset
)
2095 offset
= object
->dyst
->tocoff
;
2096 if(object
->dyst
!= NULL
&&
2097 object
->dyst
->nmodtab
!= 0 &&
2098 object
->dyst
->modtaboff
< offset
)
2099 offset
= object
->dyst
->modtaboff
;
2100 if(object
->dyst
!= NULL
&&
2101 object
->dyst
->nextrefsyms
!= 0 &&
2102 object
->dyst
->extrefsymoff
< offset
)
2103 offset
= object
->dyst
->extrefsymoff
;
2104 if(object
->st
->strsize
!= 0 &&
2105 object
->st
->stroff
< offset
)
2106 offset
= object
->st
->stroff
;
2112 * check_object_relocs() is used to check and update the external relocation
2113 * entries from a section in an object file, to make sure referenced symbols
2114 * are not stripped and are changed to refer to the new symbol table indexes.
2118 check_object_relocs(
2120 struct member
*member
,
2121 struct object
*object
,
2126 struct relocation_info
*relocs
,
2128 struct nlist
*symbols
,
2129 struct nlist_64
*symbols64
,
2132 int32_t *missing_reloc_symbols
,
2133 enum byte_sex host_byte_sex
)
2138 uint32_t value
, n_ext
;
2141 struct scattered_relocation_info
*sreloc
;
2143 for(k
= 0; k
< nreloc
; k
++){
2144 if((relocs
[k
].r_address
& R_SCATTERED
) == 0 &&
2145 relocs
[k
].r_extern
== 1){
2146 if(relocs
[k
].r_symbolnum
> nsyms
){
2147 fatal_arch(arch
, member
, "bad r_symbolnum for relocation "
2148 "entry %d in section (%.16s,%.16s) in: ", k
, segname
,
2151 if(object
->mh
!= NULL
){
2152 n_strx
= symbols
[relocs
[k
].r_symbolnum
].n_un
.n_strx
;
2153 n_value
= symbols
[relocs
[k
].r_symbolnum
].n_value
;
2156 n_strx
= symbols64
[relocs
[k
].r_symbolnum
].n_un
.n_strx
;
2157 n_value
= symbols64
[relocs
[k
].r_symbolnum
].n_value
;
2160 if(saves
[relocs
[k
].r_symbolnum
] == 0){
2161 if(*missing_reloc_symbols
== 0){
2162 error_arch(arch
, member
, "symbols referenced by "
2163 "relocation entries that can't be stripped in: ");
2164 *missing_reloc_symbols
= 1;
2166 fprintf(stderr
, "%s\n", strings
+ n_strx
);
2167 saves
[relocs
[k
].r_symbolnum
] = -1;
2169 #else /* defined(NMEDIT) */
2171 * We are letting nmedit change global coalesed symbols into
2172 * statics in MH_OBJECT file types only. Relocation entries to
2173 * global coalesced symbols are external relocs.
2175 if(object
->mh
!= NULL
)
2176 n_ext
= new_symbols
[saves
[relocs
[k
].r_symbolnum
] - 1].
2179 n_ext
= new_symbols64
[saves
[relocs
[k
].r_symbolnum
] - 1].
2181 if(n_ext
!= N_EXT
&&
2182 object
->mh_cputype
!= CPU_TYPE_X86_64
){
2184 * We need to do the relocation for this external relocation
2185 * entry so the item to be relocated is correct for a local
2186 * relocation entry. We don't need to do this for x86-64.
2188 if(relocs
[k
].r_address
+ sizeof(int32_t) > sectsize
){
2189 fatal_arch(arch
, member
, "truncated or malformed "
2190 "object (r_address of relocation entry %u of "
2191 "section (%.16s,%.16s) extends past the end "
2192 "of the section)", k
, segname
, sectname
);
2194 if(object
->mh
!= NULL
){
2195 value
= *(uint32_t *)
2196 (contents
+ relocs
[k
].r_address
);
2197 if(object
->object_byte_sex
!= host_byte_sex
)
2198 value
= SWAP_INT(value
);
2200 * We handle a very limited form here. Only VANILLA
2201 * (r_type == 0) long (r_length==2) absolute or pcrel
2202 * that won't need a scattered relocation entry.
2204 if(relocs
[k
].r_type
!= 0 ||
2205 relocs
[k
].r_length
!= 2){
2206 fatal_arch(arch
, member
, "don't have "
2207 "code to convert external relocation "
2208 "entry %d in section (%.16s,%.16s) "
2209 "for global coalesced symbol: %s "
2210 "in: ", k
, segname
, sectname
,
2214 if(object
->object_byte_sex
!= host_byte_sex
)
2215 value
= SWAP_INT(value
);
2216 *(uint32_t *)(contents
+ relocs
[k
].r_address
) =
2220 value64
= *(uint64_t *)(contents
+ relocs
[k
].r_address
);
2221 if(object
->object_byte_sex
!= host_byte_sex
)
2222 value64
= SWAP_LONG_LONG(value64
);
2224 * We handle a very limited form here. Only VANILLA
2225 * (r_type == 0) quad (r_length==3) absolute or pcrel
2226 * that won't need a scattered relocation entry.
2228 if(relocs
[k
].r_type
!= 0 ||
2229 relocs
[k
].r_length
!= 3){
2230 fatal_arch(arch
, member
, "don't have "
2231 "code to convert external relocation "
2232 "entry %d in section (%.16s,%.16s) "
2233 "for global coalesced symbol: %s "
2234 "in: ", k
, segname
, sectname
,
2238 if(object
->object_byte_sex
!= host_byte_sex
)
2239 value64
= SWAP_LONG_LONG(value64
);
2240 *(uint64_t *)(contents
+ relocs
[k
].r_address
) = value64
;
2243 * Turn the extern reloc into a local.
2245 if(object
->mh
!= NULL
)
2246 relocs
[k
].r_symbolnum
=
2247 new_symbols
[saves
[relocs
[k
].r_symbolnum
] - 1].n_sect
;
2249 relocs
[k
].r_symbolnum
=
2250 new_symbols64
[saves
[relocs
[k
].r_symbolnum
] - 1].n_sect
;
2251 relocs
[k
].r_extern
= 0;
2254 if(relocs
[k
].r_extern
== 1 &&
2255 saves
[relocs
[k
].r_symbolnum
] != -1){
2256 relocs
[k
].r_symbolnum
= saves
[relocs
[k
].r_symbolnum
] - 1;
2259 if((relocs
[k
].r_address
& R_SCATTERED
) == 0){
2260 if(reloc_has_pair(object
->mh_cputype
, relocs
[k
].r_type
) == TRUE
)
2264 sreloc
= (struct scattered_relocation_info
*)relocs
+ k
;
2265 if(reloc_has_pair(object
->mh_cputype
, sreloc
->r_type
) == TRUE
)
2272 * check_indirect_symtab() checks and updates the indirect symbol table entries
2273 * to make sure referenced symbols are not stripped and refer to the new symbol
2278 check_indirect_symtab(
2280 struct member
*member
,
2281 struct object
*object
,
2284 uint32_t section_type
,
2286 struct nlist
*symbols
,
2287 struct nlist_64
*symbols64
,
2290 int32_t *missing_reloc_symbols
,
2291 enum byte_sex host_byte_sex
)
2295 uint32_t n_strx
, value
;
2297 enum bool made_local
;
2299 for(k
= 0; k
< nitems
; k
++){
2301 index
= object
->output_indirect_symtab
[reserved1
+ k
];
2302 if(index
== INDIRECT_SYMBOL_LOCAL
||
2303 index
== INDIRECT_SYMBOL_ABS
||
2304 index
== (INDIRECT_SYMBOL_LOCAL
| INDIRECT_SYMBOL_ABS
))
2307 fatal_arch(arch
, member
,"indirect symbol table entry %d (past " "the end of the symbol table) in: ", reserved1
+ k
);
2309 if(pflag
== 0 && nmedits
[index
] == TRUE
&& saves
[index
] != -1)
2311 if(saves
[index
] == 0)
2315 * Indirect symbol table entries for defined symbols in a
2316 * non-lazy pointer section that are not saved are changed to
2317 * INDIRECT_SYMBOL_LOCAL which their values just have to be
2318 * slid if the are not absolute symbols.
2320 if(object
->mh
!= NULL
){
2321 n_type
= symbols
[index
].n_type
;
2322 n_strx
= symbols
[index
].n_un
.n_strx
;
2325 n_type
= symbols64
[index
].n_type
;
2326 n_strx
= symbols64
[index
].n_un
.n_strx
;
2328 if((n_type
&& N_TYPE
) != N_UNDF
&&
2329 (n_type
&& N_TYPE
) != N_PBUD
&&
2330 section_type
== S_NON_LAZY_SYMBOL_POINTERS
){
2331 object
->output_indirect_symtab
[reserved1
+ k
] =
2332 INDIRECT_SYMBOL_LOCAL
;
2333 if((n_type
& N_TYPE
) == N_ABS
)
2334 object
->output_indirect_symtab
[reserved1
+ k
] |=
2335 INDIRECT_SYMBOL_ABS
;
2338 * When creating a stub shared library the section contents
2339 * are not updated since they will be stripped.
2341 if(object
->mh_filetype
!= MH_DYLIB_STUB
){
2342 if(object
->mh
!= NULL
){
2343 value
= symbols
[index
].n_value
;
2344 if (symbols
[index
].n_desc
& N_ARM_THUMB_DEF
)
2346 if(object
->object_byte_sex
!= host_byte_sex
)
2347 value
= SWAP_INT(value
);
2348 *(uint32_t *)(contents
+ k
* 4) = value
;
2351 value64
= symbols64
[index
].n_value
;
2352 if(object
->object_byte_sex
!= host_byte_sex
)
2353 value64
= SWAP_LONG_LONG(value64
);
2354 *(uint64_t *)(contents
+ k
* 8) = value64
;
2360 object
->output_indirect_symtab
[reserved1
+ k
] =
2363 #else /* !defined(NMEDIT) */
2365 if(*missing_reloc_symbols
== 0){
2366 error_arch(arch
, member
, "symbols referenced by "
2367 "indirect symbol table entries that can't be "
2369 *missing_reloc_symbols
= 1;
2371 fprintf(stderr
, "%s\n", strings
+ n_strx
);
2374 #endif /* !defined(NMEDIT) */
2378 #else /* !defined(NMEDIT) */
2379 if(made_local
== FALSE
&& saves
[index
] != -1)
2380 #endif /* !defined(NMEDIT) */
2382 object
->output_indirect_symtab
[reserved1
+k
] = saves
[index
] - 1;
2389 * This is called if there is a -d option specified. It reads the file with
2390 * the strings in it and places them in the array debug_filenames and sorts
2391 * them by name. The file that contains the file names must have names one
2392 * per line with no white space (except the newlines).
2396 setup_debug_filenames(
2399 int fd
, i
, strings_size
;
2400 struct stat stat_buf
;
2403 if((fd
= open(dfile
, O_RDONLY
)) < 0){
2404 system_error("can't open: %s", dfile
);
2407 if(fstat(fd
, &stat_buf
) == -1){
2408 system_error("can't stat: %s", dfile
);
2412 strings_size
= stat_buf
.st_size
;
2413 strings
= (char *)allocate(strings_size
+ 1);
2414 strings
[strings_size
] = '\0';
2415 if(read(fd
, strings
, strings_size
) != strings_size
){
2416 system_error("can't read: %s", dfile
);
2421 for(i
= 0; i
< strings_size
; i
++){
2428 debug_filenames
= (char **)allocate(ndebug_filenames
* sizeof(char *));
2430 for(i
= 0; i
< ndebug_filenames
; i
++){
2431 debug_filenames
[i
] = p
;
2434 qsort(debug_filenames
, ndebug_filenames
, sizeof(char *),
2435 (int (*)(const void *, const void *))cmp_qsort_filename
);
2438 printf("Debug filenames:\n");
2439 for(i
= 0; i
< ndebug_filenames
; i
++){
2440 printf("filename = %s\n", debug_filenames
[i
]);
2446 * Strip the symbol table to the level specified by the command line arguments.
2447 * The new symbol table is built and new_symbols is left pointing to it. The
2448 * number of new symbols is left in new_nsyms, the new string table is built
2449 * and new_stings is left pointing to it and new_strsize is left containing it.
2450 * This routine returns zero if successfull and non-zero otherwise.
2456 struct member
*member
,
2457 struct object
*object
,
2458 struct dylib_table_of_contents
*tocs
,
2460 struct dylib_module
*mods
,
2461 struct dylib_module_64
*mods64
,
2463 struct dylib_reference
*refs
,
2464 uint32_t nextrefsyms
)
2466 uint32_t i
, j
, k
, n
, inew_syms
, save_debug
, missing_syms
;
2467 uint32_t missing_symbols
;
2468 char *p
, *q
, **pp
, *basename
;
2469 struct symbol_list
*sp
;
2470 uint32_t new_ext_strsize
, len
, *changes
, inew_undefsyms
;
2471 unsigned char nsects
;
2472 struct load_command
*lc
;
2473 struct segment_command
*sg
;
2474 struct segment_command_64
*sg64
;
2475 struct section
*s
, **sections
;
2476 struct section_64
*s64
, **sections64
;
2477 uint32_t ncmds
, mh_flags
, s_flags
, n_strx
;
2479 struct undef_map
*undef_map
;
2480 struct undef_map64
*undef_map64
;
2481 uint8_t n_type
, n_sect
;
2484 uint32_t module_name
, iextdefsym
, nextdefsym
, ilocalsym
, nlocalsym
;
2485 uint32_t irefsym
, nrefsym
;
2486 unsigned char text_nsect
;
2487 enum bool has_dwarf
, hack_5614542
;
2493 for(i
= 0; i
< nsave_symbols
; i
++)
2494 save_symbols
[i
].sym
= NULL
;
2495 for(i
= 0; i
< nremove_symbols
; i
++)
2496 remove_symbols
[i
].sym
= NULL
;
2498 for(i
= 0; i
< nsave_symbols
; i
++)
2499 save_symbols
[i
].seen
= FALSE
;
2500 for(i
= 0; i
< nremove_symbols
; i
++)
2501 remove_symbols
[i
].seen
= FALSE
;
2505 if(object
->mh
!= NULL
)
2506 new_strsize
= sizeof(int32_t);
2508 new_strsize
= sizeof(int64_t);
2512 new_ext_strsize
= 0;
2515 * If this an object file that has DWARF debugging sections to strip
2516 * then we have to run ld -r on it.
2518 if(object
->mh_filetype
== MH_OBJECT
&& (Sflag
|| xflag
)){
2520 lc
= object
->load_commands
;
2521 if(object
->mh
!= NULL
)
2522 ncmds
= object
->mh
->ncmds
;
2524 ncmds
= object
->mh64
->ncmds
;
2525 for(i
= 0; i
< ncmds
&& has_dwarf
== FALSE
; i
++){
2526 if(lc
->cmd
== LC_SEGMENT
){
2527 sg
= (struct segment_command
*)lc
;
2528 s
= (struct section
*)((char *)sg
+
2529 sizeof(struct segment_command
));
2530 for(j
= 0; j
< sg
->nsects
; j
++){
2531 if(s
->flags
& S_ATTR_DEBUG
){
2538 else if(lc
->cmd
== LC_SEGMENT_64
){
2539 sg64
= (struct segment_command_64
*)lc
;
2540 s64
= (struct section_64
*)((char *)sg64
+
2541 sizeof(struct segment_command_64
));
2542 for(j
= 0; j
< sg64
->nsects
; j
++){
2543 if(s64
->flags
& S_ATTR_DEBUG
){
2550 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2553 * Because of the bugs in ld(1) for:
2554 * radr://5675774 ld64 should preserve JBSR relocations without
2556 * radr://5658046 cctools-679 creates scattered relocations in
2557 * __TEXT,__const section in kexts, which breaks
2558 * kexts built for older systems
2559 * we can't use ld -r to strip dwarf info in 32-bit objects until
2560 * these are fixed. But if the user as specified the -l flag then
2561 * go ahead and do it and the user will have to be aware of these
2564 if((lflag
== TRUE
&& has_dwarf
== TRUE
) || object
->mh64
!= NULL
)
2565 make_ld_r_object(arch
, member
, object
);
2568 * Because of the "design" of 64-bit object files and the lack of
2569 * local relocation entries it is not possible for strip(1) to do its
2570 * job without becoming a static link editor. The "design" does not
2571 * actually strip the symbols it simply renames them to things like
2572 * "l1000". And they become static symbols but still have external
2573 * relocation entries. Thus can never actually be stripped. Also some
2574 * symbols, *.eh, symbols are not even changed to these names if there
2575 * corresponding global symbol is not stripped. So strip(1) only
2576 * recourse is to use the unified linker to create an ld -r object then
2577 * save all resulting symbols (both static and global) and hope the user
2578 * does not notice the stripping is not what they asked for.
2580 if(object
->mh_filetype
== MH_OBJECT
&&
2581 (object
->mh64
!= NULL
&& object
->ld_r_ofile
== NULL
))
2582 make_ld_r_object(arch
, member
, object
);
2585 * Since make_ld_r_object() may create an object with more symbols
2586 * this has to be done after make_ld_r_object() and nsyms is updated.
2588 saves
= (int32_t *)allocate(nsyms
* sizeof(int32_t));
2589 bzero(saves
, nsyms
* sizeof(int32_t));
2592 * Gather an array of section struct pointers so we can later determine
2593 * if we run into a global symbol in a coalesced section and not strip
2598 text_nsect
= NO_SECT
;
2599 lc
= object
->load_commands
;
2600 if(object
->mh
!= NULL
)
2601 ncmds
= object
->mh
->ncmds
;
2603 ncmds
= object
->mh64
->ncmds
;
2604 for(i
= 0; i
< ncmds
; i
++){
2605 if(lc
->cmd
== LC_SEGMENT
){
2606 sg
= (struct segment_command
*)lc
;
2607 nsects
+= sg
->nsects
;
2609 else if(lc
->cmd
== LC_SEGMENT_64
){
2610 sg64
= (struct segment_command_64
*)lc
;
2611 nsects
+= sg64
->nsects
;
2613 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2615 if(object
->mh
!= NULL
){
2616 sections
= allocate(nsects
* sizeof(struct section
*));
2621 sections64
= allocate(nsects
* sizeof(struct section_64
*));
2624 lc
= object
->load_commands
;
2625 for(i
= 0; i
< ncmds
; i
++){
2626 if(lc
->cmd
== LC_SEGMENT
){
2627 sg
= (struct segment_command
*)lc
;
2628 s
= (struct section
*)((char *)sg
+
2629 sizeof(struct segment_command
));
2630 for(j
= 0; j
< sg
->nsects
; j
++){
2631 if(strcmp((s
+ j
)->sectname
, SECT_TEXT
) == 0 &&
2632 strcmp((s
+ j
)->segname
, SEG_TEXT
) == 0)
2633 text_nsect
= nsects
+ 1;
2634 sections
[nsects
++] = s
++;
2637 else if(lc
->cmd
== LC_SEGMENT_64
){
2638 sg64
= (struct segment_command_64
*)lc
;
2639 s64
= (struct section_64
*)((char *)sg64
+
2640 sizeof(struct segment_command_64
));
2641 for(j
= 0; j
< sg64
->nsects
; j
++){
2642 if(strcmp((s64
+ j
)->sectname
, SECT_TEXT
) == 0 &&
2643 strcmp((s64
+ j
)->segname
, SEG_TEXT
) == 0)
2644 text_nsect
= nsects
+ 1;
2645 sections64
[nsects
++] = s64
++;
2648 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2651 for(i
= 0; i
< nsyms
; i
++){
2653 if(object
->mh
!= NULL
){
2654 mh_flags
= object
->mh
->flags
;
2655 n_strx
= symbols
[i
].n_un
.n_strx
;
2656 n_type
= symbols
[i
].n_type
;
2657 n_sect
= symbols
[i
].n_sect
;
2658 if((n_type
& N_TYPE
) == N_SECT
){
2659 if(n_sect
== 0 || n_sect
> nsects
){
2660 error_arch(arch
, member
, "bad n_sect for symbol "
2661 "table entry %d in: ", i
);
2664 s_flags
= sections
[n_sect
- 1]->flags
;
2666 n_desc
= symbols
[i
].n_desc
;
2667 n_value
= symbols
[i
].n_value
;
2670 mh_flags
= object
->mh64
->flags
;
2671 n_strx
= symbols64
[i
].n_un
.n_strx
;
2672 n_type
= symbols64
[i
].n_type
;
2673 n_sect
= symbols64
[i
].n_sect
;
2674 if((n_type
& N_TYPE
) == N_SECT
){
2675 if(n_sect
== 0 || n_sect
> nsects
){
2676 error_arch(arch
, member
, "bad n_sect for symbol "
2677 "table entry %d in: ", i
);
2680 s_flags
= sections64
[n_sect
- 1]->flags
;
2682 n_desc
= symbols64
[i
].n_desc
;
2683 n_value
= symbols64
[i
].n_value
;
2686 if(n_strx
> strsize
){
2687 error_arch(arch
, member
, "bad string index for symbol "
2688 "table entry %d in: ", i
);
2692 if((n_type
& N_TYPE
) == N_INDR
){
2694 if(n_value
> strsize
){
2695 error_arch(arch
, member
, "bad string index for "
2696 "indirect symbol table entry %d in: ", i
);
2701 if((n_type
& N_EXT
) == 0){ /* local symbol */
2704 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2707 saves
[i
] = new_nsyms
;
2710 * For x86_64 .o files we have run ld -r on them and are stuck
2711 * keeping all resulting symbols.
2713 else if(object
->mh
== NULL
&&
2714 object
->mh64
->cputype
== CPU_TYPE_X86_64
&&
2715 object
->mh64
->filetype
== MH_OBJECT
){
2717 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2720 saves
[i
] = new_nsyms
;
2723 * The cases a local symbol might be saved are with -X, -S, -t,
2724 * or with -d filename.
2726 else if((!strip_all
&& (Xflag
|| tflag
|| Sflag
)) || dfile
){
2727 if(n_type
& N_STAB
){ /* debug symbol */
2728 if(dfile
&& n_type
== N_SO
){
2730 basename
= strrchr(strings
+ n_strx
, '/');
2731 if(basename
!= NULL
)
2734 basename
= strings
+ n_strx
;
2735 pp
= bsearch(basename
, debug_filenames
,
2736 ndebug_filenames
, sizeof(char *),
2737 (int (*)(const void *, const void *)
2738 )cmp_bsearch_filename
);
2740 * Save the bracketing N_SO. For each N_SO that
2741 * has a filename there is an N_SO that has a
2742 * name of "" which ends the stabs for that file
2744 if(*basename
!= '\0'){
2752 * This is a bracketing SO so if we are
2753 * currently saving debug symbols save this
2754 * last one and turn off saving debug syms.
2758 new_strsize
+= strlen(strings
+
2762 saves
[i
] = new_nsyms
;
2771 if(saves
[i
] == 0 && (!Sflag
|| save_debug
)){
2773 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2776 saves
[i
] = new_nsyms
;
2779 else{ /* non-debug local symbol */
2780 if(xflag
== 0 && (Sflag
|| Xflag
|| tflag
)){
2782 * No -x (strip all local), and one of -S (strip
2783 * debug), -X (strip 'L' local), or -t (strip
2784 * local except non-'L' text) was given.
2786 if((Xflag
&& n_strx
!= 0 &&
2787 strings
[n_strx
] != 'L') ||
2788 (tflag
&& (n_type
& N_TYPE
) == N_SECT
&&
2789 n_sect
== text_nsect
&& n_strx
!= 0 &&
2790 strings
[n_strx
] != 'L') ||
2791 (Sflag
&& !Xflag
&& !tflag
)) {
2793 * If this file is a for the dynamic linker and
2794 * this symbol is in a section marked so that
2795 * static symbols are stripped then don't
2798 if((mh_flags
& MH_DYLDLINK
) != MH_DYLDLINK
||
2799 (n_type
& N_TYPE
) != N_SECT
||
2800 (s_flags
& S_ATTR_STRIP_STATIC_SYMS
) !=
2801 S_ATTR_STRIP_STATIC_SYMS
){
2802 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2805 saves
[i
] = new_nsyms
;
2810 * Treat a local symbol that was a private extern as if
2811 * were global if it is referenced by a module and save
2814 if((n_type
& N_PEXT
) == N_PEXT
){
2816 private_extern_reference_by_module(
2817 i
, refs
,nextrefsyms
) == TRUE
){
2819 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2822 saves
[i
] = new_nsyms
;
2825 * We need to save symbols that were private externs
2826 * that are used with indirect symbols.
2829 symbol_pointer_used(i
, indirectsyms
,
2830 nindirectsyms
) == TRUE
){
2832 len
= strlen(strings
+ n_strx
) + 1;
2837 saves
[i
] = new_nsyms
;
2843 * Treat a local symbol that was a private extern as if were
2844 * global if it is not referenced by a module.
2846 else if((n_type
& N_PEXT
) == N_PEXT
){
2847 if(saves
[i
] == 0 && sfile
){
2848 sp
= bsearch(strings
+ n_strx
,
2849 save_symbols
, nsave_symbols
,
2850 sizeof(struct symbol_list
),
2851 (int (*)(const void *, const void *))
2852 symbol_list_bsearch
);
2854 if(sp
->sym
== NULL
){
2855 if(object
->mh
!= NULL
)
2856 sp
->sym
= &(symbols
[i
]);
2858 sp
->sym
= &(symbols64
[i
]);
2862 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2865 saves
[i
] = new_nsyms
;
2869 private_extern_reference_by_module(
2870 i
, refs
,nextrefsyms
) == TRUE
){
2872 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2875 saves
[i
] = new_nsyms
;
2878 * We need to save symbols that were private externs that
2879 * are used with indirect symbols.
2882 symbol_pointer_used(i
, indirectsyms
, nindirectsyms
) ==
2885 len
= strlen(strings
+ n_strx
) + 1;
2890 saves
[i
] = new_nsyms
;
2894 else{ /* global symbol */
2896 * strip -R on an x86_64 .o file should do nothing.
2899 (object
->mh
!= NULL
||
2900 object
->mh64
->cputype
!= CPU_TYPE_X86_64
||
2901 object
->mh64
->filetype
!= MH_OBJECT
)){
2902 sp
= bsearch(strings
+ n_strx
,
2903 remove_symbols
, nremove_symbols
,
2904 sizeof(struct symbol_list
),
2905 (int (*)(const void *, const void *))
2906 symbol_list_bsearch
);
2908 if((n_type
& N_TYPE
) == N_UNDF
||
2909 (n_type
& N_TYPE
) == N_PBUD
){
2910 error_arch(arch
, member
, "symbol: %s undefined"
2911 " and can't be stripped from: ",
2914 else if(sp
->sym
!= NULL
){
2915 sym
= (struct nlist
*)sp
->sym
;
2916 if((sym
->n_type
& N_PEXT
) != N_PEXT
)
2917 error_arch(arch
, member
, "more than one symbol "
2918 "for: %s found in: ", sp
->name
);
2921 if(object
->mh
!= NULL
)
2922 sp
->sym
= &(symbols
[i
]);
2924 sp
->sym
= &(symbols64
[i
]);
2927 if(n_desc
& REFERENCED_DYNAMICALLY
){
2928 error_arch(arch
, member
, "symbol: %s is dynamically"
2929 " referenced and can't be stripped "
2930 "from: ", sp
->name
);
2932 if((n_type
& N_TYPE
) == N_SECT
&&
2933 (s_flags
& SECTION_TYPE
) == S_COALESCED
){
2934 error_arch(arch
, member
, "symbol: %s is a global "
2935 "coalesced symbol and can't be "
2936 "stripped from: ", sp
->name
);
2938 /* don't save this symbol */
2942 if(Aflag
&& (n_type
& N_TYPE
) == N_ABS
&&
2945 strncmp(strings
+ n_strx
,
2946 ".objc_class_name_",
2947 sizeof(".objc_class_name_") - 1) == 0))){
2948 len
= strlen(strings
+ n_strx
) + 1;
2950 new_ext_strsize
+= len
;
2953 saves
[i
] = new_nsyms
;
2955 if(saves
[i
] == 0 && (uflag
|| default_dyld_executable
) &&
2956 ((((n_type
& N_TYPE
) == N_UNDF
) &&
2958 (n_type
& N_TYPE
) == N_PBUD
)){
2960 len
= strlen(strings
+ n_strx
) + 1;
2962 new_ext_strsize
+= len
;
2966 saves
[i
] = new_nsyms
;
2968 if(saves
[i
] == 0 && nflag
&&
2969 (n_type
& N_TYPE
) == N_SECT
){
2971 len
= strlen(strings
+ n_strx
) + 1;
2973 new_ext_strsize
+= len
;
2977 saves
[i
] = new_nsyms
;
2979 if(saves
[i
] == 0 && sfile
){
2980 sp
= bsearch(strings
+ n_strx
,
2981 save_symbols
, nsave_symbols
,
2982 sizeof(struct symbol_list
),
2983 (int (*)(const void *, const void *))
2984 symbol_list_bsearch
);
2986 if(sp
->sym
!= NULL
){
2987 sym
= (struct nlist
*)sp
->sym
;
2988 if((sym
->n_type
& N_PEXT
) != N_PEXT
)
2989 error_arch(arch
, member
, "more than one symbol "
2990 "for: %s found in: ", sp
->name
);
2993 if(object
->mh
!= NULL
)
2994 sp
->sym
= &(symbols
[i
]);
2996 sp
->sym
= &(symbols64
[i
]);
2998 len
= strlen(strings
+ n_strx
) + 1;
3000 new_ext_strsize
+= len
;
3001 if((n_type
& N_TYPE
) == N_UNDF
||
3002 (n_type
& N_TYPE
) == N_PBUD
)
3007 saves
[i
] = new_nsyms
;
3012 * We only need to save coalesced symbols that are used as
3013 * indirect symbols in 32-bit applications.
3015 * In 64-bit applications, we only need to save coalesced
3016 * symbols that are used as weak definitions.
3018 if(object
->mh
!= NULL
&&
3020 (n_type
& N_TYPE
) == N_SECT
&&
3021 (s_flags
& SECTION_TYPE
) == S_COALESCED
&&
3022 symbol_pointer_used(i
, indirectsyms
, nindirectsyms
) == TRUE
){
3024 len
= strlen(strings
+ n_strx
) + 1;
3026 new_ext_strsize
+= len
;
3030 saves
[i
] = new_nsyms
;
3033 (n_type
& N_TYPE
) == N_SECT
&&
3034 (n_desc
& N_WEAK_DEF
) != 0){
3036 len
= strlen(strings
+ n_strx
) + 1;
3038 new_ext_strsize
+= len
;
3042 saves
[i
] = new_nsyms
;
3045 ((Xflag
|| Sflag
|| xflag
|| tflag
|| aflag
) ||
3046 ((rflag
|| default_dyld_executable
) &&
3047 n_desc
& REFERENCED_DYNAMICALLY
))){
3048 len
= strlen(strings
+ n_strx
) + 1;
3050 new_ext_strsize
+= len
;
3051 if((n_type
& N_TYPE
) == N_INDR
){
3052 len
= strlen(strings
+ n_value
) + 1;
3054 new_ext_strsize
+= len
;
3056 if((n_type
& N_TYPE
) == N_UNDF
||
3057 (n_type
& N_TYPE
) == N_PBUD
)
3062 saves
[i
] = new_nsyms
;
3065 * For x86_64 .o files we have run ld -r on them and are stuck
3066 * keeping all resulting symbols.
3069 object
->mh
== NULL
&&
3070 object
->mh64
->cputype
== CPU_TYPE_X86_64
&&
3071 object
->mh64
->filetype
== MH_OBJECT
){
3072 len
= strlen(strings
+ n_strx
) + 1;
3074 new_ext_strsize
+= len
;
3075 if((n_type
& N_TYPE
) == N_INDR
){
3076 len
= strlen(strings
+ n_value
) + 1;
3078 new_ext_strsize
+= len
;
3080 if((n_type
& N_TYPE
) == N_UNDF
||
3081 (n_type
& N_TYPE
) == N_PBUD
)
3086 saves
[i
] = new_nsyms
;
3091 * The module table's module names are placed with the external strings.
3092 * So size them and add this to the external string size.
3094 for(i
= 0; i
< nmodtab
; i
++){
3095 if(object
->mh
!= NULL
)
3096 module_name
= mods
[i
].module_name
;
3098 module_name
= mods64
[i
].module_name
;
3099 if(module_name
== 0 || module_name
> strsize
){
3100 error_arch(arch
, member
, "bad string index for module_name "
3101 "of module table entry %d in: ", i
);
3104 len
= strlen(strings
+ module_name
) + 1;
3106 new_ext_strsize
+= len
;
3110 * Updating the reference table may require a symbol not yet listed as
3111 * as saved to be present in the output file. If a defined external
3112 * symbol is removed and there is a undefined reference to it in the
3113 * reference table an undefined symbol needs to be created for it in
3114 * the output file. If this happens the number of new symbols and size
3115 * of the new strings are adjusted. And the array changes[] is set to
3116 * map the old symbol index to the new symbol index for the symbol that
3117 * is changed to an undefined symbol.
3119 missing_symbols
= 0;
3120 if(ref_saves
!= NULL
)
3122 ref_saves
= (int32_t *)allocate(nextrefsyms
* sizeof(int32_t));
3123 bzero(ref_saves
, nextrefsyms
* sizeof(int32_t));
3124 changes
= (uint32_t *)allocate(nsyms
* sizeof(int32_t));
3125 bzero(changes
, nsyms
* sizeof(int32_t));
3126 new_nextrefsyms
= 0;
3127 for(i
= 0; i
< nextrefsyms
; i
++){
3128 if(refs
[i
].isym
> nsyms
){
3129 error_arch(arch
, member
, "bad symbol table index for "
3130 "reference table entry %d in: ", i
);
3133 if(saves
[refs
[i
].isym
]){
3135 ref_saves
[i
] = new_nextrefsyms
;
3138 if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
||
3139 refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
){
3140 if(changes
[refs
[i
].isym
] == 0){
3141 if(object
->mh
!= NULL
)
3142 n_strx
= symbols
[refs
[i
].isym
].n_un
.n_strx
;
3144 n_strx
= symbols64
[refs
[i
].isym
].n_un
.n_strx
;
3145 len
= strlen(strings
+ n_strx
) + 1;
3147 new_ext_strsize
+= len
;
3150 changes
[refs
[i
].isym
] = new_nsyms
;
3152 ref_saves
[i
] = new_nextrefsyms
;
3157 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
||
3158 refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
){
3159 if(missing_symbols
== 0){
3160 error_arch(arch
, member
, "private extern symbols "
3161 "referenced by modules can't be stripped in: ");
3162 missing_symbols
= 1;
3164 if(object
->mh
!= NULL
)
3165 n_strx
= symbols
[refs
[i
].isym
].n_un
.n_strx
;
3167 n_strx
= symbols64
[refs
[i
].isym
].n_un
.n_strx
;
3168 fprintf(stderr
, "%s\n", strings
+ n_strx
);
3169 saves
[refs
[i
].isym
] = -1;
3174 if(missing_symbols
== 1)
3180 for(i
= 0; i
< nsave_symbols
; i
++){
3181 if(save_symbols
[i
].sym
== NULL
){
3182 if(missing_syms
== 0){
3183 error_arch(arch
, member
, "symbols names listed "
3184 "in: %s not in: ", sfile
);
3187 fprintf(stderr
, "%s\n", save_symbols
[i
].name
);
3193 * strip -R on an x86_64 .o file should do nothing.
3196 (object
->mh
!= NULL
||
3197 object
->mh64
->cputype
!= CPU_TYPE_X86_64
||
3198 object
->mh64
->filetype
!= MH_OBJECT
)){
3199 for(i
= 0; i
< nremove_symbols
; i
++){
3200 if(remove_symbols
[i
].sym
== NULL
){
3201 if(missing_syms
== 0){
3202 error_arch(arch
, member
, "symbols names listed "
3203 "in: %s not in: ", Rfile
);
3206 fprintf(stderr
, "%s\n", remove_symbols
[i
].name
);
3213 * If there is a chance that we could end up with an indirect symbol
3214 * with an index of zero we need to avoid that due to a work around
3215 * in the dynamic linker for a bug it is working around that was in
3216 * the old classic static linker. See radar bug 5614542 and the
3217 * related bugs 3685312 and 3534709.
3219 * A reasonable way to do this to know that local symbols are first in
3220 * the symbol table. So if we have any local symbols this won't happen
3221 * and if there are no indirect symbols it will also not happen. Past
3222 * that we'll just add a local symbol so it will end up at symbol index
3223 * zero and avoid any indirect symbol having that index.
3225 * If one really wanted they could build up the new symbol table then
3226 * look at all the indirect symbol table entries to see if any of them
3227 * have an index of zero then in that case throw that new symbol table
3228 * away and rebuild the symbol and string table once again after adding
3229 * a local symbol. This seems not all that resonable to save one symbol
3230 * table entry and a few bytes in the string table for the complexity it
3231 * would add and what it would save.
3233 if(new_nlocalsym
== 0 && nindirectsyms
!= 0){
3234 len
= strlen("radr://5614542") + 1;
3238 hack_5614542
= TRUE
;
3241 hack_5614542
= FALSE
;
3244 if(object
->mh
!= NULL
){
3245 new_symbols
= (struct nlist
*)
3246 allocate(new_nsyms
* sizeof(struct nlist
));
3247 new_symbols64
= NULL
;
3251 new_symbols64
= (struct nlist_64
*)
3252 allocate(new_nsyms
* sizeof(struct nlist_64
));
3254 if(object
->mh
!= NULL
)
3255 new_strsize
= rnd(new_strsize
, sizeof(int32_t));
3257 new_strsize
= rnd(new_strsize
, sizeof(int64_t));
3258 new_strings
= (char *)allocate(new_strsize
);
3259 if(object
->mh
!= NULL
){
3260 new_strings
[new_strsize
- 3] = '\0';
3261 new_strings
[new_strsize
- 2] = '\0';
3262 new_strings
[new_strsize
- 1] = '\0';
3265 new_strings
[new_strsize
- 7] = '\0';
3266 new_strings
[new_strsize
- 6] = '\0';
3267 new_strings
[new_strsize
- 5] = '\0';
3268 new_strings
[new_strsize
- 4] = '\0';
3269 new_strings
[new_strsize
- 3] = '\0';
3270 new_strings
[new_strsize
- 2] = '\0';
3271 new_strings
[new_strsize
- 1] = '\0';
3274 memset(new_strings
, '\0', sizeof(int32_t));
3275 p
= new_strings
+ sizeof(int32_t);
3276 q
= p
+ new_ext_strsize
;
3279 * If all strings were stripped set the size to zero but only for 32-bit
3280 * because the unified linker seems to set the filesize of empty .o
3281 * files to include the string table.
3283 if(object
->mh
!= NULL
&& new_strsize
== sizeof(int32_t))
3287 * Now create a symbol table and string table in this order
3290 * external defined symbols
3299 * If we are doing the hack for radar bug 5614542 (see above) add the
3300 * one local symbol and string.
3302 * We use an N_OPT stab which should be safe to use and not mess any
3303 * thing up. In Mac OS X, gcc(1) writes one N_OPT stab saying the file
3304 * is compiled with gcc(1). Then gdb(1) looks for that stab, but it
3305 * also looks at the name. If the name string is "gcc_compiled" or
3306 * "gcc2_compiled" gdb(1) sets its "compiled by gcc flag. If the N_OPT
3307 * is emitted INSIDE an N_SO section, then gdb(1) thinks that object
3308 * module was compiled by Sun's compiler, which apparently sticks one
3309 * outermost N_LBRAC/N_RBRAC pair, which gdb(1) strips off. But if the
3310 * N_OPT comes before any N_SO stabs, then gdb(1) will just ignore it.
3311 * Since this N_OPT is the first local symbol, it will always come
3312 * before any N_SO stabs that might be around and should be fine.
3314 if(hack_5614542
== TRUE
){
3315 if(object
->mh
!= NULL
){
3316 new_symbols
[inew_syms
].n_type
= N_OPT
;
3317 new_symbols
[inew_syms
].n_sect
= NO_SECT
;
3318 new_symbols
[inew_syms
].n_desc
= 0;
3319 new_symbols
[inew_syms
].n_value
= 0x05614542;
3322 new_symbols64
[inew_syms
].n_type
= N_OPT
;
3323 new_symbols64
[inew_syms
].n_sect
= NO_SECT
;
3324 new_symbols64
[inew_syms
].n_desc
= 0;
3325 new_symbols64
[inew_syms
].n_value
= 0x05614542;
3327 strcpy(q
, "radr://5614542");
3328 if(object
->mh
!= NULL
)
3329 new_symbols
[inew_syms
].n_un
.n_strx
=
3332 new_symbols64
[inew_syms
].n_un
.n_strx
=
3338 for(i
= 0; i
< nsyms
; i
++){
3340 if(object
->mh
!= NULL
){
3341 n_strx
= symbols
[i
].n_un
.n_strx
;
3342 n_type
= symbols
[i
].n_type
;
3345 n_strx
= symbols64
[i
].n_un
.n_strx
;
3346 n_type
= symbols64
[i
].n_type
;
3348 if((n_type
& N_EXT
) == 0){
3349 if(object
->mh
!= NULL
)
3350 new_symbols
[inew_syms
] = symbols
[i
];
3352 new_symbols64
[inew_syms
] = symbols64
[i
];
3354 strcpy(q
, strings
+ n_strx
);
3355 if(object
->mh
!= NULL
)
3356 new_symbols
[inew_syms
].n_un
.n_strx
=
3359 new_symbols64
[inew_syms
].n_un
.n_strx
=
3364 saves
[i
] = inew_syms
;
3369 inew_nextdefsym
= inew_syms
;
3370 #endif /* TRIE_SUPPORT */
3371 for(i
= 0; i
< nsyms
; i
++){
3373 if(object
->mh
!= NULL
){
3374 n_strx
= symbols
[i
].n_un
.n_strx
;
3375 n_type
= symbols
[i
].n_type
;
3376 n_value
= symbols
[i
].n_value
;
3379 n_strx
= symbols64
[i
].n_un
.n_strx
;
3380 n_type
= symbols64
[i
].n_type
;
3381 n_value
= symbols64
[i
].n_value
;
3383 if((n_type
& N_EXT
) == N_EXT
&&
3384 ((n_type
& N_TYPE
) != N_UNDF
&&
3385 (n_type
& N_TYPE
) != N_PBUD
)){
3386 if(object
->mh
!= NULL
)
3387 new_symbols
[inew_syms
] = symbols
[i
];
3389 new_symbols64
[inew_syms
] = symbols64
[i
];
3391 strcpy(p
, strings
+ n_strx
);
3392 if(object
->mh
!= NULL
)
3393 new_symbols
[inew_syms
].n_un
.n_strx
=
3396 new_symbols64
[inew_syms
].n_un
.n_strx
=
3400 if((n_type
& N_TYPE
) == N_INDR
){
3402 strcpy(p
, strings
+ n_value
);
3403 if(object
->mh
!= NULL
)
3404 new_symbols
[inew_syms
].n_value
=
3407 new_symbols64
[inew_syms
].n_value
=
3413 saves
[i
] = inew_syms
;
3418 * Build the new undefined symbols into a map and sort it.
3421 if(object
->mh
!= NULL
){
3422 undef_map
= (struct undef_map
*)allocate(new_nundefsym
*
3423 sizeof(struct undef_map
));
3428 undef_map64
= (struct undef_map64
*)allocate(new_nundefsym
*
3429 sizeof(struct undef_map64
));
3431 for(i
= 0; i
< nsyms
; i
++){
3433 if(object
->mh
!= NULL
){
3434 n_strx
= symbols
[i
].n_un
.n_strx
;
3435 n_type
= symbols
[i
].n_type
;
3438 n_strx
= symbols64
[i
].n_un
.n_strx
;
3439 n_type
= symbols64
[i
].n_type
;
3441 if((n_type
& N_EXT
) == N_EXT
&&
3442 ((n_type
& N_TYPE
) == N_UNDF
||
3443 (n_type
& N_TYPE
) == N_PBUD
)){
3444 if(object
->mh
!= NULL
)
3445 undef_map
[inew_undefsyms
].symbol
= symbols
[i
];
3447 undef_map64
[inew_undefsyms
].symbol64
= symbols64
[i
];
3449 strcpy(p
, strings
+ n_strx
);
3450 if(object
->mh
!= NULL
)
3451 undef_map
[inew_undefsyms
].symbol
.n_un
.n_strx
=
3454 undef_map64
[inew_undefsyms
].symbol64
.n_un
.n_strx
=
3458 if(object
->mh
!= NULL
)
3459 undef_map
[inew_undefsyms
].index
= i
;
3461 undef_map64
[inew_undefsyms
].index
= i
;
3466 for(i
= 0; i
< nsyms
; i
++){
3468 if(object
->mh
!= NULL
)
3469 n_strx
= symbols
[i
].n_un
.n_strx
;
3471 n_strx
= symbols64
[i
].n_un
.n_strx
;
3473 strcpy(p
, strings
+ n_strx
);
3474 if(object
->mh
!= NULL
)
3475 undef_map
[inew_undefsyms
].symbol
.n_un
.n_strx
=
3478 undef_map64
[inew_undefsyms
].symbol64
.n_un
.n_strx
=
3482 if(object
->mh
!= NULL
){
3483 undef_map
[inew_undefsyms
].symbol
.n_type
= N_UNDF
| N_EXT
;
3484 undef_map
[inew_undefsyms
].symbol
.n_sect
= NO_SECT
;
3485 undef_map
[inew_undefsyms
].symbol
.n_desc
= 0;
3486 undef_map
[inew_undefsyms
].symbol
.n_value
= 0;
3487 undef_map
[inew_undefsyms
].index
= i
;
3490 undef_map64
[inew_undefsyms
].symbol64
.n_type
= N_UNDF
|N_EXT
;
3491 undef_map64
[inew_undefsyms
].symbol64
.n_sect
= NO_SECT
;
3492 undef_map64
[inew_undefsyms
].symbol64
.n_desc
= 0;
3493 undef_map64
[inew_undefsyms
].symbol64
.n_value
= 0;
3494 undef_map64
[inew_undefsyms
].index
= i
;
3499 /* Sort the undefined symbols by name */
3500 qsort_strings
= new_strings
;
3501 if(object
->mh
!= NULL
)
3502 qsort(undef_map
, new_nundefsym
, sizeof(struct undef_map
),
3503 (int (*)(const void *, const void *))cmp_qsort_undef_map
);
3505 qsort(undef_map64
, new_nundefsym
, sizeof(struct undef_map64
),
3506 (int (*)(const void *, const void *))cmp_qsort_undef_map_64
);
3507 /* Copy the symbols now in sorted order into new_symbols */
3508 for(i
= 0; i
< new_nundefsym
; i
++){
3509 if(object
->mh
!= NULL
){
3510 new_symbols
[inew_syms
] = undef_map
[i
].symbol
;
3512 saves
[undef_map
[i
].index
] = inew_syms
;
3515 new_symbols64
[inew_syms
] = undef_map64
[i
].symbol64
;
3517 saves
[undef_map64
[i
].index
] = inew_syms
;
3522 * Fixup the module table's module name strings adding them to the
3523 * string table. Also fix the indexes into the symbol table for
3524 * external and local symbols. And fix up the indexes into the
3527 for(i
= 0; i
< nmodtab
; i
++){
3528 if(object
->mh
!= NULL
){
3529 strcpy(p
, strings
+ mods
[i
].module_name
);
3530 mods
[i
].module_name
= p
- new_strings
;
3531 iextdefsym
= mods
[i
].iextdefsym
;
3532 nextdefsym
= mods
[i
].nextdefsym
;
3533 ilocalsym
= mods
[i
].ilocalsym
;
3534 nlocalsym
= mods
[i
].nlocalsym
;
3535 irefsym
= mods
[i
].irefsym
;
3536 nrefsym
= mods
[i
].nrefsym
;
3539 strcpy(p
, strings
+ mods64
[i
].module_name
);
3540 mods64
[i
].module_name
= p
- new_strings
;
3541 iextdefsym
= mods64
[i
].iextdefsym
;
3542 nextdefsym
= mods64
[i
].nextdefsym
;
3543 ilocalsym
= mods64
[i
].ilocalsym
;
3544 nlocalsym
= mods64
[i
].nlocalsym
;
3545 irefsym
= mods64
[i
].irefsym
;
3546 nrefsym
= mods64
[i
].nrefsym
;
3550 if(iextdefsym
> nsyms
){
3551 error_arch(arch
, member
, "bad index into externally defined "
3552 "symbols of module table entry %d in: ", i
);
3555 if(iextdefsym
+ nextdefsym
> nsyms
){
3556 error_arch(arch
, member
, "bad number of externally defined "
3557 "symbols of module table entry %d in: ", i
);
3560 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
3561 if(saves
[j
] != 0 && changes
[j
] == 0)
3565 for(k
= j
; k
< iextdefsym
+ nextdefsym
; k
++){
3566 if(saves
[k
] != 0 && changes
[k
] == 0)
3570 if(object
->mh
!= NULL
){
3571 mods
[i
].iextdefsym
= 0;
3572 mods
[i
].nextdefsym
= 0;
3575 mods64
[i
].iextdefsym
= 0;
3576 mods64
[i
].nextdefsym
= 0;
3580 if(object
->mh
!= NULL
){
3581 mods
[i
].iextdefsym
= saves
[j
] - 1;
3582 mods
[i
].nextdefsym
= n
;
3585 mods64
[i
].iextdefsym
= saves
[j
] - 1;
3586 mods64
[i
].nextdefsym
= n
;
3590 if(ilocalsym
> nsyms
){
3591 error_arch(arch
, member
, "bad index into symbols for local "
3592 "symbols of module table entry %d in: ", i
);
3595 if(ilocalsym
+ nlocalsym
> nsyms
){
3596 error_arch(arch
, member
, "bad number of local "
3597 "symbols of module table entry %d in: ", i
);
3600 for(j
= ilocalsym
; j
< ilocalsym
+ nlocalsym
; j
++){
3605 for(k
= j
; k
< ilocalsym
+ nlocalsym
; k
++){
3610 if(object
->mh
!= NULL
){
3611 mods
[i
].ilocalsym
= 0;
3612 mods
[i
].nlocalsym
= 0;
3615 mods64
[i
].ilocalsym
= 0;
3616 mods64
[i
].nlocalsym
= 0;
3620 if(object
->mh
!= NULL
){
3621 mods
[i
].ilocalsym
= saves
[j
] - 1;
3622 mods
[i
].nlocalsym
= n
;
3625 mods64
[i
].ilocalsym
= saves
[j
] - 1;
3626 mods64
[i
].nlocalsym
= n
;
3630 if(irefsym
> nextrefsyms
){
3631 error_arch(arch
, member
, "bad index into reference table "
3632 "of module table entry %d in: ", i
);
3635 if(irefsym
+ nrefsym
> nextrefsyms
){
3636 error_arch(arch
, member
, "bad number of reference table "
3637 "entries of module table entry %d in: ", i
);
3640 for(j
= irefsym
; j
< irefsym
+ nrefsym
; j
++){
3641 if(ref_saves
[j
] != 0)
3645 for(k
= j
; k
< irefsym
+ nrefsym
; k
++){
3646 if(ref_saves
[k
] != 0)
3650 if(object
->mh
!= NULL
){
3651 mods
[i
].irefsym
= 0;
3652 mods
[i
].nrefsym
= 0;
3655 mods64
[i
].irefsym
= 0;
3656 mods64
[i
].nrefsym
= 0;
3660 if(object
->mh
!= NULL
){
3661 mods
[i
].irefsym
= ref_saves
[j
] - 1;
3662 mods
[i
].nrefsym
= n
;
3665 mods64
[i
].irefsym
= ref_saves
[j
] - 1;
3666 mods64
[i
].nrefsym
= n
;
3672 * Create a new reference table.
3674 new_refs
= allocate(new_nextrefsyms
* sizeof(struct dylib_reference
));
3676 for(i
= 0; i
< nextrefsyms
; i
++){
3678 if(saves
[refs
[i
].isym
]){
3679 new_refs
[j
].isym
= saves
[refs
[i
].isym
] - 1;
3680 new_refs
[j
].flags
= refs
[i
].flags
;
3683 if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
||
3684 refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
){
3685 new_refs
[j
].isym
= changes
[refs
[i
].isym
] - 1;
3686 new_refs
[j
].flags
= refs
[i
].flags
;
3694 * Create a new dylib table of contents.
3697 for(i
= 0; i
< ntoc
; i
++){
3698 if(tocs
[i
].symbol_index
>= nsyms
){
3699 error_arch(arch
, member
, "bad symbol index for table of "
3700 "contents table entry %d in: ", i
);
3703 if(saves
[tocs
[i
].symbol_index
] != 0 &&
3704 changes
[tocs
[i
].symbol_index
] == 0)
3707 new_tocs
= allocate(new_ntoc
* sizeof(struct dylib_table_of_contents
));
3709 for(i
= 0; i
< ntoc
; i
++){
3710 if(saves
[tocs
[i
].symbol_index
] != 0 &&
3711 changes
[tocs
[i
].symbol_index
] == 0){
3712 new_tocs
[j
].symbol_index
= saves
[tocs
[i
].symbol_index
] - 1;
3713 new_tocs
[j
].module_index
= tocs
[i
].module_index
;
3719 * Update the export trie if it has one but only call the the
3720 * prune_trie() routine when we are removing global symbols as is
3721 * done with default stripping of a dyld executable or with the -s
3724 if(object
->dyld_info
!= NULL
&&
3725 object
->dyld_info
->export_size
!= 0 &&
3726 (default_dyld_executable
|| sfile
!= NULL
|| Rfile
!= NULL
)){
3727 const char *error_string
;
3728 uint32_t trie_new_size
;
3730 error_string
= prune_trie((uint8_t *)(object
->object_addr
+
3731 object
->dyld_info
->export_off
),
3732 object
->dyld_info
->export_size
,
3735 if(error_string
!= NULL
){
3736 error_arch(arch
, member
, "%s", error_string
);
3740 #endif /* TRIE_SUPPORT */
3742 if(undef_map
!= NULL
)
3744 if(undef_map64
!= NULL
)
3748 if(sections
!= NULL
)
3750 if(sections64
!= NULL
)
3761 * prune() is called by prune_trie() and passed a name of an external symbol
3762 * in the trie. It returns 1 if the symbols is to be pruned out and 0 if the
3763 * symbol is to be kept.
3765 * Note that it may seem like a linear search of the new symbols would not be
3766 * the best approach but in 10.6 the only defined global symbol left in a
3767 * stripped executable is __mh_execute_header and new_nextdefsym is usually 1
3768 * so this never actually loops in practice.
3777 for(i
= 0; i
< new_nextdefsym
; i
++){
3778 if(new_symbols
!= NULL
){
3779 if(strcmp(name
, new_strings
+ new_symbols
[inew_nextdefsym
+ i
]
3784 if(strcmp(name
, new_strings
+ new_symbols64
[inew_nextdefsym
+ i
]
3791 #endif /* TRIE_SUPPORT */
3794 * make_ld_r_object() takes the object file contents referenced by the passed
3795 * data structures, writes that to a temporary file, runs "ld -r" plus the
3796 * specified stripping option creating a second temporary file, reads that file
3797 * in and replaces the object file contents with that and resets the variables
3798 * pointing to the symbol, string and indirect tables.
3804 struct member
*member
,
3805 struct object
*object
)
3807 enum byte_sex host_byte_sex
;
3808 char *input_file
, *output_file
;
3810 struct ofile
*ld_r_ofile
;
3811 struct arch
*ld_r_archs
;
3812 uint32_t ld_r_narchs
, save_errors
;
3814 host_byte_sex
= get_host_byte_sex();
3817 * Swap the object file back into its bytesex before writing it to the
3818 * temporary file if needed.
3820 if(object
->object_byte_sex
!= host_byte_sex
){
3821 if(object
->mh
!= NULL
){
3822 if(swap_object_headers(object
->mh
, object
->load_commands
) ==
3824 fatal("internal error: swap_object_headers() failed");
3825 swap_nlist(symbols
, nsyms
, object
->object_byte_sex
);
3828 if(swap_object_headers(object
->mh64
, object
->load_commands
) ==
3830 fatal("internal error: swap_object_headers() failed");
3831 swap_nlist_64(symbols64
, nsyms
, object
->object_byte_sex
);
3833 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
3834 object
->object_byte_sex
);
3838 * Create an input object file for the ld -r command from the bytes
3839 * of this arch's object file.
3841 input_file
= makestr("/tmp/strip.XXXXXX", NULL
);
3842 input_file
= mktemp(input_file
);
3844 if((fd
= open(input_file
, O_WRONLY
|O_CREAT
, 0600)) < 0)
3845 system_fatal("can't open temporary file: %s", input_file
);
3847 if(write(fd
, object
->object_addr
, object
->object_size
) !=
3848 object
->object_size
)
3849 system_fatal("can't write temporary file: %s", input_file
);
3852 system_fatal("can't close temporary file: %s", input_file
);
3855 * Create a temporary name for the output file of the ld -r
3857 output_file
= makestr("/tmp/strip.XXXXXX", NULL
);
3858 output_file
= mktemp(output_file
);
3861 * Create the ld -r command line and execute it.
3863 reset_execute_list();
3864 add_execute_list_with_prefix("ld");
3865 add_execute_list("-keep_private_externs");
3866 add_execute_list("-r");
3868 add_execute_list("-S");
3870 add_execute_list("-x");
3871 add_execute_list(input_file
);
3872 add_execute_list("-o");
3873 add_execute_list(output_file
);
3875 add_execute_list("-x");
3876 add_execute_list("-exported_symbols_list");
3877 add_execute_list(sfile
);
3880 add_execute_list("-unexported_symbols_list");
3881 add_execute_list(Rfile
);
3883 if(execute_list(vflag
) == 0)
3884 fatal("internal link edit command failed");
3886 save_errors
= errors
;
3888 /* breakout the output file of the ld -f for processing */
3889 ld_r_ofile
= breakout(output_file
, &ld_r_archs
, &ld_r_narchs
, FALSE
);
3891 goto make_ld_r_object_cleanup
;
3893 /* checkout the file for symbol table replacement processing */
3894 checkout(ld_r_archs
, ld_r_narchs
);
3897 * Make sure the output of the ld -r is an object file with one arch.
3899 if(ld_r_narchs
!= 1 ||
3900 ld_r_archs
->type
!= OFILE_Mach_O
||
3901 ld_r_archs
->object
== NULL
||
3902 ld_r_archs
->object
->mh_filetype
!= MH_OBJECT
)
3903 fatal("internal link edit command failed to produce a thin Mach-O "
3907 * Now reset all the data of the input object with the ld -r output
3910 nsyms
= ld_r_archs
->object
->st
->nsyms
;
3911 if(ld_r_archs
->object
->mh
!= NULL
){
3912 symbols
= (struct nlist
*)
3913 (ld_r_archs
->object
->object_addr
+
3914 ld_r_archs
->object
->st
->symoff
);
3915 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3916 swap_nlist(symbols
, nsyms
, host_byte_sex
);
3921 symbols64
= (struct nlist_64
*)
3922 (ld_r_archs
->object
->object_addr
+
3923 ld_r_archs
->object
->st
->symoff
);
3924 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3925 swap_nlist_64(symbols64
, nsyms
, host_byte_sex
);
3927 strings
= ld_r_archs
->object
->object_addr
+
3928 ld_r_archs
->object
->st
->stroff
;
3929 strsize
= ld_r_archs
->object
->st
->strsize
;
3931 if(ld_r_archs
->object
->dyst
!= NULL
&&
3932 ld_r_archs
->object
->dyst
->nindirectsyms
!= 0){
3933 nindirectsyms
= ld_r_archs
->object
->dyst
->nindirectsyms
;
3934 indirectsyms
= (uint32_t *)
3935 (ld_r_archs
->object
->object_addr
+
3936 ld_r_archs
->object
->dyst
->indirectsymoff
);
3937 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3938 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
3942 indirectsyms
= NULL
;
3946 if(ld_r_archs
->object
->mh
!= NULL
)
3947 ld_r_archs
->object
->input_sym_info_size
=
3948 nsyms
* sizeof(struct nlist
) +
3951 ld_r_archs
->object
->input_sym_info_size
=
3952 nsyms
* sizeof(struct nlist_64
) +
3956 * Copy over the object struct from the ld -r object file onto the
3957 * input object file.
3959 *object
= *ld_r_archs
->object
;
3962 * Save the ofile struct for the ld -r output so it can be umapped when
3963 * we are done. And free up the ld_r_archs now that we are done with
3966 object
->ld_r_ofile
= ld_r_ofile
;
3967 free_archs(ld_r_archs
, ld_r_narchs
);
3969 make_ld_r_object_cleanup
:
3970 errors
+= save_errors
;
3972 * Remove the input and output files and clean up.
3974 if(unlink(input_file
) == -1)
3975 system_fatal("can't remove temporary file: %s", input_file
);
3976 if(unlink(output_file
) == -1)
3977 system_fatal("can't remove temporary file: %s", output_file
);
3983 * strip_LC_UUID_commands() is called when -no_uuid is specified to remove any
3984 * LC_UUID load commands from the object's load commands.
3988 strip_LC_UUID_commands(
3990 struct member
*member
,
3991 struct object
*object
)
3993 uint32_t i
, ncmds
, nuuids
, mh_sizeofcmds
, sizeofcmds
;
3994 struct load_command
*lc1
, *lc2
, *new_load_commands
;
3995 struct segment_command
*sg
;
3998 * See if there are any LC_UUID load commands.
4001 lc1
= arch
->object
->load_commands
;
4002 if(arch
->object
->mh
!= NULL
){
4003 ncmds
= arch
->object
->mh
->ncmds
;
4004 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
4007 ncmds
= arch
->object
->mh64
->ncmds
;
4008 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
4010 for(i
= 0; i
< ncmds
; i
++){
4011 if(lc1
->cmd
== LC_UUID
){
4014 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4016 /* if no LC_UUID load commands just return */
4021 * Allocate space for the new load commands as zero it out so any holes
4022 * will be zero bytes.
4024 new_load_commands
= allocate(mh_sizeofcmds
);
4025 memset(new_load_commands
, '\0', mh_sizeofcmds
);
4028 * Copy all the load commands except the LC_UUID load commands into the
4029 * allocated space for the new load commands.
4031 lc1
= arch
->object
->load_commands
;
4032 lc2
= new_load_commands
;
4034 for(i
= 0; i
< ncmds
; i
++){
4035 if(lc1
->cmd
!= LC_UUID
){
4036 memcpy(lc2
, lc1
, lc1
->cmdsize
);
4037 sizeofcmds
+= lc2
->cmdsize
;
4038 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
4040 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4044 * Finally copy the updated load commands over the existing load
4047 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
4048 if(mh_sizeofcmds
> sizeofcmds
){
4049 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
4050 (mh_sizeofcmds
- sizeofcmds
));
4053 if(arch
->object
->mh
!= NULL
) {
4054 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
4055 arch
->object
->mh
->ncmds
= ncmds
;
4057 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
4058 arch
->object
->mh64
->ncmds
= ncmds
;
4060 free(new_load_commands
);
4062 /* reset the pointers into the load commands */
4063 lc1
= arch
->object
->load_commands
;
4064 for(i
= 0; i
< ncmds
; i
++){
4067 arch
->object
->st
= (struct symtab_command
*)lc1
;
4070 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
4072 case LC_TWOLEVEL_HINTS
:
4073 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
4075 case LC_PREBIND_CKSUM
:
4076 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
4079 sg
= (struct segment_command
*)lc1
;
4080 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
4081 arch
->object
->seg_linkedit
= sg
;
4083 case LC_SEGMENT_SPLIT_INFO
:
4084 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
4086 case LC_FUNCTION_STARTS
:
4087 object
->func_starts_info_cmd
=
4088 (struct linkedit_data_command
*)lc1
;
4090 case LC_CODE_SIGNATURE
:
4091 object
->code_sig_cmd
= (struct linkedit_data_command
*)lc1
;
4093 case LC_DYLD_INFO_ONLY
:
4095 object
->dyld_info
= (struct dyld_info_command
*)lc1
;
4097 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4103 * strip_LC_CODE_SIGNATURE_commands() is called when -c is specified to remove
4104 * any LC_CODE_SIGNATURE load commands from the object's load commands.
4108 strip_LC_CODE_SIGNATURE_commands(
4110 struct member
*member
,
4111 struct object
*object
)
4113 uint32_t i
, ncmds
, mh_sizeofcmds
, sizeofcmds
;
4114 struct load_command
*lc1
, *lc2
, *new_load_commands
;
4115 struct segment_command
*sg
;
4118 * See if there is an LC_CODE_SIGNATURE load command and if no command
4121 if(object
->code_sig_cmd
== NULL
)
4125 * Allocate space for the new load commands and zero it out so any holes
4126 * will be zero bytes.
4128 if(arch
->object
->mh
!= NULL
){
4129 ncmds
= arch
->object
->mh
->ncmds
;
4130 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
4133 ncmds
= arch
->object
->mh64
->ncmds
;
4134 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
4136 new_load_commands
= allocate(mh_sizeofcmds
);
4137 memset(new_load_commands
, '\0', mh_sizeofcmds
);
4140 * Copy all the load commands except the LC_CODE_SIGNATURE load commands
4141 * into the allocated space for the new load commands.
4143 lc1
= arch
->object
->load_commands
;
4144 lc2
= new_load_commands
;
4146 for(i
= 0; i
< ncmds
; i
++){
4147 if(lc1
->cmd
!= LC_CODE_SIGNATURE
){
4148 memcpy(lc2
, lc1
, lc1
->cmdsize
);
4149 sizeofcmds
+= lc2
->cmdsize
;
4150 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
4152 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4156 * Finally copy the updated load commands over the existing load
4159 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
4160 if(mh_sizeofcmds
> sizeofcmds
){
4161 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
4162 (mh_sizeofcmds
- sizeofcmds
));
4165 if(arch
->object
->mh
!= NULL
) {
4166 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
4167 arch
->object
->mh
->ncmds
= ncmds
;
4169 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
4170 arch
->object
->mh64
->ncmds
= ncmds
;
4172 free(new_load_commands
);
4174 /* reset the pointers into the load commands */
4175 object
->code_sig_cmd
= NULL
;
4176 lc1
= arch
->object
->load_commands
;
4177 for(i
= 0; i
< ncmds
; i
++){
4180 arch
->object
->st
= (struct symtab_command
*)lc1
;
4183 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
4185 case LC_TWOLEVEL_HINTS
:
4186 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
4188 case LC_PREBIND_CKSUM
:
4189 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
4192 sg
= (struct segment_command
*)lc1
;
4193 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
4194 arch
->object
->seg_linkedit
= sg
;
4196 case LC_SEGMENT_SPLIT_INFO
:
4197 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
4199 case LC_FUNCTION_STARTS
:
4200 object
->func_starts_info_cmd
=
4201 (struct linkedit_data_command
*)lc1
;
4204 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4209 * To get the right amount of the file copied out by writeout() for
4210 * the case when we are stripping out the section contents we
4211 * already reduce the object size by the size of the section
4212 * contents including the padding after the load commands. So here
4213 * we need to further reduce it by the load command for the
4214 * LC_CODE_SIGNATURE (a struct linkedit_data_command) we are
4217 object
->object_size
-= sizeof(struct linkedit_data_command
);
4219 * Then this size minus the size of the input symbolic information
4220 * is what is copied out from the file by writeout(). Which in this
4221 * case is just the new headers.
4225 * Finally for -c the file offset to the link edit information is to
4226 * be right after the load commands. So reset this for the updated
4227 * size of the load commands without the LC_CODE_SIGNATURE.
4229 if(object
->mh
!= NULL
)
4230 object
->seg_linkedit
->fileoff
= sizeof(struct mach_header
) +
4233 object
->seg_linkedit64
->fileoff
=
4234 sizeof(struct mach_header_64
) + sizeofcmds
;
4237 #endif /* !(NMEDIT) */
4240 * private_extern_reference_by_module() is passed a symbol_index of a private
4241 * extern symbol and the module table. If the symbol_index appears in the
4242 * module symbol table this returns TRUE else it returns FALSE.
4246 private_extern_reference_by_module(
4247 uint32_t symbol_index
,
4248 struct dylib_reference
*refs
,
4249 uint32_t nextrefsyms
)
4253 for(i
= 0; i
< nextrefsyms
; i
++){
4254 if(refs
[i
].isym
== symbol_index
){
4255 if(refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
||
4256 refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
){
4265 * symbol_pointer_used() is passed a symbol_index and the indirect table. If
4266 * the symbol_index appears in the indirect symbol table this returns TRUE else
4271 symbol_pointer_used(
4272 uint32_t symbol_index
,
4273 uint32_t *indirectsyms
,
4274 uint32_t nindirectsyms
)
4278 for(i
= 0; i
< nindirectsyms
; i
++){
4279 if(indirectsyms
[i
] == symbol_index
)
4286 * Function for qsort for comparing undefined map entries.
4290 cmp_qsort_undef_map(
4291 const struct undef_map
*sym1
,
4292 const struct undef_map
*sym2
)
4294 return(strcmp(qsort_strings
+ sym1
->symbol
.n_un
.n_strx
,
4295 qsort_strings
+ sym2
->symbol
.n_un
.n_strx
));
4300 cmp_qsort_undef_map_64(
4301 const struct undef_map64
*sym1
,
4302 const struct undef_map64
*sym2
)
4304 return(strcmp(qsort_strings
+ sym1
->symbol64
.n_un
.n_strx
,
4305 qsort_strings
+ sym2
->symbol64
.n_un
.n_strx
));
4307 #endif /* !defined(NMEDIT) */
4311 * Function for qsort for comparing object names.
4319 return(strcmp(*name1
, *name2
));
4323 * Function for bsearch for finding a object name.
4327 cmp_bsearch_filename(
4331 return(strcmp(name1
, *name2
));
4333 #endif /* !defined(NMEDIT) */
4340 struct member
*member
,
4341 struct object
*object
,
4342 struct nlist
*symbols
,
4343 struct nlist_64
*symbols64
,
4347 struct dylib_table_of_contents
*tocs
,
4349 struct dylib_module
*mods
,
4350 struct dylib_module_64
*mods64
,
4352 struct dylib_reference
*refs
,
4353 uint32_t nextrefsyms
)
4356 unsigned char data_n_sect
, nsects
;
4357 struct load_command
*lc
;
4358 struct segment_command
*sg
;
4359 struct segment_command_64
*sg64
;
4360 struct section
*s
, **sections
;
4361 struct section_64
*s64
, **sections64
;
4363 uint32_t missing_syms
;
4364 struct symbol_list
*sp
;
4365 struct nlist
**global_symbol
;
4366 struct nlist_64
**global_symbol64
;
4367 enum bool global_symbol_found
;
4368 char *global_name
, save_char
;
4369 enum bool dwarf_debug_map
;
4370 enum byte_sex host_byte_sex
;
4371 int32_t missing_reloc_symbols
;
4372 enum bool edit_symtab_return
;
4375 uint32_t new_ext_strsize
, len
, inew_syms
;
4377 struct nlist
**changed_globals
;
4378 struct nlist_64
**changed_globals64
;
4379 uint32_t nchanged_globals
;
4380 uint32_t ncmds
, s_flags
, n_strx
, module_name
, ilocalsym
, nlocalsym
;
4381 uint32_t iextdefsym
, nextdefsym
;
4382 uint8_t n_type
, n_sect
, global_symbol_n_sect
;
4384 enum bool warned_about_global_coalesced_symbols
;
4386 edit_symtab_return
= TRUE
;
4387 host_byte_sex
= get_host_byte_sex();
4388 missing_reloc_symbols
= 0;
4389 warned_about_global_coalesced_symbols
= FALSE
;
4393 nmedits
= allocate(nsyms
* sizeof(enum bool));
4394 for(i
= 0; i
< nsyms
; i
++)
4398 * If nmedit is operating on a dynamic library then symbols are turned
4399 * into private externs with the extern bit off not into static symbols.
4401 if(object
->mh_filetype
== MH_DYLIB
&& pflag
== TRUE
){
4402 error_arch(arch
, member
, "can't use -p with dynamic libraries");
4407 * As part of the MAJOR guess for the second pass to fix stabs for the
4408 * globals symbols that get turned into non-global symbols. We need to
4409 * change the stabs. To do this we to know if a N_GSYM is for a data
4410 * symbol or not to know to turn it into an N_STSYM or a N_FUN.
4411 * This logic as determined by compiling test cases with and without
4412 * the key word 'static' and looking at the difference between the STABS
4413 * the compiler generates and trying to match that here.
4415 * We also use this loop and the next to gather an array of section
4416 * struct pointers so we can later determine if we run into a global
4417 * symbol in a coalesced section and not turn those symbols into
4423 data_n_sect
= NO_SECT
;
4424 lc
= object
->load_commands
;
4425 if(object
->mh
!= NULL
)
4426 ncmds
= object
->mh
->ncmds
;
4428 ncmds
= object
->mh64
->ncmds
;
4429 for(i
= 0; i
< ncmds
; i
++){
4430 if(lc
->cmd
== LC_SEGMENT
){
4431 sg
= (struct segment_command
*)lc
;
4432 s
= (struct section
*)((char *)sg
+
4433 sizeof(struct segment_command
));
4434 nsects
+= sg
->nsects
;
4435 for(j
= 0; j
< sg
->nsects
; j
++){
4436 if(strcmp(s
->segname
, SEG_DATA
) == 0 &&
4437 strcmp(s
->sectname
, SECT_DATA
) == 0 &&
4438 data_n_sect
== NO_SECT
){
4439 data_n_sect
= n_sect
;
4446 else if(lc
->cmd
== LC_SEGMENT_64
){
4447 sg64
= (struct segment_command_64
*)lc
;
4448 s64
= (struct section_64
*)((char *)sg64
+
4449 sizeof(struct segment_command_64
));
4450 nsects
+= sg64
->nsects
;
4451 for(j
= 0; j
< sg64
->nsects
; j
++){
4452 if(strcmp(s64
->segname
, SEG_DATA
) == 0 &&
4453 strcmp(s64
->sectname
, SECT_DATA
) == 0 &&
4454 data_n_sect
== NO_SECT
){
4455 data_n_sect
= n_sect
;
4462 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
4464 if(object
->mh
!= NULL
){
4465 sections
= allocate(nsects
* sizeof(struct section
*));
4470 sections64
= allocate(nsects
* sizeof(struct section_64
*));
4473 lc
= object
->load_commands
;
4474 for(i
= 0; i
< ncmds
; i
++){
4475 if(lc
->cmd
== LC_SEGMENT
){
4476 sg
= (struct segment_command
*)lc
;
4477 s
= (struct section
*)((char *)sg
+
4478 sizeof(struct segment_command
));
4479 for(j
= 0; j
< sg
->nsects
; j
++){
4480 sections
[nsects
++] = s
++;
4483 else if(lc
->cmd
== LC_SEGMENT_64
){
4484 sg64
= (struct segment_command_64
*)lc
;
4485 s64
= (struct section_64
*)((char *)sg64
+
4486 sizeof(struct segment_command_64
));
4487 for(j
= 0; j
< sg64
->nsects
; j
++){
4488 sections64
[nsects
++] = s64
++;
4491 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
4495 * Zero out the saved symbols so they can be recorded for this file.
4497 for(i
= 0; i
< nsave_symbols
; i
++)
4498 save_symbols
[i
].sym
= NULL
;
4499 for(i
= 0; i
< nremove_symbols
; i
++)
4500 remove_symbols
[i
].sym
= NULL
;
4502 for(i
= 0; i
< nsave_symbols
; i
++)
4503 save_symbols
[i
].seen
= FALSE
;
4504 for(i
= 0; i
< nremove_symbols
; i
++)
4505 remove_symbols
[i
].seen
= FALSE
;
4508 nchanged_globals
= 0;
4509 if(object
->mh
!= NULL
){
4510 changed_globals
= allocate(nsyms
* sizeof(struct nlist
*));
4511 changed_globals64
= NULL
;
4512 for(i
= 0; i
< nsyms
; i
++)
4513 changed_globals
[i
] = NULL
;
4516 changed_globals
= NULL
;
4517 changed_globals64
= allocate(nsyms
* sizeof(struct nlist_64
*));
4518 for(i
= 0; i
< nsyms
; i
++)
4519 changed_globals64
[i
] = NULL
;
4523 * These are the variables for the new symbol table and new string
4524 * table. Since this routine only turns globals into non-globals the
4525 * number of symbols does not change. But the count of local, defined
4526 * external symbols does change.
4533 new_strsize
= sizeof(int32_t);
4534 new_ext_strsize
= 0;
4537 * First pass: turn the globals symbols into non-global symbols.
4539 for(i
= 0; i
< nsyms
; i
++){
4542 if(object
->mh
!= NULL
){
4543 n_strx
= symbols
[i
].n_un
.n_strx
;
4544 n_type
= symbols
[i
].n_type
;
4545 n_sect
= symbols
[i
].n_sect
;
4546 if((n_type
& N_TYPE
) == N_SECT
)
4547 s_flags
= sections
[n_sect
- 1]->flags
;
4548 n_value
= symbols
[i
].n_value
;
4551 n_strx
= symbols64
[i
].n_un
.n_strx
;
4552 n_type
= symbols64
[i
].n_type
;
4553 n_sect
= symbols64
[i
].n_sect
;
4554 if((n_type
& N_TYPE
) == N_SECT
)
4555 s_flags
= sections64
[n_sect
- 1]->flags
;
4556 n_value
= symbols64
[i
].n_value
;
4559 if(n_strx
> strsize
){
4560 error_arch(arch
, member
, "bad string index for symbol "
4561 "table entry %u in: ", i
);
4564 len
= strlen(strings
+ n_strx
) + 1;
4567 if((n_type
& N_TYPE
) != N_UNDF
&&
4568 (n_type
& N_TYPE
) != N_PBUD
){
4569 if((n_type
& N_TYPE
) == N_SECT
){
4570 if(n_sect
> nsects
){
4571 error_arch(arch
, member
, "bad n_sect for symbol "
4572 "table entry %u in: ", i
);
4575 if(((s_flags
& SECTION_TYPE
) == S_COALESCED
) &&
4577 object
->mh_filetype
!= MH_OBJECT
){
4578 /* this remains a global defined symbol */
4579 if(warned_about_global_coalesced_symbols
== FALSE
){
4580 warning_arch(arch
, member
, "can't make global "
4581 "coalesced symbols (like %s) into static "
4582 "symbols (use ld(1)'s "
4583 "-exported_symbols_list option) in a final "
4584 "linked image: ", strings
+ n_strx
);
4585 warned_about_global_coalesced_symbols
= TRUE
;
4588 new_ext_strsize
+= len
;
4590 sp
= bsearch(strings
+ n_strx
,
4591 remove_symbols
, nremove_symbols
,
4592 sizeof(struct symbol_list
),
4593 (int (*)(const void *, const void *))
4594 symbol_list_bsearch
);
4596 if(sp
->sym
!= NULL
){
4597 error_arch(arch
, member
, "more than one "
4598 "symbol for: %s found in: ", sp
->name
);
4602 if(object
->mh
!= NULL
)
4603 sp
->sym
= &(symbols
[i
]);
4605 sp
->sym
= &(symbols64
[i
]);
4607 warning_arch(arch
, member
, "can't make "
4608 "global coalesced symbol: %s into a "
4609 "static symbol in: ", sp
->name
);
4613 * In case the user has listed this coalesced
4614 * symbol in the save list look for it and mark it
4615 * as seen so we don't complain about not seeing it.
4617 sp
= bsearch(strings
+ n_strx
,
4618 save_symbols
, nsave_symbols
,
4619 sizeof(struct symbol_list
),
4620 (int (*)(const void *, const void *))
4621 symbol_list_bsearch
);
4623 if(sp
->sym
!= NULL
){
4624 error_arch(arch
, member
, "more than one "
4625 "symbol for: %s found in: ", sp
->name
);
4629 if(object
->mh
!= NULL
)
4630 sp
->sym
= &(symbols
[i
]);
4632 sp
->sym
= &(symbols64
[i
]);
4636 continue; /* leave this symbol unchanged */
4639 sp
= bsearch(strings
+ n_strx
,
4640 remove_symbols
, nremove_symbols
,
4641 sizeof(struct symbol_list
),
4642 (int (*)(const void *, const void *))
4643 symbol_list_bsearch
);
4645 if(sp
->sym
!= NULL
){
4646 error_arch(arch
, member
, "more than one symbol "
4647 "for: %s found in: ", sp
->name
);
4651 if(object
->mh
!= NULL
)
4652 sp
->sym
= &(symbols
[i
]);
4654 sp
->sym
= &(symbols64
[i
]);
4661 * If there is no list of saved symbols, then all
4662 * symbols will be saved unless listed in the remove
4667 * There is no save list, so if there is also no
4668 * remove list but the -p flag is specified or it is
4669 * a dynamic library then change all symbols.
4671 if((pflag
|| object
->mh_filetype
== MH_DYLIB
)
4672 && nremove_symbols
== 0)
4674 /* this remains a global defined symbol */
4676 new_ext_strsize
+= len
;
4678 continue; /* leave this symbol unchanged */
4681 sp
= bsearch(strings
+ n_strx
,
4682 save_symbols
, nsave_symbols
,
4683 sizeof(struct symbol_list
),
4684 (int (*)(const void *, const void *))
4685 symbol_list_bsearch
);
4687 if(sp
->sym
!= NULL
){
4688 error_arch(arch
, member
, "more than one symbol "
4689 "for: %s found in: ", sp
->name
);
4693 if(object
->mh
!= NULL
)
4694 sp
->sym
= &(symbols
[i
]);
4696 sp
->sym
= &(symbols64
[i
]);
4698 /* this remains a global defined symbol */
4700 new_ext_strsize
+= len
;
4705 if(Aflag
&& n_type
== (N_EXT
| N_ABS
) &&
4708 strncmp(strings
+ n_strx
,
4709 ".objc_class_name_",
4710 sizeof(".objc_class_name_") - 1) == 0))){
4711 /* this remains a global defined symbol */
4713 new_ext_strsize
+= len
;
4718 if((n_type
& N_TYPE
) != N_INDR
){
4720 if(object
->mh
!= NULL
)
4721 changed_globals
[nchanged_globals
++] =
4724 changed_globals64
[nchanged_globals
++] =
4727 /* this remains a global defined symbol */
4729 new_ext_strsize
+= len
;
4733 /* this will become a non-global symbol */
4739 /* this remains a global defined symbol */
4741 new_ext_strsize
+= len
;
4748 /* this is an undefined symbol */
4750 new_ext_strsize
+= len
;
4755 /* this is a local symbol */
4762 * The module table's module names are placed with the external
4763 * strings. So size them and add this to the external string size.
4765 for(i
= 0; i
< nmodtab
; i
++){
4766 if(object
->mh
!= NULL
)
4767 module_name
= mods
[i
].module_name
;
4769 module_name
= mods64
[i
].module_name
;
4770 if(module_name
== 0 || module_name
> strsize
){
4771 error_arch(arch
, member
, "bad string index for module_name "
4772 "of module table entry %d in: ", i
);
4775 len
= strlen(strings
+ module_name
) + 1;
4777 new_ext_strsize
+= len
;
4781 * Warn about symbols to be saved that were missing.
4786 for(i
= 0; i
< nsave_symbols
; i
++){
4787 if(save_symbols
[i
].sym
== NULL
){
4788 if(missing_syms
== 0){
4789 error_arch(arch
, member
, "symbols names listed "
4790 "in: %s not in: ", sfile
);
4793 fprintf(stderr
, "%s\n", save_symbols
[i
].name
);
4796 for(i
= 0; i
< nremove_symbols
; i
++){
4797 if(remove_symbols
[i
].sym
== NULL
){
4798 if(missing_syms
== 0){
4799 error_arch(arch
, member
, "symbols names listed "
4800 "in: %s not in: ", Rfile
);
4803 fprintf(stderr
, "%s\n", remove_symbols
[i
].name
);
4810 * Second pass: fix stabs for the globals symbols that got turned into
4811 * non-global symbols. This is a MAJOR guess. The specific changes
4812 * to do here were determined by compiling test cases with and without
4813 * the key word 'static' and looking at the difference between the STABS
4814 * the compiler generates and trying to match that here.
4816 global_strings
= strings
;
4817 if(object
->mh
!= NULL
)
4818 qsort(changed_globals
, nchanged_globals
, sizeof(struct nlist
*),
4819 (int (*)(const void *, const void *))cmp_qsort_global
);
4821 qsort(changed_globals64
, nchanged_globals
,sizeof(struct nlist_64
*),
4822 (int (*)(const void *, const void *))cmp_qsort_global_64
);
4823 dwarf_debug_map
= FALSE
;
4824 for(i
= 0; i
< nsyms
; i
++){
4826 if(object
->mh
!= NULL
){
4827 n_strx
= symbols
[i
].n_un
.n_strx
;
4828 n_type
= symbols
[i
].n_type
;
4829 n_desc
= symbols
[i
].n_desc
;
4832 n_strx
= symbols64
[i
].n_un
.n_strx
;
4833 n_type
= symbols64
[i
].n_type
;
4834 n_desc
= symbols64
[i
].n_desc
;
4837 dwarf_debug_map
= FALSE
;
4838 else if (n_type
== N_OSO
)
4839 dwarf_debug_map
= n_desc
!= 0;
4840 else if (dwarf_debug_map
&& n_type
== N_GSYM
){
4841 global_name
= strings
+ n_strx
;
4842 if(object
->mh
!= NULL
){
4843 global_symbol
= bsearch(global_name
, changed_globals
,
4844 nchanged_globals
,sizeof(struct nlist
*),
4845 (int (*)(const void *, const void *))
4846 cmp_bsearch_global
);
4847 if(global_symbol
!= NULL
){
4848 symbols
[i
].n_type
= N_STSYM
;
4849 symbols
[i
].n_sect
= (*global_symbol
)->n_sect
;
4850 symbols
[i
].n_value
= (*global_symbol
)->n_value
;
4854 global_symbol64
= bsearch(global_name
, changed_globals64
,
4856 sizeof(struct nlist_64
*),
4857 (int (*)(const void *, const void *))
4858 cmp_bsearch_global_64
);
4859 if(global_symbol64
!= NULL
){
4860 symbols64
[i
].n_type
= N_STSYM
;
4861 symbols64
[i
].n_sect
= (*global_symbol64
)->n_sect
;
4862 symbols64
[i
].n_value
= (*global_symbol64
)->n_value
;
4866 else if(! dwarf_debug_map
&&
4867 (n_type
== N_GSYM
|| n_type
== N_FUN
) &&
4868 (n_strx
!= 0 && strings
[n_strx
] != '\0')){
4869 global_name
= strings
+ n_strx
;
4870 if((global_name
[0] == '+' || global_name
[0] == '-') &&
4871 global_name
[1] == '['){
4873 while(j
+ n_strx
< strsize
&& global_name
[j
] != ']')
4875 if(j
+ n_strx
< strsize
&& global_name
[j
] == ']')
4880 while(j
+ n_strx
< strsize
&& global_name
[j
] != ':')
4882 if(j
+ n_strx
>= strsize
){
4883 error_arch(arch
, member
, "bad N_STAB symbol name for entry "
4884 "%u (does not contain ':' separating name from type) "
4888 save_char
= global_name
[j
];
4889 global_name
[j
] = '\0';
4891 global_symbol_found
= FALSE
;
4892 global_symbol_n_sect
= 0;
4893 if(object
->mh
!= NULL
){
4894 global_symbol
= bsearch(global_name
, changed_globals
,
4895 nchanged_globals
,sizeof(struct nlist
*),
4896 (int (*)(const void *, const void *))
4897 cmp_bsearch_global_stab
);
4898 global_symbol64
= NULL
;
4899 if(global_symbol
!= NULL
){
4900 global_symbol_found
= TRUE
;
4901 global_symbol_n_sect
= (*global_symbol
)->n_sect
;
4905 global_symbol64
= bsearch(global_name
, changed_globals64
,
4907 sizeof(struct nlist_64
*),
4908 (int (*)(const void *, const void *))
4909 cmp_bsearch_global_stab_64
);
4910 global_symbol
= NULL
;
4911 if(global_symbol64
!= NULL
){
4912 global_symbol_found
= TRUE
;
4913 global_symbol_n_sect
= (*global_symbol64
)->n_sect
;
4916 global_name
[j
] = save_char
;
4917 if(global_symbol_found
== TRUE
){
4918 if(n_type
== N_GSYM
){
4919 if(global_symbol_n_sect
== data_n_sect
){
4920 if(object
->mh
!= NULL
)
4921 symbols
[i
].n_type
= N_STSYM
;
4923 symbols64
[i
].n_type
= N_STSYM
;
4926 if(object
->mh
!= NULL
)
4927 symbols
[i
].n_type
= N_FUN
;
4929 symbols64
[i
].n_type
= N_FUN
;
4931 if(object
->mh
!= NULL
){
4932 symbols
[i
].n_sect
= (*global_symbol
)->n_sect
;
4933 symbols
[i
].n_value
= (*global_symbol
)->n_value
;
4934 symbols
[i
].n_desc
= (*global_symbol
)->n_desc
;
4937 symbols64
[i
].n_sect
= (*global_symbol64
)->n_sect
;
4938 symbols64
[i
].n_value
= (*global_symbol64
)->n_value
;
4939 symbols64
[i
].n_desc
= (*global_symbol64
)->n_desc
;
4941 if(j
+ 1 + n_strx
>= strsize
||
4942 global_name
[j
+1] != 'G'){
4943 error_arch(arch
, member
, "bad N_GSYM symbol name "
4944 "for entry %u (does not have type 'G' after "
4945 "':' in name) in: ", i
);
4948 global_name
[j
+1] = 'S';
4950 else{ /* n_type == N_FUN */
4951 if(j
+ 1 + n_strx
>= strsize
||
4952 global_name
[j
+1] == 'F'){
4953 global_name
[j
+1] = 'f';
4959 global_strings
= NULL
;
4962 * Now what needs to be done is to create the new symbol table moving
4963 * those global symbols being changed into non-globals into the areas
4964 * in the symbol table for local symbols. The symbol table and string
4965 * table must be in this order:
4969 * external defined symbols
4977 saves
= (int32_t *)allocate(nsyms
* sizeof(int32_t));
4978 bzero(saves
, nsyms
* sizeof(int32_t));
4980 if(object
->mh
!= NULL
){
4981 new_symbols
= (struct nlist
*)
4982 allocate(new_nsyms
* sizeof(struct nlist
));
4983 new_symbols64
= NULL
;
4987 new_symbols64
= (struct nlist_64
*)
4988 allocate(new_nsyms
* sizeof(struct nlist_64
));
4990 new_strsize
= rnd(new_strsize
, sizeof(int32_t));
4991 new_strings
= (char *)allocate(new_strsize
);
4992 new_strings
[new_strsize
- 3] = '\0';
4993 new_strings
[new_strsize
- 2] = '\0';
4994 new_strings
[new_strsize
- 1] = '\0';
4996 memset(new_strings
, '\0', sizeof(int32_t));
4997 p
= new_strings
+ sizeof(int32_t);
4998 q
= p
+ new_ext_strsize
;
5001 * If this is a dynamic library the movement of the symbols has to be
5002 * done with respect to the modules. As the local symbols, and external
5003 * defined symbols are grouped together for each module. Then a new
5004 * module table needs to be created with the new indexes into the symbol
5005 * table for each module.
5007 new_nmodtab
= nmodtab
;
5009 new_nextrefsyms
= nextrefsyms
;
5010 if(object
->mh_filetype
== MH_DYLIB
&& nmodtab
!= 0){
5011 if(object
->mh
!= NULL
){
5012 new_mods
= allocate(nmodtab
* sizeof(struct dylib_module
));
5017 new_mods64
= allocate(nmodtab
* sizeof(struct dylib_module_64
));
5022 * This first loop through the module table sets the index and
5023 * counts of the local symbols for each module.
5025 for(i
= 0; i
< nmodtab
; i
++){
5027 * First put the existing local symbols into the new symbol
5030 if(object
->mh
!= NULL
){
5031 new_mods
[i
].ilocalsym
= inew_syms
;
5032 new_mods
[i
].nlocalsym
= 0;
5033 ilocalsym
= mods
[i
].ilocalsym
;
5034 nlocalsym
= mods
[i
].nlocalsym
;
5037 new_mods64
[i
].ilocalsym
= inew_syms
;
5038 new_mods64
[i
].nlocalsym
= 0;
5039 ilocalsym
= mods64
[i
].ilocalsym
;
5040 nlocalsym
= mods64
[i
].nlocalsym
;
5042 for(j
= ilocalsym
; j
< ilocalsym
+ nlocalsym
; j
++){
5043 if(object
->mh
!= NULL
){
5044 n_strx
= symbols
[j
].n_un
.n_strx
;
5045 n_type
= symbols
[j
].n_type
;
5048 n_strx
= symbols64
[j
].n_un
.n_strx
;
5049 n_type
= symbols64
[j
].n_type
;
5051 if((n_type
& N_EXT
) == 0){
5052 if(object
->mh
!= NULL
)
5053 new_symbols
[inew_syms
] = symbols
[j
];
5055 new_symbols64
[inew_syms
] = symbols64
[j
];
5057 strcpy(q
, strings
+ n_strx
);
5058 if(object
->mh
!= NULL
)
5059 new_symbols
[inew_syms
].n_un
.n_strx
=
5062 new_symbols64
[inew_syms
].n_un
.n_strx
=
5067 saves
[j
] = inew_syms
;
5068 if(object
->mh
!= NULL
)
5069 new_mods
[i
].nlocalsym
++;
5071 new_mods64
[i
].nlocalsym
++;
5075 * Next put the global symbols that were changed into
5076 * non-global symbols into the new symbol table and moved their
5077 * counts to the local symbol counts.
5079 if(object
->mh
!= NULL
){
5080 iextdefsym
= mods
[i
].iextdefsym
;
5081 nextdefsym
= mods
[i
].nextdefsym
;
5084 iextdefsym
= mods64
[i
].iextdefsym
;
5085 nextdefsym
= mods64
[i
].nextdefsym
;
5087 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
5088 if(object
->mh
!= NULL
){
5089 n_strx
= symbols
[j
].n_un
.n_strx
;
5090 n_type
= symbols
[j
].n_type
;
5093 n_strx
= symbols64
[j
].n_un
.n_strx
;
5094 n_type
= symbols64
[j
].n_type
;
5096 if((n_type
& N_EXT
) != 0){
5097 if(nmedits
[j
] == TRUE
){
5099 * Change the new symbol to a private extern symbol
5100 * with the extern bit off.
5102 if(object
->mh
!= NULL
){
5103 new_symbols
[inew_syms
] = symbols
[j
];
5104 new_symbols
[inew_syms
].n_type
|= N_PEXT
;
5105 new_symbols
[inew_syms
].n_type
&= ~N_EXT
;
5108 new_symbols64
[inew_syms
] = symbols64
[j
];
5109 new_symbols64
[inew_syms
].n_type
|= N_PEXT
;
5110 new_symbols64
[inew_syms
].n_type
&= ~N_EXT
;
5113 strcpy(q
, strings
+ n_strx
);
5114 if(object
->mh
!= NULL
)
5115 new_symbols
[inew_syms
].n_un
.n_strx
=
5118 new_symbols64
[inew_syms
].n_un
.n_strx
=
5123 saves
[j
] = inew_syms
;
5124 if(object
->mh
!= NULL
)
5125 new_mods
[i
].nlocalsym
++;
5127 new_mods64
[i
].nlocalsym
++;
5133 * Next put the unchanged defined global symbols into the new
5136 for(i
= 0; i
< nmodtab
; i
++){
5137 if(object
->mh
!= NULL
){
5138 new_mods
[i
].iextdefsym
= inew_syms
;
5139 new_mods
[i
].nextdefsym
= 0;
5140 iextdefsym
= mods
[i
].iextdefsym
;
5141 nextdefsym
= mods
[i
].nextdefsym
;
5144 new_mods64
[i
].iextdefsym
= inew_syms
;
5145 new_mods64
[i
].nextdefsym
= 0;
5146 iextdefsym
= mods64
[i
].iextdefsym
;
5147 nextdefsym
= mods64
[i
].nextdefsym
;
5149 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
5150 if(object
->mh
!= NULL
){
5151 n_strx
= symbols
[j
].n_un
.n_strx
;
5152 n_type
= symbols
[j
].n_type
;
5155 n_strx
= symbols64
[j
].n_un
.n_strx
;
5156 n_type
= symbols64
[j
].n_type
;
5158 if((n_type
& N_EXT
) != 0){
5159 if(nmedits
[j
] == FALSE
){
5160 if(object
->mh
!= NULL
)
5161 new_symbols
[inew_syms
] = symbols
[j
];
5163 new_symbols64
[inew_syms
] = symbols64
[j
];
5165 strcpy(p
, strings
+ n_strx
);
5166 if(object
->mh
!= NULL
)
5167 new_symbols
[inew_syms
].n_un
.n_strx
=
5170 new_symbols64
[inew_syms
].n_un
.n_strx
=
5175 saves
[j
] = inew_syms
;
5176 if(object
->mh
!= NULL
)
5177 new_mods
[i
].nextdefsym
++;
5179 new_mods64
[i
].nextdefsym
++;
5185 * Last put the undefined symbols into the new symbol table.
5187 for(i
= 0; i
< nsyms
; i
++){
5188 if(object
->mh
!= NULL
){
5189 n_strx
= symbols
[i
].n_un
.n_strx
;
5190 n_type
= symbols
[i
].n_type
;
5193 n_strx
= symbols64
[i
].n_un
.n_strx
;
5194 n_type
= symbols64
[i
].n_type
;
5196 if((n_type
& N_EXT
) != 0 &&
5197 ((n_type
& N_TYPE
) == N_UNDF
||
5198 (n_type
& N_TYPE
) == N_PBUD
)){
5199 if(object
->mh
!= NULL
)
5200 new_symbols
[inew_syms
] = symbols
[i
];
5202 new_symbols64
[inew_syms
] = symbols64
[i
];
5204 strcpy(p
, strings
+ n_strx
);
5205 if(object
->mh
!= NULL
)
5206 new_symbols
[inew_syms
].n_un
.n_strx
=
5209 new_symbols64
[inew_syms
].n_un
.n_strx
=
5214 saves
[i
] = inew_syms
;
5219 * Place the module table's module names with the external strings
5220 * and set the names in the new module table. And then copy the
5221 * other unchanged fields.
5223 for(i
= 0; i
< nmodtab
; i
++){
5224 if(object
->mh
!= NULL
){
5225 strcpy(p
, strings
+ mods
[i
].module_name
);
5226 new_mods
[i
].module_name
= p
- new_strings
;
5229 new_mods
[i
].irefsym
= mods
[i
].irefsym
;
5230 new_mods
[i
].nrefsym
= mods
[i
].nrefsym
;
5231 new_mods
[i
].iextrel
= mods
[i
].iextrel
;
5232 new_mods
[i
].nextrel
= mods
[i
].nextrel
;
5233 new_mods
[i
].iinit_iterm
= mods
[i
].iinit_iterm
;
5234 new_mods
[i
].ninit_nterm
= mods
[i
].ninit_nterm
;
5235 new_mods
[i
].objc_module_info_addr
=
5236 mods
[i
].objc_module_info_addr
;
5237 new_mods
[i
].objc_module_info_size
=
5238 mods
[i
].objc_module_info_size
;
5241 strcpy(p
, strings
+ mods64
[i
].module_name
);
5242 new_mods64
[i
].module_name
= p
- new_strings
;
5245 new_mods64
[i
].irefsym
= mods64
[i
].irefsym
;
5246 new_mods64
[i
].nrefsym
= mods64
[i
].nrefsym
;
5247 new_mods64
[i
].iextrel
= mods64
[i
].iextrel
;
5248 new_mods64
[i
].nextrel
= mods64
[i
].nextrel
;
5249 new_mods64
[i
].iinit_iterm
= mods64
[i
].iinit_iterm
;
5250 new_mods64
[i
].ninit_nterm
= mods64
[i
].ninit_nterm
;
5251 new_mods64
[i
].objc_module_info_addr
=
5252 mods64
[i
].objc_module_info_addr
;
5253 new_mods64
[i
].objc_module_info_size
=
5254 mods64
[i
].objc_module_info_size
;
5259 * Update the reference table with the new symbol indexes for all
5260 * entries and change type of reference (the flags field) for those
5261 * symbols that got changed from globals to non-globals.
5263 new_nextrefsyms
= nextrefsyms
;
5264 new_refs
= allocate(new_nextrefsyms
*
5265 sizeof(struct dylib_reference
));
5267 for(i
= 0; i
< nextrefsyms
; i
++){
5268 if(nmedits
[refs
[i
].isym
] == TRUE
){
5269 if(refs
[i
].flags
== REFERENCE_FLAG_DEFINED
)
5271 REFERENCE_FLAG_PRIVATE_DEFINED
;
5272 else if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
)
5274 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
;
5275 else if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
)
5277 REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
;
5279 new_refs
[i
].flags
= refs
[i
].flags
;
5282 new_refs
[i
].flags
= refs
[i
].flags
;
5284 new_refs
[i
].isym
= saves
[refs
[i
].isym
] - 1;
5288 * Create a new dylib table of contents without the global symbols
5289 * that got turned into non-globals.
5291 new_ntoc
= ntoc
- nchanged_globals
;
5292 new_tocs
= allocate(new_ntoc
*
5293 sizeof(struct dylib_table_of_contents
));
5295 for(i
= 0; i
< ntoc
; i
++){
5296 if(tocs
[i
].symbol_index
>= nsyms
){
5297 error_arch(arch
, member
, "bad symbol index for table of "
5298 "contents table entry %d in: ", i
);
5301 if(nmedits
[tocs
[i
].symbol_index
] == FALSE
){
5302 new_tocs
[k
].symbol_index
= saves
[tocs
[i
].symbol_index
] - 1;
5303 new_tocs
[k
].module_index
= tocs
[i
].module_index
;
5309 * If is not a dynamic library so all global symbols changed into
5310 * statics can be moved to the end of the local symbols. If the pflag
5311 * is set then the changed symbols remain global and just get the
5312 * private extern bit set.
5316 * First put the existing local symbols into the new symbol table.
5319 for(i
= 0; i
< nsyms
; i
++){
5320 if(object
->mh
!= NULL
){
5321 n_strx
= symbols
[i
].n_un
.n_strx
;
5322 n_type
= symbols
[i
].n_type
;
5325 n_strx
= symbols64
[i
].n_un
.n_strx
;
5326 n_type
= symbols64
[i
].n_type
;
5328 if((n_type
& N_EXT
) == 0){
5329 if(object
->mh
!= NULL
)
5330 new_symbols
[inew_syms
] = symbols
[i
];
5332 new_symbols64
[inew_syms
] = symbols64
[i
];
5334 strcpy(q
, strings
+ n_strx
);
5335 if(object
->mh
!= NULL
)
5336 new_symbols
[inew_syms
].n_un
.n_strx
=
5339 new_symbols64
[inew_syms
].n_un
.n_strx
=
5344 saves
[i
] = inew_syms
;
5348 * Next put the global symbols that were changed into statics
5349 * symbols into the new symbol table.
5352 for(i
= 0; i
< nsyms
; i
++){
5353 if(object
->mh
!= NULL
){
5354 n_strx
= symbols
[i
].n_un
.n_strx
;
5355 n_type
= symbols
[i
].n_type
;
5358 n_strx
= symbols64
[i
].n_un
.n_strx
;
5359 n_type
= symbols64
[i
].n_type
;
5361 if((n_type
& N_EXT
) != 0){
5362 if(nmedits
[i
] == TRUE
){
5364 * Change the new symbol to not be an extern symbol
5365 * by turning off the extern bit.
5367 if(object
->mh
!= NULL
){
5368 new_symbols
[inew_syms
] = symbols
[i
];
5369 new_symbols
[inew_syms
].n_type
&= ~N_EXT
;
5370 new_symbols
[inew_syms
].n_desc
&= ~N_WEAK_DEF
;
5373 new_symbols64
[inew_syms
] = symbols64
[i
];
5374 new_symbols64
[inew_syms
].n_type
&= ~N_EXT
;
5375 new_symbols64
[inew_syms
].n_desc
&= ~N_WEAK_DEF
;
5378 strcpy(q
, strings
+ n_strx
);
5379 if(object
->mh
!= NULL
)
5380 new_symbols
[inew_syms
].n_un
.n_strx
=
5383 new_symbols64
[inew_syms
].n_un
.n_strx
=
5388 saves
[i
] = inew_syms
;
5394 * Last put the unchanged global symbols into the new symbol table
5395 * and symbols changed into private externs.
5397 for(i
= 0; i
< nsyms
; i
++){
5398 if(object
->mh
!= NULL
){
5399 n_strx
= symbols
[i
].n_un
.n_strx
;
5400 n_type
= symbols
[i
].n_type
;
5403 n_strx
= symbols64
[i
].n_un
.n_strx
;
5404 n_type
= symbols64
[i
].n_type
;
5406 if((n_type
& N_EXT
) != 0){
5407 if(nmedits
[i
] == FALSE
|| pflag
== TRUE
){
5408 if(object
->mh
!= NULL
)
5409 new_symbols
[inew_syms
] = symbols
[i
];
5411 new_symbols64
[inew_syms
] = symbols64
[i
];
5412 if(nmedits
[i
] == TRUE
&& pflag
== TRUE
){
5414 * Change the new symbol to be a private extern
5415 * symbol by turning on the private extern bit.
5417 if(object
->mh
!= NULL
)
5418 new_symbols
[inew_syms
].n_type
|= N_PEXT
;
5420 new_symbols64
[inew_syms
].n_type
|= N_PEXT
;
5423 strcpy(p
, strings
+ n_strx
);
5424 if(object
->mh
!= NULL
)
5425 new_symbols
[inew_syms
].n_un
.n_strx
=
5428 new_symbols64
[inew_syms
].n_un
.n_strx
=
5433 saves
[i
] = inew_syms
;
5439 if(sections
!= NULL
)
5441 if(sections64
!= NULL
)
5451 * Function for qsort for comparing global symbol names.
5456 const struct nlist
**sym1
,
5457 const struct nlist
**sym2
)
5459 return(strcmp(global_strings
+ (*sym1
)->n_un
.n_strx
,
5460 global_strings
+ (*sym2
)->n_un
.n_strx
));
5465 cmp_qsort_global_64(
5466 const struct nlist_64
**sym1
,
5467 const struct nlist_64
**sym2
)
5469 return(strcmp(global_strings
+ (*sym1
)->n_un
.n_strx
,
5470 global_strings
+ (*sym2
)->n_un
.n_strx
));
5474 * Function for bsearch for finding a global symbol that matches a stab name.
5478 cmp_bsearch_global_stab(
5480 const struct nlist
**sym
)
5483 * The +1 is for the '_' on the global symbol that is not on the
5484 * stab string that is trying to be matched.
5486 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
+ 1));
5491 cmp_bsearch_global_stab_64(
5493 const struct nlist_64
**sym
)
5496 * The +1 is for the '_' on the global symbol that is not on the
5497 * stab string that is trying to be matched.
5499 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
+ 1));
5503 * Function for bsearch for finding a global symbol that matches a stab name
5510 const struct nlist
**sym
)
5512 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
));
5517 cmp_bsearch_global_64(
5519 const struct nlist_64
**sym
)
5521 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
));
5523 #endif /* defined(NMEDIT) */