2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * The strip(1) and nmedit(l) program. This understands only Mach-O format
25 * files (with the restriction the symbol table is at the end of the file) and
26 * fat files with Mach-O files in them.
34 #include <sys/types.h>
36 #include <mach-o/loader.h>
37 #include <mach-o/reloc.h>
38 #include <mach-o/nlist.h>
39 #include <mach-o/stab.h>
40 #include "stuff/breakout.h"
41 #include "stuff/allocate.h"
42 #include "stuff/errors.h"
43 #include "stuff/rnd.h"
44 #include "stuff/reloc.h"
45 #include "stuff/reloc.h"
46 #include "stuff/symbol_list.h"
47 #include "stuff/unix_standard_mode.h"
48 #include "stuff/execute.h"
50 #include <mach-o/prune_trie.h>
51 #endif /* TRIE_SUPPORT */
53 /* These are set from the command line arguments */
55 char *progname
= NULL
; /* name of the program for error messages (argv[0]) */
56 static char *output_file
;/* name of the output file */
57 static char *sfile
; /* filename of global symbol names to keep */
58 static char *Rfile
; /* filename of global symbol names to remove */
59 static uint32_t Aflag
; /* save only absolute symbols with non-zero value and
60 .objc_class_name_* symbols */
61 static uint32_t iflag
; /* -i ignore symbols in -s file not in object */
63 static uint32_t pflag
; /* make all defined global symbols private extern */
64 #else /* !defined(NMEDIT) */
65 static char *dfile
; /* filename of filenames of debugger symbols to keep */
66 static uint32_t uflag
; /* save undefined symbols */
67 static uint32_t rflag
; /* save symbols referenced dynamically */
68 static uint32_t nflag
; /* save N_SECT global symbols */
69 static uint32_t Sflag
; /* -S strip only debugger symbols N_STAB */
70 static uint32_t xflag
; /* -x strip non-globals */
71 static uint32_t Xflag
; /* -X strip local symbols with 'L' names */
72 static uint32_t cflag
; /* -c strip section contents from dynamic libraries
73 files to create stub libraries */
74 static uint32_t no_uuid
;/* -no_uuid strip LC_UUID load commands */
75 static uint32_t vflag
; /* -v for verbose debugging ld -r executions */
76 static uint32_t lflag
; /* -l do ld -r executions even if it has bugs */
77 static uint32_t strip_all
= 1;
79 * This is set on an object by object basis if the strip_all flag is still set
80 * and the object is an executable that is for use with the dynamic linker.
81 * This has the same effect as -r and -u.
83 static enum bool default_dyld_executable
= FALSE
;
87 * Data structures to perform selective stripping of symbol table entries.
88 * save_symbols is the names of the symbols from the -s <file> argument.
89 * remove_symbols is the names of the symbols from the -R <file> argument.
91 static struct symbol_list
*save_symbols
= NULL
;
92 static uint32_t nsave_symbols
= 0;
93 static struct symbol_list
*remove_symbols
= NULL
;
94 static uint32_t nremove_symbols
= 0;
97 * saves points to an array of uint32_t's that is allocated. This array is a
98 * map of old symbol indexes to new symbol indexes. The new symbol indexes are
99 * plus 1 and zero value means that old symbol is not in the new symbol table.
100 * ref_saves is used in the same way but for the reference table.
101 * nmedits is an array and indexed by the symbol index the value indicates if
102 * the symbol was edited and turned into a non-global.
104 static int32_t *saves
= NULL
;
106 static int32_t *ref_saves
= NULL
;
108 static enum bool *nmedits
= NULL
;
112 * These hold pointers to the symbol, string and indirect tables being worked on
113 * by strip_object and strip_symtab() from an input object file or possiblity
114 * changed to an ld -r (-S or -x) file by make_ld_r_object().
116 static struct nlist
*symbols
= NULL
;
117 static struct nlist_64
*symbols64
= NULL
;
118 static uint32_t nsyms
= 0;
119 static char *strings
= NULL
;
120 static uint32_t strsize
= 0;
121 static uint32_t *indirectsyms
= NULL
;
122 static uint32_t nindirectsyms
= 0;
125 * These hold the new symbol and string table created by strip_symtab()
126 * and the new counts of local, defined external and undefined symbols.
128 static struct nlist
*new_symbols
= NULL
;
129 static struct nlist_64
*new_symbols64
= NULL
;
130 static uint32_t new_nsyms
= 0;
131 static char *new_strings
= NULL
;
132 static uint32_t new_strsize
= 0;
133 static uint32_t new_nlocalsym
= 0;
134 static uint32_t new_nextdefsym
= 0;
135 static uint32_t new_nundefsym
= 0;
136 #if defined(TRIE_SUPPORT) && !defined(NMEDIT)
138 * The index into the new symbols where the defined external start.
140 static uint32_t inew_nextdefsym
= 0;
144 * These hold the new table of contents, reference table and module table for
147 static struct dylib_table_of_contents
*new_tocs
= NULL
;
148 static uint32_t new_ntoc
= 0;
149 static struct dylib_reference
*new_refs
= NULL
;
150 static uint32_t new_nextrefsyms
= 0;
152 static struct dylib_module
*new_mods
= NULL
;
153 static struct dylib_module_64
*new_mods64
= NULL
;
154 static uint32_t new_nmodtab
= 0;
159 * The list of file names to save debugging symbols from.
161 static char **debug_filenames
= NULL
;
162 static uint32_t ndebug_filenames
= 0;
169 struct nlist_64 symbol64
;
171 static char *qsort_strings
= NULL
;
172 #endif /* !defined(NMEDIT) */
175 /* Internal routines */
179 static void strip_file(
181 struct arch_flag
*arch_flags
,
182 uint32_t narch_flags
,
183 enum bool all_archs
);
185 static void strip_arch(
188 struct arch_flag
*arch_flags
,
189 uint32_t narch_flags
,
190 enum bool all_archs
);
192 static void strip_object(
194 struct member
*member
,
195 struct object
*object
);
197 static uint32_t get_starting_syminfo_offset(
198 struct object
*object
);
200 static void check_object_relocs(
202 struct member
*member
,
203 struct object
*object
,
208 struct relocation_info
*relocs
,
210 struct nlist
*symbols
,
211 struct nlist_64
*symbols64
,
214 int32_t *missing_reloc_symbols
,
215 enum byte_sex host_byte_sex
);
217 static void check_indirect_symtab(
219 struct member
*member
,
220 struct object
*object
,
223 uint32_t section_type
,
225 struct nlist
*symbols
,
226 struct nlist_64
*symbols64
,
229 int32_t *missing_reloc_symbols
,
230 enum byte_sex host_byte_sex
);
233 static enum bool strip_symtab(
235 struct member
*member
,
236 struct object
*object
,
237 struct dylib_table_of_contents
*tocs
,
239 struct dylib_module
*mods
,
240 struct dylib_module_64
*mods64
,
242 struct dylib_reference
*refs
,
243 uint32_t nextrefsyms
);
248 #endif /* TRIE_SUPPORT */
250 static void make_ld_r_object(
252 struct member
*member
,
253 struct object
*object
);
255 static void strip_LC_UUID_commands(
257 struct member
*member
,
258 struct object
*object
);
261 static void strip_LC_CODE_SIGNATURE_commands(
263 struct member
*member
,
264 struct object
*object
);
265 #endif /* !(NMEDIT) */
267 static enum bool private_extern_reference_by_module(
268 uint32_t symbol_index
,
269 struct dylib_reference
*refs
,
270 uint32_t nextrefsyms
);
272 static enum bool symbol_pointer_used(
273 uint32_t symbol_index
,
274 uint32_t *indirectsyms
,
275 uint32_t nindirectsyms
);
277 static int cmp_qsort_undef_map(
278 const struct undef_map
*sym1
,
279 const struct undef_map
*sym2
);
281 static int cmp_qsort_undef_map_64(
282 const struct undef_map64
*sym1
,
283 const struct undef_map64
*sym2
);
284 #endif /* !defined(NMEDIT) */
287 static enum bool edit_symtab(
289 struct member
*member
,
290 struct object
*object
,
291 struct nlist
*symbols
,
292 struct nlist_64
*symbols64
,
296 struct dylib_table_of_contents
*tocs
,
298 struct dylib_module
*mods
,
299 struct dylib_module_64
*mods64
,
301 struct dylib_reference
*refs
,
302 uint32_t nextrefsyms
);
306 static void setup_debug_filenames(
309 static int cmp_qsort_filename(
313 static int cmp_bsearch_filename(
320 * This variable and routines are used for nmedit(1) only.
322 static char *global_strings
= NULL
;
324 static int cmp_qsort_global(
325 const struct nlist
**sym1
,
326 const struct nlist
**sym2
);
328 static int cmp_qsort_global_64(
329 const struct nlist_64
**sym1
,
330 const struct nlist_64
**sym2
);
332 static int cmp_bsearch_global_stab(
334 const struct nlist
**sym
);
336 static int cmp_bsearch_global_stab_64(
338 const struct nlist_64
**sym
);
340 static int cmp_bsearch_global(
342 const struct nlist
**sym
);
344 static int cmp_bsearch_global_64(
346 const struct nlist_64
**sym
);
356 uint32_t j
, args_left
, files_specified
;
357 struct arch_flag
*arch_flags
;
358 uint32_t narch_flags
;
360 struct symbol_list
*sp
;
370 for (i
= 1; i
< argc
; i
++){
371 if(argv
[i
][0] == '-'){
372 if(argv
[i
][1] == '\0'){
376 if(strcmp(argv
[i
], "-o") == 0){
378 fatal("-o requires an argument");
379 if(output_file
!= NULL
)
380 fatal("only one -o option allowed");
381 output_file
= argv
[i
+ 1];
384 else if(strcmp(argv
[i
], "-s") == 0){
386 fatal("-s requires an argument");
388 fatal("only one -s option allowed");
392 else if(strcmp(argv
[i
], "-R") == 0){
394 fatal("-R requires an argument");
396 fatal("only one -R option allowed");
401 else if(strcmp(argv
[i
], "-d") == 0){
403 fatal("-d requires an argument");
405 fatal("only one -d option allowed");
409 else if(strcmp(argv
[i
], "-no_uuid") == 0){
412 #endif /* !defined(NMEDIT) */
413 else if(strcmp(argv
[i
], "-arch") == 0){
415 error("missing argument(s) to %s option", argv
[i
]);
418 if(strcmp("all", argv
[i
+1]) == 0){
422 arch_flags
= reallocate(arch_flags
,
423 (narch_flags
+ 1) * sizeof(struct arch_flag
));
424 if(get_arch_from_flag(argv
[i
+1],
425 arch_flags
+ narch_flags
) == 0){
426 error("unknown architecture specification flag: "
427 "%s %s", argv
[i
], argv
[i
+1]);
431 for(j
= 0; j
< narch_flags
; j
++){
432 if(arch_flags
[j
].cputype
==
433 arch_flags
[narch_flags
].cputype
&&
434 (arch_flags
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
435 (arch_flags
[narch_flags
].cpusubtype
&
436 ~CPU_SUBTYPE_MASK
) &&
437 strcmp(arch_flags
[j
].name
,
438 arch_flags
[narch_flags
].name
) == 0)
447 for(j
= 1; argv
[i
][j
] != '\0'; j
++){
453 #else /* !defined(NMEDIT) */
481 #endif /* !defined(NMEDIT) */
486 #endif /* !defined(NMEDIT) */
501 error("unrecognized option: %s", argv
[i
]);
511 files_specified
+= argc
- (i
+ 1);
513 if(files_specified
> 1 && output_file
!= NULL
){
514 error("-o <filename> can only be used when one file is specified");
519 setup_symbol_list(sfile
, &save_symbols
, &nsave_symbols
);
523 if(Rfile
== NULL
&& pflag
== 0){
524 error("-s <filename>, -R <filename> or -p argument required");
531 setup_symbol_list(Rfile
, &remove_symbols
, &nremove_symbols
);
533 for(j
= 0; j
< nremove_symbols
; j
++){
534 sp
= bsearch(remove_symbols
[j
].name
,
535 save_symbols
, nsave_symbols
,
536 sizeof(struct symbol_list
),
537 (int (*)(const void *, const void *))
538 symbol_list_bsearch
);
540 error("symbol name: %s is listed in both -s %s and -R "
541 "%s files (can't be both saved and removed)",
542 remove_symbols
[j
].name
, sfile
, Rfile
);
550 /* the default when no -arch flags is present is to strip all archs */
556 setup_debug_filenames(dfile
);
558 #endif /* !defined(NMEDIT) */
562 for (i
= 1; i
< argc
; i
++) {
563 if(args_left
&& argv
[i
][0] == '-'){
564 if(argv
[i
][1] == '\0')
566 else if(strcmp(argv
[i
], "-o") == 0 ||
567 strcmp(argv
[i
], "-s") == 0 ||
568 strcmp(argv
[i
], "-R") == 0 ||
570 strcmp(argv
[i
], "-d") == 0 ||
571 #endif /* !defined(NMEDIT) */
572 strcmp(argv
[i
], "-arch") == 0)
576 char resolved_path
[PATH_MAX
+ 1];
578 if(realpath(argv
[i
], resolved_path
) == NULL
)
579 strip_file(argv
[i
], arch_flags
, narch_flags
, all_archs
);
581 strip_file(resolved_path
, arch_flags
,narch_flags
,all_archs
);
585 if(files_specified
== 0)
586 fatal("no files specified");
589 return(EXIT_FAILURE
);
591 return(EXIT_SUCCESS
);
600 fprintf(stderr
, "Usage: %s [-AnuSXx] [-] [-d filename] [-s filename] "
601 "[-R filename] [-o output] file [...] \n", progname
);
602 #else /* defined(NMEDIT) */
603 fprintf(stderr
, "Usage: %s -s filename [-R filename] [-p] [-A] [-] "
604 "[-o output] file [...] \n",
614 struct arch_flag
*arch_flags
,
615 uint32_t narch_flags
,
621 struct stat stat_buf
;
622 uint32_t previous_errors
;
623 enum bool unix_standard_mode
;
632 previous_errors
= errors
;
635 /* breakout the file for processing */
636 ofile
= breakout(input_file
, &archs
, &narchs
, FALSE
);
640 /* checkout the file for symbol table replacement processing */
641 checkout(archs
, narchs
);
643 /* process the symbols in the input file */
644 strip_arch(archs
, narchs
, arch_flags
, narch_flags
, all_archs
);
646 free_archs(archs
, narchs
);
651 /* create the output file */
652 if(stat(input_file
, &stat_buf
) == -1)
653 system_error("can't stat input file: %s", input_file
);
654 if(output_file
!= NULL
){
655 writeout(archs
, narchs
, output_file
, stat_buf
.st_mode
& 0777,
656 TRUE
, FALSE
, FALSE
, NULL
);
659 unix_standard_mode
= get_unix_standard_mode();
663 output_file
= makestr(input_file
, ".nmedit", NULL
);
664 #else /* !defined(NMEDIT) */
666 * In UNIX standard conformance mode we are not allowed to replace
667 * a file that is not writeable.
669 if(unix_standard_mode
== TRUE
&&
670 access(input_file
, W_OK
) == -1){
671 system_error("file: %s is not writable", input_file
);
672 goto strip_file_return
;
674 output_file
= makestr(input_file
, ".strip", NULL
);
677 * The UNIX standard conformance test suite expects files of
678 * MAXPATHLEN to work.
680 if(strlen(output_file
) >= MAXPATHLEN
){
682 * If there is a directory path in the name try to change
683 * the current working directory to that path.
685 if((p
= rindex(output_file
, '/')) != NULL
){
686 if((cwd_fd
= open(".", O_RDONLY
, 0)) == -1){
687 system_error("can't open current working directory");
688 goto strip_file_return
;
691 if(chdir(output_file
) == -1){
692 system_error("can't change current working directory "
693 "to: %s", output_file
);
694 goto strip_file_return
;
696 p
= rindex(input_file
, '/');
697 rename_file
= makestr(p
+ 1, NULL
);
700 * Create what might be a short enough name.
703 output_file
= makestr("strip.XXXXXX", NULL
);
704 output_file
= mktemp(output_file
);
707 writeout(archs
, narchs
, output_file
, stat_buf
.st_mode
& 0777,
708 TRUE
, FALSE
, FALSE
, NULL
);
709 if(rename_file
!= NULL
){
710 if(rename(output_file
, rename_file
) == -1)
711 system_error("can't move temporary file: %s to file: %s",
712 output_file
, rename_file
);
716 if(rename(output_file
, input_file
) == -1)
717 system_error("can't move temporary file: %s to input "
718 "file: %s", output_file
, input_file
);
724 * If we changed the current working directory change back to
725 * the previous working directory.
728 if(fchdir(cwd_fd
) == -1)
729 system_error("can't change back to previous working "
731 if(close(cwd_fd
) == -1)
732 system_error("can't close previous working directory");
738 #endif /* !defined(NMEDIT) */
739 /* clean-up data structures */
740 free_archs(archs
, narchs
);
743 errors
+= previous_errors
;
751 struct arch_flag
*arch_flags
,
752 uint32_t narch_flags
,
755 uint32_t i
, j
, k
, offset
, size
, missing_syms
;
757 cpu_subtype_t cpusubtype
;
758 struct arch_flag host_arch_flag
;
759 enum bool arch_process
, any_processing
, *arch_flag_processed
, family
;
760 const struct arch_flag
*family_arch_flag
;
763 * Using the specified arch_flags process specified objects for those
766 any_processing
= FALSE
;
767 arch_flag_processed
= NULL
;
769 arch_flag_processed
= allocate(narch_flags
* sizeof(enum bool));
770 memset(arch_flag_processed
, '\0', narch_flags
* sizeof(enum bool));
771 for(i
= 0; i
< narchs
; i
++){
773 * Determine the architecture (cputype and cpusubtype) of arch[i]
777 if(archs
[i
].type
== OFILE_ARCHIVE
){
778 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
779 if(archs
[i
].members
[j
].type
== OFILE_Mach_O
){
780 cputype
= archs
[i
].members
[j
].object
->mh_cputype
;
781 cpusubtype
= archs
[i
].members
[j
].object
->mh_cpusubtype
;
786 else if(archs
[i
].type
== OFILE_Mach_O
){
787 cputype
= archs
[i
].object
->mh_cputype
;
788 cpusubtype
= archs
[i
].object
->mh_cpusubtype
;
790 else if(archs
[i
].fat_arch
!= NULL
){
791 cputype
= archs
[i
].fat_arch
->cputype
;
792 cpusubtype
= archs
[i
].fat_arch
->cpusubtype
;
794 arch_process
= FALSE
;
795 if(all_archs
== TRUE
){
798 else if(narch_flags
!= 0){
800 if(narch_flags
== 1){
802 get_arch_family_from_cputype(arch_flags
[0].cputype
);
803 if(family_arch_flag
!= NULL
)
805 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
806 (arch_flags
[0].cpusubtype
& ~CPU_SUBTYPE_MASK
));
808 for(j
= 0; j
< narch_flags
; j
++){
809 if(arch_flags
[j
].cputype
== cputype
&&
810 ((arch_flags
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
811 (cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
814 arch_flag_processed
[j
] = TRUE
;
820 (void)get_arch_from_host(&host_arch_flag
, NULL
);
821 if(host_arch_flag
.cputype
== cputype
&&
822 (host_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
823 (cpusubtype
& ~CPU_SUBTYPE_MASK
))
826 if(narchs
!= 1 && arch_process
== FALSE
)
828 any_processing
= TRUE
;
831 * Now this arch[i] has been selected to be processed so process it
832 * according to its type.
834 if(archs
[i
].type
== OFILE_ARCHIVE
){
835 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
836 if(archs
[i
].members
[j
].type
== OFILE_Mach_O
){
837 strip_object(archs
+ i
, archs
[i
].members
+ j
,
838 archs
[i
].members
[j
].object
);
843 for(k
= 0; k
< nsave_symbols
; k
++){
844 if(save_symbols
[k
].seen
== FALSE
){
845 if(missing_syms
== 0){
846 error_arch(archs
+ i
, NULL
, "symbols names "
847 "listed in: %s not in: ", sfile
);
850 fprintf(stderr
, "%s\n", save_symbols
[k
].name
);
854 for(k
= 0; k
< nsave_symbols
; k
++){
855 save_symbols
[k
].seen
= FALSE
;
859 for(k
= 0; k
< nremove_symbols
; k
++){
860 if(remove_symbols
[k
].seen
== FALSE
){
861 if(missing_syms
== 0){
862 error_arch(archs
+ i
, NULL
, "symbols names "
863 "listed in: %s not defined in: ",
867 fprintf(stderr
, "%s\n", remove_symbols
[k
].name
);
871 for(k
= 0; k
< nremove_symbols
; k
++){
872 remove_symbols
[k
].seen
= FALSE
;
875 * Reset the library offsets and size.
878 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
879 archs
[i
].members
[j
].offset
= offset
;
881 if(archs
[i
].members
[j
].member_long_name
== TRUE
){
882 size
= rnd(archs
[i
].members
[j
].member_name_size
, 8) +
883 (rnd(sizeof(struct ar_hdr
), 8) -
884 sizeof(struct ar_hdr
));
885 archs
[i
].toc_long_name
= TRUE
;
887 if(archs
[i
].members
[j
].object
!= NULL
){
889 rnd(archs
[i
].members
[j
].object
->object_size
-
890 archs
[i
].members
[j
].object
->input_sym_info_size
+
891 archs
[i
].members
[j
].object
->output_sym_info_size
,
893 sprintf(archs
[i
].members
[j
].ar_hdr
->ar_size
, "%-*ld",
894 (int)sizeof(archs
[i
].members
[j
].ar_hdr
->ar_size
),
897 * This has to be done by hand because sprintf puts a
898 * null at the end of the buffer.
900 memcpy(archs
[i
].members
[j
].ar_hdr
->ar_fmag
, ARFMAG
,
901 (int)sizeof(archs
[i
].members
[j
].ar_hdr
->ar_fmag
));
904 size
+= archs
[i
].members
[j
].unknown_size
;
906 offset
+= sizeof(struct ar_hdr
) + size
;
908 archs
[i
].library_size
= offset
;
910 else if(archs
[i
].type
== OFILE_Mach_O
){
911 strip_object(archs
+ i
, NULL
, archs
[i
].object
);
914 warning_arch(archs
+ i
, NULL
, "can't process non-object and "
915 "non-archive file: ");
919 if(all_archs
== FALSE
&& narch_flags
!= 0){
920 for(i
= 0; i
< narch_flags
; i
++){
921 if(arch_flag_processed
[i
] == FALSE
)
922 error("file: %s does not contain architecture: %s",
923 archs
[0].file_name
, arch_flags
[i
].name
);
925 free(arch_flag_processed
);
927 if(any_processing
== FALSE
)
928 fatal("no processing done on input file: %s (specify a -arch flag)",
936 struct member
*member
,
937 struct object
*object
)
939 enum byte_sex host_byte_sex
;
941 struct dylib_table_of_contents
*tocs
;
943 struct dylib_module
*mods
;
944 struct dylib_module_64
*mods64
;
946 struct dylib_reference
*refs
;
947 uint32_t nextrefsyms
;
949 struct load_command
*lc
;
950 struct segment_command
*sg
;
951 struct segment_command_64
*sg64
;
953 struct section_64
*s64
;
954 struct relocation_info
*relocs
;
955 struct scattered_relocation_info
*sreloc
;
956 int32_t missing_reloc_symbols
;
957 uint32_t stride
, section_type
, nitems
;
959 uint32_t dyld_info_start
;
960 uint32_t dyld_info_end
;
967 host_byte_sex
= get_host_byte_sex();
969 /* Don't do anything to stub dylibs which have no load commands. */
970 if(object
->mh_filetype
== MH_DYLIB_STUB
){
971 if((object
->mh
!= NULL
&& object
->mh
->ncmds
== 0) ||
972 (object
->mh64
!= NULL
&& object
->mh64
->ncmds
== 0)){
976 if(object
->mh_filetype
== MH_DSYM
)
977 fatal_arch(arch
, member
, "can't process dSYM companion file: ");
978 if(object
->st
== NULL
|| object
->st
->nsyms
== 0){
979 warning_arch(arch
, member
, "input object file stripped: ");
983 nsyms
= object
->st
->nsyms
;
984 if(object
->mh
!= NULL
){
985 symbols
= (struct nlist
*)
986 (object
->object_addr
+ object
->st
->symoff
);
987 if(object
->object_byte_sex
!= host_byte_sex
)
988 swap_nlist(symbols
, nsyms
, host_byte_sex
);
993 symbols64
= (struct nlist_64
*)
994 (object
->object_addr
+ object
->st
->symoff
);
995 if(object
->object_byte_sex
!= host_byte_sex
)
996 swap_nlist_64(symbols64
, nsyms
, host_byte_sex
);
998 strings
= object
->object_addr
+ object
->st
->stroff
;
999 strsize
= object
->st
->strsize
;
1002 if(object
->mh
!= NULL
)
1003 flags
= object
->mh
->flags
;
1005 flags
= object
->mh64
->flags
;
1006 if(object
->mh_filetype
== MH_DYLIB
&&
1007 (flags
& MH_PREBOUND
) != MH_PREBOUND
){
1008 arch
->dont_update_LC_ID_DYLIB_timestamp
= TRUE
;
1010 if(object
->mh_filetype
!= MH_DYLIB
&& cflag
)
1011 fatal_arch(arch
, member
, "-c can't be used on non-dynamic "
1013 #endif /* !(NMEDIT) */
1014 if(object
->mh_filetype
== MH_DYLIB_STUB
)
1015 fatal_arch(arch
, member
, "dynamic stub library can't be changed "
1018 if(object
->mh_filetype
== MH_DYLIB
){
1019 tocs
= (struct dylib_table_of_contents
*)
1020 (object
->object_addr
+ object
->dyst
->tocoff
);
1021 ntoc
= object
->dyst
->ntoc
;
1022 nmodtab
= object
->dyst
->nmodtab
;
1023 if(object
->mh
!= NULL
){
1024 mods
= (struct dylib_module
*)
1025 (object
->object_addr
+ object
->dyst
->modtaboff
);
1026 if(object
->object_byte_sex
!= host_byte_sex
)
1027 swap_dylib_module(mods
, nmodtab
, host_byte_sex
);
1032 mods64
= (struct dylib_module_64
*)
1033 (object
->object_addr
+ object
->dyst
->modtaboff
);
1034 if(object
->object_byte_sex
!= host_byte_sex
)
1035 swap_dylib_module_64(mods64
, nmodtab
, host_byte_sex
);
1037 refs
= (struct dylib_reference
*)
1038 (object
->object_addr
+ object
->dyst
->extrefsymoff
);
1039 nextrefsyms
= object
->dyst
->nextrefsyms
;
1040 if(object
->object_byte_sex
!= host_byte_sex
){
1041 swap_dylib_table_of_contents(tocs
, ntoc
, host_byte_sex
);
1042 swap_dylib_reference(refs
, nextrefsyms
, host_byte_sex
);
1046 * In the -c flag is specified then strip the section contents of
1047 * this dynamic library and change it into a stub library. When
1048 * creating a stub library the timestamp is not changed.
1051 arch
->dont_update_LC_ID_DYLIB_timestamp
= TRUE
;
1053 lc
= object
->load_commands
;
1054 if(object
->mh
!= NULL
){
1055 ncmds
= object
->mh
->ncmds
;
1056 object
->mh_filetype
= MH_DYLIB_STUB
;
1057 object
->mh
->filetype
= MH_DYLIB_STUB
;
1060 ncmds
= object
->mh64
->ncmds
;
1061 object
->mh_filetype
= MH_DYLIB_STUB
;
1062 object
->mh64
->filetype
= MH_DYLIB_STUB
;
1064 for(i
= 0; i
< ncmds
; i
++){
1065 if(lc
->cmd
== LC_SEGMENT
){
1066 sg
= (struct segment_command
*)lc
;
1067 if(strcmp(sg
->segname
, SEG_LINKEDIT
) != 0){
1069 * Zero out the section offset, reloff, and size
1070 * fields as the section contents are being removed.
1072 s
= (struct section
*)
1073 ((char *)sg
+ sizeof(struct segment_command
));
1074 for(j
= 0; j
< sg
->nsects
; j
++){
1076 * For section types with indirect tables we
1077 * do not zero out the section size in a stub
1078 * library. As the section size is needed to
1079 * know now many indirect table entries the
1080 * section has. This is a bit odd but programs
1081 * dealing with MH_DYLIB_STUB filetypes special
1084 section_type
= s
[j
].flags
& SECTION_TYPE
;
1085 if(section_type
!= S_SYMBOL_STUBS
&&
1086 section_type
!= S_LAZY_SYMBOL_POINTERS
&&
1087 section_type
!= S_LAZY_DYLIB_SYMBOL_POINTERS
&&
1088 section_type
!= S_NON_LAZY_SYMBOL_POINTERS
){
1095 /* zero out file offset and size in the segment */
1100 else if(lc
->cmd
== LC_SEGMENT_64
){
1101 sg64
= (struct segment_command_64
*)lc
;
1102 if(strcmp(sg64
->segname
, SEG_LINKEDIT
) != 0){
1104 * Zero out the section offset, reloff, and size
1105 * fields as the section contents are being removed.
1107 s64
= (struct section_64
*)
1109 sizeof(struct segment_command_64
));
1110 for(j
= 0; j
< sg64
->nsects
; j
++){
1112 * For section types with indirect tables we
1113 * do not zero out the section size in a stub
1114 * library. As the section size is needed to
1115 * know now many indirect table entries the
1116 * section has. This is a bit odd but programs
1117 * dealing with MH_DYLIB_STUB filetypes special
1120 section_type
= s64
[j
].flags
& SECTION_TYPE
;
1121 if(section_type
!= S_SYMBOL_STUBS
&&
1122 section_type
!= S_LAZY_SYMBOL_POINTERS
&&
1123 section_type
!= S_LAZY_DYLIB_SYMBOL_POINTERS
&&
1124 section_type
!= S_NON_LAZY_SYMBOL_POINTERS
){
1131 /* zero out file offset and size in the segment */
1136 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1139 * To get the right amount of the file copied out by writeout()
1140 * for the case when we are stripping out the section contents
1141 * we reduce the object size by the size of the section contents
1142 * including the padding after the load commands. Then this
1143 * size minus the size of the input symbolic information is
1146 if(object
->mh
!= NULL
){
1147 object
->object_size
-= (object
->seg_linkedit
->fileoff
-
1148 (sizeof(struct mach_header
) +
1149 object
->mh
->sizeofcmds
));
1151 * Set the file offset to the link edit information to be
1152 * right after the load commands.
1154 object
->seg_linkedit
->fileoff
=
1155 sizeof(struct mach_header
) +
1156 object
->mh
->sizeofcmds
;
1159 object
->object_size
-= (object
->seg_linkedit64
->fileoff
-
1160 (sizeof(struct mach_header_64
) +
1161 object
->mh64
->sizeofcmds
));
1163 * Set the file offset to the link edit information to be
1164 * right after the load commands.
1166 object
->seg_linkedit64
->fileoff
=
1167 sizeof(struct mach_header_64
) +
1168 object
->mh64
->sizeofcmds
;
1171 #endif /* !(NMEDIT) */
1184 * coalesced symbols can be stripped only if they are not used via an
1185 * symbol pointer. So to know that strip_symtab() needs to be passed
1186 * the indirect symbol table.
1188 if(object
->dyst
!= NULL
&& object
->dyst
->nindirectsyms
!= 0){
1189 nindirectsyms
= object
->dyst
->nindirectsyms
;
1190 indirectsyms
= (uint32_t *)
1191 (object
->object_addr
+ object
->dyst
->indirectsymoff
);
1192 if(object
->object_byte_sex
!= host_byte_sex
)
1193 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
1197 indirectsyms
= NULL
;
1201 if(object
->mh
!= NULL
)
1202 object
->input_sym_info_size
=
1203 nsyms
* sizeof(struct nlist
) +
1206 object
->input_sym_info_size
=
1207 nsyms
* sizeof(struct nlist_64
) +
1210 if(object
->mh
!= NULL
)
1211 flags
= object
->mh
->flags
;
1213 flags
= object
->mh64
->flags
;
1215 (flags
& MH_DYLDLINK
) == MH_DYLDLINK
&&
1216 object
->mh_filetype
== MH_EXECUTE
)
1217 default_dyld_executable
= TRUE
;
1219 default_dyld_executable
= FALSE
;
1220 #endif /* !defined(NMEDIT) */
1223 if(sfile
!= NULL
|| Rfile
!= NULL
|| dfile
!= NULL
|| Aflag
|| uflag
||
1224 Sflag
|| xflag
|| Xflag
|| nflag
|| rflag
||
1225 default_dyld_executable
|| object
->mh_filetype
== MH_DYLIB
||
1226 object
->mh_filetype
== MH_DYLINKER
)
1227 #endif /* !defined(NMEDIT) */
1230 if(edit_symtab(arch
, member
, object
, symbols
, symbols64
, nsyms
,
1231 strings
, strsize
, tocs
, ntoc
, mods
, mods64
, nmodtab
, refs
,
1232 nextrefsyms
) == FALSE
)
1234 #else /* !defined(NMEDIT) */
1235 if(strip_symtab(arch
, member
, object
, tocs
, ntoc
, mods
, mods64
,
1236 nmodtab
, refs
, nextrefsyms
) == FALSE
)
1239 strip_LC_UUID_commands(arch
, member
, object
);
1240 #endif /* !defined(NMEDIT) */
1241 if(object
->mh
!= NULL
)
1242 object
->output_sym_info_size
=
1243 new_nsyms
* sizeof(struct nlist
) +
1246 object
->output_sym_info_size
=
1247 new_nsyms
* sizeof(struct nlist_64
) +
1250 object
->st
->nsyms
= new_nsyms
;
1251 object
->st
->strsize
= new_strsize
;
1253 if(object
->mh
!= NULL
)
1254 object
->output_symbols
= new_symbols
;
1256 object
->output_symbols64
= new_symbols64
;
1257 object
->output_nsymbols
= new_nsyms
;
1258 object
->output_strings
= new_strings
;
1259 object
->output_strings_size
= new_strsize
;
1261 if(object
->dyld_info
!= NULL
){
1262 /* there are five parts to the dyld info, but
1263 strip does not alter them, so copy as a block */
1264 dyld_info_start
= 0;
1265 if (object
->dyld_info
->rebase_off
!= 0)
1266 dyld_info_start
= object
->dyld_info
->rebase_off
;
1267 else if (object
->dyld_info
->bind_off
!= 0)
1268 dyld_info_start
= object
->dyld_info
->bind_off
;
1269 else if (object
->dyld_info
->weak_bind_off
!= 0)
1270 dyld_info_start
= object
->dyld_info
->weak_bind_off
;
1271 else if (object
->dyld_info
->lazy_bind_off
!= 0)
1272 dyld_info_start
= object
->dyld_info
->lazy_bind_off
;
1273 else if (object
->dyld_info
->export_off
!= 0)
1274 dyld_info_start
= object
->dyld_info
->export_off
;
1276 if (object
->dyld_info
->export_size
!= 0)
1277 dyld_info_end
= object
->dyld_info
->export_off
1278 + object
->dyld_info
->export_size
;
1279 else if (object
->dyld_info
->lazy_bind_size
!= 0)
1280 dyld_info_end
= object
->dyld_info
->lazy_bind_off
1281 + object
->dyld_info
->lazy_bind_size
;
1282 else if (object
->dyld_info
->weak_bind_size
!= 0)
1283 dyld_info_end
= object
->dyld_info
->weak_bind_off
1284 + object
->dyld_info
->weak_bind_size
;
1285 else if (object
->dyld_info
->bind_size
!= 0)
1286 dyld_info_end
= object
->dyld_info
->bind_off
1287 + object
->dyld_info
->bind_size
;
1288 else if (object
->dyld_info
->rebase_size
!= 0)
1289 dyld_info_end
= object
->dyld_info
->rebase_off
1290 + object
->dyld_info
->rebase_size
;
1291 object
->output_dyld_info
= object
->object_addr
+dyld_info_start
;
1292 object
->output_dyld_info_size
= dyld_info_end
- dyld_info_start
;
1293 object
->output_sym_info_size
+= object
->output_dyld_info_size
;
1295 * Warn about strip -s or -R on a final linked image with
1298 if(nsave_symbols
!= 0){
1299 warning_arch(arch
, NULL
, "removing global symbols from a "
1300 "final linked no longer supported. Use "
1301 "-exported_symbols_list at link time when "
1305 if(object
->split_info_cmd
!= NULL
){
1306 object
->output_split_info_data
= object
->object_addr
+
1307 object
->split_info_cmd
->dataoff
;
1308 object
->output_split_info_data_size
=
1309 object
->split_info_cmd
->datasize
;
1311 if(object
->func_starts_info_cmd
!= NULL
){
1312 object
->output_func_start_info_data
= object
->object_addr
+
1313 object
->func_starts_info_cmd
->dataoff
;
1314 object
->output_func_start_info_data_size
=
1315 object
->func_starts_info_cmd
->datasize
;
1317 if(object
->code_sig_cmd
!= NULL
){
1320 #endif /* !(NMEDIT) */
1322 object
->output_code_sig_data
= object
->object_addr
+
1323 object
->code_sig_cmd
->dataoff
;
1324 object
->output_code_sig_data_size
=
1325 object
->code_sig_cmd
->datasize
;
1329 if(object
->dyst
!= NULL
){
1330 object
->dyst
->ilocalsym
= 0;
1331 object
->dyst
->nlocalsym
= new_nlocalsym
;
1332 object
->dyst
->iextdefsym
= new_nlocalsym
;
1333 object
->dyst
->nextdefsym
= new_nextdefsym
;
1334 object
->dyst
->iundefsym
= new_nlocalsym
+ new_nextdefsym
;
1335 object
->dyst
->nundefsym
= new_nundefsym
;
1336 if(object
->dyst
->nindirectsyms
!= 0){
1337 object
->output_indirect_symtab
= indirectsyms
;
1338 if(object
->object_byte_sex
!= host_byte_sex
)
1339 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
1340 object
->object_byte_sex
);
1344 * If the -c option is specified the object's filetype will
1345 * have been changed from MH_DYLIB to MH_DYLIB_STUB above.
1347 if(object
->mh_filetype
== MH_DYLIB
||
1348 object
->mh_filetype
== MH_DYLIB_STUB
){
1349 object
->output_tocs
= new_tocs
;
1350 object
->output_ntoc
= new_ntoc
;
1352 if(object
->mh
!= NULL
)
1353 object
->output_mods
= new_mods
;
1355 object
->output_mods64
= new_mods64
;
1356 object
->output_nmodtab
= new_nmodtab
;
1358 object
->output_mods
= mods
;
1359 object
->output_nmodtab
= nmodtab
;
1361 object
->output_refs
= new_refs
;
1362 object
->output_nextrefsyms
= new_nextrefsyms
;
1363 if(object
->object_byte_sex
!= host_byte_sex
){
1364 swap_dylib_table_of_contents(new_tocs
, new_ntoc
,
1365 object
->object_byte_sex
);
1367 if(object
->mh
!= NULL
)
1368 swap_dylib_module(new_mods
, new_nmodtab
,
1369 object
->object_byte_sex
);
1371 swap_dylib_module_64(new_mods64
, new_nmodtab
,
1372 object
->object_byte_sex
);
1374 if(object
->mh
!= NULL
)
1375 swap_dylib_module(mods
, nmodtab
,
1376 object
->object_byte_sex
);
1378 swap_dylib_module_64(mods64
, nmodtab
,
1379 object
->object_byte_sex
);
1381 swap_dylib_reference(new_refs
, new_nextrefsyms
,
1382 object
->object_byte_sex
);
1385 if(object
->dyld_info
!= NULL
){
1386 object
->input_sym_info_size
+= object
->dyld_info
->rebase_size
1387 + object
->dyld_info
->bind_size
1388 + object
->dyld_info
->weak_bind_size
1389 + object
->dyld_info
->lazy_bind_size
1390 + object
->dyld_info
->export_size
;
1392 object
->input_sym_info_size
+=
1393 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1394 object
->dyst
->nextrel
* sizeof(struct relocation_info
) +
1395 object
->dyst
->ntoc
* sizeof(struct dylib_table_of_contents
)+
1396 object
->dyst
->nextrefsyms
* sizeof(struct dylib_reference
);
1397 if(object
->mh
!= NULL
){
1398 object
->input_sym_info_size
+=
1399 object
->dyst
->nmodtab
* sizeof(struct dylib_module
) +
1400 object
->dyst
->nindirectsyms
* sizeof(uint32_t);
1403 object
->input_sym_info_size
+=
1404 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
) +
1405 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1406 object
->input_indirectsym_pad
;
1410 * When stripping out the section contents to create a
1411 * dynamic library stub the relocation info also gets
1415 #endif /* !(NMEDIT) */
1417 object
->output_sym_info_size
+=
1418 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1419 object
->dyst
->nextrel
* sizeof(struct relocation_info
);
1421 object
->output_sym_info_size
+=
1422 new_ntoc
* sizeof(struct dylib_table_of_contents
)+
1423 new_nextrefsyms
* sizeof(struct dylib_reference
) +
1424 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1425 object
->input_indirectsym_pad
;
1426 if(object
->mh
!= NULL
){
1427 object
->output_sym_info_size
+=
1428 object
->dyst
->nmodtab
* sizeof(struct dylib_module
);
1431 object
->output_sym_info_size
+=
1432 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
);
1434 if(object
->hints_cmd
!= NULL
){
1435 object
->input_sym_info_size
+=
1436 object
->hints_cmd
->nhints
*
1437 sizeof(struct twolevel_hint
);
1438 object
->output_sym_info_size
+=
1439 object
->hints_cmd
->nhints
*
1440 sizeof(struct twolevel_hint
);
1442 if(object
->split_info_cmd
!= NULL
){
1443 object
->input_sym_info_size
+=
1444 object
->split_info_cmd
->datasize
;
1445 object
->output_sym_info_size
+=
1446 object
->split_info_cmd
->datasize
;
1448 if(object
->func_starts_info_cmd
!= NULL
){
1449 object
->input_sym_info_size
+=
1450 object
->func_starts_info_cmd
->datasize
;
1451 object
->output_sym_info_size
+=
1452 object
->func_starts_info_cmd
->datasize
;
1454 if(object
->code_sig_cmd
!= NULL
){
1455 object
->input_sym_info_size
=
1456 rnd(object
->input_sym_info_size
, 16);
1457 object
->input_sym_info_size
+=
1458 object
->code_sig_cmd
->datasize
;
1461 strip_LC_CODE_SIGNATURE_commands(arch
, member
, object
);
1464 #endif /* !(NMEDIT) */
1466 object
->output_sym_info_size
=
1467 rnd(object
->output_sym_info_size
, 16);
1468 object
->output_sym_info_size
+=
1469 object
->code_sig_cmd
->datasize
;
1473 object
->dyst
->ntoc
= new_ntoc
;
1474 object
->dyst
->nextrefsyms
= new_nextrefsyms
;
1476 offset
= get_starting_syminfo_offset(object
);
1478 if(object
->dyld_info
!= 0){
1479 if (object
->dyld_info
->rebase_off
!= 0){
1480 object
->dyld_info
->rebase_off
= offset
;
1481 offset
+= object
->dyld_info
->rebase_size
;
1483 if (object
->dyld_info
->bind_off
!= 0){
1484 object
->dyld_info
->bind_off
= offset
;
1485 offset
+= object
->dyld_info
->bind_size
;
1487 if (object
->dyld_info
->weak_bind_off
!= 0){
1488 object
->dyld_info
->weak_bind_off
= offset
;
1489 offset
+= object
->dyld_info
->weak_bind_size
;
1491 if (object
->dyld_info
->lazy_bind_off
!= 0){
1492 object
->dyld_info
->lazy_bind_off
= offset
;
1493 offset
+= object
->dyld_info
->lazy_bind_size
;
1495 if (object
->dyld_info
->export_off
!= 0){
1496 object
->dyld_info
->export_off
= offset
;
1497 offset
+= object
->dyld_info
->export_size
;
1501 if(object
->dyst
->nlocrel
!= 0){
1502 object
->output_loc_relocs
= (struct relocation_info
*)
1503 (object
->object_addr
+ object
->dyst
->locreloff
);
1506 * When stripping out the section contents to create a
1507 * dynamic library stub the relocation info also gets
1511 object
->dyst
->nlocrel
= 0;
1512 object
->dyst
->locreloff
= 0;
1515 #endif /* defined(NMEDIT) */
1517 object
->dyst
->locreloff
= offset
;
1518 offset
+= object
->dyst
->nlocrel
*
1519 sizeof(struct relocation_info
);
1523 object
->dyst
->locreloff
= 0;
1525 if(object
->split_info_cmd
!= NULL
){
1526 object
->split_info_cmd
->dataoff
= offset
;
1527 offset
+= object
->split_info_cmd
->datasize
;
1530 if(object
->func_starts_info_cmd
!= NULL
){
1531 object
->func_starts_info_cmd
->dataoff
= offset
;
1532 offset
+= object
->func_starts_info_cmd
->datasize
;
1535 if(object
->st
->nsyms
!= 0){
1536 object
->st
->symoff
= offset
;
1537 if(object
->mh
!= NULL
)
1538 offset
+= object
->st
->nsyms
* sizeof(struct nlist
);
1540 offset
+= object
->st
->nsyms
* sizeof(struct nlist_64
);
1543 object
->st
->symoff
= 0;
1545 if(object
->hints_cmd
!= NULL
){
1546 if(object
->hints_cmd
->nhints
!= 0){
1547 object
->output_hints
= (struct twolevel_hint
*)
1548 (object
->object_addr
+ object
->hints_cmd
->offset
);
1549 object
->hints_cmd
->offset
= offset
;
1550 offset
+= object
->hints_cmd
->nhints
*
1551 sizeof(struct twolevel_hint
);
1554 object
->hints_cmd
->offset
= 0;
1557 if(object
->dyst
->nextrel
!= 0){
1558 object
->output_ext_relocs
= (struct relocation_info
*)
1559 (object
->object_addr
+ object
->dyst
->extreloff
);
1562 * When stripping out the section contents to create a
1563 * dynamic library stub the relocation info also gets
1567 object
->dyst
->nextrel
= 0;
1568 object
->dyst
->extreloff
= 0;
1571 #endif /* defined(NMEDIT) */
1573 object
->dyst
->extreloff
= offset
;
1574 offset
+= object
->dyst
->nextrel
*
1575 sizeof(struct relocation_info
);
1579 object
->dyst
->extreloff
= 0;
1581 if(object
->dyst
->nindirectsyms
!= 0){
1582 object
->dyst
->indirectsymoff
= offset
;
1583 offset
+= object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1584 object
->input_indirectsym_pad
;
1587 object
->dyst
->indirectsymoff
= 0;;
1589 if(object
->dyst
->ntoc
!= 0){
1590 object
->dyst
->tocoff
= offset
;
1591 offset
+= object
->dyst
->ntoc
*
1592 sizeof(struct dylib_table_of_contents
);
1595 object
->dyst
->tocoff
= 0;
1597 if(object
->dyst
->nmodtab
!= 0){
1600 * When stripping out the section contents to create a
1601 * dynamic library stub zero out the fields in the module
1602 * table for the sections and relocation information and
1603 * clear Objective-C address and size from modules.
1606 if(object
->mh
!= NULL
){
1607 for(k
= 0; k
< object
->dyst
->nmodtab
; k
++){
1608 mods
[k
].iinit_iterm
= 0;
1609 mods
[k
].ninit_nterm
= 0;
1610 mods
[k
].iextrel
= 0;
1611 mods
[k
].nextrel
= 0;
1612 mods
[k
].objc_module_info_addr
= 0;
1613 mods
[k
].objc_module_info_size
= 0;
1617 for(k
= 0; k
< object
->dyst
->nmodtab
; k
++){
1618 mods64
[k
].iinit_iterm
= 0;
1619 mods64
[k
].ninit_nterm
= 0;
1620 mods64
[k
].iextrel
= 0;
1621 mods64
[k
].nextrel
= 0;
1622 mods64
[k
].objc_module_info_addr
= 0;
1623 mods64
[k
].objc_module_info_size
= 0;
1627 #endif /* !(NMEDIT) */
1628 object
->dyst
->modtaboff
= offset
;
1629 if(object
->mh
!= NULL
)
1630 offset
+= object
->dyst
->nmodtab
*
1631 sizeof(struct dylib_module
);
1633 offset
+= object
->dyst
->nmodtab
*
1634 sizeof(struct dylib_module_64
);
1637 object
->dyst
->modtaboff
= 0;
1639 if(object
->dyst
->nextrefsyms
!= 0){
1640 object
->dyst
->extrefsymoff
= offset
;
1641 offset
+= object
->dyst
->nextrefsyms
*
1642 sizeof(struct dylib_reference
);
1645 object
->dyst
->extrefsymoff
= 0;
1647 if(object
->st
->strsize
!= 0){
1648 object
->st
->stroff
= offset
;
1649 offset
+= object
->st
->strsize
;
1652 object
->st
->stroff
= 0;
1654 if(object
->code_sig_cmd
!= NULL
){
1655 offset
= rnd(offset
, 16);
1656 object
->code_sig_cmd
->dataoff
= offset
;
1657 offset
+= object
->code_sig_cmd
->datasize
;
1661 if(new_strsize
!= 0){
1662 if(object
->mh
!= NULL
)
1663 object
->st
->stroff
= object
->st
->symoff
+
1664 new_nsyms
* sizeof(struct nlist
);
1666 object
->st
->stroff
= object
->st
->symoff
+
1667 new_nsyms
* sizeof(struct nlist_64
);
1670 object
->st
->stroff
= 0;
1672 object
->st
->symoff
= 0;
1678 * Here we are doing a full symbol strip. In some cases it may
1679 * leave the local relocation entries as well as LOCAL indirect
1680 * symbol table entries.
1684 saves
= (int32_t *)allocate(object
->st
->nsyms
* sizeof(int32_t));
1685 bzero(saves
, object
->st
->nsyms
* sizeof(int32_t));
1688 * Account for the symbolic info in the input file.
1690 if(object
->dyst
!= NULL
){
1691 object
->input_sym_info_size
+=
1692 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1693 object
->dyst
->nextrel
* sizeof(struct relocation_info
) +
1694 object
->dyst
->ntoc
* sizeof(struct dylib_table_of_contents
)+
1695 object
->dyst
->nextrefsyms
* sizeof(struct dylib_reference
);
1696 if(object
->mh
!= NULL
){
1697 object
->input_sym_info_size
+=
1698 object
->dyst
->nmodtab
* sizeof(struct dylib_module
) +
1699 object
->dyst
->nindirectsyms
* sizeof(uint32_t);
1702 object
->input_sym_info_size
+=
1703 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
) +
1704 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1705 object
->input_indirectsym_pad
;
1710 * Determine the offset where the remaining symbolic info will start
1711 * in the output file (if any).
1713 offset
= get_starting_syminfo_offset(object
);
1716 * For a full symbol strip all these values in the output file are
1719 object
->st
->symoff
= 0;
1720 object
->st
->nsyms
= 0;
1721 object
->st
->stroff
= 0;
1722 object
->st
->strsize
= 0;
1723 if(object
->dyst
!= NULL
){
1724 object
->dyst
->ilocalsym
= 0;
1725 object
->dyst
->nlocalsym
= 0;
1726 object
->dyst
->iextdefsym
= 0;
1727 object
->dyst
->nextdefsym
= 0;
1728 object
->dyst
->iundefsym
= 0;
1729 object
->dyst
->nundefsym
= 0;
1733 * This will accumulate any remaining symbolic info size in the
1736 object
->output_sym_info_size
= 0;
1739 * We set these so that checking can be done below to report the
1740 * symbols that can't be stripped because of relocation entries
1741 * or indirect symbol table entries. Normally if these table have a
1742 * non-zero number of entries it will be an error as we are trying
1743 * to strip everything. But it maybe that there are only LOCAL
1744 * indirect entries which is odd but will be OK.
1746 if(object
->dyst
!= NULL
){
1747 if(object
->dyst
->nextrel
!= 0){
1748 object
->output_ext_relocs
= (struct relocation_info
*)
1749 (object
->object_addr
+ object
->dyst
->extreloff
);
1752 * Since this file has a dynamic symbol table and if this file
1753 * has local relocation entries on input make sure they are
1754 * there on output. This is a rare case that it will not have
1755 * external relocs or indirect symbols but can happen as is the
1756 * case with the dynamic linker itself.
1758 if(object
->dyst
->nlocrel
!= 0){
1759 object
->output_loc_relocs
= (struct relocation_info
*)
1760 (object
->object_addr
+ object
->dyst
->locreloff
);
1761 object
->output_sym_info_size
+=
1762 object
->dyst
->nlocrel
* sizeof(struct relocation_info
);
1764 object
->dyst
->locreloff
= offset
;
1765 offset
+= object
->dyst
->nlocrel
*
1766 sizeof(struct relocation_info
);
1769 if(object
->dyst
->nindirectsyms
!= 0){
1770 object
->output_indirect_symtab
= (uint32_t *)
1771 (object
->object_addr
+
1772 object
->dyst
->indirectsymoff
);
1773 if(object
->object_byte_sex
!= host_byte_sex
)
1774 swap_indirect_symbols(
1775 object
->output_indirect_symtab
,
1776 object
->dyst
->nindirectsyms
,
1777 object
->object_byte_sex
);
1779 object
->output_sym_info_size
+=
1780 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1781 object
->input_indirectsym_pad
;
1783 object
->dyst
->indirectsymoff
= offset
;
1784 offset
+= object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1785 object
->input_indirectsym_pad
;
1789 #endif /* !defined(NMEDIT) */
1792 * Always clear the prebind checksum if any when creating a new file.
1794 if(object
->cs
!= NULL
)
1795 object
->cs
->cksum
= 0;
1797 if(object
->seg_linkedit
!= NULL
){
1798 object
->seg_linkedit
->filesize
+= object
->output_sym_info_size
-
1799 object
->input_sym_info_size
;
1800 object
->seg_linkedit
->vmsize
= object
->seg_linkedit
->filesize
;
1802 else if(object
->seg_linkedit64
!= NULL
){
1803 /* Do this in two steps to avoid 32/64-bit casting problems. */
1804 object
->seg_linkedit64
->filesize
-= object
->input_sym_info_size
;
1805 object
->seg_linkedit64
->filesize
+= object
->output_sym_info_size
;
1806 object
->seg_linkedit64
->vmsize
= object
->seg_linkedit64
->filesize
;
1810 * Check and update the external relocation entries to make sure
1811 * referenced symbols are not stripped and refer to the new symbol
1814 * The external relocation entries can be located in one of two places,
1815 * first off of the sections or second off of the dynamic symtab.
1817 missing_reloc_symbols
= 0;
1818 lc
= object
->load_commands
;
1819 if(object
->mh
!= NULL
)
1820 ncmds
= object
->mh
->ncmds
;
1822 ncmds
= object
->mh64
->ncmds
;
1823 for(i
= 0; i
< ncmds
; i
++){
1824 if(lc
->cmd
== LC_SEGMENT
&&
1825 object
->seg_linkedit
!= (struct segment_command
*)lc
){
1826 sg
= (struct segment_command
*)lc
;
1827 s
= (struct section
*)((char *)sg
+
1828 sizeof(struct segment_command
));
1829 for(j
= 0; j
< sg
->nsects
; j
++){
1831 if(s
->reloff
+ s
->nreloc
*
1832 sizeof(struct relocation_info
) >
1833 object
->object_size
){
1834 fatal_arch(arch
, member
, "truncated or malformed "
1835 "object (relocation entries for section (%.16s,"
1836 "%.16s) extends past the end of the file)",
1837 s
->segname
, s
->sectname
);
1839 relocs
= (struct relocation_info
*)
1840 (object
->object_addr
+ s
->reloff
);
1841 if(object
->object_byte_sex
!= host_byte_sex
)
1842 swap_relocation_info(relocs
, s
->nreloc
,
1844 if(s
->offset
+ s
->size
> object
->object_size
){
1845 fatal_arch(arch
, member
, "truncated or malformed "
1846 "object (contents of section (%.16s,"
1847 "%.16s) extends past the end of the file)",
1848 s
->segname
, s
->sectname
);
1850 contents
= object
->object_addr
+ s
->offset
;
1851 check_object_relocs(arch
, member
, object
, s
->segname
,
1852 s
->sectname
, s
->size
, contents
, relocs
, s
->nreloc
,
1853 symbols
, symbols64
, nsyms
, strings
,
1854 &missing_reloc_symbols
, host_byte_sex
);
1855 if(object
->object_byte_sex
!= host_byte_sex
)
1856 swap_relocation_info(relocs
, s
->nreloc
,
1857 object
->object_byte_sex
);
1862 else if(lc
->cmd
== LC_SEGMENT_64
&&
1863 object
->seg_linkedit64
!= (struct segment_command_64
*)lc
){
1864 sg64
= (struct segment_command_64
*)lc
;
1865 s64
= (struct section_64
*)((char *)sg64
+
1866 sizeof(struct segment_command_64
));
1867 for(j
= 0; j
< sg64
->nsects
; j
++){
1868 if(s64
->nreloc
!= 0){
1869 if(s64
->reloff
+ s64
->nreloc
*
1870 sizeof(struct relocation_info
) >
1871 object
->object_size
){
1872 fatal_arch(arch
, member
, "truncated or malformed "
1873 "object (relocation entries for section (%.16s,"
1874 "%.16s) extends past the end of the file)",
1875 s64
->segname
, s64
->sectname
);
1877 relocs
= (struct relocation_info
*)
1878 (object
->object_addr
+ s64
->reloff
);
1879 if(object
->object_byte_sex
!= host_byte_sex
)
1880 swap_relocation_info(relocs
, s64
->nreloc
,
1882 if(s64
->offset
+ s64
->size
> object
->object_size
){
1883 fatal_arch(arch
, member
, "truncated or malformed "
1884 "object (contents of section (%.16s,"
1885 "%.16s) extends past the end of the file)",
1886 s64
->segname
, s64
->sectname
);
1888 contents
= object
->object_addr
+ s64
->offset
;
1889 check_object_relocs(arch
, member
, object
, s64
->segname
,
1890 s64
->sectname
, s64
->size
, contents
, relocs
,
1891 s64
->nreloc
, symbols
, symbols64
, nsyms
, strings
,
1892 &missing_reloc_symbols
, host_byte_sex
);
1893 if(object
->object_byte_sex
!= host_byte_sex
)
1894 swap_relocation_info(relocs
, s64
->nreloc
,
1895 object
->object_byte_sex
);
1900 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1902 if(object
->dyst
!= NULL
&& object
->dyst
->nextrel
!= 0){
1903 relocs
= object
->output_ext_relocs
;
1904 if(object
->object_byte_sex
!= host_byte_sex
)
1905 swap_relocation_info(relocs
, object
->dyst
->nextrel
,
1908 for(i
= 0; i
< object
->dyst
->nextrel
; i
++){
1909 if((relocs
[i
].r_address
& R_SCATTERED
) == 0 &&
1910 relocs
[i
].r_extern
== 1){
1911 if(relocs
[i
].r_symbolnum
> nsyms
){
1912 fatal_arch(arch
, member
, "bad r_symbolnum for external "
1913 "relocation entry %d in: ", i
);
1915 if(saves
[relocs
[i
].r_symbolnum
] == 0){
1916 if(missing_reloc_symbols
== 0){
1917 error_arch(arch
, member
, "symbols referenced by "
1918 "relocation entries that can't be stripped in: ");
1919 missing_reloc_symbols
= 1;
1921 if(object
->mh
!= NULL
){
1922 fprintf(stderr
, "%s\n", strings
+ symbols
1923 [relocs
[i
].r_symbolnum
].n_un
.n_strx
);
1926 fprintf(stderr
, "%s\n", strings
+ symbols64
1927 [relocs
[i
].r_symbolnum
].n_un
.n_strx
);
1929 saves
[relocs
[i
].r_symbolnum
] = -1;
1931 if(saves
[relocs
[i
].r_symbolnum
] != -1){
1932 relocs
[i
].r_symbolnum
=
1933 saves
[relocs
[i
].r_symbolnum
] - 1;
1937 fatal_arch(arch
, member
, "bad external relocation entry "
1938 "%d (not external) in: ", i
);
1940 if((relocs
[i
].r_address
& R_SCATTERED
) == 0){
1941 if(reloc_has_pair(object
->mh_cputype
, relocs
[i
].r_type
))
1945 sreloc
= (struct scattered_relocation_info
*)relocs
+ i
;
1946 if(reloc_has_pair(object
->mh_cputype
, sreloc
->r_type
))
1950 if(object
->object_byte_sex
!= host_byte_sex
)
1951 swap_relocation_info(relocs
, object
->dyst
->nextrel
,
1952 object
->object_byte_sex
);
1956 * Check and update the indirect symbol table entries to make sure
1957 * referenced symbols are not stripped and refer to the new symbol
1960 if(object
->dyst
!= NULL
&& object
->dyst
->nindirectsyms
!= 0){
1961 if(object
->object_byte_sex
!= host_byte_sex
)
1962 swap_indirect_symbols(object
->output_indirect_symtab
,
1963 object
->dyst
->nindirectsyms
, host_byte_sex
);
1965 lc
= object
->load_commands
;
1966 if(object
->mh
!= NULL
)
1967 ncmds
= object
->mh
->ncmds
;
1969 ncmds
= object
->mh64
->ncmds
;
1970 for(i
= 0; i
< ncmds
; i
++){
1971 if(lc
->cmd
== LC_SEGMENT
&&
1972 object
->seg_linkedit
!= (struct segment_command
*)lc
){
1973 sg
= (struct segment_command
*)lc
;
1974 s
= (struct section
*)((char *)sg
+
1975 sizeof(struct segment_command
));
1976 for(j
= 0; j
< sg
->nsects
; j
++){
1977 section_type
= s
->flags
& SECTION_TYPE
;
1978 if(section_type
== S_LAZY_SYMBOL_POINTERS
||
1979 section_type
== S_LAZY_DYLIB_SYMBOL_POINTERS
||
1980 section_type
== S_NON_LAZY_SYMBOL_POINTERS
)
1982 else if(section_type
== S_SYMBOL_STUBS
)
1983 stride
= s
->reserved2
;
1988 nitems
= s
->size
/ stride
;
1989 contents
= object
->object_addr
+ s
->offset
;
1990 check_indirect_symtab(arch
, member
, object
, nitems
,
1991 s
->reserved1
, section_type
, contents
, symbols
,
1992 symbols64
, nsyms
, strings
, &missing_reloc_symbols
,
1997 else if(lc
->cmd
== LC_SEGMENT_64
&&
1998 object
->seg_linkedit64
!= (struct segment_command_64
*)lc
){
1999 sg64
= (struct segment_command_64
*)lc
;
2000 s64
= (struct section_64
*)((char *)sg64
+
2001 sizeof(struct segment_command_64
));
2002 for(j
= 0; j
< sg64
->nsects
; j
++){
2003 section_type
= s64
->flags
& SECTION_TYPE
;
2004 if(section_type
== S_LAZY_SYMBOL_POINTERS
||
2005 section_type
== S_LAZY_DYLIB_SYMBOL_POINTERS
||
2006 section_type
== S_NON_LAZY_SYMBOL_POINTERS
)
2008 else if(section_type
== S_SYMBOL_STUBS
)
2009 stride
= s64
->reserved2
;
2014 nitems
= s64
->size
/ stride
;
2015 contents
= object
->object_addr
+ s64
->offset
;
2016 check_indirect_symtab(arch
, member
, object
, nitems
,
2017 s64
->reserved1
, section_type
, contents
, symbols
,
2018 symbols64
, nsyms
, strings
, &missing_reloc_symbols
,
2023 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2026 if(object
->object_byte_sex
!= host_byte_sex
)
2027 swap_indirect_symbols(object
->output_indirect_symtab
,
2028 object
->dyst
->nindirectsyms
, object
->object_byte_sex
);
2032 * Issue a warning if object file has a code signature that the
2033 * operation will invalidate it.
2035 if(object
->code_sig_cmd
!= NULL
)
2036 warning_arch(arch
, member
, "changes being made to the file will "
2037 "invalidate the code signature in: ");
2041 * get_starting_syminfo_offset() returns the starting offset of the symbolic
2042 * info in the object file.
2046 get_starting_syminfo_offset(
2047 struct object
*object
)
2051 if(object
->seg_linkedit
!= NULL
||
2052 object
->seg_linkedit64
!= NULL
){
2053 if(object
->mh
!= NULL
)
2054 offset
= object
->seg_linkedit
->fileoff
;
2056 offset
= object
->seg_linkedit64
->fileoff
;
2060 if(object
->dyst
!= NULL
&&
2061 object
->dyst
->nlocrel
!= 0 &&
2062 object
->dyst
->locreloff
< offset
)
2063 offset
= object
->dyst
->locreloff
;
2064 if(object
->st
->nsyms
!= 0 &&
2065 object
->st
->symoff
< offset
)
2066 offset
= object
->st
->symoff
;
2067 if(object
->dyst
!= NULL
&&
2068 object
->dyst
->nextrel
!= 0 &&
2069 object
->dyst
->extreloff
< offset
)
2070 offset
= object
->dyst
->extreloff
;
2071 if(object
->dyst
!= NULL
&&
2072 object
->dyst
->nindirectsyms
!= 0 &&
2073 object
->dyst
->indirectsymoff
< offset
)
2074 offset
= object
->dyst
->indirectsymoff
;
2075 if(object
->dyst
!= NULL
&&
2076 object
->dyst
->ntoc
!= 0 &&
2077 object
->dyst
->tocoff
< offset
)
2078 offset
= object
->dyst
->tocoff
;
2079 if(object
->dyst
!= NULL
&&
2080 object
->dyst
->nmodtab
!= 0 &&
2081 object
->dyst
->modtaboff
< offset
)
2082 offset
= object
->dyst
->modtaboff
;
2083 if(object
->dyst
!= NULL
&&
2084 object
->dyst
->nextrefsyms
!= 0 &&
2085 object
->dyst
->extrefsymoff
< offset
)
2086 offset
= object
->dyst
->extrefsymoff
;
2087 if(object
->st
->strsize
!= 0 &&
2088 object
->st
->stroff
< offset
)
2089 offset
= object
->st
->stroff
;
2095 * check_object_relocs() is used to check and update the external relocation
2096 * entries from a section in an object file, to make sure referenced symbols
2097 * are not stripped and are changed to refer to the new symbol table indexes.
2101 check_object_relocs(
2103 struct member
*member
,
2104 struct object
*object
,
2109 struct relocation_info
*relocs
,
2111 struct nlist
*symbols
,
2112 struct nlist_64
*symbols64
,
2115 int32_t *missing_reloc_symbols
,
2116 enum byte_sex host_byte_sex
)
2121 uint32_t value
, n_ext
;
2124 struct scattered_relocation_info
*sreloc
;
2126 for(k
= 0; k
< nreloc
; k
++){
2127 if((relocs
[k
].r_address
& R_SCATTERED
) == 0 &&
2128 relocs
[k
].r_extern
== 1){
2129 if(relocs
[k
].r_symbolnum
> nsyms
){
2130 fatal_arch(arch
, member
, "bad r_symbolnum for relocation "
2131 "entry %d in section (%.16s,%.16s) in: ", k
, segname
,
2134 if(object
->mh
!= NULL
){
2135 n_strx
= symbols
[relocs
[k
].r_symbolnum
].n_un
.n_strx
;
2136 n_value
= symbols
[relocs
[k
].r_symbolnum
].n_value
;
2139 n_strx
= symbols64
[relocs
[k
].r_symbolnum
].n_un
.n_strx
;
2140 n_value
= symbols64
[relocs
[k
].r_symbolnum
].n_value
;
2143 if(saves
[relocs
[k
].r_symbolnum
] == 0){
2144 if(*missing_reloc_symbols
== 0){
2145 error_arch(arch
, member
, "symbols referenced by "
2146 "relocation entries that can't be stripped in: ");
2147 *missing_reloc_symbols
= 1;
2149 fprintf(stderr
, "%s\n", strings
+ n_strx
);
2150 saves
[relocs
[k
].r_symbolnum
] = -1;
2152 #else /* defined(NMEDIT) */
2154 * We are letting nmedit change global coalesed symbols into
2155 * statics in MH_OBJECT file types only. Relocation entries to
2156 * global coalesced symbols are external relocs.
2158 if(object
->mh
!= NULL
)
2159 n_ext
= new_symbols
[saves
[relocs
[k
].r_symbolnum
] - 1].
2162 n_ext
= new_symbols64
[saves
[relocs
[k
].r_symbolnum
] - 1].
2164 if(n_ext
!= N_EXT
&&
2165 object
->mh_cputype
!= CPU_TYPE_X86_64
){
2167 * We need to do the relocation for this external relocation
2168 * entry so the item to be relocated is correct for a local
2169 * relocation entry. We don't need to do this for x86-64.
2171 if(relocs
[k
].r_address
+ sizeof(int32_t) > sectsize
){
2172 fatal_arch(arch
, member
, "truncated or malformed "
2173 "object (r_address of relocation entry %u of "
2174 "section (%.16s,%.16s) extends past the end "
2175 "of the section)", k
, segname
, sectname
);
2177 if(object
->mh
!= NULL
){
2178 value
= *(uint32_t *)
2179 (contents
+ relocs
[k
].r_address
);
2180 if(object
->object_byte_sex
!= host_byte_sex
)
2181 value
= SWAP_INT(value
);
2183 * We handle a very limited form here. Only VANILLA
2184 * (r_type == 0) long (r_length==2) absolute or pcrel
2185 * that won't need a scattered relocation entry.
2187 if(relocs
[k
].r_type
!= 0 ||
2188 relocs
[k
].r_length
!= 2){
2189 fatal_arch(arch
, member
, "don't have "
2190 "code to convert external relocation "
2191 "entry %d in section (%.16s,%.16s) "
2192 "for global coalesced symbol: %s "
2193 "in: ", k
, segname
, sectname
,
2197 if(object
->object_byte_sex
!= host_byte_sex
)
2198 value
= SWAP_INT(value
);
2199 *(uint32_t *)(contents
+ relocs
[k
].r_address
) =
2203 value64
= *(uint64_t *)(contents
+ relocs
[k
].r_address
);
2204 if(object
->object_byte_sex
!= host_byte_sex
)
2205 value64
= SWAP_LONG_LONG(value64
);
2207 * We handle a very limited form here. Only VANILLA
2208 * (r_type == 0) quad (r_length==3) absolute or pcrel
2209 * that won't need a scattered relocation entry.
2211 if(relocs
[k
].r_type
!= 0 ||
2212 relocs
[k
].r_length
!= 3){
2213 fatal_arch(arch
, member
, "don't have "
2214 "code to convert external relocation "
2215 "entry %d in section (%.16s,%.16s) "
2216 "for global coalesced symbol: %s "
2217 "in: ", k
, segname
, sectname
,
2221 if(object
->object_byte_sex
!= host_byte_sex
)
2222 value64
= SWAP_LONG_LONG(value64
);
2223 *(uint64_t *)(contents
+ relocs
[k
].r_address
) = value64
;
2226 * Turn the extern reloc into a local.
2228 if(object
->mh
!= NULL
)
2229 relocs
[k
].r_symbolnum
=
2230 new_symbols
[saves
[relocs
[k
].r_symbolnum
] - 1].n_sect
;
2232 relocs
[k
].r_symbolnum
=
2233 new_symbols64
[saves
[relocs
[k
].r_symbolnum
] - 1].n_sect
;
2234 relocs
[k
].r_extern
= 0;
2237 if(relocs
[k
].r_extern
== 1 &&
2238 saves
[relocs
[k
].r_symbolnum
] != -1){
2239 relocs
[k
].r_symbolnum
= saves
[relocs
[k
].r_symbolnum
] - 1;
2242 if((relocs
[k
].r_address
& R_SCATTERED
) == 0){
2243 if(reloc_has_pair(object
->mh_cputype
, relocs
[k
].r_type
) == TRUE
)
2247 sreloc
= (struct scattered_relocation_info
*)relocs
+ k
;
2248 if(reloc_has_pair(object
->mh_cputype
, sreloc
->r_type
) == TRUE
)
2255 * check_indirect_symtab() checks and updates the indirect symbol table entries
2256 * to make sure referenced symbols are not stripped and refer to the new symbol
2261 check_indirect_symtab(
2263 struct member
*member
,
2264 struct object
*object
,
2267 uint32_t section_type
,
2269 struct nlist
*symbols
,
2270 struct nlist_64
*symbols64
,
2273 int32_t *missing_reloc_symbols
,
2274 enum byte_sex host_byte_sex
)
2278 uint32_t n_strx
, value
;
2280 enum bool made_local
;
2282 for(k
= 0; k
< nitems
; k
++){
2284 index
= object
->output_indirect_symtab
[reserved1
+ k
];
2285 if(index
== INDIRECT_SYMBOL_LOCAL
||
2286 index
== INDIRECT_SYMBOL_ABS
||
2287 index
== (INDIRECT_SYMBOL_LOCAL
| INDIRECT_SYMBOL_ABS
))
2290 fatal_arch(arch
, member
,"indirect symbol table entry %d (past " "the end of the symbol table) in: ", reserved1
+ k
);
2292 if(pflag
== 0 && nmedits
[index
] == TRUE
&& saves
[index
] != -1)
2294 if(saves
[index
] == 0)
2298 * Indirect symbol table entries for defined symbols in a
2299 * non-lazy pointer section that are not saved are changed to
2300 * INDIRECT_SYMBOL_LOCAL which their values just have to be
2301 * slid if the are not absolute symbols.
2303 if(object
->mh
!= NULL
){
2304 n_type
= symbols
[index
].n_type
;
2305 n_strx
= symbols
[index
].n_un
.n_strx
;
2308 n_type
= symbols64
[index
].n_type
;
2309 n_strx
= symbols64
[index
].n_un
.n_strx
;
2311 if((n_type
&& N_TYPE
) != N_UNDF
&&
2312 (n_type
&& N_TYPE
) != N_PBUD
&&
2313 section_type
== S_NON_LAZY_SYMBOL_POINTERS
){
2314 object
->output_indirect_symtab
[reserved1
+ k
] =
2315 INDIRECT_SYMBOL_LOCAL
;
2316 if((n_type
& N_TYPE
) == N_ABS
)
2317 object
->output_indirect_symtab
[reserved1
+ k
] |=
2318 INDIRECT_SYMBOL_ABS
;
2321 * When creating a stub shared library the section contents
2322 * are not updated since they will be stripped.
2324 if(object
->mh_filetype
!= MH_DYLIB_STUB
){
2325 if(object
->mh
!= NULL
){
2326 value
= symbols
[index
].n_value
;
2327 if (symbols
[index
].n_desc
& N_ARM_THUMB_DEF
)
2329 if(object
->object_byte_sex
!= host_byte_sex
)
2330 value
= SWAP_INT(value
);
2331 *(uint32_t *)(contents
+ k
* 4) = value
;
2334 value64
= symbols64
[index
].n_value
;
2335 if(object
->object_byte_sex
!= host_byte_sex
)
2336 value64
= SWAP_LONG_LONG(value64
);
2337 *(uint64_t *)(contents
+ k
* 8) = value64
;
2343 object
->output_indirect_symtab
[reserved1
+ k
] =
2346 #else /* !defined(NMEDIT) */
2348 if(*missing_reloc_symbols
== 0){
2349 error_arch(arch
, member
, "symbols referenced by "
2350 "indirect symbol table entries that can't be "
2352 *missing_reloc_symbols
= 1;
2354 fprintf(stderr
, "%s\n", strings
+ n_strx
);
2357 #endif /* !defined(NMEDIT) */
2361 #else /* !defined(NMEDIT) */
2362 if(made_local
== FALSE
&& saves
[index
] != -1)
2363 #endif /* !defined(NMEDIT) */
2365 object
->output_indirect_symtab
[reserved1
+k
] = saves
[index
] - 1;
2372 * This is called if there is a -d option specified. It reads the file with
2373 * the strings in it and places them in the array debug_filenames and sorts
2374 * them by name. The file that contains the file names must have names one
2375 * per line with no white space (except the newlines).
2379 setup_debug_filenames(
2382 int fd
, i
, strings_size
;
2383 struct stat stat_buf
;
2386 if((fd
= open(dfile
, O_RDONLY
)) < 0){
2387 system_error("can't open: %s", dfile
);
2390 if(fstat(fd
, &stat_buf
) == -1){
2391 system_error("can't stat: %s", dfile
);
2395 strings_size
= stat_buf
.st_size
;
2396 strings
= (char *)allocate(strings_size
+ 1);
2397 strings
[strings_size
] = '\0';
2398 if(read(fd
, strings
, strings_size
) != strings_size
){
2399 system_error("can't read: %s", dfile
);
2404 for(i
= 0; i
< strings_size
; i
++){
2411 debug_filenames
= (char **)allocate(ndebug_filenames
* sizeof(char *));
2413 for(i
= 0; i
< ndebug_filenames
; i
++){
2414 debug_filenames
[i
] = p
;
2417 qsort(debug_filenames
, ndebug_filenames
, sizeof(char *),
2418 (int (*)(const void *, const void *))cmp_qsort_filename
);
2421 printf("Debug filenames:\n");
2422 for(i
= 0; i
< ndebug_filenames
; i
++){
2423 printf("filename = %s\n", debug_filenames
[i
]);
2429 * Strip the symbol table to the level specified by the command line arguments.
2430 * The new symbol table is built and new_symbols is left pointing to it. The
2431 * number of new symbols is left in new_nsyms, the new string table is built
2432 * and new_stings is left pointing to it and new_strsize is left containing it.
2433 * This routine returns zero if successfull and non-zero otherwise.
2439 struct member
*member
,
2440 struct object
*object
,
2441 struct dylib_table_of_contents
*tocs
,
2443 struct dylib_module
*mods
,
2444 struct dylib_module_64
*mods64
,
2446 struct dylib_reference
*refs
,
2447 uint32_t nextrefsyms
)
2449 uint32_t i
, j
, k
, n
, inew_syms
, save_debug
, missing_syms
;
2450 uint32_t missing_symbols
;
2451 char *p
, *q
, **pp
, *basename
;
2452 struct symbol_list
*sp
;
2453 uint32_t new_ext_strsize
, len
, *changes
, inew_undefsyms
;
2454 unsigned char nsects
;
2455 struct load_command
*lc
;
2456 struct segment_command
*sg
;
2457 struct segment_command_64
*sg64
;
2458 struct section
*s
, **sections
;
2459 struct section_64
*s64
, **sections64
;
2460 uint32_t ncmds
, mh_flags
, s_flags
, n_strx
;
2462 struct undef_map
*undef_map
;
2463 struct undef_map64
*undef_map64
;
2464 uint8_t n_type
, n_sect
;
2467 uint32_t module_name
, iextdefsym
, nextdefsym
, ilocalsym
, nlocalsym
;
2468 uint32_t irefsym
, nrefsym
;
2469 enum bool has_dwarf
, hack_5614542
;
2475 for(i
= 0; i
< nsave_symbols
; i
++)
2476 save_symbols
[i
].sym
= NULL
;
2477 for(i
= 0; i
< nremove_symbols
; i
++)
2478 remove_symbols
[i
].sym
= NULL
;
2480 for(i
= 0; i
< nsave_symbols
; i
++)
2481 save_symbols
[i
].seen
= FALSE
;
2482 for(i
= 0; i
< nremove_symbols
; i
++)
2483 remove_symbols
[i
].seen
= FALSE
;
2487 if(object
->mh
!= NULL
)
2488 new_strsize
= sizeof(int32_t);
2490 new_strsize
= sizeof(int64_t);
2494 new_ext_strsize
= 0;
2497 * If this an object file that has DWARF debugging sections to strip
2498 * then we have to run ld -r on it.
2500 if(object
->mh_filetype
== MH_OBJECT
&& (Sflag
|| xflag
)){
2502 lc
= object
->load_commands
;
2503 if(object
->mh
!= NULL
)
2504 ncmds
= object
->mh
->ncmds
;
2506 ncmds
= object
->mh64
->ncmds
;
2507 for(i
= 0; i
< ncmds
&& has_dwarf
== FALSE
; i
++){
2508 if(lc
->cmd
== LC_SEGMENT
){
2509 sg
= (struct segment_command
*)lc
;
2510 s
= (struct section
*)((char *)sg
+
2511 sizeof(struct segment_command
));
2512 for(j
= 0; j
< sg
->nsects
; j
++){
2513 if(s
->flags
& S_ATTR_DEBUG
){
2520 else if(lc
->cmd
== LC_SEGMENT_64
){
2521 sg64
= (struct segment_command_64
*)lc
;
2522 s64
= (struct section_64
*)((char *)sg64
+
2523 sizeof(struct segment_command_64
));
2524 for(j
= 0; j
< sg64
->nsects
; j
++){
2525 if(s64
->flags
& S_ATTR_DEBUG
){
2532 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2535 * Because of the bugs in ld(1) for:
2536 * radr://5675774 ld64 should preserve JBSR relocations without
2538 * radr://5658046 cctools-679 creates scattered relocations in
2539 * __TEXT,__const section in kexts, which breaks
2540 * kexts built for older systems
2541 * we can't use ld -r to strip dwarf info in 32-bit objects until
2542 * these are fixed. But if the user as specified the -l flag then
2543 * go ahead and do it and the user will have to be aware of these
2546 if((lflag
== TRUE
&& has_dwarf
== TRUE
) || object
->mh64
!= NULL
)
2547 make_ld_r_object(arch
, member
, object
);
2550 * Because of the "design" of 64-bit object files and the lack of
2551 * local relocation entries it is not possible for strip(1) to do its
2552 * job without becoming a static link editor. The "design" does not
2553 * actually strip the symbols it simply renames them to things like
2554 * "l1000". And they become static symbols but still have external
2555 * relocation entries. Thus can never actually be stripped. Also some
2556 * symbols, *.eh, symbols are not even changed to these names if there
2557 * corresponding global symbol is not stripped. So strip(1) only
2558 * recourse is to use the unified linker to create an ld -r object then
2559 * save all resulting symbols (both static and global) and hope the user
2560 * does not notice the stripping is not what they asked for.
2562 if(object
->mh_filetype
== MH_OBJECT
&&
2563 (object
->mh64
!= NULL
&& object
->ld_r_ofile
== NULL
))
2564 make_ld_r_object(arch
, member
, object
);
2567 * Since make_ld_r_object() may create an object with more symbols
2568 * this has to be done after make_ld_r_object() and nsyms is updated.
2570 saves
= (int32_t *)allocate(nsyms
* sizeof(int32_t));
2571 bzero(saves
, nsyms
* sizeof(int32_t));
2574 * Gather an array of section struct pointers so we can later determine
2575 * if we run into a global symbol in a coalesced section and not strip
2580 lc
= object
->load_commands
;
2581 if(object
->mh
!= NULL
)
2582 ncmds
= object
->mh
->ncmds
;
2584 ncmds
= object
->mh64
->ncmds
;
2585 for(i
= 0; i
< ncmds
; i
++){
2586 if(lc
->cmd
== LC_SEGMENT
){
2587 sg
= (struct segment_command
*)lc
;
2588 nsects
+= sg
->nsects
;
2590 else if(lc
->cmd
== LC_SEGMENT_64
){
2591 sg64
= (struct segment_command_64
*)lc
;
2592 nsects
+= sg64
->nsects
;
2594 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2596 if(object
->mh
!= NULL
){
2597 sections
= allocate(nsects
* sizeof(struct section
*));
2602 sections64
= allocate(nsects
* sizeof(struct section_64
*));
2605 lc
= object
->load_commands
;
2606 for(i
= 0; i
< ncmds
; i
++){
2607 if(lc
->cmd
== LC_SEGMENT
){
2608 sg
= (struct segment_command
*)lc
;
2609 s
= (struct section
*)((char *)sg
+
2610 sizeof(struct segment_command
));
2611 for(j
= 0; j
< sg
->nsects
; j
++)
2612 sections
[nsects
++] = s
++;
2614 else if(lc
->cmd
== LC_SEGMENT_64
){
2615 sg64
= (struct segment_command_64
*)lc
;
2616 s64
= (struct section_64
*)((char *)sg64
+
2617 sizeof(struct segment_command_64
));
2618 for(j
= 0; j
< sg64
->nsects
; j
++)
2619 sections64
[nsects
++] = s64
++;
2621 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2624 for(i
= 0; i
< nsyms
; i
++){
2626 if(object
->mh
!= NULL
){
2627 mh_flags
= object
->mh
->flags
;
2628 n_strx
= symbols
[i
].n_un
.n_strx
;
2629 n_type
= symbols
[i
].n_type
;
2630 n_sect
= symbols
[i
].n_sect
;
2631 if((n_type
& N_TYPE
) == N_SECT
){
2632 if(n_sect
== 0 || n_sect
> nsects
){
2633 error_arch(arch
, member
, "bad n_sect for symbol "
2634 "table entry %d in: ", i
);
2637 s_flags
= sections
[n_sect
- 1]->flags
;
2639 n_desc
= symbols
[i
].n_desc
;
2640 n_value
= symbols
[i
].n_value
;
2643 mh_flags
= object
->mh64
->flags
;
2644 n_strx
= symbols64
[i
].n_un
.n_strx
;
2645 n_type
= symbols64
[i
].n_type
;
2646 n_sect
= symbols64
[i
].n_sect
;
2647 if((n_type
& N_TYPE
) == N_SECT
){
2648 if(n_sect
== 0 || n_sect
> nsects
){
2649 error_arch(arch
, member
, "bad n_sect for symbol "
2650 "table entry %d in: ", i
);
2653 s_flags
= sections64
[n_sect
- 1]->flags
;
2655 n_desc
= symbols64
[i
].n_desc
;
2656 n_value
= symbols64
[i
].n_value
;
2659 if(n_strx
> strsize
){
2660 error_arch(arch
, member
, "bad string index for symbol "
2661 "table entry %d in: ", i
);
2665 if((n_type
& N_TYPE
) == N_INDR
){
2667 if(n_value
> strsize
){
2668 error_arch(arch
, member
, "bad string index for "
2669 "indirect symbol table entry %d in: ", i
);
2674 if((n_type
& N_EXT
) == 0){ /* local symbol */
2676 * For x86_64 .o files we have run ld -r on them and are stuck
2677 * keeping all resulting symbols.
2679 if(object
->mh
== NULL
&& (
2680 object
->mh64
->cputype
== CPU_TYPE_X86_64
) &&
2681 object
->mh64
->filetype
== MH_OBJECT
){
2683 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2686 saves
[i
] = new_nsyms
;
2689 * The cases a local symbol might be saved is with -X -S or
2692 else if((!strip_all
&& (Xflag
|| Sflag
)) || dfile
){
2693 if(n_type
& N_STAB
){ /* debug symbol */
2694 if(dfile
&& n_type
== N_SO
){
2696 basename
= strrchr(strings
+ n_strx
, '/');
2697 if(basename
!= NULL
)
2700 basename
= strings
+ n_strx
;
2701 pp
= bsearch(basename
, debug_filenames
,
2702 ndebug_filenames
, sizeof(char *),
2703 (int (*)(const void *, const void *)
2704 )cmp_bsearch_filename
);
2706 * Save the bracketing N_SO. For each N_SO that
2707 * has a filename there is an N_SO that has a
2708 * name of "" which ends the stabs for that file
2710 if(*basename
!= '\0'){
2718 * This is a bracketing SO so if we are
2719 * currently saving debug symbols save this
2720 * last one and turn off saving debug syms.
2724 new_strsize
+= strlen(strings
+
2728 saves
[i
] = new_nsyms
;
2737 if(saves
[i
] == 0 && (!Sflag
|| save_debug
)){
2739 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2742 saves
[i
] = new_nsyms
;
2745 else{ /* non-debug local symbol */
2746 if(xflag
== 0 && (Sflag
|| Xflag
)){
2749 strings
[n_strx
] != 'L')){
2751 * If this file is a for the dynamic linker and
2752 * this symbol is in a section marked so that
2753 * static symbols are stripped then don't
2756 if((mh_flags
& MH_DYLDLINK
) != MH_DYLDLINK
||
2757 (n_type
& N_TYPE
) != N_SECT
||
2758 (s_flags
& S_ATTR_STRIP_STATIC_SYMS
) !=
2759 S_ATTR_STRIP_STATIC_SYMS
){
2760 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2763 saves
[i
] = new_nsyms
;
2768 * Treat a local symbol that was a private extern as if
2769 * were global if it is referenced by a module and save
2772 if((n_type
& N_PEXT
) == N_PEXT
){
2774 private_extern_reference_by_module(
2775 i
, refs
,nextrefsyms
) == TRUE
){
2777 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2780 saves
[i
] = new_nsyms
;
2783 * We need to save symbols that were private externs
2784 * that are used with indirect symbols.
2787 symbol_pointer_used(i
, indirectsyms
,
2788 nindirectsyms
) == TRUE
){
2790 len
= strlen(strings
+ n_strx
) + 1;
2795 saves
[i
] = new_nsyms
;
2801 * Treat a local symbol that was a private extern as if were
2802 * global if it is not referenced by a module.
2804 else if((n_type
& N_PEXT
) == N_PEXT
){
2805 if(saves
[i
] == 0 && sfile
){
2806 sp
= bsearch(strings
+ n_strx
,
2807 save_symbols
, nsave_symbols
,
2808 sizeof(struct symbol_list
),
2809 (int (*)(const void *, const void *))
2810 symbol_list_bsearch
);
2812 if(sp
->sym
== NULL
){
2813 if(object
->mh
!= NULL
)
2814 sp
->sym
= &(symbols
[i
]);
2816 sp
->sym
= &(symbols64
[i
]);
2820 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2823 saves
[i
] = new_nsyms
;
2827 private_extern_reference_by_module(
2828 i
, refs
,nextrefsyms
) == TRUE
){
2830 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2833 saves
[i
] = new_nsyms
;
2836 * We need to save symbols that were private externs that
2837 * are used with indirect symbols.
2840 symbol_pointer_used(i
, indirectsyms
, nindirectsyms
) ==
2843 len
= strlen(strings
+ n_strx
) + 1;
2848 saves
[i
] = new_nsyms
;
2852 else{ /* global symbol */
2854 * strip -R on an x86_64 .o file should do nothing.
2857 (object
->mh
!= NULL
||
2858 object
->mh64
->cputype
!= CPU_TYPE_X86_64
||
2859 object
->mh64
->filetype
!= MH_OBJECT
)){
2860 sp
= bsearch(strings
+ n_strx
,
2861 remove_symbols
, nremove_symbols
,
2862 sizeof(struct symbol_list
),
2863 (int (*)(const void *, const void *))
2864 symbol_list_bsearch
);
2866 if((n_type
& N_TYPE
) == N_UNDF
||
2867 (n_type
& N_TYPE
) == N_PBUD
){
2868 error_arch(arch
, member
, "symbol: %s undefined"
2869 " and can't be stripped from: ",
2872 else if(sp
->sym
!= NULL
){
2873 sym
= (struct nlist
*)sp
->sym
;
2874 if((sym
->n_type
& N_PEXT
) != N_PEXT
)
2875 error_arch(arch
, member
, "more than one symbol "
2876 "for: %s found in: ", sp
->name
);
2879 if(object
->mh
!= NULL
)
2880 sp
->sym
= &(symbols
[i
]);
2882 sp
->sym
= &(symbols64
[i
]);
2885 if(n_desc
& REFERENCED_DYNAMICALLY
){
2886 error_arch(arch
, member
, "symbol: %s is dynamically"
2887 " referenced and can't be stripped "
2888 "from: ", sp
->name
);
2890 if((n_type
& N_TYPE
) == N_SECT
&&
2891 (s_flags
& SECTION_TYPE
) == S_COALESCED
){
2892 error_arch(arch
, member
, "symbol: %s is a global "
2893 "coalesced symbol and can't be "
2894 "stripped from: ", sp
->name
);
2896 /* don't save this symbol */
2900 if(Aflag
&& (n_type
& N_TYPE
) == N_ABS
&&
2903 strncmp(strings
+ n_strx
,
2904 ".objc_class_name_",
2905 sizeof(".objc_class_name_") - 1) == 0))){
2906 len
= strlen(strings
+ n_strx
) + 1;
2908 new_ext_strsize
+= len
;
2911 saves
[i
] = new_nsyms
;
2913 if(saves
[i
] == 0 && (uflag
|| default_dyld_executable
) &&
2914 ((((n_type
& N_TYPE
) == N_UNDF
) &&
2916 (n_type
& N_TYPE
) == N_PBUD
)){
2918 len
= strlen(strings
+ n_strx
) + 1;
2920 new_ext_strsize
+= len
;
2924 saves
[i
] = new_nsyms
;
2926 if(saves
[i
] == 0 && nflag
&&
2927 (n_type
& N_TYPE
) == N_SECT
){
2929 len
= strlen(strings
+ n_strx
) + 1;
2931 new_ext_strsize
+= len
;
2935 saves
[i
] = new_nsyms
;
2937 if(saves
[i
] == 0 && sfile
){
2938 sp
= bsearch(strings
+ n_strx
,
2939 save_symbols
, nsave_symbols
,
2940 sizeof(struct symbol_list
),
2941 (int (*)(const void *, const void *))
2942 symbol_list_bsearch
);
2944 if(sp
->sym
!= NULL
){
2945 sym
= (struct nlist
*)sp
->sym
;
2946 if((sym
->n_type
& N_PEXT
) != N_PEXT
)
2947 error_arch(arch
, member
, "more than one symbol "
2948 "for: %s found in: ", sp
->name
);
2951 if(object
->mh
!= NULL
)
2952 sp
->sym
= &(symbols
[i
]);
2954 sp
->sym
= &(symbols64
[i
]);
2956 len
= strlen(strings
+ n_strx
) + 1;
2958 new_ext_strsize
+= len
;
2959 if((n_type
& N_TYPE
) == N_UNDF
||
2960 (n_type
& N_TYPE
) == N_PBUD
)
2965 saves
[i
] = new_nsyms
;
2970 * We only need to save coalesced symbols that are used as
2971 * indirect symbols in 32-bit applications.
2973 * In 64-bit applications, we only need to save coalesced
2974 * symbols that are used as weak definitions.
2976 if(object
->mh
!= NULL
&&
2978 (n_type
& N_TYPE
) == N_SECT
&&
2979 (s_flags
& SECTION_TYPE
) == S_COALESCED
&&
2980 symbol_pointer_used(i
, indirectsyms
, nindirectsyms
) == TRUE
){
2982 len
= strlen(strings
+ n_strx
) + 1;
2984 new_ext_strsize
+= len
;
2988 saves
[i
] = new_nsyms
;
2991 (n_type
& N_TYPE
) == N_SECT
&&
2992 (n_desc
& N_WEAK_DEF
) != 0){
2994 len
= strlen(strings
+ n_strx
) + 1;
2996 new_ext_strsize
+= len
;
3000 saves
[i
] = new_nsyms
;
3002 if(saves
[i
] == 0 && ((Xflag
|| Sflag
|| xflag
) ||
3003 ((rflag
|| default_dyld_executable
) &&
3004 n_desc
& REFERENCED_DYNAMICALLY
))){
3005 len
= strlen(strings
+ n_strx
) + 1;
3007 new_ext_strsize
+= len
;
3008 if((n_type
& N_TYPE
) == N_INDR
){
3009 len
= strlen(strings
+ n_value
) + 1;
3011 new_ext_strsize
+= len
;
3013 if((n_type
& N_TYPE
) == N_UNDF
||
3014 (n_type
& N_TYPE
) == N_PBUD
)
3019 saves
[i
] = new_nsyms
;
3022 * For x86_64 .o files we have run ld -r on them and are stuck
3023 * keeping all resulting symbols.
3026 object
->mh
== NULL
&&
3027 object
->mh64
->cputype
== CPU_TYPE_X86_64
&&
3028 object
->mh64
->filetype
== MH_OBJECT
){
3029 len
= strlen(strings
+ n_strx
) + 1;
3031 new_ext_strsize
+= len
;
3032 if((n_type
& N_TYPE
) == N_INDR
){
3033 len
= strlen(strings
+ n_value
) + 1;
3035 new_ext_strsize
+= len
;
3037 if((n_type
& N_TYPE
) == N_UNDF
||
3038 (n_type
& N_TYPE
) == N_PBUD
)
3043 saves
[i
] = new_nsyms
;
3048 * The module table's module names are placed with the external strings.
3049 * So size them and add this to the external string size.
3051 for(i
= 0; i
< nmodtab
; i
++){
3052 if(object
->mh
!= NULL
)
3053 module_name
= mods
[i
].module_name
;
3055 module_name
= mods64
[i
].module_name
;
3056 if(module_name
== 0 || module_name
> strsize
){
3057 error_arch(arch
, member
, "bad string index for module_name "
3058 "of module table entry %d in: ", i
);
3061 len
= strlen(strings
+ module_name
) + 1;
3063 new_ext_strsize
+= len
;
3067 * Updating the reference table may require a symbol not yet listed as
3068 * as saved to be present in the output file. If a defined external
3069 * symbol is removed and there is a undefined reference to it in the
3070 * reference table an undefined symbol needs to be created for it in
3071 * the output file. If this happens the number of new symbols and size
3072 * of the new strings are adjusted. And the array changes[] is set to
3073 * map the old symbol index to the new symbol index for the symbol that
3074 * is changed to an undefined symbol.
3076 missing_symbols
= 0;
3077 if(ref_saves
!= NULL
)
3079 ref_saves
= (int32_t *)allocate(nextrefsyms
* sizeof(int32_t));
3080 bzero(ref_saves
, nextrefsyms
* sizeof(int32_t));
3081 changes
= (uint32_t *)allocate(nsyms
* sizeof(int32_t));
3082 bzero(changes
, nsyms
* sizeof(int32_t));
3083 new_nextrefsyms
= 0;
3084 for(i
= 0; i
< nextrefsyms
; i
++){
3085 if(refs
[i
].isym
> nsyms
){
3086 error_arch(arch
, member
, "bad symbol table index for "
3087 "reference table entry %d in: ", i
);
3090 if(saves
[refs
[i
].isym
]){
3092 ref_saves
[i
] = new_nextrefsyms
;
3095 if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
||
3096 refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
){
3097 if(changes
[refs
[i
].isym
] == 0){
3098 if(object
->mh
!= NULL
)
3099 n_strx
= symbols
[refs
[i
].isym
].n_un
.n_strx
;
3101 n_strx
= symbols64
[refs
[i
].isym
].n_un
.n_strx
;
3102 len
= strlen(strings
+ n_strx
) + 1;
3104 new_ext_strsize
+= len
;
3107 changes
[refs
[i
].isym
] = new_nsyms
;
3109 ref_saves
[i
] = new_nextrefsyms
;
3114 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
||
3115 refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
){
3116 if(missing_symbols
== 0){
3117 error_arch(arch
, member
, "private extern symbols "
3118 "referenced by modules can't be stripped in: ");
3119 missing_symbols
= 1;
3121 if(object
->mh
!= NULL
)
3122 n_strx
= symbols
[refs
[i
].isym
].n_un
.n_strx
;
3124 n_strx
= symbols64
[refs
[i
].isym
].n_un
.n_strx
;
3125 fprintf(stderr
, "%s\n", strings
+ n_strx
);
3126 saves
[refs
[i
].isym
] = -1;
3131 if(missing_symbols
== 1)
3137 for(i
= 0; i
< nsave_symbols
; i
++){
3138 if(save_symbols
[i
].sym
== NULL
){
3139 if(missing_syms
== 0){
3140 error_arch(arch
, member
, "symbols names listed "
3141 "in: %s not in: ", sfile
);
3144 fprintf(stderr
, "%s\n", save_symbols
[i
].name
);
3150 * strip -R on an x86_64 .o file should do nothing.
3153 (object
->mh
!= NULL
||
3154 object
->mh64
->cputype
!= CPU_TYPE_X86_64
||
3155 object
->mh64
->filetype
!= MH_OBJECT
)){
3156 for(i
= 0; i
< nremove_symbols
; i
++){
3157 if(remove_symbols
[i
].sym
== NULL
){
3158 if(missing_syms
== 0){
3159 error_arch(arch
, member
, "symbols names listed "
3160 "in: %s not in: ", Rfile
);
3163 fprintf(stderr
, "%s\n", remove_symbols
[i
].name
);
3170 * If there is a chance that we could end up with an indirect symbol
3171 * with an index of zero we need to avoid that due to a work around
3172 * in the dynamic linker for a bug it is working around that was in
3173 * the old classic static linker. See radar bug 5614542 and the
3174 * related bugs 3685312 and 3534709.
3176 * A reasonable way to do this to know that local symbols are first in
3177 * the symbol table. So if we have any local symbols this won't happen
3178 * and if there are no indirect symbols it will also not happen. Past
3179 * that we'll just add a local symbol so it will end up at symbol index
3180 * zero and avoid any indirect symbol having that index.
3182 * If one really wanted they could build up the new symbol table then
3183 * look at all the indirect symbol table entries to see if any of them
3184 * have an index of zero then in that case throw that new symbol table
3185 * away and rebuild the symbol and string table once again after adding
3186 * a local symbol. This seems not all that resonable to save one symbol
3187 * table entry and a few bytes in the string table for the complexity it
3188 * would add and what it would save.
3190 if(new_nlocalsym
== 0 && nindirectsyms
!= 0){
3191 len
= strlen("radr://5614542") + 1;
3195 hack_5614542
= TRUE
;
3198 hack_5614542
= FALSE
;
3201 if(object
->mh
!= NULL
){
3202 new_symbols
= (struct nlist
*)
3203 allocate(new_nsyms
* sizeof(struct nlist
));
3204 new_symbols64
= NULL
;
3208 new_symbols64
= (struct nlist_64
*)
3209 allocate(new_nsyms
* sizeof(struct nlist_64
));
3211 if(object
->mh
!= NULL
)
3212 new_strsize
= rnd(new_strsize
, sizeof(int32_t));
3214 new_strsize
= rnd(new_strsize
, sizeof(int64_t));
3215 new_strings
= (char *)allocate(new_strsize
);
3216 if(object
->mh
!= NULL
){
3217 new_strings
[new_strsize
- 3] = '\0';
3218 new_strings
[new_strsize
- 2] = '\0';
3219 new_strings
[new_strsize
- 1] = '\0';
3222 new_strings
[new_strsize
- 7] = '\0';
3223 new_strings
[new_strsize
- 6] = '\0';
3224 new_strings
[new_strsize
- 5] = '\0';
3225 new_strings
[new_strsize
- 4] = '\0';
3226 new_strings
[new_strsize
- 3] = '\0';
3227 new_strings
[new_strsize
- 2] = '\0';
3228 new_strings
[new_strsize
- 1] = '\0';
3231 memset(new_strings
, '\0', sizeof(int32_t));
3232 p
= new_strings
+ sizeof(int32_t);
3233 q
= p
+ new_ext_strsize
;
3236 * If all strings were stripped set the size to zero but only for 32-bit
3237 * because the unified linker seems to set the filesize of empty .o
3238 * files to include the string table.
3240 if(object
->mh
!= NULL
&& new_strsize
== sizeof(int32_t))
3244 * Now create a symbol table and string table in this order
3247 * external defined symbols
3256 * If we are doing the hack for radar bug 5614542 (see above) add the
3257 * one local symbol and string.
3259 * We use an N_OPT stab which should be safe to use and not mess any
3260 * thing up. In Mac OS X, gcc(1) writes one N_OPT stab saying the file
3261 * is compiled with gcc(1). Then gdb(1) looks for that stab, but it
3262 * also looks at the name. If the name string is "gcc_compiled" or
3263 * "gcc2_compiled" gdb(1) sets its "compiled by gcc flag. If the N_OPT
3264 * is emitted INSIDE an N_SO section, then gdb(1) thinks that object
3265 * module was compiled by Sun's compiler, which apparently sticks one
3266 * outermost N_LBRAC/N_RBRAC pair, which gdb(1) strips off. But if the
3267 * N_OPT comes before any N_SO stabs, then gdb(1) will just ignore it.
3268 * Since this N_OPT is the first local symbol, it will always come
3269 * before any N_SO stabs that might be around and should be fine.
3271 if(hack_5614542
== TRUE
){
3272 if(object
->mh
!= NULL
){
3273 new_symbols
[inew_syms
].n_type
= N_OPT
;
3274 new_symbols
[inew_syms
].n_sect
= NO_SECT
;
3275 new_symbols
[inew_syms
].n_desc
= 0;
3276 new_symbols
[inew_syms
].n_value
= 0x05614542;
3279 new_symbols64
[inew_syms
].n_type
= N_OPT
;
3280 new_symbols64
[inew_syms
].n_sect
= NO_SECT
;
3281 new_symbols64
[inew_syms
].n_desc
= 0;
3282 new_symbols64
[inew_syms
].n_value
= 0x05614542;
3284 strcpy(q
, "radr://5614542");
3285 if(object
->mh
!= NULL
)
3286 new_symbols
[inew_syms
].n_un
.n_strx
=
3289 new_symbols64
[inew_syms
].n_un
.n_strx
=
3295 for(i
= 0; i
< nsyms
; i
++){
3297 if(object
->mh
!= NULL
){
3298 n_strx
= symbols
[i
].n_un
.n_strx
;
3299 n_type
= symbols
[i
].n_type
;
3302 n_strx
= symbols64
[i
].n_un
.n_strx
;
3303 n_type
= symbols64
[i
].n_type
;
3305 if((n_type
& N_EXT
) == 0){
3306 if(object
->mh
!= NULL
)
3307 new_symbols
[inew_syms
] = symbols
[i
];
3309 new_symbols64
[inew_syms
] = symbols64
[i
];
3311 strcpy(q
, strings
+ n_strx
);
3312 if(object
->mh
!= NULL
)
3313 new_symbols
[inew_syms
].n_un
.n_strx
=
3316 new_symbols64
[inew_syms
].n_un
.n_strx
=
3321 saves
[i
] = inew_syms
;
3326 inew_nextdefsym
= inew_syms
;
3327 #endif /* TRIE_SUPPORT */
3328 for(i
= 0; i
< nsyms
; i
++){
3330 if(object
->mh
!= NULL
){
3331 n_strx
= symbols
[i
].n_un
.n_strx
;
3332 n_type
= symbols
[i
].n_type
;
3333 n_value
= symbols
[i
].n_value
;
3336 n_strx
= symbols64
[i
].n_un
.n_strx
;
3337 n_type
= symbols64
[i
].n_type
;
3338 n_value
= symbols64
[i
].n_value
;
3340 if((n_type
& N_EXT
) == N_EXT
&&
3341 ((n_type
& N_TYPE
) != N_UNDF
&&
3342 (n_type
& N_TYPE
) != N_PBUD
)){
3343 if(object
->mh
!= NULL
)
3344 new_symbols
[inew_syms
] = symbols
[i
];
3346 new_symbols64
[inew_syms
] = symbols64
[i
];
3348 strcpy(p
, strings
+ n_strx
);
3349 if(object
->mh
!= NULL
)
3350 new_symbols
[inew_syms
].n_un
.n_strx
=
3353 new_symbols64
[inew_syms
].n_un
.n_strx
=
3357 if((n_type
& N_TYPE
) == N_INDR
){
3359 strcpy(p
, strings
+ n_value
);
3360 if(object
->mh
!= NULL
)
3361 new_symbols
[inew_syms
].n_value
=
3364 new_symbols64
[inew_syms
].n_value
=
3370 saves
[i
] = inew_syms
;
3375 * Build the new undefined symbols into a map and sort it.
3378 if(object
->mh
!= NULL
){
3379 undef_map
= (struct undef_map
*)allocate(new_nundefsym
*
3380 sizeof(struct undef_map
));
3385 undef_map64
= (struct undef_map64
*)allocate(new_nundefsym
*
3386 sizeof(struct undef_map64
));
3388 for(i
= 0; i
< nsyms
; i
++){
3390 if(object
->mh
!= NULL
){
3391 n_strx
= symbols
[i
].n_un
.n_strx
;
3392 n_type
= symbols
[i
].n_type
;
3395 n_strx
= symbols64
[i
].n_un
.n_strx
;
3396 n_type
= symbols64
[i
].n_type
;
3398 if((n_type
& N_EXT
) == N_EXT
&&
3399 ((n_type
& N_TYPE
) == N_UNDF
||
3400 (n_type
& N_TYPE
) == N_PBUD
)){
3401 if(object
->mh
!= NULL
)
3402 undef_map
[inew_undefsyms
].symbol
= symbols
[i
];
3404 undef_map64
[inew_undefsyms
].symbol64
= symbols64
[i
];
3406 strcpy(p
, strings
+ n_strx
);
3407 if(object
->mh
!= NULL
)
3408 undef_map
[inew_undefsyms
].symbol
.n_un
.n_strx
=
3411 undef_map64
[inew_undefsyms
].symbol64
.n_un
.n_strx
=
3415 if(object
->mh
!= NULL
)
3416 undef_map
[inew_undefsyms
].index
= i
;
3418 undef_map64
[inew_undefsyms
].index
= i
;
3423 for(i
= 0; i
< nsyms
; i
++){
3425 if(object
->mh
!= NULL
)
3426 n_strx
= symbols
[i
].n_un
.n_strx
;
3428 n_strx
= symbols64
[i
].n_un
.n_strx
;
3430 strcpy(p
, strings
+ n_strx
);
3431 if(object
->mh
!= NULL
)
3432 undef_map
[inew_undefsyms
].symbol
.n_un
.n_strx
=
3435 undef_map64
[inew_undefsyms
].symbol64
.n_un
.n_strx
=
3439 if(object
->mh
!= NULL
){
3440 undef_map
[inew_undefsyms
].symbol
.n_type
= N_UNDF
| N_EXT
;
3441 undef_map
[inew_undefsyms
].symbol
.n_sect
= NO_SECT
;
3442 undef_map
[inew_undefsyms
].symbol
.n_desc
= 0;
3443 undef_map
[inew_undefsyms
].symbol
.n_value
= 0;
3444 undef_map
[inew_undefsyms
].index
= i
;
3447 undef_map64
[inew_undefsyms
].symbol64
.n_type
= N_UNDF
|N_EXT
;
3448 undef_map64
[inew_undefsyms
].symbol64
.n_sect
= NO_SECT
;
3449 undef_map64
[inew_undefsyms
].symbol64
.n_desc
= 0;
3450 undef_map64
[inew_undefsyms
].symbol64
.n_value
= 0;
3451 undef_map64
[inew_undefsyms
].index
= i
;
3456 /* Sort the undefined symbols by name */
3457 qsort_strings
= new_strings
;
3458 if(object
->mh
!= NULL
)
3459 qsort(undef_map
, new_nundefsym
, sizeof(struct undef_map
),
3460 (int (*)(const void *, const void *))cmp_qsort_undef_map
);
3462 qsort(undef_map64
, new_nundefsym
, sizeof(struct undef_map64
),
3463 (int (*)(const void *, const void *))cmp_qsort_undef_map_64
);
3464 /* Copy the symbols now in sorted order into new_symbols */
3465 for(i
= 0; i
< new_nundefsym
; i
++){
3466 if(object
->mh
!= NULL
){
3467 new_symbols
[inew_syms
] = undef_map
[i
].symbol
;
3469 saves
[undef_map
[i
].index
] = inew_syms
;
3472 new_symbols64
[inew_syms
] = undef_map64
[i
].symbol64
;
3474 saves
[undef_map64
[i
].index
] = inew_syms
;
3479 * Fixup the module table's module name strings adding them to the
3480 * string table. Also fix the indexes into the symbol table for
3481 * external and local symbols. And fix up the indexes into the
3484 for(i
= 0; i
< nmodtab
; i
++){
3485 if(object
->mh
!= NULL
){
3486 strcpy(p
, strings
+ mods
[i
].module_name
);
3487 mods
[i
].module_name
= p
- new_strings
;
3488 iextdefsym
= mods
[i
].iextdefsym
;
3489 nextdefsym
= mods
[i
].nextdefsym
;
3490 ilocalsym
= mods
[i
].ilocalsym
;
3491 nlocalsym
= mods
[i
].nlocalsym
;
3492 irefsym
= mods
[i
].irefsym
;
3493 nrefsym
= mods
[i
].nrefsym
;
3496 strcpy(p
, strings
+ mods64
[i
].module_name
);
3497 mods64
[i
].module_name
= p
- new_strings
;
3498 iextdefsym
= mods64
[i
].iextdefsym
;
3499 nextdefsym
= mods64
[i
].nextdefsym
;
3500 ilocalsym
= mods64
[i
].ilocalsym
;
3501 nlocalsym
= mods64
[i
].nlocalsym
;
3502 irefsym
= mods64
[i
].irefsym
;
3503 nrefsym
= mods64
[i
].nrefsym
;
3507 if(iextdefsym
> nsyms
){
3508 error_arch(arch
, member
, "bad index into externally defined "
3509 "symbols of module table entry %d in: ", i
);
3512 if(iextdefsym
+ nextdefsym
> nsyms
){
3513 error_arch(arch
, member
, "bad number of externally defined "
3514 "symbols of module table entry %d in: ", i
);
3517 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
3518 if(saves
[j
] != 0 && changes
[j
] == 0)
3522 for(k
= j
; k
< iextdefsym
+ nextdefsym
; k
++){
3523 if(saves
[k
] != 0 && changes
[k
] == 0)
3527 if(object
->mh
!= NULL
){
3528 mods
[i
].iextdefsym
= 0;
3529 mods
[i
].nextdefsym
= 0;
3532 mods64
[i
].iextdefsym
= 0;
3533 mods64
[i
].nextdefsym
= 0;
3537 if(object
->mh
!= NULL
){
3538 mods
[i
].iextdefsym
= saves
[j
] - 1;
3539 mods
[i
].nextdefsym
= n
;
3542 mods64
[i
].iextdefsym
= saves
[j
] - 1;
3543 mods64
[i
].nextdefsym
= n
;
3547 if(ilocalsym
> nsyms
){
3548 error_arch(arch
, member
, "bad index into symbols for local "
3549 "symbols of module table entry %d in: ", i
);
3552 if(ilocalsym
+ nlocalsym
> nsyms
){
3553 error_arch(arch
, member
, "bad number of local "
3554 "symbols of module table entry %d in: ", i
);
3557 for(j
= ilocalsym
; j
< ilocalsym
+ nlocalsym
; j
++){
3562 for(k
= j
; k
< ilocalsym
+ nlocalsym
; k
++){
3567 if(object
->mh
!= NULL
){
3568 mods
[i
].ilocalsym
= 0;
3569 mods
[i
].nlocalsym
= 0;
3572 mods64
[i
].ilocalsym
= 0;
3573 mods64
[i
].nlocalsym
= 0;
3577 if(object
->mh
!= NULL
){
3578 mods
[i
].ilocalsym
= saves
[j
] - 1;
3579 mods
[i
].nlocalsym
= n
;
3582 mods64
[i
].ilocalsym
= saves
[j
] - 1;
3583 mods64
[i
].nlocalsym
= n
;
3587 if(irefsym
> nextrefsyms
){
3588 error_arch(arch
, member
, "bad index into reference table "
3589 "of module table entry %d in: ", i
);
3592 if(irefsym
+ nrefsym
> nextrefsyms
){
3593 error_arch(arch
, member
, "bad number of reference table "
3594 "entries of module table entry %d in: ", i
);
3597 for(j
= irefsym
; j
< irefsym
+ nrefsym
; j
++){
3598 if(ref_saves
[j
] != 0)
3602 for(k
= j
; k
< irefsym
+ nrefsym
; k
++){
3603 if(ref_saves
[k
] != 0)
3607 if(object
->mh
!= NULL
){
3608 mods
[i
].irefsym
= 0;
3609 mods
[i
].nrefsym
= 0;
3612 mods64
[i
].irefsym
= 0;
3613 mods64
[i
].nrefsym
= 0;
3617 if(object
->mh
!= NULL
){
3618 mods
[i
].irefsym
= ref_saves
[j
] - 1;
3619 mods
[i
].nrefsym
= n
;
3622 mods64
[i
].irefsym
= ref_saves
[j
] - 1;
3623 mods64
[i
].nrefsym
= n
;
3629 * Create a new reference table.
3631 new_refs
= allocate(new_nextrefsyms
* sizeof(struct dylib_reference
));
3633 for(i
= 0; i
< nextrefsyms
; i
++){
3635 if(saves
[refs
[i
].isym
]){
3636 new_refs
[j
].isym
= saves
[refs
[i
].isym
] - 1;
3637 new_refs
[j
].flags
= refs
[i
].flags
;
3640 if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
||
3641 refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
){
3642 new_refs
[j
].isym
= changes
[refs
[i
].isym
] - 1;
3643 new_refs
[j
].flags
= refs
[i
].flags
;
3651 * Create a new dylib table of contents.
3654 for(i
= 0; i
< ntoc
; i
++){
3655 if(tocs
[i
].symbol_index
>= nsyms
){
3656 error_arch(arch
, member
, "bad symbol index for table of "
3657 "contents table entry %d in: ", i
);
3660 if(saves
[tocs
[i
].symbol_index
] != 0 &&
3661 changes
[tocs
[i
].symbol_index
] == 0)
3664 new_tocs
= allocate(new_ntoc
* sizeof(struct dylib_table_of_contents
));
3666 for(i
= 0; i
< ntoc
; i
++){
3667 if(saves
[tocs
[i
].symbol_index
] != 0 &&
3668 changes
[tocs
[i
].symbol_index
] == 0){
3669 new_tocs
[j
].symbol_index
= saves
[tocs
[i
].symbol_index
] - 1;
3670 new_tocs
[j
].module_index
= tocs
[i
].module_index
;
3676 * Update the export trie if it has one but only call the the
3677 * prune_trie() routine when we are removing global symbols as is
3678 * done with default stripping of a dyld executable or with the -s
3681 if(object
->dyld_info
!= NULL
&&
3682 object
->dyld_info
->export_size
!= 0 &&
3683 (default_dyld_executable
|| sfile
!= NULL
|| Rfile
!= NULL
)){
3684 const char *error_string
;
3685 uint32_t trie_new_size
;
3687 error_string
= prune_trie((uint8_t *)(object
->object_addr
+
3688 object
->dyld_info
->export_off
),
3689 object
->dyld_info
->export_size
,
3692 if(error_string
!= NULL
){
3693 error_arch(arch
, member
, "%s", error_string
);
3697 #endif /* TRIE_SUPPORT */
3699 if(undef_map
!= NULL
)
3701 if(undef_map64
!= NULL
)
3705 if(sections
!= NULL
)
3707 if(sections64
!= NULL
)
3718 * prune() is called by prune_trie() and passed a name of an external symbol
3719 * in the trie. It returns 1 if the symbols is to be pruned out and 0 if the
3720 * symbol is to be kept.
3722 * Note that it may seem like a linear search of the new symbols would not be
3723 * the best approach but in 10.6 the only defined global symbol left in a
3724 * stripped executable is __mh_execute_header and new_nextdefsym is usually 1
3725 * so this never actually loops in practice.
3734 for(i
= 0; i
< new_nextdefsym
; i
++){
3735 if(new_symbols
!= NULL
){
3736 if(strcmp(name
, new_strings
+ new_symbols
[inew_nextdefsym
+ i
]
3741 if(strcmp(name
, new_strings
+ new_symbols64
[inew_nextdefsym
+ i
]
3748 #endif /* TRIE_SUPPORT */
3751 * make_ld_r_object() takes the object file contents referenced by the passed
3752 * data structures, writes that to a temporary file, runs "ld -r" plus the
3753 * specified stripping option creating a second temporary file, reads that file
3754 * in and replaces the object file contents with that and resets the variables
3755 * pointing to the symbol, string and indirect tables.
3761 struct member
*member
,
3762 struct object
*object
)
3764 enum byte_sex host_byte_sex
;
3765 char *input_file
, *output_file
;
3767 struct ofile
*ld_r_ofile
;
3768 struct arch
*ld_r_archs
;
3769 uint32_t ld_r_narchs
, save_errors
;
3771 host_byte_sex
= get_host_byte_sex();
3774 * Swap the object file back into its bytesex before writing it to the
3775 * temporary file if needed.
3777 if(object
->object_byte_sex
!= host_byte_sex
){
3778 if(object
->mh
!= NULL
){
3779 if(swap_object_headers(object
->mh
, object
->load_commands
) ==
3781 fatal("internal error: swap_object_headers() failed");
3782 swap_nlist(symbols
, nsyms
, object
->object_byte_sex
);
3785 if(swap_object_headers(object
->mh64
, object
->load_commands
) ==
3787 fatal("internal error: swap_object_headers() failed");
3788 swap_nlist_64(symbols64
, nsyms
, object
->object_byte_sex
);
3790 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
3791 object
->object_byte_sex
);
3795 * Create an input object file for the ld -r command from the bytes
3796 * of this arch's object file.
3798 input_file
= makestr("/tmp/strip.XXXXXX", NULL
);
3799 input_file
= mktemp(input_file
);
3801 if((fd
= open(input_file
, O_WRONLY
|O_CREAT
, 0600)) < 0)
3802 system_fatal("can't open temporary file: %s", input_file
);
3804 if(write(fd
, object
->object_addr
, object
->object_size
) !=
3805 object
->object_size
)
3806 system_fatal("can't write temporary file: %s", input_file
);
3809 system_fatal("can't close temporary file: %s", input_file
);
3812 * Create a temporary name for the output file of the ld -r
3814 output_file
= makestr("/tmp/strip.XXXXXX", NULL
);
3815 output_file
= mktemp(output_file
);
3818 * Create the ld -r command line and execute it.
3820 reset_execute_list();
3821 add_execute_list_with_prefix("ld");
3822 add_execute_list("-keep_private_externs");
3823 add_execute_list("-r");
3825 add_execute_list("-S");
3827 add_execute_list("-x");
3828 add_execute_list(input_file
);
3829 add_execute_list("-o");
3830 add_execute_list(output_file
);
3832 add_execute_list("-x");
3833 add_execute_list("-exported_symbols_list");
3834 add_execute_list(sfile
);
3837 add_execute_list("-unexported_symbols_list");
3838 add_execute_list(Rfile
);
3840 if(execute_list(vflag
) == 0)
3841 fatal("internal link edit command failed");
3843 save_errors
= errors
;
3845 /* breakout the output file of the ld -f for processing */
3846 ld_r_ofile
= breakout(output_file
, &ld_r_archs
, &ld_r_narchs
, FALSE
);
3848 goto make_ld_r_object_cleanup
;
3850 /* checkout the file for symbol table replacement processing */
3851 checkout(ld_r_archs
, ld_r_narchs
);
3854 * Make sure the output of the ld -r is an object file with one arch.
3856 if(ld_r_narchs
!= 1 ||
3857 ld_r_archs
->type
!= OFILE_Mach_O
||
3858 ld_r_archs
->object
== NULL
||
3859 ld_r_archs
->object
->mh_filetype
!= MH_OBJECT
)
3860 fatal("internal link edit command failed to produce a thin Mach-O "
3864 * Now reset all the data of the input object with the ld -r output
3867 nsyms
= ld_r_archs
->object
->st
->nsyms
;
3868 if(ld_r_archs
->object
->mh
!= NULL
){
3869 symbols
= (struct nlist
*)
3870 (ld_r_archs
->object
->object_addr
+
3871 ld_r_archs
->object
->st
->symoff
);
3872 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3873 swap_nlist(symbols
, nsyms
, host_byte_sex
);
3878 symbols64
= (struct nlist_64
*)
3879 (ld_r_archs
->object
->object_addr
+
3880 ld_r_archs
->object
->st
->symoff
);
3881 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3882 swap_nlist_64(symbols64
, nsyms
, host_byte_sex
);
3884 strings
= ld_r_archs
->object
->object_addr
+
3885 ld_r_archs
->object
->st
->stroff
;
3886 strsize
= ld_r_archs
->object
->st
->strsize
;
3888 if(ld_r_archs
->object
->dyst
!= NULL
&&
3889 ld_r_archs
->object
->dyst
->nindirectsyms
!= 0){
3890 nindirectsyms
= ld_r_archs
->object
->dyst
->nindirectsyms
;
3891 indirectsyms
= (uint32_t *)
3892 (ld_r_archs
->object
->object_addr
+
3893 ld_r_archs
->object
->dyst
->indirectsymoff
);
3894 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3895 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
3899 indirectsyms
= NULL
;
3903 if(ld_r_archs
->object
->mh
!= NULL
)
3904 ld_r_archs
->object
->input_sym_info_size
=
3905 nsyms
* sizeof(struct nlist
) +
3908 ld_r_archs
->object
->input_sym_info_size
=
3909 nsyms
* sizeof(struct nlist_64
) +
3913 * Copy over the object struct from the ld -r object file onto the
3914 * input object file.
3916 *object
= *ld_r_archs
->object
;
3919 * Save the ofile struct for the ld -r output so it can be umapped when
3920 * we are done. And free up the ld_r_archs now that we are done with
3923 object
->ld_r_ofile
= ld_r_ofile
;
3924 free_archs(ld_r_archs
, ld_r_narchs
);
3926 make_ld_r_object_cleanup
:
3927 errors
+= save_errors
;
3929 * Remove the input and output files and clean up.
3931 if(unlink(input_file
) == -1)
3932 system_fatal("can't remove temporary file: %s", input_file
);
3933 if(unlink(output_file
) == -1)
3934 system_fatal("can't remove temporary file: %s", output_file
);
3940 * strip_LC_UUID_commands() is called when -no_uuid is specified to remove any
3941 * LC_UUID load commands from the object's load commands.
3945 strip_LC_UUID_commands(
3947 struct member
*member
,
3948 struct object
*object
)
3950 uint32_t i
, ncmds
, nuuids
, mh_sizeofcmds
, sizeofcmds
;
3951 struct load_command
*lc1
, *lc2
, *new_load_commands
;
3952 struct segment_command
*sg
;
3955 * See if there are any LC_UUID load commands.
3958 lc1
= arch
->object
->load_commands
;
3959 if(arch
->object
->mh
!= NULL
){
3960 ncmds
= arch
->object
->mh
->ncmds
;
3961 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
3964 ncmds
= arch
->object
->mh64
->ncmds
;
3965 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
3967 for(i
= 0; i
< ncmds
; i
++){
3968 if(lc1
->cmd
== LC_UUID
){
3971 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
3973 /* if no LC_UUID load commands just return */
3978 * Allocate space for the new load commands as zero it out so any holes
3979 * will be zero bytes.
3981 new_load_commands
= allocate(mh_sizeofcmds
);
3982 memset(new_load_commands
, '\0', mh_sizeofcmds
);
3985 * Copy all the load commands except the LC_UUID load commands into the
3986 * allocated space for the new load commands.
3988 lc1
= arch
->object
->load_commands
;
3989 lc2
= new_load_commands
;
3991 for(i
= 0; i
< ncmds
; i
++){
3992 if(lc1
->cmd
!= LC_UUID
){
3993 memcpy(lc2
, lc1
, lc1
->cmdsize
);
3994 sizeofcmds
+= lc2
->cmdsize
;
3995 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
3997 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4001 * Finally copy the updated load commands over the existing load
4004 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
4005 if(mh_sizeofcmds
> sizeofcmds
){
4006 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
4007 (mh_sizeofcmds
- sizeofcmds
));
4010 if(arch
->object
->mh
!= NULL
) {
4011 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
4012 arch
->object
->mh
->ncmds
= ncmds
;
4014 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
4015 arch
->object
->mh64
->ncmds
= ncmds
;
4017 free(new_load_commands
);
4019 /* reset the pointers into the load commands */
4020 lc1
= arch
->object
->load_commands
;
4021 for(i
= 0; i
< ncmds
; i
++){
4024 arch
->object
->st
= (struct symtab_command
*)lc1
;
4027 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
4029 case LC_TWOLEVEL_HINTS
:
4030 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
4032 case LC_PREBIND_CKSUM
:
4033 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
4036 sg
= (struct segment_command
*)lc1
;
4037 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
4038 arch
->object
->seg_linkedit
= sg
;
4040 case LC_SEGMENT_SPLIT_INFO
:
4041 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
4043 case LC_FUNCTION_STARTS
:
4044 object
->func_starts_info_cmd
=
4045 (struct linkedit_data_command
*)lc1
;
4047 case LC_CODE_SIGNATURE
:
4048 object
->code_sig_cmd
= (struct linkedit_data_command
*)lc1
;
4050 case LC_DYLD_INFO_ONLY
:
4052 object
->dyld_info
= (struct dyld_info_command
*)lc1
;
4054 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4060 * strip_LC_CODE_SIGNATURE_commands() is called when -c is specified to remove
4061 * any LC_CODE_SIGNATURE load commands from the object's load commands.
4065 strip_LC_CODE_SIGNATURE_commands(
4067 struct member
*member
,
4068 struct object
*object
)
4070 uint32_t i
, ncmds
, mh_sizeofcmds
, sizeofcmds
;
4071 struct load_command
*lc1
, *lc2
, *new_load_commands
;
4072 struct segment_command
*sg
;
4075 * See if there is an LC_CODE_SIGNATURE load command and if no command
4078 if(object
->code_sig_cmd
== NULL
)
4082 * Allocate space for the new load commands and zero it out so any holes
4083 * will be zero bytes.
4085 if(arch
->object
->mh
!= NULL
){
4086 ncmds
= arch
->object
->mh
->ncmds
;
4087 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
4090 ncmds
= arch
->object
->mh64
->ncmds
;
4091 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
4093 new_load_commands
= allocate(mh_sizeofcmds
);
4094 memset(new_load_commands
, '\0', mh_sizeofcmds
);
4097 * Copy all the load commands except the LC_CODE_SIGNATURE load commands
4098 * into the allocated space for the new load commands.
4100 lc1
= arch
->object
->load_commands
;
4101 lc2
= new_load_commands
;
4103 for(i
= 0; i
< ncmds
; i
++){
4104 if(lc1
->cmd
!= LC_CODE_SIGNATURE
){
4105 memcpy(lc2
, lc1
, lc1
->cmdsize
);
4106 sizeofcmds
+= lc2
->cmdsize
;
4107 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
4109 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4113 * Finally copy the updated load commands over the existing load
4116 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
4117 if(mh_sizeofcmds
> sizeofcmds
){
4118 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
4119 (mh_sizeofcmds
- sizeofcmds
));
4122 if(arch
->object
->mh
!= NULL
) {
4123 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
4124 arch
->object
->mh
->ncmds
= ncmds
;
4126 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
4127 arch
->object
->mh64
->ncmds
= ncmds
;
4129 free(new_load_commands
);
4131 /* reset the pointers into the load commands */
4132 object
->code_sig_cmd
= NULL
;
4133 lc1
= arch
->object
->load_commands
;
4134 for(i
= 0; i
< ncmds
; i
++){
4137 arch
->object
->st
= (struct symtab_command
*)lc1
;
4140 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
4142 case LC_TWOLEVEL_HINTS
:
4143 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
4145 case LC_PREBIND_CKSUM
:
4146 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
4149 sg
= (struct segment_command
*)lc1
;
4150 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
4151 arch
->object
->seg_linkedit
= sg
;
4153 case LC_SEGMENT_SPLIT_INFO
:
4154 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
4156 case LC_FUNCTION_STARTS
:
4157 object
->func_starts_info_cmd
=
4158 (struct linkedit_data_command
*)lc1
;
4161 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4165 * To get the right amount of the file copied out by writeout() for the
4166 * case when we are stripping out the section contents we already reduce
4167 * the object size by the size of the section contents including the
4168 * padding after the load commands. So here we need to further reduce
4169 * it by the load command for the LC_CODE_SIGNATURE (a struct
4170 * linkedit_data_command) we are removing.
4172 object
->object_size
-= sizeof(struct linkedit_data_command
);
4174 * Then this size minus the size of the input symbolic information is
4175 * what is copied out from the file by writeout(). Which in this case
4176 * is just the new headers.
4180 * Finally for -c the file offset to the link edit information is to be
4181 * right after the load commands. So reset this for the updated size
4182 * of the load commands without the LC_CODE_SIGNATURE.
4184 if(object
->mh
!= NULL
)
4185 object
->seg_linkedit
->fileoff
= sizeof(struct mach_header
) +
4188 object
->seg_linkedit64
->fileoff
= sizeof(struct mach_header_64
) +
4191 #endif /* !(NMEDIT) */
4194 * private_extern_reference_by_module() is passed a symbol_index of a private
4195 * extern symbol and the module table. If the symbol_index appears in the
4196 * module symbol table this returns TRUE else it returns FALSE.
4200 private_extern_reference_by_module(
4201 uint32_t symbol_index
,
4202 struct dylib_reference
*refs
,
4203 uint32_t nextrefsyms
)
4207 for(i
= 0; i
< nextrefsyms
; i
++){
4208 if(refs
[i
].isym
== symbol_index
){
4209 if(refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
||
4210 refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
){
4219 * symbol_pointer_used() is passed a symbol_index and the indirect table. If
4220 * the symbol_index appears in the indirect symbol table this returns TRUE else
4225 symbol_pointer_used(
4226 uint32_t symbol_index
,
4227 uint32_t *indirectsyms
,
4228 uint32_t nindirectsyms
)
4232 for(i
= 0; i
< nindirectsyms
; i
++){
4233 if(indirectsyms
[i
] == symbol_index
)
4240 * Function for qsort for comparing undefined map entries.
4244 cmp_qsort_undef_map(
4245 const struct undef_map
*sym1
,
4246 const struct undef_map
*sym2
)
4248 return(strcmp(qsort_strings
+ sym1
->symbol
.n_un
.n_strx
,
4249 qsort_strings
+ sym2
->symbol
.n_un
.n_strx
));
4254 cmp_qsort_undef_map_64(
4255 const struct undef_map64
*sym1
,
4256 const struct undef_map64
*sym2
)
4258 return(strcmp(qsort_strings
+ sym1
->symbol64
.n_un
.n_strx
,
4259 qsort_strings
+ sym2
->symbol64
.n_un
.n_strx
));
4261 #endif /* !defined(NMEDIT) */
4265 * Function for qsort for comparing object names.
4273 return(strcmp(*name1
, *name2
));
4277 * Function for bsearch for finding a object name.
4281 cmp_bsearch_filename(
4285 return(strcmp(name1
, *name2
));
4287 #endif /* !defined(NMEDIT) */
4294 struct member
*member
,
4295 struct object
*object
,
4296 struct nlist
*symbols
,
4297 struct nlist_64
*symbols64
,
4301 struct dylib_table_of_contents
*tocs
,
4303 struct dylib_module
*mods
,
4304 struct dylib_module_64
*mods64
,
4306 struct dylib_reference
*refs
,
4307 uint32_t nextrefsyms
)
4310 unsigned char data_n_sect
, nsects
;
4311 struct load_command
*lc
;
4312 struct segment_command
*sg
;
4313 struct segment_command_64
*sg64
;
4314 struct section
*s
, **sections
;
4315 struct section_64
*s64
, **sections64
;
4317 uint32_t missing_syms
;
4318 struct symbol_list
*sp
;
4319 struct nlist
**global_symbol
;
4320 struct nlist_64
**global_symbol64
;
4321 enum bool global_symbol_found
;
4322 char *global_name
, save_char
;
4323 enum bool dwarf_debug_map
;
4324 enum byte_sex host_byte_sex
;
4325 int32_t missing_reloc_symbols
;
4326 enum bool edit_symtab_return
;
4329 uint32_t new_ext_strsize
, len
, inew_syms
;
4331 struct nlist
**changed_globals
;
4332 struct nlist_64
**changed_globals64
;
4333 uint32_t nchanged_globals
;
4334 uint32_t ncmds
, s_flags
, n_strx
, module_name
, ilocalsym
, nlocalsym
;
4335 uint32_t iextdefsym
, nextdefsym
;
4336 uint8_t n_type
, n_sect
, global_symbol_n_sect
;
4338 enum bool warned_about_global_coalesced_symbols
;
4340 edit_symtab_return
= TRUE
;
4341 host_byte_sex
= get_host_byte_sex();
4342 missing_reloc_symbols
= 0;
4343 warned_about_global_coalesced_symbols
= FALSE
;
4347 nmedits
= allocate(nsyms
* sizeof(enum bool));
4348 for(i
= 0; i
< nsyms
; i
++)
4352 * If nmedit is operating on a dynamic library then symbols are turned
4353 * into private externs with the extern bit off not into static symbols.
4355 if(object
->mh_filetype
== MH_DYLIB
&& pflag
== TRUE
){
4356 error_arch(arch
, member
, "can't use -p with dynamic libraries");
4361 * As part of the MAJOR guess for the second pass to fix stabs for the
4362 * globals symbols that get turned into non-global symbols. We need to
4363 * change the stabs. To do this we to know if a N_GSYM is for a data
4364 * symbol or not to know to turn it into an N_STSYM or a N_FUN.
4365 * This logic as determined by compiling test cases with and without
4366 * the key word 'static' and looking at the difference between the STABS
4367 * the compiler generates and trying to match that here.
4369 * We also use this loop and the next to gather an array of section
4370 * struct pointers so we can later determine if we run into a global
4371 * symbol in a coalesced section and not turn those symbols into
4377 data_n_sect
= NO_SECT
;
4378 lc
= object
->load_commands
;
4379 if(object
->mh
!= NULL
)
4380 ncmds
= object
->mh
->ncmds
;
4382 ncmds
= object
->mh64
->ncmds
;
4383 for(i
= 0; i
< ncmds
; i
++){
4384 if(lc
->cmd
== LC_SEGMENT
){
4385 sg
= (struct segment_command
*)lc
;
4386 s
= (struct section
*)((char *)sg
+
4387 sizeof(struct segment_command
));
4388 nsects
+= sg
->nsects
;
4389 for(j
= 0; j
< sg
->nsects
; j
++){
4390 if(strcmp(s
->segname
, SEG_DATA
) == 0 &&
4391 strcmp(s
->sectname
, SECT_DATA
) == 0 &&
4392 data_n_sect
== NO_SECT
){
4393 data_n_sect
= n_sect
;
4400 else if(lc
->cmd
== LC_SEGMENT_64
){
4401 sg64
= (struct segment_command_64
*)lc
;
4402 s64
= (struct section_64
*)((char *)sg64
+
4403 sizeof(struct segment_command_64
));
4404 nsects
+= sg64
->nsects
;
4405 for(j
= 0; j
< sg64
->nsects
; j
++){
4406 if(strcmp(s64
->segname
, SEG_DATA
) == 0 &&
4407 strcmp(s64
->sectname
, SECT_DATA
) == 0 &&
4408 data_n_sect
== NO_SECT
){
4409 data_n_sect
= n_sect
;
4416 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
4418 if(object
->mh
!= NULL
){
4419 sections
= allocate(nsects
* sizeof(struct section
*));
4424 sections64
= allocate(nsects
* sizeof(struct section_64
*));
4427 lc
= object
->load_commands
;
4428 for(i
= 0; i
< ncmds
; i
++){
4429 if(lc
->cmd
== LC_SEGMENT
){
4430 sg
= (struct segment_command
*)lc
;
4431 s
= (struct section
*)((char *)sg
+
4432 sizeof(struct segment_command
));
4433 for(j
= 0; j
< sg
->nsects
; j
++){
4434 sections
[nsects
++] = s
++;
4437 else if(lc
->cmd
== LC_SEGMENT_64
){
4438 sg64
= (struct segment_command_64
*)lc
;
4439 s64
= (struct section_64
*)((char *)sg64
+
4440 sizeof(struct segment_command_64
));
4441 for(j
= 0; j
< sg64
->nsects
; j
++){
4442 sections64
[nsects
++] = s64
++;
4445 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
4449 * Zero out the saved symbols so they can be recorded for this file.
4451 for(i
= 0; i
< nsave_symbols
; i
++)
4452 save_symbols
[i
].sym
= NULL
;
4453 for(i
= 0; i
< nremove_symbols
; i
++)
4454 remove_symbols
[i
].sym
= NULL
;
4456 for(i
= 0; i
< nsave_symbols
; i
++)
4457 save_symbols
[i
].seen
= FALSE
;
4458 for(i
= 0; i
< nremove_symbols
; i
++)
4459 remove_symbols
[i
].seen
= FALSE
;
4462 nchanged_globals
= 0;
4463 if(object
->mh
!= NULL
){
4464 changed_globals
= allocate(nsyms
* sizeof(struct nlist
*));
4465 changed_globals64
= NULL
;
4466 for(i
= 0; i
< nsyms
; i
++)
4467 changed_globals
[i
] = NULL
;
4470 changed_globals
= NULL
;
4471 changed_globals64
= allocate(nsyms
* sizeof(struct nlist_64
*));
4472 for(i
= 0; i
< nsyms
; i
++)
4473 changed_globals64
[i
] = NULL
;
4477 * These are the variables for the new symbol table and new string
4478 * table. Since this routine only turns globals into non-globals the
4479 * number of symbols does not change. But the count of local, defined
4480 * external symbols does change.
4487 new_strsize
= sizeof(int32_t);
4488 new_ext_strsize
= 0;
4491 * First pass: turn the globals symbols into non-global symbols.
4493 for(i
= 0; i
< nsyms
; i
++){
4496 if(object
->mh
!= NULL
){
4497 n_strx
= symbols
[i
].n_un
.n_strx
;
4498 n_type
= symbols
[i
].n_type
;
4499 n_sect
= symbols
[i
].n_sect
;
4500 if((n_type
& N_TYPE
) == N_SECT
)
4501 s_flags
= sections
[n_sect
- 1]->flags
;
4502 n_value
= symbols
[i
].n_value
;
4505 n_strx
= symbols64
[i
].n_un
.n_strx
;
4506 n_type
= symbols64
[i
].n_type
;
4507 n_sect
= symbols64
[i
].n_sect
;
4508 if((n_type
& N_TYPE
) == N_SECT
)
4509 s_flags
= sections64
[n_sect
- 1]->flags
;
4510 n_value
= symbols64
[i
].n_value
;
4513 if(n_strx
> strsize
){
4514 error_arch(arch
, member
, "bad string index for symbol "
4515 "table entry %u in: ", i
);
4518 len
= strlen(strings
+ n_strx
) + 1;
4521 if((n_type
& N_TYPE
) != N_UNDF
&&
4522 (n_type
& N_TYPE
) != N_PBUD
){
4523 if((n_type
& N_TYPE
) == N_SECT
){
4524 if(n_sect
> nsects
){
4525 error_arch(arch
, member
, "bad n_sect for symbol "
4526 "table entry %u in: ", i
);
4529 if(((s_flags
& SECTION_TYPE
) == S_COALESCED
) &&
4531 object
->mh_filetype
!= MH_OBJECT
){
4532 /* this remains a global defined symbol */
4533 if(warned_about_global_coalesced_symbols
== FALSE
){
4534 warning_arch(arch
, member
, "can't make global "
4535 "coalesced symbols (like %s) into static "
4536 "symbols (use ld(1)'s "
4537 "-exported_symbols_list option) in a final "
4538 "linked image: ", strings
+ n_strx
);
4539 warned_about_global_coalesced_symbols
= TRUE
;
4542 new_ext_strsize
+= len
;
4544 sp
= bsearch(strings
+ n_strx
,
4545 remove_symbols
, nremove_symbols
,
4546 sizeof(struct symbol_list
),
4547 (int (*)(const void *, const void *))
4548 symbol_list_bsearch
);
4550 if(sp
->sym
!= NULL
){
4551 error_arch(arch
, member
, "more than one "
4552 "symbol for: %s found in: ", sp
->name
);
4556 if(object
->mh
!= NULL
)
4557 sp
->sym
= &(symbols
[i
]);
4559 sp
->sym
= &(symbols64
[i
]);
4561 warning_arch(arch
, member
, "can't make "
4562 "global coalesced symbol: %s into a "
4563 "static symbol in: ", sp
->name
);
4567 * In case the user has listed this coalesced
4568 * symbol in the save list look for it and mark it
4569 * as seen so we don't complain about not seeing it.
4571 sp
= bsearch(strings
+ n_strx
,
4572 save_symbols
, nsave_symbols
,
4573 sizeof(struct symbol_list
),
4574 (int (*)(const void *, const void *))
4575 symbol_list_bsearch
);
4577 if(sp
->sym
!= NULL
){
4578 error_arch(arch
, member
, "more than one "
4579 "symbol for: %s found in: ", sp
->name
);
4583 if(object
->mh
!= NULL
)
4584 sp
->sym
= &(symbols
[i
]);
4586 sp
->sym
= &(symbols64
[i
]);
4590 continue; /* leave this symbol unchanged */
4593 sp
= bsearch(strings
+ n_strx
,
4594 remove_symbols
, nremove_symbols
,
4595 sizeof(struct symbol_list
),
4596 (int (*)(const void *, const void *))
4597 symbol_list_bsearch
);
4599 if(sp
->sym
!= NULL
){
4600 error_arch(arch
, member
, "more than one symbol "
4601 "for: %s found in: ", sp
->name
);
4605 if(object
->mh
!= NULL
)
4606 sp
->sym
= &(symbols
[i
]);
4608 sp
->sym
= &(symbols64
[i
]);
4615 * If there is no list of saved symbols, then all
4616 * symbols will be saved unless listed in the remove
4621 * There is no save list, so if there is also no
4622 * remove list but the -p flag is specified or it is
4623 * a dynamic library then change all symbols.
4625 if((pflag
|| object
->mh_filetype
== MH_DYLIB
)
4626 && nremove_symbols
== 0)
4628 /* this remains a global defined symbol */
4630 new_ext_strsize
+= len
;
4632 continue; /* leave this symbol unchanged */
4635 sp
= bsearch(strings
+ n_strx
,
4636 save_symbols
, nsave_symbols
,
4637 sizeof(struct symbol_list
),
4638 (int (*)(const void *, const void *))
4639 symbol_list_bsearch
);
4641 if(sp
->sym
!= NULL
){
4642 error_arch(arch
, member
, "more than one symbol "
4643 "for: %s found in: ", sp
->name
);
4647 if(object
->mh
!= NULL
)
4648 sp
->sym
= &(symbols
[i
]);
4650 sp
->sym
= &(symbols64
[i
]);
4652 /* this remains a global defined symbol */
4654 new_ext_strsize
+= len
;
4659 if(Aflag
&& n_type
== (N_EXT
| N_ABS
) &&
4662 strncmp(strings
+ n_strx
,
4663 ".objc_class_name_",
4664 sizeof(".objc_class_name_") - 1) == 0))){
4665 /* this remains a global defined symbol */
4667 new_ext_strsize
+= len
;
4672 if((n_type
& N_TYPE
) != N_INDR
){
4674 if(object
->mh
!= NULL
)
4675 changed_globals
[nchanged_globals
++] =
4678 changed_globals64
[nchanged_globals
++] =
4681 /* this remains a global defined symbol */
4683 new_ext_strsize
+= len
;
4687 /* this will become a non-global symbol */
4693 /* this remains a global defined symbol */
4695 new_ext_strsize
+= len
;
4702 /* this is an undefined symbol */
4704 new_ext_strsize
+= len
;
4709 /* this is a local symbol */
4716 * The module table's module names are placed with the external
4717 * strings. So size them and add this to the external string size.
4719 for(i
= 0; i
< nmodtab
; i
++){
4720 if(object
->mh
!= NULL
)
4721 module_name
= mods
[i
].module_name
;
4723 module_name
= mods64
[i
].module_name
;
4724 if(module_name
== 0 || module_name
> strsize
){
4725 error_arch(arch
, member
, "bad string index for module_name "
4726 "of module table entry %d in: ", i
);
4729 len
= strlen(strings
+ module_name
) + 1;
4731 new_ext_strsize
+= len
;
4735 * Warn about symbols to be saved that were missing.
4740 for(i
= 0; i
< nsave_symbols
; i
++){
4741 if(save_symbols
[i
].sym
== NULL
){
4742 if(missing_syms
== 0){
4743 error_arch(arch
, member
, "symbols names listed "
4744 "in: %s not in: ", sfile
);
4747 fprintf(stderr
, "%s\n", save_symbols
[i
].name
);
4750 for(i
= 0; i
< nremove_symbols
; i
++){
4751 if(remove_symbols
[i
].sym
== NULL
){
4752 if(missing_syms
== 0){
4753 error_arch(arch
, member
, "symbols names listed "
4754 "in: %s not in: ", Rfile
);
4757 fprintf(stderr
, "%s\n", remove_symbols
[i
].name
);
4764 * Second pass: fix stabs for the globals symbols that got turned into
4765 * non-global symbols. This is a MAJOR guess. The specific changes
4766 * to do here were determined by compiling test cases with and without
4767 * the key word 'static' and looking at the difference between the STABS
4768 * the compiler generates and trying to match that here.
4770 global_strings
= strings
;
4771 if(object
->mh
!= NULL
)
4772 qsort(changed_globals
, nchanged_globals
, sizeof(struct nlist
*),
4773 (int (*)(const void *, const void *))cmp_qsort_global
);
4775 qsort(changed_globals64
, nchanged_globals
,sizeof(struct nlist_64
*),
4776 (int (*)(const void *, const void *))cmp_qsort_global_64
);
4777 dwarf_debug_map
= FALSE
;
4778 for(i
= 0; i
< nsyms
; i
++){
4780 if(object
->mh
!= NULL
){
4781 n_strx
= symbols
[i
].n_un
.n_strx
;
4782 n_type
= symbols
[i
].n_type
;
4783 n_desc
= symbols
[i
].n_desc
;
4786 n_strx
= symbols64
[i
].n_un
.n_strx
;
4787 n_type
= symbols64
[i
].n_type
;
4788 n_desc
= symbols64
[i
].n_desc
;
4791 dwarf_debug_map
= FALSE
;
4792 else if (n_type
== N_OSO
)
4793 dwarf_debug_map
= n_desc
!= 0;
4794 else if (dwarf_debug_map
&& n_type
== N_GSYM
){
4795 global_name
= strings
+ n_strx
;
4796 if(object
->mh
!= NULL
){
4797 global_symbol
= bsearch(global_name
, changed_globals
,
4798 nchanged_globals
,sizeof(struct nlist
*),
4799 (int (*)(const void *, const void *))
4800 cmp_bsearch_global
);
4801 if(global_symbol
!= NULL
){
4802 symbols
[i
].n_type
= N_STSYM
;
4803 symbols
[i
].n_sect
= (*global_symbol
)->n_sect
;
4804 symbols
[i
].n_value
= (*global_symbol
)->n_value
;
4808 global_symbol64
= bsearch(global_name
, changed_globals64
,
4810 sizeof(struct nlist_64
*),
4811 (int (*)(const void *, const void *))
4812 cmp_bsearch_global_64
);
4813 if(global_symbol64
!= NULL
){
4814 symbols64
[i
].n_type
= N_STSYM
;
4815 symbols64
[i
].n_sect
= (*global_symbol64
)->n_sect
;
4816 symbols64
[i
].n_value
= (*global_symbol64
)->n_value
;
4820 else if(! dwarf_debug_map
&&
4821 (n_type
== N_GSYM
|| n_type
== N_FUN
) &&
4822 (n_strx
!= 0 && strings
[n_strx
] != '\0')){
4823 global_name
= strings
+ n_strx
;
4824 if((global_name
[0] == '+' || global_name
[0] == '-') &&
4825 global_name
[1] == '['){
4827 while(j
+ n_strx
< strsize
&& global_name
[j
] != ']')
4829 if(j
+ n_strx
< strsize
&& global_name
[j
] == ']')
4834 while(j
+ n_strx
< strsize
&& global_name
[j
] != ':')
4836 if(j
+ n_strx
>= strsize
){
4837 error_arch(arch
, member
, "bad N_STAB symbol name for entry "
4838 "%u (does not contain ':' separating name from type) "
4842 save_char
= global_name
[j
];
4843 global_name
[j
] = '\0';
4845 global_symbol_found
= FALSE
;
4846 global_symbol_n_sect
= 0;
4847 if(object
->mh
!= NULL
){
4848 global_symbol
= bsearch(global_name
, changed_globals
,
4849 nchanged_globals
,sizeof(struct nlist
*),
4850 (int (*)(const void *, const void *))
4851 cmp_bsearch_global_stab
);
4852 global_symbol64
= NULL
;
4853 if(global_symbol
!= NULL
){
4854 global_symbol_found
= TRUE
;
4855 global_symbol_n_sect
= (*global_symbol
)->n_sect
;
4859 global_symbol64
= bsearch(global_name
, changed_globals64
,
4861 sizeof(struct nlist_64
*),
4862 (int (*)(const void *, const void *))
4863 cmp_bsearch_global_stab_64
);
4864 global_symbol
= NULL
;
4865 if(global_symbol64
!= NULL
){
4866 global_symbol_found
= TRUE
;
4867 global_symbol_n_sect
= (*global_symbol64
)->n_sect
;
4870 global_name
[j
] = save_char
;
4871 if(global_symbol_found
== TRUE
){
4872 if(n_type
== N_GSYM
){
4873 if(global_symbol_n_sect
== data_n_sect
){
4874 if(object
->mh
!= NULL
)
4875 symbols
[i
].n_type
= N_STSYM
;
4877 symbols64
[i
].n_type
= N_STSYM
;
4880 if(object
->mh
!= NULL
)
4881 symbols
[i
].n_type
= N_FUN
;
4883 symbols64
[i
].n_type
= N_FUN
;
4885 if(object
->mh
!= NULL
){
4886 symbols
[i
].n_sect
= (*global_symbol
)->n_sect
;
4887 symbols
[i
].n_value
= (*global_symbol
)->n_value
;
4888 symbols
[i
].n_desc
= (*global_symbol
)->n_desc
;
4891 symbols64
[i
].n_sect
= (*global_symbol64
)->n_sect
;
4892 symbols64
[i
].n_value
= (*global_symbol64
)->n_value
;
4893 symbols64
[i
].n_desc
= (*global_symbol64
)->n_desc
;
4895 if(j
+ 1 + n_strx
>= strsize
||
4896 global_name
[j
+1] != 'G'){
4897 error_arch(arch
, member
, "bad N_GSYM symbol name "
4898 "for entry %u (does not have type 'G' after "
4899 "':' in name) in: ", i
);
4902 global_name
[j
+1] = 'S';
4904 else{ /* n_type == N_FUN */
4905 if(j
+ 1 + n_strx
>= strsize
||
4906 global_name
[j
+1] == 'F'){
4907 global_name
[j
+1] = 'f';
4913 global_strings
= NULL
;
4916 * Now what needs to be done is to create the new symbol table moving
4917 * those global symbols being changed into non-globals into the areas
4918 * in the symbol table for local symbols. The symbol table and string
4919 * table must be in this order:
4923 * external defined symbols
4931 saves
= (int32_t *)allocate(nsyms
* sizeof(int32_t));
4932 bzero(saves
, nsyms
* sizeof(int32_t));
4934 if(object
->mh
!= NULL
){
4935 new_symbols
= (struct nlist
*)
4936 allocate(new_nsyms
* sizeof(struct nlist
));
4937 new_symbols64
= NULL
;
4941 new_symbols64
= (struct nlist_64
*)
4942 allocate(new_nsyms
* sizeof(struct nlist_64
));
4944 new_strsize
= rnd(new_strsize
, sizeof(int32_t));
4945 new_strings
= (char *)allocate(new_strsize
);
4946 new_strings
[new_strsize
- 3] = '\0';
4947 new_strings
[new_strsize
- 2] = '\0';
4948 new_strings
[new_strsize
- 1] = '\0';
4950 memset(new_strings
, '\0', sizeof(int32_t));
4951 p
= new_strings
+ sizeof(int32_t);
4952 q
= p
+ new_ext_strsize
;
4955 * If this is a dynamic library the movement of the symbols has to be
4956 * done with respect to the modules. As the local symbols, and external
4957 * defined symbols are grouped together for each module. Then a new
4958 * module table needs to be created with the new indexes into the symbol
4959 * table for each module.
4961 new_nmodtab
= nmodtab
;
4963 new_nextrefsyms
= nextrefsyms
;
4964 if(object
->mh_filetype
== MH_DYLIB
&& nmodtab
!= 0){
4965 if(object
->mh
!= NULL
){
4966 new_mods
= allocate(nmodtab
* sizeof(struct dylib_module
));
4971 new_mods64
= allocate(nmodtab
* sizeof(struct dylib_module_64
));
4976 * This first loop through the module table sets the index and
4977 * counts of the local symbols for each module.
4979 for(i
= 0; i
< nmodtab
; i
++){
4981 * First put the existing local symbols into the new symbol
4984 if(object
->mh
!= NULL
){
4985 new_mods
[i
].ilocalsym
= inew_syms
;
4986 new_mods
[i
].nlocalsym
= 0;
4987 ilocalsym
= mods
[i
].ilocalsym
;
4988 nlocalsym
= mods
[i
].nlocalsym
;
4991 new_mods64
[i
].ilocalsym
= inew_syms
;
4992 new_mods64
[i
].nlocalsym
= 0;
4993 ilocalsym
= mods64
[i
].ilocalsym
;
4994 nlocalsym
= mods64
[i
].nlocalsym
;
4996 for(j
= ilocalsym
; j
< ilocalsym
+ nlocalsym
; j
++){
4997 if(object
->mh
!= NULL
){
4998 n_strx
= symbols
[j
].n_un
.n_strx
;
4999 n_type
= symbols
[j
].n_type
;
5002 n_strx
= symbols64
[j
].n_un
.n_strx
;
5003 n_type
= symbols64
[j
].n_type
;
5005 if((n_type
& N_EXT
) == 0){
5006 if(object
->mh
!= NULL
)
5007 new_symbols
[inew_syms
] = symbols
[j
];
5009 new_symbols64
[inew_syms
] = symbols64
[j
];
5011 strcpy(q
, strings
+ n_strx
);
5012 if(object
->mh
!= NULL
)
5013 new_symbols
[inew_syms
].n_un
.n_strx
=
5016 new_symbols64
[inew_syms
].n_un
.n_strx
=
5021 saves
[j
] = inew_syms
;
5022 if(object
->mh
!= NULL
)
5023 new_mods
[i
].nlocalsym
++;
5025 new_mods64
[i
].nlocalsym
++;
5029 * Next put the global symbols that were changed into
5030 * non-global symbols into the new symbol table and moved their
5031 * counts to the local symbol counts.
5033 if(object
->mh
!= NULL
){
5034 iextdefsym
= mods
[i
].iextdefsym
;
5035 nextdefsym
= mods
[i
].nextdefsym
;
5038 iextdefsym
= mods64
[i
].iextdefsym
;
5039 nextdefsym
= mods64
[i
].nextdefsym
;
5041 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
5042 if(object
->mh
!= NULL
){
5043 n_strx
= symbols
[j
].n_un
.n_strx
;
5044 n_type
= symbols
[j
].n_type
;
5047 n_strx
= symbols64
[j
].n_un
.n_strx
;
5048 n_type
= symbols64
[j
].n_type
;
5050 if((n_type
& N_EXT
) != 0){
5051 if(nmedits
[j
] == TRUE
){
5053 * Change the new symbol to a private extern symbol
5054 * with the extern bit off.
5056 if(object
->mh
!= NULL
){
5057 new_symbols
[inew_syms
] = symbols
[j
];
5058 new_symbols
[inew_syms
].n_type
|= N_PEXT
;
5059 new_symbols
[inew_syms
].n_type
&= ~N_EXT
;
5062 new_symbols64
[inew_syms
] = symbols64
[j
];
5063 new_symbols64
[inew_syms
].n_type
|= N_PEXT
;
5064 new_symbols64
[inew_syms
].n_type
&= ~N_EXT
;
5067 strcpy(q
, strings
+ n_strx
);
5068 if(object
->mh
!= NULL
)
5069 new_symbols
[inew_syms
].n_un
.n_strx
=
5072 new_symbols64
[inew_syms
].n_un
.n_strx
=
5077 saves
[j
] = inew_syms
;
5078 if(object
->mh
!= NULL
)
5079 new_mods
[i
].nlocalsym
++;
5081 new_mods64
[i
].nlocalsym
++;
5087 * Next put the unchanged defined global symbols into the new
5090 for(i
= 0; i
< nmodtab
; i
++){
5091 if(object
->mh
!= NULL
){
5092 new_mods
[i
].iextdefsym
= inew_syms
;
5093 new_mods
[i
].nextdefsym
= 0;
5094 iextdefsym
= mods
[i
].iextdefsym
;
5095 nextdefsym
= mods
[i
].nextdefsym
;
5098 new_mods64
[i
].iextdefsym
= inew_syms
;
5099 new_mods64
[i
].nextdefsym
= 0;
5100 iextdefsym
= mods64
[i
].iextdefsym
;
5101 nextdefsym
= mods64
[i
].nextdefsym
;
5103 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
5104 if(object
->mh
!= NULL
){
5105 n_strx
= symbols
[j
].n_un
.n_strx
;
5106 n_type
= symbols
[j
].n_type
;
5109 n_strx
= symbols64
[j
].n_un
.n_strx
;
5110 n_type
= symbols64
[j
].n_type
;
5112 if((n_type
& N_EXT
) != 0){
5113 if(nmedits
[j
] == FALSE
){
5114 if(object
->mh
!= NULL
)
5115 new_symbols
[inew_syms
] = symbols
[j
];
5117 new_symbols64
[inew_syms
] = symbols64
[j
];
5119 strcpy(p
, strings
+ n_strx
);
5120 if(object
->mh
!= NULL
)
5121 new_symbols
[inew_syms
].n_un
.n_strx
=
5124 new_symbols64
[inew_syms
].n_un
.n_strx
=
5129 saves
[j
] = inew_syms
;
5130 if(object
->mh
!= NULL
)
5131 new_mods
[i
].nextdefsym
++;
5133 new_mods64
[i
].nextdefsym
++;
5139 * Last put the undefined symbols into the new symbol table.
5141 for(i
= 0; i
< nsyms
; i
++){
5142 if(object
->mh
!= NULL
){
5143 n_strx
= symbols
[i
].n_un
.n_strx
;
5144 n_type
= symbols
[i
].n_type
;
5147 n_strx
= symbols64
[i
].n_un
.n_strx
;
5148 n_type
= symbols64
[i
].n_type
;
5150 if((n_type
& N_EXT
) != 0 &&
5151 ((n_type
& N_TYPE
) == N_UNDF
||
5152 (n_type
& N_TYPE
) == N_PBUD
)){
5153 if(object
->mh
!= NULL
)
5154 new_symbols
[inew_syms
] = symbols
[i
];
5156 new_symbols64
[inew_syms
] = symbols64
[i
];
5158 strcpy(p
, strings
+ n_strx
);
5159 if(object
->mh
!= NULL
)
5160 new_symbols
[inew_syms
].n_un
.n_strx
=
5163 new_symbols64
[inew_syms
].n_un
.n_strx
=
5168 saves
[i
] = inew_syms
;
5173 * Place the module table's module names with the external strings
5174 * and set the names in the new module table. And then copy the
5175 * other unchanged fields.
5177 for(i
= 0; i
< nmodtab
; i
++){
5178 if(object
->mh
!= NULL
){
5179 strcpy(p
, strings
+ mods
[i
].module_name
);
5180 new_mods
[i
].module_name
= p
- new_strings
;
5183 new_mods
[i
].irefsym
= mods
[i
].irefsym
;
5184 new_mods
[i
].nrefsym
= mods
[i
].nrefsym
;
5185 new_mods
[i
].iextrel
= mods
[i
].iextrel
;
5186 new_mods
[i
].nextrel
= mods
[i
].nextrel
;
5187 new_mods
[i
].iinit_iterm
= mods
[i
].iinit_iterm
;
5188 new_mods
[i
].ninit_nterm
= mods
[i
].ninit_nterm
;
5189 new_mods
[i
].objc_module_info_addr
=
5190 mods
[i
].objc_module_info_addr
;
5191 new_mods
[i
].objc_module_info_size
=
5192 mods
[i
].objc_module_info_size
;
5195 strcpy(p
, strings
+ mods64
[i
].module_name
);
5196 new_mods64
[i
].module_name
= p
- new_strings
;
5199 new_mods64
[i
].irefsym
= mods64
[i
].irefsym
;
5200 new_mods64
[i
].nrefsym
= mods64
[i
].nrefsym
;
5201 new_mods64
[i
].iextrel
= mods64
[i
].iextrel
;
5202 new_mods64
[i
].nextrel
= mods64
[i
].nextrel
;
5203 new_mods64
[i
].iinit_iterm
= mods64
[i
].iinit_iterm
;
5204 new_mods64
[i
].ninit_nterm
= mods64
[i
].ninit_nterm
;
5205 new_mods64
[i
].objc_module_info_addr
=
5206 mods64
[i
].objc_module_info_addr
;
5207 new_mods64
[i
].objc_module_info_size
=
5208 mods64
[i
].objc_module_info_size
;
5213 * Update the reference table with the new symbol indexes for all
5214 * entries and change type of reference (the flags field) for those
5215 * symbols that got changed from globals to non-globals.
5217 new_nextrefsyms
= nextrefsyms
;
5218 new_refs
= allocate(new_nextrefsyms
*
5219 sizeof(struct dylib_reference
));
5221 for(i
= 0; i
< nextrefsyms
; i
++){
5222 if(nmedits
[refs
[i
].isym
] == TRUE
){
5223 if(refs
[i
].flags
== REFERENCE_FLAG_DEFINED
)
5225 REFERENCE_FLAG_PRIVATE_DEFINED
;
5226 else if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
)
5228 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
;
5229 else if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
)
5231 REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
;
5233 new_refs
[i
].flags
= refs
[i
].flags
;
5236 new_refs
[i
].flags
= refs
[i
].flags
;
5238 new_refs
[i
].isym
= saves
[refs
[i
].isym
] - 1;
5242 * Create a new dylib table of contents without the global symbols
5243 * that got turned into non-globals.
5245 new_ntoc
= ntoc
- nchanged_globals
;
5246 new_tocs
= allocate(new_ntoc
*
5247 sizeof(struct dylib_table_of_contents
));
5249 for(i
= 0; i
< ntoc
; i
++){
5250 if(tocs
[i
].symbol_index
>= nsyms
){
5251 error_arch(arch
, member
, "bad symbol index for table of "
5252 "contents table entry %d in: ", i
);
5255 if(nmedits
[tocs
[i
].symbol_index
] == FALSE
){
5256 new_tocs
[k
].symbol_index
= saves
[tocs
[i
].symbol_index
] - 1;
5257 new_tocs
[k
].module_index
= tocs
[i
].module_index
;
5263 * If is not a dynamic library so all global symbols changed into
5264 * statics can be moved to the end of the local symbols. If the pflag
5265 * is set then the changed symbols remain global and just get the
5266 * private extern bit set.
5270 * First put the existing local symbols into the new symbol table.
5273 for(i
= 0; i
< nsyms
; i
++){
5274 if(object
->mh
!= NULL
){
5275 n_strx
= symbols
[i
].n_un
.n_strx
;
5276 n_type
= symbols
[i
].n_type
;
5279 n_strx
= symbols64
[i
].n_un
.n_strx
;
5280 n_type
= symbols64
[i
].n_type
;
5282 if((n_type
& N_EXT
) == 0){
5283 if(object
->mh
!= NULL
)
5284 new_symbols
[inew_syms
] = symbols
[i
];
5286 new_symbols64
[inew_syms
] = symbols64
[i
];
5288 strcpy(q
, strings
+ n_strx
);
5289 if(object
->mh
!= NULL
)
5290 new_symbols
[inew_syms
].n_un
.n_strx
=
5293 new_symbols64
[inew_syms
].n_un
.n_strx
=
5298 saves
[i
] = inew_syms
;
5302 * Next put the global symbols that were changed into statics
5303 * symbols into the new symbol table.
5306 for(i
= 0; i
< nsyms
; i
++){
5307 if(object
->mh
!= NULL
){
5308 n_strx
= symbols
[i
].n_un
.n_strx
;
5309 n_type
= symbols
[i
].n_type
;
5312 n_strx
= symbols64
[i
].n_un
.n_strx
;
5313 n_type
= symbols64
[i
].n_type
;
5315 if((n_type
& N_EXT
) != 0){
5316 if(nmedits
[i
] == TRUE
){
5318 * Change the new symbol to not be an extern symbol
5319 * by turning off the extern bit.
5321 if(object
->mh
!= NULL
){
5322 new_symbols
[inew_syms
] = symbols
[i
];
5323 new_symbols
[inew_syms
].n_type
&= ~N_EXT
;
5324 new_symbols
[inew_syms
].n_desc
&= ~N_WEAK_DEF
;
5327 new_symbols64
[inew_syms
] = symbols64
[i
];
5328 new_symbols64
[inew_syms
].n_type
&= ~N_EXT
;
5329 new_symbols64
[inew_syms
].n_desc
&= ~N_WEAK_DEF
;
5332 strcpy(q
, strings
+ n_strx
);
5333 if(object
->mh
!= NULL
)
5334 new_symbols
[inew_syms
].n_un
.n_strx
=
5337 new_symbols64
[inew_syms
].n_un
.n_strx
=
5342 saves
[i
] = inew_syms
;
5348 * Last put the unchanged global symbols into the new symbol table
5349 * and symbols changed into private externs.
5351 for(i
= 0; i
< nsyms
; i
++){
5352 if(object
->mh
!= NULL
){
5353 n_strx
= symbols
[i
].n_un
.n_strx
;
5354 n_type
= symbols
[i
].n_type
;
5357 n_strx
= symbols64
[i
].n_un
.n_strx
;
5358 n_type
= symbols64
[i
].n_type
;
5360 if((n_type
& N_EXT
) != 0){
5361 if(nmedits
[i
] == FALSE
|| pflag
== TRUE
){
5362 if(object
->mh
!= NULL
)
5363 new_symbols
[inew_syms
] = symbols
[i
];
5365 new_symbols64
[inew_syms
] = symbols64
[i
];
5366 if(nmedits
[i
] == TRUE
&& pflag
== TRUE
){
5368 * Change the new symbol to be a private extern
5369 * symbol by turning on the private extern bit.
5371 if(object
->mh
!= NULL
)
5372 new_symbols
[inew_syms
].n_type
|= N_PEXT
;
5374 new_symbols64
[inew_syms
].n_type
|= N_PEXT
;
5377 strcpy(p
, strings
+ n_strx
);
5378 if(object
->mh
!= NULL
)
5379 new_symbols
[inew_syms
].n_un
.n_strx
=
5382 new_symbols64
[inew_syms
].n_un
.n_strx
=
5387 saves
[i
] = inew_syms
;
5393 if(sections
!= NULL
)
5395 if(sections64
!= NULL
)
5405 * Function for qsort for comparing global symbol names.
5410 const struct nlist
**sym1
,
5411 const struct nlist
**sym2
)
5413 return(strcmp(global_strings
+ (*sym1
)->n_un
.n_strx
,
5414 global_strings
+ (*sym2
)->n_un
.n_strx
));
5419 cmp_qsort_global_64(
5420 const struct nlist_64
**sym1
,
5421 const struct nlist_64
**sym2
)
5423 return(strcmp(global_strings
+ (*sym1
)->n_un
.n_strx
,
5424 global_strings
+ (*sym2
)->n_un
.n_strx
));
5428 * Function for bsearch for finding a global symbol that matches a stab name.
5432 cmp_bsearch_global_stab(
5434 const struct nlist
**sym
)
5437 * The +1 is for the '_' on the global symbol that is not on the
5438 * stab string that is trying to be matched.
5440 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
+ 1));
5445 cmp_bsearch_global_stab_64(
5447 const struct nlist_64
**sym
)
5450 * The +1 is for the '_' on the global symbol that is not on the
5451 * stab string that is trying to be matched.
5453 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
+ 1));
5457 * Function for bsearch for finding a global symbol that matches a stab name
5464 const struct nlist
**sym
)
5466 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
));
5471 cmp_bsearch_global_64(
5473 const struct nlist_64
**sym
)
5475 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
));
5477 #endif /* defined(NMEDIT) */