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/round.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
= round(archs
[i
].members
[j
].member_name_size
, 8) +
883 (round(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 round(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
;
1294 /* warn about strip -s or -R on a final linked image with dyld_info */
1295 if(nsave_symbols
!= 0){
1296 warning_arch(arch
, NULL
, "removing global symbols from a final linked"
1297 " no longer supported. Use -exported_symbols_list at link time when building: ");
1300 if(object
->split_info_cmd
!= NULL
){
1301 object
->output_split_info_data
= object
->object_addr
+
1302 object
->split_info_cmd
->dataoff
;
1303 object
->output_split_info_data_size
=
1304 object
->split_info_cmd
->datasize
;
1306 if(object
->code_sig_cmd
!= NULL
){
1309 #endif /* !(NMEDIT) */
1311 object
->output_code_sig_data
= object
->object_addr
+
1312 object
->code_sig_cmd
->dataoff
;
1313 object
->output_code_sig_data_size
=
1314 object
->code_sig_cmd
->datasize
;
1318 if(object
->dyst
!= NULL
){
1319 object
->dyst
->ilocalsym
= 0;
1320 object
->dyst
->nlocalsym
= new_nlocalsym
;
1321 object
->dyst
->iextdefsym
= new_nlocalsym
;
1322 object
->dyst
->nextdefsym
= new_nextdefsym
;
1323 object
->dyst
->iundefsym
= new_nlocalsym
+ new_nextdefsym
;
1324 object
->dyst
->nundefsym
= new_nundefsym
;
1325 if(object
->dyst
->nindirectsyms
!= 0){
1326 object
->output_indirect_symtab
= indirectsyms
;
1327 if(object
->object_byte_sex
!= host_byte_sex
)
1328 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
1329 object
->object_byte_sex
);
1333 * If the -c option is specified the object's filetype will
1334 * have been changed from MH_DYLIB to MH_DYLIB_STUB above.
1336 if(object
->mh_filetype
== MH_DYLIB
||
1337 object
->mh_filetype
== MH_DYLIB_STUB
){
1338 object
->output_tocs
= new_tocs
;
1339 object
->output_ntoc
= new_ntoc
;
1341 if(object
->mh
!= NULL
)
1342 object
->output_mods
= new_mods
;
1344 object
->output_mods64
= new_mods64
;
1345 object
->output_nmodtab
= new_nmodtab
;
1347 object
->output_mods
= mods
;
1348 object
->output_nmodtab
= nmodtab
;
1350 object
->output_refs
= new_refs
;
1351 object
->output_nextrefsyms
= new_nextrefsyms
;
1352 if(object
->object_byte_sex
!= host_byte_sex
){
1353 swap_dylib_table_of_contents(new_tocs
, new_ntoc
,
1354 object
->object_byte_sex
);
1356 if(object
->mh
!= NULL
)
1357 swap_dylib_module(new_mods
, new_nmodtab
,
1358 object
->object_byte_sex
);
1360 swap_dylib_module_64(new_mods64
, new_nmodtab
,
1361 object
->object_byte_sex
);
1363 if(object
->mh
!= NULL
)
1364 swap_dylib_module(mods
, nmodtab
,
1365 object
->object_byte_sex
);
1367 swap_dylib_module_64(mods64
, nmodtab
,
1368 object
->object_byte_sex
);
1370 swap_dylib_reference(new_refs
, new_nextrefsyms
,
1371 object
->object_byte_sex
);
1374 if(object
->dyld_info
!= NULL
){
1375 object
->input_sym_info_size
+= object
->dyld_info
->rebase_size
1376 + object
->dyld_info
->bind_size
1377 + object
->dyld_info
->weak_bind_size
1378 + object
->dyld_info
->lazy_bind_size
1379 + object
->dyld_info
->export_size
;
1381 object
->input_sym_info_size
+=
1382 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1383 object
->dyst
->nextrel
* sizeof(struct relocation_info
) +
1384 object
->dyst
->ntoc
* sizeof(struct dylib_table_of_contents
)+
1385 object
->dyst
->nextrefsyms
* sizeof(struct dylib_reference
);
1386 if(object
->mh
!= NULL
){
1387 object
->input_sym_info_size
+=
1388 object
->dyst
->nmodtab
* sizeof(struct dylib_module
) +
1389 object
->dyst
->nindirectsyms
* sizeof(uint32_t);
1392 object
->input_sym_info_size
+=
1393 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
) +
1394 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1395 object
->input_indirectsym_pad
;
1399 * When stripping out the section contents to create a
1400 * dynamic library stub the relocation info also gets
1404 #endif /* !(NMEDIT) */
1406 object
->output_sym_info_size
+=
1407 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1408 object
->dyst
->nextrel
* sizeof(struct relocation_info
);
1410 object
->output_sym_info_size
+=
1411 new_ntoc
* sizeof(struct dylib_table_of_contents
)+
1412 new_nextrefsyms
* sizeof(struct dylib_reference
) +
1413 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1414 object
->input_indirectsym_pad
;
1415 if(object
->mh
!= NULL
){
1416 object
->output_sym_info_size
+=
1417 object
->dyst
->nmodtab
* sizeof(struct dylib_module
);
1420 object
->output_sym_info_size
+=
1421 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
);
1423 if(object
->hints_cmd
!= NULL
){
1424 object
->input_sym_info_size
+=
1425 object
->hints_cmd
->nhints
*
1426 sizeof(struct twolevel_hint
);
1427 object
->output_sym_info_size
+=
1428 object
->hints_cmd
->nhints
*
1429 sizeof(struct twolevel_hint
);
1431 if(object
->split_info_cmd
!= NULL
){
1432 object
->input_sym_info_size
+=
1433 object
->split_info_cmd
->datasize
;
1434 object
->output_sym_info_size
+=
1435 object
->split_info_cmd
->datasize
;
1437 if(object
->code_sig_cmd
!= NULL
){
1438 object
->input_sym_info_size
=
1439 round(object
->input_sym_info_size
, 16);
1440 object
->input_sym_info_size
+=
1441 object
->code_sig_cmd
->datasize
;
1444 strip_LC_CODE_SIGNATURE_commands(arch
, member
, object
);
1447 #endif /* !(NMEDIT) */
1449 object
->output_sym_info_size
=
1450 round(object
->output_sym_info_size
, 16);
1451 object
->output_sym_info_size
+=
1452 object
->code_sig_cmd
->datasize
;
1456 object
->dyst
->ntoc
= new_ntoc
;
1457 object
->dyst
->nextrefsyms
= new_nextrefsyms
;
1459 offset
= get_starting_syminfo_offset(object
);
1461 if(object
->dyld_info
!= 0){
1462 if (object
->dyld_info
->rebase_off
!= 0){
1463 object
->dyld_info
->rebase_off
= offset
;
1464 offset
+= object
->dyld_info
->rebase_size
;
1466 if (object
->dyld_info
->bind_off
!= 0){
1467 object
->dyld_info
->bind_off
= offset
;
1468 offset
+= object
->dyld_info
->bind_size
;
1470 if (object
->dyld_info
->weak_bind_off
!= 0){
1471 object
->dyld_info
->weak_bind_off
= offset
;
1472 offset
+= object
->dyld_info
->weak_bind_size
;
1474 if (object
->dyld_info
->lazy_bind_off
!= 0){
1475 object
->dyld_info
->lazy_bind_off
= offset
;
1476 offset
+= object
->dyld_info
->lazy_bind_size
;
1478 if (object
->dyld_info
->export_off
!= 0){
1479 object
->dyld_info
->export_off
= offset
;
1480 offset
+= object
->dyld_info
->export_size
;
1484 if(object
->dyst
->nlocrel
!= 0){
1485 object
->output_loc_relocs
= (struct relocation_info
*)
1486 (object
->object_addr
+ object
->dyst
->locreloff
);
1489 * When stripping out the section contents to create a
1490 * dynamic library stub the relocation info also gets
1494 object
->dyst
->nlocrel
= 0;
1495 object
->dyst
->locreloff
= 0;
1498 #endif /* defined(NMEDIT) */
1500 object
->dyst
->locreloff
= offset
;
1501 offset
+= object
->dyst
->nlocrel
*
1502 sizeof(struct relocation_info
);
1506 object
->dyst
->locreloff
= 0;
1508 if(object
->split_info_cmd
!= NULL
){
1509 object
->split_info_cmd
->dataoff
= offset
;
1510 offset
+= object
->split_info_cmd
->datasize
;
1513 if(object
->st
->nsyms
!= 0){
1514 object
->st
->symoff
= offset
;
1515 if(object
->mh
!= NULL
)
1516 offset
+= object
->st
->nsyms
* sizeof(struct nlist
);
1518 offset
+= object
->st
->nsyms
* sizeof(struct nlist_64
);
1521 object
->st
->symoff
= 0;
1523 if(object
->hints_cmd
!= NULL
){
1524 if(object
->hints_cmd
->nhints
!= 0){
1525 object
->output_hints
= (struct twolevel_hint
*)
1526 (object
->object_addr
+ object
->hints_cmd
->offset
);
1527 object
->hints_cmd
->offset
= offset
;
1528 offset
+= object
->hints_cmd
->nhints
*
1529 sizeof(struct twolevel_hint
);
1532 object
->hints_cmd
->offset
= 0;
1535 if(object
->dyst
->nextrel
!= 0){
1536 object
->output_ext_relocs
= (struct relocation_info
*)
1537 (object
->object_addr
+ object
->dyst
->extreloff
);
1540 * When stripping out the section contents to create a
1541 * dynamic library stub the relocation info also gets
1545 object
->dyst
->nextrel
= 0;
1546 object
->dyst
->extreloff
= 0;
1549 #endif /* defined(NMEDIT) */
1551 object
->dyst
->extreloff
= offset
;
1552 offset
+= object
->dyst
->nextrel
*
1553 sizeof(struct relocation_info
);
1557 object
->dyst
->extreloff
= 0;
1559 if(object
->dyst
->nindirectsyms
!= 0){
1560 object
->dyst
->indirectsymoff
= offset
;
1561 offset
+= object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1562 object
->input_indirectsym_pad
;
1565 object
->dyst
->indirectsymoff
= 0;;
1567 if(object
->dyst
->ntoc
!= 0){
1568 object
->dyst
->tocoff
= offset
;
1569 offset
+= object
->dyst
->ntoc
*
1570 sizeof(struct dylib_table_of_contents
);
1573 object
->dyst
->tocoff
= 0;
1575 if(object
->dyst
->nmodtab
!= 0){
1578 * When stripping out the section contents to create a
1579 * dynamic library stub zero out the fields in the module
1580 * table for the sections and relocation information and
1581 * clear Objective-C address and size from modules.
1584 if(object
->mh
!= NULL
){
1585 for(k
= 0; k
< object
->dyst
->nmodtab
; k
++){
1586 mods
[k
].iinit_iterm
= 0;
1587 mods
[k
].ninit_nterm
= 0;
1588 mods
[k
].iextrel
= 0;
1589 mods
[k
].nextrel
= 0;
1590 mods
[k
].objc_module_info_addr
= 0;
1591 mods
[k
].objc_module_info_size
= 0;
1595 for(k
= 0; k
< object
->dyst
->nmodtab
; k
++){
1596 mods64
[k
].iinit_iterm
= 0;
1597 mods64
[k
].ninit_nterm
= 0;
1598 mods64
[k
].iextrel
= 0;
1599 mods64
[k
].nextrel
= 0;
1600 mods64
[k
].objc_module_info_addr
= 0;
1601 mods64
[k
].objc_module_info_size
= 0;
1605 #endif /* !(NMEDIT) */
1606 object
->dyst
->modtaboff
= offset
;
1607 if(object
->mh
!= NULL
)
1608 offset
+= object
->dyst
->nmodtab
*
1609 sizeof(struct dylib_module
);
1611 offset
+= object
->dyst
->nmodtab
*
1612 sizeof(struct dylib_module_64
);
1615 object
->dyst
->modtaboff
= 0;
1617 if(object
->dyst
->nextrefsyms
!= 0){
1618 object
->dyst
->extrefsymoff
= offset
;
1619 offset
+= object
->dyst
->nextrefsyms
*
1620 sizeof(struct dylib_reference
);
1623 object
->dyst
->extrefsymoff
= 0;
1625 if(object
->st
->strsize
!= 0){
1626 object
->st
->stroff
= offset
;
1627 offset
+= object
->st
->strsize
;
1630 object
->st
->stroff
= 0;
1632 if(object
->code_sig_cmd
!= NULL
){
1633 offset
= round(offset
, 16);
1634 object
->code_sig_cmd
->dataoff
= offset
;
1635 offset
+= object
->code_sig_cmd
->datasize
;
1639 if(new_strsize
!= 0){
1640 if(object
->mh
!= NULL
)
1641 object
->st
->stroff
= object
->st
->symoff
+
1642 new_nsyms
* sizeof(struct nlist
);
1644 object
->st
->stroff
= object
->st
->symoff
+
1645 new_nsyms
* sizeof(struct nlist_64
);
1648 object
->st
->stroff
= 0;
1650 object
->st
->symoff
= 0;
1656 * Here we are doing a full symbol strip. In some cases it may
1657 * leave the local relocation entries as well as LOCAL indirect
1658 * symbol table entries.
1662 saves
= (int32_t *)allocate(object
->st
->nsyms
* sizeof(int32_t));
1663 bzero(saves
, object
->st
->nsyms
* sizeof(int32_t));
1666 * Account for the symbolic info in the input file.
1668 if(object
->dyst
!= NULL
){
1669 object
->input_sym_info_size
+=
1670 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1671 object
->dyst
->nextrel
* sizeof(struct relocation_info
) +
1672 object
->dyst
->ntoc
* sizeof(struct dylib_table_of_contents
)+
1673 object
->dyst
->nextrefsyms
* sizeof(struct dylib_reference
);
1674 if(object
->mh
!= NULL
){
1675 object
->input_sym_info_size
+=
1676 object
->dyst
->nmodtab
* sizeof(struct dylib_module
) +
1677 object
->dyst
->nindirectsyms
* sizeof(uint32_t);
1680 object
->input_sym_info_size
+=
1681 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
) +
1682 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1683 object
->input_indirectsym_pad
;
1688 * Determine the offset where the remaining symbolic info will start
1689 * in the output file (if any).
1691 offset
= get_starting_syminfo_offset(object
);
1694 * For a full symbol strip all these values in the output file are
1697 object
->st
->symoff
= 0;
1698 object
->st
->nsyms
= 0;
1699 object
->st
->stroff
= 0;
1700 object
->st
->strsize
= 0;
1701 if(object
->dyst
!= NULL
){
1702 object
->dyst
->ilocalsym
= 0;
1703 object
->dyst
->nlocalsym
= 0;
1704 object
->dyst
->iextdefsym
= 0;
1705 object
->dyst
->nextdefsym
= 0;
1706 object
->dyst
->iundefsym
= 0;
1707 object
->dyst
->nundefsym
= 0;
1711 * This will accumulate any remaining symbolic info size in the
1714 object
->output_sym_info_size
= 0;
1717 * We set these so that checking can be done below to report the
1718 * symbols that can't be stripped because of relocation entries
1719 * or indirect symbol table entries. Normally if these table have a
1720 * non-zero number of entries it will be an error as we are trying
1721 * to strip everything. But it maybe that there are only LOCAL
1722 * indirect entries which is odd but will be OK.
1724 if(object
->dyst
!= NULL
){
1725 if(object
->dyst
->nextrel
!= 0){
1726 object
->output_ext_relocs
= (struct relocation_info
*)
1727 (object
->object_addr
+ object
->dyst
->extreloff
);
1730 * Since this file has a dynamic symbol table and if this file
1731 * has local relocation entries on input make sure they are
1732 * there on output. This is a rare case that it will not have
1733 * external relocs or indirect symbols but can happen as is the
1734 * case with the dynamic linker itself.
1736 if(object
->dyst
->nlocrel
!= 0){
1737 object
->output_loc_relocs
= (struct relocation_info
*)
1738 (object
->object_addr
+ object
->dyst
->locreloff
);
1739 object
->output_sym_info_size
+=
1740 object
->dyst
->nlocrel
* sizeof(struct relocation_info
);
1742 object
->dyst
->locreloff
= offset
;
1743 offset
+= object
->dyst
->nlocrel
*
1744 sizeof(struct relocation_info
);
1747 if(object
->dyst
->nindirectsyms
!= 0){
1748 object
->output_indirect_symtab
= (uint32_t *)
1749 (object
->object_addr
+
1750 object
->dyst
->indirectsymoff
);
1751 if(object
->object_byte_sex
!= host_byte_sex
)
1752 swap_indirect_symbols(
1753 object
->output_indirect_symtab
,
1754 object
->dyst
->nindirectsyms
,
1755 object
->object_byte_sex
);
1757 object
->output_sym_info_size
+=
1758 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1759 object
->input_indirectsym_pad
;
1761 object
->dyst
->indirectsymoff
= offset
;
1762 offset
+= object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1763 object
->input_indirectsym_pad
;
1767 #endif /* !defined(NMEDIT) */
1770 * Always clear the prebind checksum if any when creating a new file.
1772 if(object
->cs
!= NULL
)
1773 object
->cs
->cksum
= 0;
1775 if(object
->seg_linkedit
!= NULL
){
1776 object
->seg_linkedit
->filesize
+= object
->output_sym_info_size
-
1777 object
->input_sym_info_size
;
1778 object
->seg_linkedit
->vmsize
= object
->seg_linkedit
->filesize
;
1780 else if(object
->seg_linkedit64
!= NULL
){
1781 /* Do this in two steps to avoid 32/64-bit casting problems. */
1782 object
->seg_linkedit64
->filesize
-= object
->input_sym_info_size
;
1783 object
->seg_linkedit64
->filesize
+= object
->output_sym_info_size
;
1784 object
->seg_linkedit64
->vmsize
= object
->seg_linkedit64
->filesize
;
1788 * Check and update the external relocation entries to make sure
1789 * referenced symbols are not stripped and refer to the new symbol
1792 * The external relocation entries can be located in one of two places,
1793 * first off of the sections or second off of the dynamic symtab.
1795 missing_reloc_symbols
= 0;
1796 lc
= object
->load_commands
;
1797 if(object
->mh
!= NULL
)
1798 ncmds
= object
->mh
->ncmds
;
1800 ncmds
= object
->mh64
->ncmds
;
1801 for(i
= 0; i
< ncmds
; i
++){
1802 if(lc
->cmd
== LC_SEGMENT
&&
1803 object
->seg_linkedit
!= (struct segment_command
*)lc
){
1804 sg
= (struct segment_command
*)lc
;
1805 s
= (struct section
*)((char *)sg
+
1806 sizeof(struct segment_command
));
1807 for(j
= 0; j
< sg
->nsects
; j
++){
1809 if(s
->reloff
+ s
->nreloc
*
1810 sizeof(struct relocation_info
) >
1811 object
->object_size
){
1812 fatal_arch(arch
, member
, "truncated or malformed "
1813 "object (relocation entries for section (%.16s,"
1814 "%.16s) extends past the end of the file)",
1815 s
->segname
, s
->sectname
);
1817 relocs
= (struct relocation_info
*)
1818 (object
->object_addr
+ s
->reloff
);
1819 if(object
->object_byte_sex
!= host_byte_sex
)
1820 swap_relocation_info(relocs
, s
->nreloc
,
1822 if(s
->offset
+ s
->size
> object
->object_size
){
1823 fatal_arch(arch
, member
, "truncated or malformed "
1824 "object (contents of section (%.16s,"
1825 "%.16s) extends past the end of the file)",
1826 s
->segname
, s
->sectname
);
1828 contents
= object
->object_addr
+ s
->offset
;
1829 check_object_relocs(arch
, member
, object
, s
->segname
,
1830 s
->sectname
, s
->size
, contents
, relocs
, s
->nreloc
,
1831 symbols
, symbols64
, nsyms
, strings
,
1832 &missing_reloc_symbols
, host_byte_sex
);
1833 if(object
->object_byte_sex
!= host_byte_sex
)
1834 swap_relocation_info(relocs
, s
->nreloc
,
1835 object
->object_byte_sex
);
1840 else if(lc
->cmd
== LC_SEGMENT_64
&&
1841 object
->seg_linkedit64
!= (struct segment_command_64
*)lc
){
1842 sg64
= (struct segment_command_64
*)lc
;
1843 s64
= (struct section_64
*)((char *)sg64
+
1844 sizeof(struct segment_command_64
));
1845 for(j
= 0; j
< sg64
->nsects
; j
++){
1846 if(s64
->nreloc
!= 0){
1847 if(s64
->reloff
+ s64
->nreloc
*
1848 sizeof(struct relocation_info
) >
1849 object
->object_size
){
1850 fatal_arch(arch
, member
, "truncated or malformed "
1851 "object (relocation entries for section (%.16s,"
1852 "%.16s) extends past the end of the file)",
1853 s64
->segname
, s64
->sectname
);
1855 relocs
= (struct relocation_info
*)
1856 (object
->object_addr
+ s64
->reloff
);
1857 if(object
->object_byte_sex
!= host_byte_sex
)
1858 swap_relocation_info(relocs
, s64
->nreloc
,
1860 if(s64
->offset
+ s64
->size
> object
->object_size
){
1861 fatal_arch(arch
, member
, "truncated or malformed "
1862 "object (contents of section (%.16s,"
1863 "%.16s) extends past the end of the file)",
1864 s64
->segname
, s64
->sectname
);
1866 contents
= object
->object_addr
+ s64
->offset
;
1867 check_object_relocs(arch
, member
, object
, s64
->segname
,
1868 s64
->sectname
, s64
->size
, contents
, relocs
,
1869 s64
->nreloc
, symbols
, symbols64
, nsyms
, strings
,
1870 &missing_reloc_symbols
, host_byte_sex
);
1871 if(object
->object_byte_sex
!= host_byte_sex
)
1872 swap_relocation_info(relocs
, s64
->nreloc
,
1873 object
->object_byte_sex
);
1878 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1880 if(object
->dyst
!= NULL
&& object
->dyst
->nextrel
!= 0){
1881 relocs
= object
->output_ext_relocs
;
1882 if(object
->object_byte_sex
!= host_byte_sex
)
1883 swap_relocation_info(relocs
, object
->dyst
->nextrel
,
1886 for(i
= 0; i
< object
->dyst
->nextrel
; i
++){
1887 if((relocs
[i
].r_address
& R_SCATTERED
) == 0 &&
1888 relocs
[i
].r_extern
== 1){
1889 if(relocs
[i
].r_symbolnum
> nsyms
){
1890 fatal_arch(arch
, member
, "bad r_symbolnum for external "
1891 "relocation entry %d in: ", i
);
1893 if(saves
[relocs
[i
].r_symbolnum
] == 0){
1894 if(missing_reloc_symbols
== 0){
1895 error_arch(arch
, member
, "symbols referenced by "
1896 "relocation entries that can't be stripped in: ");
1897 missing_reloc_symbols
= 1;
1899 if(object
->mh
!= NULL
){
1900 fprintf(stderr
, "%s\n", strings
+ symbols
1901 [relocs
[i
].r_symbolnum
].n_un
.n_strx
);
1904 fprintf(stderr
, "%s\n", strings
+ symbols64
1905 [relocs
[i
].r_symbolnum
].n_un
.n_strx
);
1907 saves
[relocs
[i
].r_symbolnum
] = -1;
1909 if(saves
[relocs
[i
].r_symbolnum
] != -1){
1910 relocs
[i
].r_symbolnum
=
1911 saves
[relocs
[i
].r_symbolnum
] - 1;
1915 fatal_arch(arch
, member
, "bad external relocation entry "
1916 "%d (not external) in: ", i
);
1918 if((relocs
[i
].r_address
& R_SCATTERED
) == 0){
1919 if(reloc_has_pair(object
->mh_cputype
, relocs
[i
].r_type
))
1923 sreloc
= (struct scattered_relocation_info
*)relocs
+ i
;
1924 if(reloc_has_pair(object
->mh_cputype
, sreloc
->r_type
))
1928 if(object
->object_byte_sex
!= host_byte_sex
)
1929 swap_relocation_info(relocs
, object
->dyst
->nextrel
,
1930 object
->object_byte_sex
);
1934 * Check and update the indirect symbol table entries to make sure
1935 * referenced symbols are not stripped and refer to the new symbol
1938 if(object
->dyst
!= NULL
&& object
->dyst
->nindirectsyms
!= 0){
1939 if(object
->object_byte_sex
!= host_byte_sex
)
1940 swap_indirect_symbols(object
->output_indirect_symtab
,
1941 object
->dyst
->nindirectsyms
, host_byte_sex
);
1943 lc
= object
->load_commands
;
1944 if(object
->mh
!= NULL
)
1945 ncmds
= object
->mh
->ncmds
;
1947 ncmds
= object
->mh64
->ncmds
;
1948 for(i
= 0; i
< ncmds
; i
++){
1949 if(lc
->cmd
== LC_SEGMENT
&&
1950 object
->seg_linkedit
!= (struct segment_command
*)lc
){
1951 sg
= (struct segment_command
*)lc
;
1952 s
= (struct section
*)((char *)sg
+
1953 sizeof(struct segment_command
));
1954 for(j
= 0; j
< sg
->nsects
; j
++){
1955 section_type
= s
->flags
& SECTION_TYPE
;
1956 if(section_type
== S_LAZY_SYMBOL_POINTERS
||
1957 section_type
== S_LAZY_DYLIB_SYMBOL_POINTERS
||
1958 section_type
== S_NON_LAZY_SYMBOL_POINTERS
)
1960 else if(section_type
== S_SYMBOL_STUBS
)
1961 stride
= s
->reserved2
;
1966 nitems
= s
->size
/ stride
;
1967 contents
= object
->object_addr
+ s
->offset
;
1968 check_indirect_symtab(arch
, member
, object
, nitems
,
1969 s
->reserved1
, section_type
, contents
, symbols
,
1970 symbols64
, nsyms
, strings
, &missing_reloc_symbols
,
1975 else if(lc
->cmd
== LC_SEGMENT_64
&&
1976 object
->seg_linkedit64
!= (struct segment_command_64
*)lc
){
1977 sg64
= (struct segment_command_64
*)lc
;
1978 s64
= (struct section_64
*)((char *)sg64
+
1979 sizeof(struct segment_command_64
));
1980 for(j
= 0; j
< sg64
->nsects
; j
++){
1981 section_type
= s64
->flags
& SECTION_TYPE
;
1982 if(section_type
== S_LAZY_SYMBOL_POINTERS
||
1983 section_type
== S_LAZY_DYLIB_SYMBOL_POINTERS
||
1984 section_type
== S_NON_LAZY_SYMBOL_POINTERS
)
1986 else if(section_type
== S_SYMBOL_STUBS
)
1987 stride
= s64
->reserved2
;
1992 nitems
= s64
->size
/ stride
;
1993 contents
= object
->object_addr
+ s64
->offset
;
1994 check_indirect_symtab(arch
, member
, object
, nitems
,
1995 s64
->reserved1
, section_type
, contents
, symbols
,
1996 symbols64
, nsyms
, strings
, &missing_reloc_symbols
,
2001 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2004 if(object
->object_byte_sex
!= host_byte_sex
)
2005 swap_indirect_symbols(object
->output_indirect_symtab
,
2006 object
->dyst
->nindirectsyms
, object
->object_byte_sex
);
2010 * Issue a warning if object file has a code signature that the
2011 * operation will invalidate it.
2013 if(object
->code_sig_cmd
!= NULL
)
2014 warning_arch(arch
, member
, "changes being made to the file will "
2015 "invalidate the code signature in: ");
2019 * get_starting_syminfo_offset() returns the starting offset of the symbolic
2020 * info in the object file.
2024 get_starting_syminfo_offset(
2025 struct object
*object
)
2029 if(object
->seg_linkedit
!= NULL
||
2030 object
->seg_linkedit64
!= NULL
){
2031 if(object
->mh
!= NULL
)
2032 offset
= object
->seg_linkedit
->fileoff
;
2034 offset
= object
->seg_linkedit64
->fileoff
;
2038 if(object
->dyst
!= NULL
&&
2039 object
->dyst
->nlocrel
!= 0 &&
2040 object
->dyst
->locreloff
< offset
)
2041 offset
= object
->dyst
->locreloff
;
2042 if(object
->st
->nsyms
!= 0 &&
2043 object
->st
->symoff
< offset
)
2044 offset
= object
->st
->symoff
;
2045 if(object
->dyst
!= NULL
&&
2046 object
->dyst
->nextrel
!= 0 &&
2047 object
->dyst
->extreloff
< offset
)
2048 offset
= object
->dyst
->extreloff
;
2049 if(object
->dyst
!= NULL
&&
2050 object
->dyst
->nindirectsyms
!= 0 &&
2051 object
->dyst
->indirectsymoff
< offset
)
2052 offset
= object
->dyst
->indirectsymoff
;
2053 if(object
->dyst
!= NULL
&&
2054 object
->dyst
->ntoc
!= 0 &&
2055 object
->dyst
->tocoff
< offset
)
2056 offset
= object
->dyst
->tocoff
;
2057 if(object
->dyst
!= NULL
&&
2058 object
->dyst
->nmodtab
!= 0 &&
2059 object
->dyst
->modtaboff
< offset
)
2060 offset
= object
->dyst
->modtaboff
;
2061 if(object
->dyst
!= NULL
&&
2062 object
->dyst
->nextrefsyms
!= 0 &&
2063 object
->dyst
->extrefsymoff
< offset
)
2064 offset
= object
->dyst
->extrefsymoff
;
2065 if(object
->st
->strsize
!= 0 &&
2066 object
->st
->stroff
< offset
)
2067 offset
= object
->st
->stroff
;
2073 * check_object_relocs() is used to check and update the external relocation
2074 * entries from a section in an object file, to make sure referenced symbols
2075 * are not stripped and are changed to refer to the new symbol table indexes.
2079 check_object_relocs(
2081 struct member
*member
,
2082 struct object
*object
,
2087 struct relocation_info
*relocs
,
2089 struct nlist
*symbols
,
2090 struct nlist_64
*symbols64
,
2093 int32_t *missing_reloc_symbols
,
2094 enum byte_sex host_byte_sex
)
2099 uint32_t value
, n_ext
;
2102 struct scattered_relocation_info
*sreloc
;
2104 for(k
= 0; k
< nreloc
; k
++){
2105 if((relocs
[k
].r_address
& R_SCATTERED
) == 0 &&
2106 relocs
[k
].r_extern
== 1){
2107 if(relocs
[k
].r_symbolnum
> nsyms
){
2108 fatal_arch(arch
, member
, "bad r_symbolnum for relocation "
2109 "entry %d in section (%.16s,%.16s) in: ", k
, segname
,
2112 if(object
->mh
!= NULL
){
2113 n_strx
= symbols
[relocs
[k
].r_symbolnum
].n_un
.n_strx
;
2114 n_value
= symbols
[relocs
[k
].r_symbolnum
].n_value
;
2117 n_strx
= symbols64
[relocs
[k
].r_symbolnum
].n_un
.n_strx
;
2118 n_value
= symbols64
[relocs
[k
].r_symbolnum
].n_value
;
2121 if(saves
[relocs
[k
].r_symbolnum
] == 0){
2122 if(*missing_reloc_symbols
== 0){
2123 error_arch(arch
, member
, "symbols referenced by "
2124 "relocation entries that can't be stripped in: ");
2125 *missing_reloc_symbols
= 1;
2127 fprintf(stderr
, "%s\n", strings
+ n_strx
);
2128 saves
[relocs
[k
].r_symbolnum
] = -1;
2130 #else /* defined(NMEDIT) */
2132 * We are letting nmedit change global coalesed symbols into
2133 * statics in MH_OBJECT file types only. Relocation entries to
2134 * global coalesced symbols are external relocs.
2136 if(object
->mh
!= NULL
)
2137 n_ext
= new_symbols
[saves
[relocs
[k
].r_symbolnum
] - 1].
2140 n_ext
= new_symbols64
[saves
[relocs
[k
].r_symbolnum
] - 1].
2142 if(n_ext
!= N_EXT
&&
2143 object
->mh_cputype
!= CPU_TYPE_X86_64
){
2145 * We need to do the relocation for this external relocation
2146 * entry so the item to be relocated is correct for a local
2147 * relocation entry. We don't need to do this for x86-64.
2149 if(relocs
[k
].r_address
+ sizeof(int32_t) > sectsize
){
2150 fatal_arch(arch
, member
, "truncated or malformed "
2151 "object (r_address of relocation entry %u of "
2152 "section (%.16s,%.16s) extends past the end "
2153 "of the section)", k
, segname
, sectname
);
2155 if(object
->mh
!= NULL
){
2156 value
= *(uint32_t *)
2157 (contents
+ relocs
[k
].r_address
);
2158 if(object
->object_byte_sex
!= host_byte_sex
)
2159 value
= SWAP_INT(value
);
2161 * We handle a very limited form here. Only VANILLA
2162 * (r_type == 0) long (r_length==2) absolute or pcrel
2163 * that won't need a scattered relocation entry.
2165 if(relocs
[k
].r_type
!= 0 ||
2166 relocs
[k
].r_length
!= 2){
2167 fatal_arch(arch
, member
, "don't have "
2168 "code to convert external relocation "
2169 "entry %d in section (%.16s,%.16s) "
2170 "for global coalesced symbol: %s "
2171 "in: ", k
, segname
, sectname
,
2175 if(object
->object_byte_sex
!= host_byte_sex
)
2176 value
= SWAP_INT(value
);
2177 *(uint32_t *)(contents
+ relocs
[k
].r_address
) =
2181 value64
= *(uint64_t *)(contents
+ relocs
[k
].r_address
);
2182 if(object
->object_byte_sex
!= host_byte_sex
)
2183 value64
= SWAP_LONG_LONG(value64
);
2185 * We handle a very limited form here. Only VANILLA
2186 * (r_type == 0) quad (r_length==3) absolute or pcrel
2187 * that won't need a scattered relocation entry.
2189 if(relocs
[k
].r_type
!= 0 ||
2190 relocs
[k
].r_length
!= 3){
2191 fatal_arch(arch
, member
, "don't have "
2192 "code to convert external relocation "
2193 "entry %d in section (%.16s,%.16s) "
2194 "for global coalesced symbol: %s "
2195 "in: ", k
, segname
, sectname
,
2199 if(object
->object_byte_sex
!= host_byte_sex
)
2200 value64
= SWAP_LONG_LONG(value64
);
2201 *(uint64_t *)(contents
+ relocs
[k
].r_address
) = value64
;
2204 * Turn the extern reloc into a local.
2206 if(object
->mh
!= NULL
)
2207 relocs
[k
].r_symbolnum
=
2208 new_symbols
[saves
[relocs
[k
].r_symbolnum
] - 1].n_sect
;
2210 relocs
[k
].r_symbolnum
=
2211 new_symbols64
[saves
[relocs
[k
].r_symbolnum
] - 1].n_sect
;
2212 relocs
[k
].r_extern
= 0;
2215 if(relocs
[k
].r_extern
== 1 &&
2216 saves
[relocs
[k
].r_symbolnum
] != -1){
2217 relocs
[k
].r_symbolnum
= saves
[relocs
[k
].r_symbolnum
] - 1;
2220 if((relocs
[k
].r_address
& R_SCATTERED
) == 0){
2221 if(reloc_has_pair(object
->mh_cputype
, relocs
[k
].r_type
) == TRUE
)
2225 sreloc
= (struct scattered_relocation_info
*)relocs
+ k
;
2226 if(reloc_has_pair(object
->mh_cputype
, sreloc
->r_type
) == TRUE
)
2233 * check_indirect_symtab() checks and updates the indirect symbol table entries
2234 * to make sure referenced symbols are not stripped and refer to the new symbol
2239 check_indirect_symtab(
2241 struct member
*member
,
2242 struct object
*object
,
2245 uint32_t section_type
,
2247 struct nlist
*symbols
,
2248 struct nlist_64
*symbols64
,
2251 int32_t *missing_reloc_symbols
,
2252 enum byte_sex host_byte_sex
)
2256 uint32_t n_strx
, value
;
2258 enum bool made_local
;
2260 for(k
= 0; k
< nitems
; k
++){
2262 index
= object
->output_indirect_symtab
[reserved1
+ k
];
2263 if(index
== INDIRECT_SYMBOL_LOCAL
||
2264 index
== INDIRECT_SYMBOL_ABS
||
2265 index
== (INDIRECT_SYMBOL_LOCAL
| INDIRECT_SYMBOL_ABS
))
2268 fatal_arch(arch
, member
,"indirect symbol table entry %d (past " "the end of the symbol table) in: ", reserved1
+ k
);
2270 if(pflag
== 0 && nmedits
[index
] == TRUE
&& saves
[index
] != -1)
2272 if(saves
[index
] == 0)
2276 * Indirect symbol table entries for defined symbols in a
2277 * non-lazy pointer section that are not saved are changed to
2278 * INDIRECT_SYMBOL_LOCAL which their values just have to be
2279 * slid if the are not absolute symbols.
2281 if(object
->mh
!= NULL
){
2282 n_type
= symbols
[index
].n_type
;
2283 n_strx
= symbols
[index
].n_un
.n_strx
;
2286 n_type
= symbols64
[index
].n_type
;
2287 n_strx
= symbols64
[index
].n_un
.n_strx
;
2289 if((n_type
&& N_TYPE
) != N_UNDF
&&
2290 (n_type
&& N_TYPE
) != N_PBUD
&&
2291 section_type
== S_NON_LAZY_SYMBOL_POINTERS
){
2292 object
->output_indirect_symtab
[reserved1
+ k
] =
2293 INDIRECT_SYMBOL_LOCAL
;
2294 if((n_type
& N_TYPE
) == N_ABS
)
2295 object
->output_indirect_symtab
[reserved1
+ k
] |=
2296 INDIRECT_SYMBOL_ABS
;
2299 * When creating a stub shared library the section contents
2300 * are not updated since they will be stripped.
2302 if(object
->mh_filetype
!= MH_DYLIB_STUB
){
2303 if(object
->mh
!= NULL
){
2304 value
= symbols
[index
].n_value
;
2305 if (symbols
[index
].n_desc
& N_ARM_THUMB_DEF
)
2307 if(object
->object_byte_sex
!= host_byte_sex
)
2308 value
= SWAP_INT(value
);
2309 *(uint32_t *)(contents
+ k
* 4) = value
;
2312 value64
= symbols64
[index
].n_value
;
2313 if(object
->object_byte_sex
!= host_byte_sex
)
2314 value64
= SWAP_LONG_LONG(value64
);
2315 *(uint64_t *)(contents
+ k
* 8) = value64
;
2321 object
->output_indirect_symtab
[reserved1
+ k
] =
2324 #else /* !defined(NMEDIT) */
2326 if(*missing_reloc_symbols
== 0){
2327 error_arch(arch
, member
, "symbols referenced by "
2328 "indirect symbol table entries that can't be "
2330 *missing_reloc_symbols
= 1;
2332 fprintf(stderr
, "%s\n", strings
+ n_strx
);
2335 #endif /* !defined(NMEDIT) */
2339 #else /* !defined(NMEDIT) */
2340 if(made_local
== FALSE
&& saves
[index
] != -1)
2341 #endif /* !defined(NMEDIT) */
2343 object
->output_indirect_symtab
[reserved1
+k
] = saves
[index
] - 1;
2350 * This is called if there is a -d option specified. It reads the file with
2351 * the strings in it and places them in the array debug_filenames and sorts
2352 * them by name. The file that contains the file names must have names one
2353 * per line with no white space (except the newlines).
2357 setup_debug_filenames(
2360 int fd
, i
, strings_size
;
2361 struct stat stat_buf
;
2364 if((fd
= open(dfile
, O_RDONLY
)) < 0){
2365 system_error("can't open: %s", dfile
);
2368 if(fstat(fd
, &stat_buf
) == -1){
2369 system_error("can't stat: %s", dfile
);
2373 strings_size
= stat_buf
.st_size
;
2374 strings
= (char *)allocate(strings_size
+ 1);
2375 strings
[strings_size
] = '\0';
2376 if(read(fd
, strings
, strings_size
) != strings_size
){
2377 system_error("can't read: %s", dfile
);
2382 for(i
= 0; i
< strings_size
; i
++){
2389 debug_filenames
= (char **)allocate(ndebug_filenames
* sizeof(char *));
2391 for(i
= 0; i
< ndebug_filenames
; i
++){
2392 debug_filenames
[i
] = p
;
2395 qsort(debug_filenames
, ndebug_filenames
, sizeof(char *),
2396 (int (*)(const void *, const void *))cmp_qsort_filename
);
2399 printf("Debug filenames:\n");
2400 for(i
= 0; i
< ndebug_filenames
; i
++){
2401 printf("filename = %s\n", debug_filenames
[i
]);
2407 * Strip the symbol table to the level specified by the command line arguments.
2408 * The new symbol table is built and new_symbols is left pointing to it. The
2409 * number of new symbols is left in new_nsyms, the new string table is built
2410 * and new_stings is left pointing to it and new_strsize is left containing it.
2411 * This routine returns zero if successfull and non-zero otherwise.
2417 struct member
*member
,
2418 struct object
*object
,
2419 struct dylib_table_of_contents
*tocs
,
2421 struct dylib_module
*mods
,
2422 struct dylib_module_64
*mods64
,
2424 struct dylib_reference
*refs
,
2425 uint32_t nextrefsyms
)
2427 uint32_t i
, j
, k
, n
, inew_syms
, save_debug
, missing_syms
;
2428 uint32_t missing_symbols
;
2429 char *p
, *q
, **pp
, *basename
;
2430 struct symbol_list
*sp
;
2431 uint32_t new_ext_strsize
, len
, *changes
, inew_undefsyms
;
2432 unsigned char nsects
;
2433 struct load_command
*lc
;
2434 struct segment_command
*sg
;
2435 struct segment_command_64
*sg64
;
2436 struct section
*s
, **sections
;
2437 struct section_64
*s64
, **sections64
;
2438 uint32_t ncmds
, mh_flags
, s_flags
, n_strx
;
2440 struct undef_map
*undef_map
;
2441 struct undef_map64
*undef_map64
;
2442 uint8_t n_type
, n_sect
;
2445 uint32_t module_name
, iextdefsym
, nextdefsym
, ilocalsym
, nlocalsym
;
2446 uint32_t irefsym
, nrefsym
;
2447 enum bool has_dwarf
, hack_5614542
;
2453 for(i
= 0; i
< nsave_symbols
; i
++)
2454 save_symbols
[i
].sym
= NULL
;
2455 for(i
= 0; i
< nremove_symbols
; i
++)
2456 remove_symbols
[i
].sym
= NULL
;
2458 for(i
= 0; i
< nsave_symbols
; i
++)
2459 save_symbols
[i
].seen
= FALSE
;
2460 for(i
= 0; i
< nremove_symbols
; i
++)
2461 remove_symbols
[i
].seen
= FALSE
;
2465 if(object
->mh
!= NULL
)
2466 new_strsize
= sizeof(int32_t);
2468 new_strsize
= sizeof(int64_t);
2472 new_ext_strsize
= 0;
2475 * If this an object file that has DWARF debugging sections to strip
2476 * then we have to run ld -r on it.
2478 if(object
->mh_filetype
== MH_OBJECT
&& (Sflag
|| xflag
)){
2480 lc
= object
->load_commands
;
2481 if(object
->mh
!= NULL
)
2482 ncmds
= object
->mh
->ncmds
;
2484 ncmds
= object
->mh64
->ncmds
;
2485 for(i
= 0; i
< ncmds
&& has_dwarf
== FALSE
; i
++){
2486 if(lc
->cmd
== LC_SEGMENT
){
2487 sg
= (struct segment_command
*)lc
;
2488 s
= (struct section
*)((char *)sg
+
2489 sizeof(struct segment_command
));
2490 for(j
= 0; j
< sg
->nsects
; j
++){
2491 if(s
->flags
& S_ATTR_DEBUG
){
2498 else if(lc
->cmd
== LC_SEGMENT_64
){
2499 sg64
= (struct segment_command_64
*)lc
;
2500 s64
= (struct section_64
*)((char *)sg64
+
2501 sizeof(struct segment_command_64
));
2502 for(j
= 0; j
< sg64
->nsects
; j
++){
2503 if(s64
->flags
& S_ATTR_DEBUG
){
2510 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2513 * Because of the bugs in ld(1) for:
2514 * radr://5675774 ld64 should preserve JBSR relocations without
2516 * radr://5658046 cctools-679 creates scattered relocations in
2517 * __TEXT,__const section in kexts, which breaks
2518 * kexts built for older systems
2519 * we can't use ld -r to strip dwarf info in 32-bit objects until
2520 * these are fixed. But if the user as specified the -l flag then
2521 * go ahead and do it and the user will have to be aware of these
2524 if((lflag
== TRUE
&& has_dwarf
== TRUE
) || object
->mh64
!= NULL
)
2525 make_ld_r_object(arch
, member
, object
);
2528 * Because of the "design" of 64-bit object files and the lack of
2529 * local relocation entries it is not possible for strip(1) to do its
2530 * job without becoming a static link editor. The "design" does not
2531 * actually strip the symbols it simply renames them to things like
2532 * "l1000". And they become static symbols but still have external
2533 * relocation entries. Thus can never actually be stripped. Also some
2534 * symbols, *.eh, symbols are not even changed to these names if there
2535 * corresponding global symbol is not stripped. So strip(1) only
2536 * recourse is to use the unified linker to create an ld -r object then
2537 * save all resulting symbols (both static and global) and hope the user
2538 * does not notice the stripping is not what they asked for.
2540 if(object
->mh_filetype
== MH_OBJECT
&&
2541 (object
->mh64
!= NULL
&& object
->ld_r_ofile
== NULL
))
2542 make_ld_r_object(arch
, member
, object
);
2545 * Since make_ld_r_object() may create an object with more symbols
2546 * this has to be done after make_ld_r_object() and nsyms is updated.
2548 saves
= (int32_t *)allocate(nsyms
* sizeof(int32_t));
2549 bzero(saves
, nsyms
* sizeof(int32_t));
2552 * Gather an array of section struct pointers so we can later determine
2553 * if we run into a global symbol in a coalesced section and not strip
2558 lc
= object
->load_commands
;
2559 if(object
->mh
!= NULL
)
2560 ncmds
= object
->mh
->ncmds
;
2562 ncmds
= object
->mh64
->ncmds
;
2563 for(i
= 0; i
< ncmds
; i
++){
2564 if(lc
->cmd
== LC_SEGMENT
){
2565 sg
= (struct segment_command
*)lc
;
2566 nsects
+= sg
->nsects
;
2568 else if(lc
->cmd
== LC_SEGMENT_64
){
2569 sg64
= (struct segment_command_64
*)lc
;
2570 nsects
+= sg64
->nsects
;
2572 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2574 if(object
->mh
!= NULL
){
2575 sections
= allocate(nsects
* sizeof(struct section
*));
2580 sections64
= allocate(nsects
* sizeof(struct section_64
*));
2583 lc
= object
->load_commands
;
2584 for(i
= 0; i
< ncmds
; i
++){
2585 if(lc
->cmd
== LC_SEGMENT
){
2586 sg
= (struct segment_command
*)lc
;
2587 s
= (struct section
*)((char *)sg
+
2588 sizeof(struct segment_command
));
2589 for(j
= 0; j
< sg
->nsects
; j
++)
2590 sections
[nsects
++] = s
++;
2592 else if(lc
->cmd
== LC_SEGMENT_64
){
2593 sg64
= (struct segment_command_64
*)lc
;
2594 s64
= (struct section_64
*)((char *)sg64
+
2595 sizeof(struct segment_command_64
));
2596 for(j
= 0; j
< sg64
->nsects
; j
++)
2597 sections64
[nsects
++] = s64
++;
2599 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2602 for(i
= 0; i
< nsyms
; i
++){
2604 if(object
->mh
!= NULL
){
2605 mh_flags
= object
->mh
->flags
;
2606 n_strx
= symbols
[i
].n_un
.n_strx
;
2607 n_type
= symbols
[i
].n_type
;
2608 n_sect
= symbols
[i
].n_sect
;
2609 if((n_type
& N_TYPE
) == N_SECT
){
2610 if(n_sect
== 0 || n_sect
> nsects
){
2611 error_arch(arch
, member
, "bad n_sect for symbol "
2612 "table entry %d in: ", i
);
2615 s_flags
= sections
[n_sect
- 1]->flags
;
2617 n_desc
= symbols
[i
].n_desc
;
2618 n_value
= symbols
[i
].n_value
;
2621 mh_flags
= object
->mh64
->flags
;
2622 n_strx
= symbols64
[i
].n_un
.n_strx
;
2623 n_type
= symbols64
[i
].n_type
;
2624 n_sect
= symbols64
[i
].n_sect
;
2625 if((n_type
& N_TYPE
) == N_SECT
){
2626 if(n_sect
== 0 || n_sect
> nsects
){
2627 error_arch(arch
, member
, "bad n_sect for symbol "
2628 "table entry %d in: ", i
);
2631 s_flags
= sections64
[n_sect
- 1]->flags
;
2633 n_desc
= symbols64
[i
].n_desc
;
2634 n_value
= symbols64
[i
].n_value
;
2637 if(n_strx
> strsize
){
2638 error_arch(arch
, member
, "bad string index for symbol "
2639 "table entry %d in: ", i
);
2643 if((n_type
& N_TYPE
) == N_INDR
){
2645 if(n_value
> strsize
){
2646 error_arch(arch
, member
, "bad string index for "
2647 "indirect symbol table entry %d in: ", i
);
2652 if((n_type
& N_EXT
) == 0){ /* local symbol */
2654 * For x86_64 .o files we have run ld -r on them and are stuck
2655 * keeping all resulting symbols.
2657 if(object
->mh
== NULL
&&
2658 object
->mh64
->cputype
== CPU_TYPE_X86_64
&&
2659 object
->mh64
->filetype
== MH_OBJECT
){
2661 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2664 saves
[i
] = new_nsyms
;
2667 * The cases a local symbol might be saved is with -X -S or
2670 else if((!strip_all
&& (Xflag
|| Sflag
)) || dfile
){
2671 if(n_type
& N_STAB
){ /* debug symbol */
2672 if(dfile
&& n_type
== N_SO
){
2674 basename
= strrchr(strings
+ n_strx
, '/');
2675 if(basename
!= NULL
)
2678 basename
= strings
+ n_strx
;
2679 pp
= bsearch(basename
, debug_filenames
,
2680 ndebug_filenames
, sizeof(char *),
2681 (int (*)(const void *, const void *)
2682 )cmp_bsearch_filename
);
2684 * Save the bracketing N_SO. For each N_SO that
2685 * has a filename there is an N_SO that has a
2686 * name of "" which ends the stabs for that file
2688 if(*basename
!= '\0'){
2696 * This is a bracketing SO so if we are
2697 * currently saving debug symbols save this
2698 * last one and turn off saving debug syms.
2702 new_strsize
+= strlen(strings
+
2706 saves
[i
] = new_nsyms
;
2715 if(saves
[i
] == 0 && (!Sflag
|| save_debug
)){
2717 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2720 saves
[i
] = new_nsyms
;
2723 else{ /* non-debug local symbol */
2724 if(xflag
== 0 && (Sflag
|| Xflag
)){
2727 strings
[n_strx
] != 'L')){
2729 * If this file is a for the dynamic linker and
2730 * this symbol is in a section marked so that
2731 * static symbols are stripped then don't
2734 if((mh_flags
& MH_DYLDLINK
) != MH_DYLDLINK
||
2735 (n_type
& N_TYPE
) != N_SECT
||
2736 (s_flags
& S_ATTR_STRIP_STATIC_SYMS
) !=
2737 S_ATTR_STRIP_STATIC_SYMS
){
2738 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2741 saves
[i
] = new_nsyms
;
2746 * Treat a local symbol that was a private extern as if
2747 * were global if it is referenced by a module and save
2750 if((n_type
& N_PEXT
) == N_PEXT
){
2752 private_extern_reference_by_module(
2753 i
, refs
,nextrefsyms
) == TRUE
){
2755 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2758 saves
[i
] = new_nsyms
;
2761 * We need to save symbols that were private externs
2762 * that are used with indirect symbols.
2765 symbol_pointer_used(i
, indirectsyms
,
2766 nindirectsyms
) == TRUE
){
2768 len
= strlen(strings
+ n_strx
) + 1;
2773 saves
[i
] = new_nsyms
;
2779 * Treat a local symbol that was a private extern as if were
2780 * global if it is not referenced by a module.
2782 else if((n_type
& N_PEXT
) == N_PEXT
){
2783 if(saves
[i
] == 0 && sfile
){
2784 sp
= bsearch(strings
+ n_strx
,
2785 save_symbols
, nsave_symbols
,
2786 sizeof(struct symbol_list
),
2787 (int (*)(const void *, const void *))
2788 symbol_list_bsearch
);
2790 if(sp
->sym
== NULL
){
2791 if(object
->mh
!= NULL
)
2792 sp
->sym
= &(symbols
[i
]);
2794 sp
->sym
= &(symbols64
[i
]);
2798 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2801 saves
[i
] = new_nsyms
;
2805 private_extern_reference_by_module(
2806 i
, refs
,nextrefsyms
) == TRUE
){
2808 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2811 saves
[i
] = new_nsyms
;
2814 * We need to save symbols that were private externs that
2815 * are used with indirect symbols.
2818 symbol_pointer_used(i
, indirectsyms
, nindirectsyms
) ==
2821 len
= strlen(strings
+ n_strx
) + 1;
2826 saves
[i
] = new_nsyms
;
2830 else{ /* global symbol */
2832 * strip -R on an x86_64 .o file should do nothing.
2835 (object
->mh
!= NULL
||
2836 object
->mh64
->cputype
!= CPU_TYPE_X86_64
||
2837 object
->mh64
->filetype
!= MH_OBJECT
)){
2838 sp
= bsearch(strings
+ n_strx
,
2839 remove_symbols
, nremove_symbols
,
2840 sizeof(struct symbol_list
),
2841 (int (*)(const void *, const void *))
2842 symbol_list_bsearch
);
2844 if((n_type
& N_TYPE
) == N_UNDF
||
2845 (n_type
& N_TYPE
) == N_PBUD
){
2846 error_arch(arch
, member
, "symbol: %s undefined"
2847 " and can't be stripped from: ",
2850 else if(sp
->sym
!= NULL
){
2851 sym
= (struct nlist
*)sp
->sym
;
2852 if((sym
->n_type
& N_PEXT
) != N_PEXT
)
2853 error_arch(arch
, member
, "more than one symbol "
2854 "for: %s found in: ", sp
->name
);
2857 if(object
->mh
!= NULL
)
2858 sp
->sym
= &(symbols
[i
]);
2860 sp
->sym
= &(symbols64
[i
]);
2863 if(n_desc
& REFERENCED_DYNAMICALLY
){
2864 error_arch(arch
, member
, "symbol: %s is dynamically"
2865 " referenced and can't be stripped "
2866 "from: ", sp
->name
);
2868 if((n_type
& N_TYPE
) == N_SECT
&&
2869 (s_flags
& SECTION_TYPE
) == S_COALESCED
){
2870 error_arch(arch
, member
, "symbol: %s is a global "
2871 "coalesced symbol and can't be "
2872 "stripped from: ", sp
->name
);
2874 /* don't save this symbol */
2878 if(Aflag
&& (n_type
& N_TYPE
) == N_ABS
&&
2881 strncmp(strings
+ n_strx
,
2882 ".objc_class_name_",
2883 sizeof(".objc_class_name_") - 1) == 0))){
2884 len
= strlen(strings
+ n_strx
) + 1;
2886 new_ext_strsize
+= len
;
2889 saves
[i
] = new_nsyms
;
2891 if(saves
[i
] == 0 && (uflag
|| default_dyld_executable
) &&
2892 ((((n_type
& N_TYPE
) == N_UNDF
) &&
2894 (n_type
& N_TYPE
) == N_PBUD
)){
2896 len
= strlen(strings
+ n_strx
) + 1;
2898 new_ext_strsize
+= len
;
2902 saves
[i
] = new_nsyms
;
2904 if(saves
[i
] == 0 && nflag
&&
2905 (n_type
& N_TYPE
) == N_SECT
){
2907 len
= strlen(strings
+ n_strx
) + 1;
2909 new_ext_strsize
+= len
;
2913 saves
[i
] = new_nsyms
;
2915 if(saves
[i
] == 0 && sfile
){
2916 sp
= bsearch(strings
+ n_strx
,
2917 save_symbols
, nsave_symbols
,
2918 sizeof(struct symbol_list
),
2919 (int (*)(const void *, const void *))
2920 symbol_list_bsearch
);
2922 if(sp
->sym
!= NULL
){
2923 sym
= (struct nlist
*)sp
->sym
;
2924 if((sym
->n_type
& N_PEXT
) != N_PEXT
)
2925 error_arch(arch
, member
, "more than one symbol "
2926 "for: %s found in: ", sp
->name
);
2929 if(object
->mh
!= NULL
)
2930 sp
->sym
= &(symbols
[i
]);
2932 sp
->sym
= &(symbols64
[i
]);
2934 len
= strlen(strings
+ n_strx
) + 1;
2936 new_ext_strsize
+= len
;
2937 if((n_type
& N_TYPE
) == N_UNDF
||
2938 (n_type
& N_TYPE
) == N_PBUD
)
2943 saves
[i
] = new_nsyms
;
2948 * We only need to save coalesced symbols that are used as
2949 * indirect symbols in 32-bit applications.
2951 * In 64-bit applications, we only need to save coalesced
2952 * symbols that are used as weak definitions.
2954 if(object
->mh
!= NULL
&&
2956 (n_type
& N_TYPE
) == N_SECT
&&
2957 (s_flags
& SECTION_TYPE
) == S_COALESCED
&&
2958 symbol_pointer_used(i
, indirectsyms
, nindirectsyms
) == TRUE
){
2960 len
= strlen(strings
+ n_strx
) + 1;
2962 new_ext_strsize
+= len
;
2966 saves
[i
] = new_nsyms
;
2969 (n_type
& N_TYPE
) == N_SECT
&&
2970 (n_desc
& N_WEAK_DEF
) != 0){
2972 len
= strlen(strings
+ n_strx
) + 1;
2974 new_ext_strsize
+= len
;
2978 saves
[i
] = new_nsyms
;
2980 if(saves
[i
] == 0 && ((Xflag
|| Sflag
|| xflag
) ||
2981 ((rflag
|| default_dyld_executable
) &&
2982 n_desc
& REFERENCED_DYNAMICALLY
))){
2983 len
= strlen(strings
+ n_strx
) + 1;
2985 new_ext_strsize
+= len
;
2986 if((n_type
& N_TYPE
) == N_INDR
){
2987 len
= strlen(strings
+ n_value
) + 1;
2989 new_ext_strsize
+= len
;
2991 if((n_type
& N_TYPE
) == N_UNDF
||
2992 (n_type
& N_TYPE
) == N_PBUD
)
2997 saves
[i
] = new_nsyms
;
3000 * For x86_64 .o files we have run ld -r on them and are stuck
3001 * keeping all resulting symbols.
3004 object
->mh
== NULL
&&
3005 object
->mh64
->cputype
== CPU_TYPE_X86_64
&&
3006 object
->mh64
->filetype
== MH_OBJECT
){
3007 len
= strlen(strings
+ n_strx
) + 1;
3009 new_ext_strsize
+= len
;
3010 if((n_type
& N_TYPE
) == N_INDR
){
3011 len
= strlen(strings
+ n_value
) + 1;
3013 new_ext_strsize
+= len
;
3015 if((n_type
& N_TYPE
) == N_UNDF
||
3016 (n_type
& N_TYPE
) == N_PBUD
)
3021 saves
[i
] = new_nsyms
;
3026 * The module table's module names are placed with the external strings.
3027 * So size them and add this to the external string size.
3029 for(i
= 0; i
< nmodtab
; i
++){
3030 if(object
->mh
!= NULL
)
3031 module_name
= mods
[i
].module_name
;
3033 module_name
= mods64
[i
].module_name
;
3034 if(module_name
== 0 || module_name
> strsize
){
3035 error_arch(arch
, member
, "bad string index for module_name "
3036 "of module table entry %d in: ", i
);
3039 len
= strlen(strings
+ module_name
) + 1;
3041 new_ext_strsize
+= len
;
3045 * Updating the reference table may require a symbol not yet listed as
3046 * as saved to be present in the output file. If a defined external
3047 * symbol is removed and there is a undefined reference to it in the
3048 * reference table an undefined symbol needs to be created for it in
3049 * the output file. If this happens the number of new symbols and size
3050 * of the new strings are adjusted. And the array changes[] is set to
3051 * map the old symbol index to the new symbol index for the symbol that
3052 * is changed to an undefined symbol.
3054 missing_symbols
= 0;
3055 if(ref_saves
!= NULL
)
3057 ref_saves
= (int32_t *)allocate(nextrefsyms
* sizeof(int32_t));
3058 bzero(ref_saves
, nextrefsyms
* sizeof(int32_t));
3059 changes
= (uint32_t *)allocate(nsyms
* sizeof(int32_t));
3060 bzero(changes
, nsyms
* sizeof(int32_t));
3061 new_nextrefsyms
= 0;
3062 for(i
= 0; i
< nextrefsyms
; i
++){
3063 if(refs
[i
].isym
> nsyms
){
3064 error_arch(arch
, member
, "bad symbol table index for "
3065 "reference table entry %d in: ", i
);
3068 if(saves
[refs
[i
].isym
]){
3070 ref_saves
[i
] = new_nextrefsyms
;
3073 if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
||
3074 refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
){
3075 if(changes
[refs
[i
].isym
] == 0){
3076 if(object
->mh
!= NULL
)
3077 n_strx
= symbols
[refs
[i
].isym
].n_un
.n_strx
;
3079 n_strx
= symbols64
[refs
[i
].isym
].n_un
.n_strx
;
3080 len
= strlen(strings
+ n_strx
) + 1;
3082 new_ext_strsize
+= len
;
3085 changes
[refs
[i
].isym
] = new_nsyms
;
3087 ref_saves
[i
] = new_nextrefsyms
;
3092 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
||
3093 refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
){
3094 if(missing_symbols
== 0){
3095 error_arch(arch
, member
, "private extern symbols "
3096 "referenced by modules can't be stripped in: ");
3097 missing_symbols
= 1;
3099 if(object
->mh
!= NULL
)
3100 n_strx
= symbols
[refs
[i
].isym
].n_un
.n_strx
;
3102 n_strx
= symbols64
[refs
[i
].isym
].n_un
.n_strx
;
3103 fprintf(stderr
, "%s\n", strings
+ n_strx
);
3104 saves
[refs
[i
].isym
] = -1;
3109 if(missing_symbols
== 1)
3115 for(i
= 0; i
< nsave_symbols
; i
++){
3116 if(save_symbols
[i
].sym
== NULL
){
3117 if(missing_syms
== 0){
3118 error_arch(arch
, member
, "symbols names listed "
3119 "in: %s not in: ", sfile
);
3122 fprintf(stderr
, "%s\n", save_symbols
[i
].name
);
3128 * strip -R on an x86_64 .o file should do nothing.
3131 (object
->mh
!= NULL
||
3132 object
->mh64
->cputype
!= CPU_TYPE_X86_64
||
3133 object
->mh64
->filetype
!= MH_OBJECT
)){
3134 for(i
= 0; i
< nremove_symbols
; i
++){
3135 if(remove_symbols
[i
].sym
== NULL
){
3136 if(missing_syms
== 0){
3137 error_arch(arch
, member
, "symbols names listed "
3138 "in: %s not in: ", Rfile
);
3141 fprintf(stderr
, "%s\n", remove_symbols
[i
].name
);
3148 * If there is a chance that we could end up with an indirect symbol
3149 * with an index of zero we need to avoid that due to a work around
3150 * in the dynamic linker for a bug it is working around that was in
3151 * the old classic static linker. See radar bug 5614542 and the
3152 * related bugs 3685312 and 3534709.
3154 * A reasonable way to do this to know that local symbols are first in
3155 * the symbol table. So if we have any local symbols this won't happen
3156 * and if there are no indirect symbols it will also not happen. Past
3157 * that we'll just add a local symbol so it will end up at symbol index
3158 * zero and avoid any indirect symbol having that index.
3160 * If one really wanted they could build up the new symbol table then
3161 * look at all the indirect symbol table entries to see if any of them
3162 * have an index of zero then in that case throw that new symbol table
3163 * away and rebuild the symbol and string table once again after adding
3164 * a local symbol. This seems not all that resonable to save one symbol
3165 * table entry and a few bytes in the string table for the complexity it
3166 * would add and what it would save.
3168 if(new_nlocalsym
== 0 && nindirectsyms
!= 0){
3169 len
= strlen("radr://5614542") + 1;
3173 hack_5614542
= TRUE
;
3176 hack_5614542
= FALSE
;
3179 if(object
->mh
!= NULL
){
3180 new_symbols
= (struct nlist
*)
3181 allocate(new_nsyms
* sizeof(struct nlist
));
3182 new_symbols64
= NULL
;
3186 new_symbols64
= (struct nlist_64
*)
3187 allocate(new_nsyms
* sizeof(struct nlist_64
));
3189 if(object
->mh
!= NULL
)
3190 new_strsize
= round(new_strsize
, sizeof(int32_t));
3192 new_strsize
= round(new_strsize
, sizeof(int64_t));
3193 new_strings
= (char *)allocate(new_strsize
);
3194 if(object
->mh
!= NULL
){
3195 new_strings
[new_strsize
- 3] = '\0';
3196 new_strings
[new_strsize
- 2] = '\0';
3197 new_strings
[new_strsize
- 1] = '\0';
3200 new_strings
[new_strsize
- 7] = '\0';
3201 new_strings
[new_strsize
- 6] = '\0';
3202 new_strings
[new_strsize
- 5] = '\0';
3203 new_strings
[new_strsize
- 4] = '\0';
3204 new_strings
[new_strsize
- 3] = '\0';
3205 new_strings
[new_strsize
- 2] = '\0';
3206 new_strings
[new_strsize
- 1] = '\0';
3209 memset(new_strings
, '\0', sizeof(int32_t));
3210 p
= new_strings
+ sizeof(int32_t);
3211 q
= p
+ new_ext_strsize
;
3214 * If all strings were stripped set the size to zero but only for 32-bit
3215 * because the unified linker seems to set the filesize of empty .o
3216 * files to include the string table.
3218 if(object
->mh
!= NULL
&& new_strsize
== sizeof(int32_t))
3222 * Now create a symbol table and string table in this order
3225 * external defined symbols
3234 * If we are doing the hack for radar bug 5614542 (see above) add the
3235 * one local symbol and string.
3237 * We use an N_OPT stab which should be safe to use and not mess any
3238 * thing up. In Mac OS X, gcc(1) writes one N_OPT stab saying the file
3239 * is compiled with gcc(1). Then gdb(1) looks for that stab, but it
3240 * also looks at the name. If the name string is "gcc_compiled" or
3241 * "gcc2_compiled" gdb(1) sets its "compiled by gcc flag. If the N_OPT
3242 * is emitted INSIDE an N_SO section, then gdb(1) thinks that object
3243 * module was compiled by Sun's compiler, which apparently sticks one
3244 * outermost N_LBRAC/N_RBRAC pair, which gdb(1) strips off. But if the
3245 * N_OPT comes before any N_SO stabs, then gdb(1) will just ignore it.
3246 * Since this N_OPT is the first local symbol, it will always come
3247 * before any N_SO stabs that might be around and should be fine.
3249 if(hack_5614542
== TRUE
){
3250 if(object
->mh
!= NULL
){
3251 new_symbols
[inew_syms
].n_type
= N_OPT
;
3252 new_symbols
[inew_syms
].n_sect
= NO_SECT
;
3253 new_symbols
[inew_syms
].n_desc
= 0;
3254 new_symbols
[inew_syms
].n_value
= 0x05614542;
3257 new_symbols64
[inew_syms
].n_type
= N_OPT
;
3258 new_symbols64
[inew_syms
].n_sect
= NO_SECT
;
3259 new_symbols64
[inew_syms
].n_desc
= 0;
3260 new_symbols64
[inew_syms
].n_value
= 0x05614542;
3262 strcpy(q
, "radr://5614542");
3263 if(object
->mh
!= NULL
)
3264 new_symbols
[inew_syms
].n_un
.n_strx
=
3267 new_symbols64
[inew_syms
].n_un
.n_strx
=
3273 for(i
= 0; i
< nsyms
; i
++){
3275 if(object
->mh
!= NULL
){
3276 n_strx
= symbols
[i
].n_un
.n_strx
;
3277 n_type
= symbols
[i
].n_type
;
3280 n_strx
= symbols64
[i
].n_un
.n_strx
;
3281 n_type
= symbols64
[i
].n_type
;
3283 if((n_type
& N_EXT
) == 0){
3284 if(object
->mh
!= NULL
)
3285 new_symbols
[inew_syms
] = symbols
[i
];
3287 new_symbols64
[inew_syms
] = symbols64
[i
];
3289 strcpy(q
, strings
+ n_strx
);
3290 if(object
->mh
!= NULL
)
3291 new_symbols
[inew_syms
].n_un
.n_strx
=
3294 new_symbols64
[inew_syms
].n_un
.n_strx
=
3299 saves
[i
] = inew_syms
;
3304 inew_nextdefsym
= inew_syms
;
3305 #endif /* TRIE_SUPPORT */
3306 for(i
= 0; i
< nsyms
; i
++){
3308 if(object
->mh
!= NULL
){
3309 n_strx
= symbols
[i
].n_un
.n_strx
;
3310 n_type
= symbols
[i
].n_type
;
3311 n_value
= symbols
[i
].n_value
;
3314 n_strx
= symbols64
[i
].n_un
.n_strx
;
3315 n_type
= symbols64
[i
].n_type
;
3316 n_value
= symbols64
[i
].n_value
;
3318 if((n_type
& N_EXT
) == N_EXT
&&
3319 ((n_type
& N_TYPE
) != N_UNDF
&&
3320 (n_type
& N_TYPE
) != N_PBUD
)){
3321 if(object
->mh
!= NULL
)
3322 new_symbols
[inew_syms
] = symbols
[i
];
3324 new_symbols64
[inew_syms
] = symbols64
[i
];
3326 strcpy(p
, strings
+ n_strx
);
3327 if(object
->mh
!= NULL
)
3328 new_symbols
[inew_syms
].n_un
.n_strx
=
3331 new_symbols64
[inew_syms
].n_un
.n_strx
=
3335 if((n_type
& N_TYPE
) == N_INDR
){
3337 strcpy(p
, strings
+ n_value
);
3338 if(object
->mh
!= NULL
)
3339 new_symbols
[inew_syms
].n_value
=
3342 new_symbols64
[inew_syms
].n_value
=
3348 saves
[i
] = inew_syms
;
3353 * Build the new undefined symbols into a map and sort it.
3356 if(object
->mh
!= NULL
){
3357 undef_map
= (struct undef_map
*)allocate(new_nundefsym
*
3358 sizeof(struct undef_map
));
3363 undef_map64
= (struct undef_map64
*)allocate(new_nundefsym
*
3364 sizeof(struct undef_map64
));
3366 for(i
= 0; i
< nsyms
; i
++){
3368 if(object
->mh
!= NULL
){
3369 n_strx
= symbols
[i
].n_un
.n_strx
;
3370 n_type
= symbols
[i
].n_type
;
3373 n_strx
= symbols64
[i
].n_un
.n_strx
;
3374 n_type
= symbols64
[i
].n_type
;
3376 if((n_type
& N_EXT
) == N_EXT
&&
3377 ((n_type
& N_TYPE
) == N_UNDF
||
3378 (n_type
& N_TYPE
) == N_PBUD
)){
3379 if(object
->mh
!= NULL
)
3380 undef_map
[inew_undefsyms
].symbol
= symbols
[i
];
3382 undef_map64
[inew_undefsyms
].symbol64
= symbols64
[i
];
3384 strcpy(p
, strings
+ n_strx
);
3385 if(object
->mh
!= NULL
)
3386 undef_map
[inew_undefsyms
].symbol
.n_un
.n_strx
=
3389 undef_map64
[inew_undefsyms
].symbol64
.n_un
.n_strx
=
3393 if(object
->mh
!= NULL
)
3394 undef_map
[inew_undefsyms
].index
= i
;
3396 undef_map64
[inew_undefsyms
].index
= i
;
3401 for(i
= 0; i
< nsyms
; i
++){
3403 if(object
->mh
!= NULL
)
3404 n_strx
= symbols
[i
].n_un
.n_strx
;
3406 n_strx
= symbols64
[i
].n_un
.n_strx
;
3408 strcpy(p
, strings
+ n_strx
);
3409 if(object
->mh
!= NULL
)
3410 undef_map
[inew_undefsyms
].symbol
.n_un
.n_strx
=
3413 undef_map64
[inew_undefsyms
].symbol64
.n_un
.n_strx
=
3417 if(object
->mh
!= NULL
){
3418 undef_map
[inew_undefsyms
].symbol
.n_type
= N_UNDF
| N_EXT
;
3419 undef_map
[inew_undefsyms
].symbol
.n_sect
= NO_SECT
;
3420 undef_map
[inew_undefsyms
].symbol
.n_desc
= 0;
3421 undef_map
[inew_undefsyms
].symbol
.n_value
= 0;
3422 undef_map
[inew_undefsyms
].index
= i
;
3425 undef_map64
[inew_undefsyms
].symbol64
.n_type
= N_UNDF
|N_EXT
;
3426 undef_map64
[inew_undefsyms
].symbol64
.n_sect
= NO_SECT
;
3427 undef_map64
[inew_undefsyms
].symbol64
.n_desc
= 0;
3428 undef_map64
[inew_undefsyms
].symbol64
.n_value
= 0;
3429 undef_map64
[inew_undefsyms
].index
= i
;
3434 /* Sort the undefined symbols by name */
3435 qsort_strings
= new_strings
;
3436 if(object
->mh
!= NULL
)
3437 qsort(undef_map
, new_nundefsym
, sizeof(struct undef_map
),
3438 (int (*)(const void *, const void *))cmp_qsort_undef_map
);
3440 qsort(undef_map64
, new_nundefsym
, sizeof(struct undef_map64
),
3441 (int (*)(const void *, const void *))cmp_qsort_undef_map_64
);
3442 /* Copy the symbols now in sorted order into new_symbols */
3443 for(i
= 0; i
< new_nundefsym
; i
++){
3444 if(object
->mh
!= NULL
){
3445 new_symbols
[inew_syms
] = undef_map
[i
].symbol
;
3447 saves
[undef_map
[i
].index
] = inew_syms
;
3450 new_symbols64
[inew_syms
] = undef_map64
[i
].symbol64
;
3452 saves
[undef_map64
[i
].index
] = inew_syms
;
3457 * Fixup the module table's module name strings adding them to the
3458 * string table. Also fix the indexes into the symbol table for
3459 * external and local symbols. And fix up the indexes into the
3462 for(i
= 0; i
< nmodtab
; i
++){
3463 if(object
->mh
!= NULL
){
3464 strcpy(p
, strings
+ mods
[i
].module_name
);
3465 mods
[i
].module_name
= p
- new_strings
;
3466 iextdefsym
= mods
[i
].iextdefsym
;
3467 nextdefsym
= mods
[i
].nextdefsym
;
3468 ilocalsym
= mods
[i
].ilocalsym
;
3469 nlocalsym
= mods
[i
].nlocalsym
;
3470 irefsym
= mods
[i
].irefsym
;
3471 nrefsym
= mods
[i
].nrefsym
;
3474 strcpy(p
, strings
+ mods64
[i
].module_name
);
3475 mods64
[i
].module_name
= p
- new_strings
;
3476 iextdefsym
= mods64
[i
].iextdefsym
;
3477 nextdefsym
= mods64
[i
].nextdefsym
;
3478 ilocalsym
= mods64
[i
].ilocalsym
;
3479 nlocalsym
= mods64
[i
].nlocalsym
;
3480 irefsym
= mods64
[i
].irefsym
;
3481 nrefsym
= mods64
[i
].nrefsym
;
3485 if(iextdefsym
> nsyms
){
3486 error_arch(arch
, member
, "bad index into externally defined "
3487 "symbols of module table entry %d in: ", i
);
3490 if(iextdefsym
+ nextdefsym
> nsyms
){
3491 error_arch(arch
, member
, "bad number of externally defined "
3492 "symbols of module table entry %d in: ", i
);
3495 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
3496 if(saves
[j
] != 0 && changes
[j
] == 0)
3500 for(k
= j
; k
< iextdefsym
+ nextdefsym
; k
++){
3501 if(saves
[k
] != 0 && changes
[k
] == 0)
3505 if(object
->mh
!= NULL
){
3506 mods
[i
].iextdefsym
= 0;
3507 mods
[i
].nextdefsym
= 0;
3510 mods64
[i
].iextdefsym
= 0;
3511 mods64
[i
].nextdefsym
= 0;
3515 if(object
->mh
!= NULL
){
3516 mods
[i
].iextdefsym
= saves
[j
] - 1;
3517 mods
[i
].nextdefsym
= n
;
3520 mods64
[i
].iextdefsym
= saves
[j
] - 1;
3521 mods64
[i
].nextdefsym
= n
;
3525 if(ilocalsym
> nsyms
){
3526 error_arch(arch
, member
, "bad index into symbols for local "
3527 "symbols of module table entry %d in: ", i
);
3530 if(ilocalsym
+ nlocalsym
> nsyms
){
3531 error_arch(arch
, member
, "bad number of local "
3532 "symbols of module table entry %d in: ", i
);
3535 for(j
= ilocalsym
; j
< ilocalsym
+ nlocalsym
; j
++){
3540 for(k
= j
; k
< ilocalsym
+ nlocalsym
; k
++){
3545 if(object
->mh
!= NULL
){
3546 mods
[i
].ilocalsym
= 0;
3547 mods
[i
].nlocalsym
= 0;
3550 mods64
[i
].ilocalsym
= 0;
3551 mods64
[i
].nlocalsym
= 0;
3555 if(object
->mh
!= NULL
){
3556 mods
[i
].ilocalsym
= saves
[j
] - 1;
3557 mods
[i
].nlocalsym
= n
;
3560 mods64
[i
].ilocalsym
= saves
[j
] - 1;
3561 mods64
[i
].nlocalsym
= n
;
3565 if(irefsym
> nextrefsyms
){
3566 error_arch(arch
, member
, "bad index into reference table "
3567 "of module table entry %d in: ", i
);
3570 if(irefsym
+ nrefsym
> nextrefsyms
){
3571 error_arch(arch
, member
, "bad number of reference table "
3572 "entries of module table entry %d in: ", i
);
3575 for(j
= irefsym
; j
< irefsym
+ nrefsym
; j
++){
3576 if(ref_saves
[j
] != 0)
3580 for(k
= j
; k
< irefsym
+ nrefsym
; k
++){
3581 if(ref_saves
[k
] != 0)
3585 if(object
->mh
!= NULL
){
3586 mods
[i
].irefsym
= 0;
3587 mods
[i
].nrefsym
= 0;
3590 mods64
[i
].irefsym
= 0;
3591 mods64
[i
].nrefsym
= 0;
3595 if(object
->mh
!= NULL
){
3596 mods
[i
].irefsym
= ref_saves
[j
] - 1;
3597 mods
[i
].nrefsym
= n
;
3600 mods64
[i
].irefsym
= ref_saves
[j
] - 1;
3601 mods64
[i
].nrefsym
= n
;
3607 * Create a new reference table.
3609 new_refs
= allocate(new_nextrefsyms
* sizeof(struct dylib_reference
));
3611 for(i
= 0; i
< nextrefsyms
; i
++){
3613 if(saves
[refs
[i
].isym
]){
3614 new_refs
[j
].isym
= saves
[refs
[i
].isym
] - 1;
3615 new_refs
[j
].flags
= refs
[i
].flags
;
3618 if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
||
3619 refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
){
3620 new_refs
[j
].isym
= changes
[refs
[i
].isym
] - 1;
3621 new_refs
[j
].flags
= refs
[i
].flags
;
3629 * Create a new dylib table of contents.
3632 for(i
= 0; i
< ntoc
; i
++){
3633 if(tocs
[i
].symbol_index
>= nsyms
){
3634 error_arch(arch
, member
, "bad symbol index for table of "
3635 "contents table entry %d in: ", i
);
3638 if(saves
[tocs
[i
].symbol_index
] != 0 &&
3639 changes
[tocs
[i
].symbol_index
] == 0)
3642 new_tocs
= allocate(new_ntoc
* sizeof(struct dylib_table_of_contents
));
3644 for(i
= 0; i
< ntoc
; i
++){
3645 if(saves
[tocs
[i
].symbol_index
] != 0 &&
3646 changes
[tocs
[i
].symbol_index
] == 0){
3647 new_tocs
[j
].symbol_index
= saves
[tocs
[i
].symbol_index
] - 1;
3648 new_tocs
[j
].module_index
= tocs
[i
].module_index
;
3654 * Update the export trie if it has one but only call the the
3655 * prune_trie() routine when we are removing global symbols as is
3656 * done with default stripping of a dyld executable or with the -s
3659 if(object
->dyld_info
!= NULL
&&
3660 object
->dyld_info
->export_size
!= 0 &&
3661 (default_dyld_executable
|| sfile
!= NULL
|| Rfile
!= NULL
)){
3662 const char *error_string
;
3663 uint32_t trie_new_size
;
3665 error_string
= prune_trie((uint8_t *)(object
->object_addr
+
3666 object
->dyld_info
->export_off
),
3667 object
->dyld_info
->export_size
,
3670 if(error_string
!= NULL
){
3671 error_arch(arch
, member
, "%s", error_string
);
3675 #endif /* TRIE_SUPPORT */
3677 if(undef_map
!= NULL
)
3679 if(undef_map64
!= NULL
)
3683 if(sections
!= NULL
)
3685 if(sections64
!= NULL
)
3696 * prune() is called by prune_trie() and passed a name of an external symbol
3697 * in the trie. It returns 1 if the symbols is to be pruned out and 0 if the
3698 * symbol is to be kept.
3700 * Note that it may seem like a linear search of the new symbols would not be
3701 * the best approach but in 10.6 the only defined global symbol left in a
3702 * stripped executable is __mh_execute_header and new_nextdefsym is usually 1
3703 * so this never actually loops in practice.
3712 for(i
= 0; i
< new_nextdefsym
; i
++){
3713 if(new_symbols
!= NULL
){
3714 if(strcmp(name
, new_strings
+ new_symbols
[inew_nextdefsym
+ i
]
3719 if(strcmp(name
, new_strings
+ new_symbols64
[inew_nextdefsym
+ i
]
3726 #endif /* TRIE_SUPPORT */
3729 * make_ld_r_object() takes the object file contents referenced by the passed
3730 * data structures, writes that to a temporary file, runs "ld -r" plus the
3731 * specified stripping option creating a second temporary file, reads that file
3732 * in and replaces the object file contents with that and resets the variables
3733 * pointing to the symbol, string and indirect tables.
3739 struct member
*member
,
3740 struct object
*object
)
3742 enum byte_sex host_byte_sex
;
3743 char *input_file
, *output_file
;
3745 struct ofile
*ld_r_ofile
;
3746 struct arch
*ld_r_archs
;
3747 uint32_t ld_r_narchs
, save_errors
;
3749 host_byte_sex
= get_host_byte_sex();
3752 * Swap the object file back into its bytesex before writing it to the
3753 * temporary file if needed.
3755 if(object
->object_byte_sex
!= host_byte_sex
){
3756 if(object
->mh
!= NULL
){
3757 if(swap_object_headers(object
->mh
, object
->load_commands
) ==
3759 fatal("internal error: swap_object_headers() failed");
3760 swap_nlist(symbols
, nsyms
, object
->object_byte_sex
);
3763 if(swap_object_headers(object
->mh64
, object
->load_commands
) ==
3765 fatal("internal error: swap_object_headers() failed");
3766 swap_nlist_64(symbols64
, nsyms
, object
->object_byte_sex
);
3768 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
3769 object
->object_byte_sex
);
3773 * Create an input object file for the ld -r command from the bytes
3774 * of this arch's object file.
3776 input_file
= makestr("/tmp/strip.XXXXXX", NULL
);
3777 input_file
= mktemp(input_file
);
3779 if((fd
= open(input_file
, O_WRONLY
|O_CREAT
, 0600)) < 0)
3780 system_fatal("can't open temporary file: %s", input_file
);
3782 if(write(fd
, object
->object_addr
, object
->object_size
) !=
3783 object
->object_size
)
3784 system_fatal("can't write temporary file: %s", input_file
);
3787 system_fatal("can't close temporary file: %s", input_file
);
3790 * Create a temporary name for the output file of the ld -r
3792 output_file
= makestr("/tmp/strip.XXXXXX", NULL
);
3793 output_file
= mktemp(output_file
);
3796 * Create the ld -r command line and execute it.
3798 reset_execute_list();
3799 add_execute_list_with_prefix("ld");
3800 add_execute_list("-keep_private_externs");
3801 add_execute_list("-r");
3803 add_execute_list("-S");
3805 add_execute_list("-x");
3806 add_execute_list(input_file
);
3807 add_execute_list("-o");
3808 add_execute_list(output_file
);
3810 add_execute_list("-x");
3811 add_execute_list("-exported_symbols_list");
3812 add_execute_list(sfile
);
3815 add_execute_list("-unexported_symbols_list");
3816 add_execute_list(Rfile
);
3818 if(execute_list(vflag
) == 0)
3819 fatal("internal link edit command failed");
3821 save_errors
= errors
;
3823 /* breakout the output file of the ld -f for processing */
3824 ld_r_ofile
= breakout(output_file
, &ld_r_archs
, &ld_r_narchs
, FALSE
);
3826 goto make_ld_r_object_cleanup
;
3828 /* checkout the file for symbol table replacement processing */
3829 checkout(ld_r_archs
, ld_r_narchs
);
3832 * Make sure the output of the ld -r is an object file with one arch.
3834 if(ld_r_narchs
!= 1 ||
3835 ld_r_archs
->type
!= OFILE_Mach_O
||
3836 ld_r_archs
->object
== NULL
||
3837 ld_r_archs
->object
->mh_filetype
!= MH_OBJECT
)
3838 fatal("internal link edit command failed to produce a thin Mach-O "
3842 * Now reset all the data of the input object with the ld -r output
3845 nsyms
= ld_r_archs
->object
->st
->nsyms
;
3846 if(ld_r_archs
->object
->mh
!= NULL
){
3847 symbols
= (struct nlist
*)
3848 (ld_r_archs
->object
->object_addr
+
3849 ld_r_archs
->object
->st
->symoff
);
3850 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3851 swap_nlist(symbols
, nsyms
, host_byte_sex
);
3856 symbols64
= (struct nlist_64
*)
3857 (ld_r_archs
->object
->object_addr
+
3858 ld_r_archs
->object
->st
->symoff
);
3859 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3860 swap_nlist_64(symbols64
, nsyms
, host_byte_sex
);
3862 strings
= ld_r_archs
->object
->object_addr
+
3863 ld_r_archs
->object
->st
->stroff
;
3864 strsize
= ld_r_archs
->object
->st
->strsize
;
3866 if(ld_r_archs
->object
->dyst
!= NULL
&&
3867 ld_r_archs
->object
->dyst
->nindirectsyms
!= 0){
3868 nindirectsyms
= ld_r_archs
->object
->dyst
->nindirectsyms
;
3869 indirectsyms
= (uint32_t *)
3870 (ld_r_archs
->object
->object_addr
+
3871 ld_r_archs
->object
->dyst
->indirectsymoff
);
3872 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3873 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
3877 indirectsyms
= NULL
;
3881 if(ld_r_archs
->object
->mh
!= NULL
)
3882 ld_r_archs
->object
->input_sym_info_size
=
3883 nsyms
* sizeof(struct nlist
) +
3886 ld_r_archs
->object
->input_sym_info_size
=
3887 nsyms
* sizeof(struct nlist_64
) +
3891 * Copy over the object struct from the ld -r object file onto the
3892 * input object file.
3894 *object
= *ld_r_archs
->object
;
3897 * Save the ofile struct for the ld -r output so it can be umapped when
3898 * we are done. And free up the ld_r_archs now that we are done with
3901 object
->ld_r_ofile
= ld_r_ofile
;
3902 free_archs(ld_r_archs
, ld_r_narchs
);
3904 make_ld_r_object_cleanup
:
3905 errors
+= save_errors
;
3907 * Remove the input and output files and clean up.
3909 if(unlink(input_file
) == -1)
3910 system_fatal("can't remove temporary file: %s", input_file
);
3911 if(unlink(output_file
) == -1)
3912 system_fatal("can't remove temporary file: %s", output_file
);
3918 * strip_LC_UUID_commands() is called when -no_uuid is specified to remove any
3919 * LC_UUID load commands from the object's load commands.
3923 strip_LC_UUID_commands(
3925 struct member
*member
,
3926 struct object
*object
)
3928 uint32_t i
, ncmds
, nuuids
, mh_sizeofcmds
, sizeofcmds
;
3929 struct load_command
*lc1
, *lc2
, *new_load_commands
;
3930 struct segment_command
*sg
;
3933 * See if there are any LC_UUID load commands.
3936 lc1
= arch
->object
->load_commands
;
3937 if(arch
->object
->mh
!= NULL
){
3938 ncmds
= arch
->object
->mh
->ncmds
;
3939 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
3942 ncmds
= arch
->object
->mh64
->ncmds
;
3943 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
3945 for(i
= 0; i
< ncmds
; i
++){
3946 if(lc1
->cmd
== LC_UUID
){
3949 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
3951 /* if no LC_UUID load commands just return */
3956 * Allocate space for the new load commands as zero it out so any holes
3957 * will be zero bytes.
3959 new_load_commands
= allocate(mh_sizeofcmds
);
3960 memset(new_load_commands
, '\0', mh_sizeofcmds
);
3963 * Copy all the load commands except the LC_UUID load commands into the
3964 * allocated space for the new load commands.
3966 lc1
= arch
->object
->load_commands
;
3967 lc2
= new_load_commands
;
3969 for(i
= 0; i
< ncmds
; i
++){
3970 if(lc1
->cmd
!= LC_UUID
){
3971 memcpy(lc2
, lc1
, lc1
->cmdsize
);
3972 sizeofcmds
+= lc2
->cmdsize
;
3973 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
3975 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
3979 * Finally copy the updated load commands over the existing load
3982 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
3983 if(mh_sizeofcmds
> sizeofcmds
){
3984 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
3985 (mh_sizeofcmds
- sizeofcmds
));
3988 if(arch
->object
->mh
!= NULL
) {
3989 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
3990 arch
->object
->mh
->ncmds
= ncmds
;
3992 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
3993 arch
->object
->mh64
->ncmds
= ncmds
;
3995 free(new_load_commands
);
3997 /* reset the pointers into the load commands */
3998 lc1
= arch
->object
->load_commands
;
3999 for(i
= 0; i
< ncmds
; i
++){
4002 arch
->object
->st
= (struct symtab_command
*)lc1
;
4005 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
4007 case LC_TWOLEVEL_HINTS
:
4008 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
4010 case LC_PREBIND_CKSUM
:
4011 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
4014 sg
= (struct segment_command
*)lc1
;
4015 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
4016 arch
->object
->seg_linkedit
= sg
;
4018 case LC_SEGMENT_SPLIT_INFO
:
4019 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
4021 case LC_CODE_SIGNATURE
:
4022 object
->code_sig_cmd
= (struct linkedit_data_command
*)lc1
;
4024 case LC_DYLD_INFO_ONLY
:
4026 object
->dyld_info
= (struct dyld_info_command
*)lc1
;
4028 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4034 * strip_LC_CODE_SIGNATURE_commands() is called when -c is specified to remove
4035 * any LC_CODE_SIGNATURE load commands from the object's load commands.
4039 strip_LC_CODE_SIGNATURE_commands(
4041 struct member
*member
,
4042 struct object
*object
)
4044 uint32_t i
, ncmds
, mh_sizeofcmds
, sizeofcmds
;
4045 struct load_command
*lc1
, *lc2
, *new_load_commands
;
4046 struct segment_command
*sg
;
4049 * See if there is an LC_CODE_SIGNATURE load command and if no command
4052 if(object
->code_sig_cmd
== NULL
)
4056 * Allocate space for the new load commands and zero it out so any holes
4057 * will be zero bytes.
4059 if(arch
->object
->mh
!= NULL
){
4060 ncmds
= arch
->object
->mh
->ncmds
;
4061 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
4064 ncmds
= arch
->object
->mh64
->ncmds
;
4065 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
4067 new_load_commands
= allocate(mh_sizeofcmds
);
4068 memset(new_load_commands
, '\0', mh_sizeofcmds
);
4071 * Copy all the load commands except the LC_CODE_SIGNATURE load commands
4072 * into the allocated space for the new load commands.
4074 lc1
= arch
->object
->load_commands
;
4075 lc2
= new_load_commands
;
4077 for(i
= 0; i
< ncmds
; i
++){
4078 if(lc1
->cmd
!= LC_CODE_SIGNATURE
){
4079 memcpy(lc2
, lc1
, lc1
->cmdsize
);
4080 sizeofcmds
+= lc2
->cmdsize
;
4081 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
4083 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4087 * Finally copy the updated load commands over the existing load
4090 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
4091 if(mh_sizeofcmds
> sizeofcmds
){
4092 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
4093 (mh_sizeofcmds
- sizeofcmds
));
4096 if(arch
->object
->mh
!= NULL
) {
4097 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
4098 arch
->object
->mh
->ncmds
= ncmds
;
4100 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
4101 arch
->object
->mh64
->ncmds
= ncmds
;
4103 free(new_load_commands
);
4105 /* reset the pointers into the load commands */
4106 object
->code_sig_cmd
= NULL
;
4107 lc1
= arch
->object
->load_commands
;
4108 for(i
= 0; i
< ncmds
; i
++){
4111 arch
->object
->st
= (struct symtab_command
*)lc1
;
4114 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
4116 case LC_TWOLEVEL_HINTS
:
4117 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
4119 case LC_PREBIND_CKSUM
:
4120 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
4123 sg
= (struct segment_command
*)lc1
;
4124 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
4125 arch
->object
->seg_linkedit
= sg
;
4127 case LC_SEGMENT_SPLIT_INFO
:
4128 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
4131 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4135 * To get the right amount of the file copied out by writeout() for the
4136 * case when we are stripping out the section contents we already reduce
4137 * the object size by the size of the section contents including the
4138 * padding after the load commands. So here we need to further reduce
4139 * it by the load command for the LC_CODE_SIGNATURE (a struct
4140 * linkedit_data_command) we are removing.
4142 object
->object_size
-= sizeof(struct linkedit_data_command
);
4144 * Then this size minus the size of the input symbolic information is
4145 * what is copied out from the file by writeout(). Which in this case
4146 * is just the new headers.
4150 * Finally for -c the file offset to the link edit information is to be
4151 * right after the load commands. So reset this for the updated size
4152 * of the load commands without the LC_CODE_SIGNATURE.
4154 if(object
->mh
!= NULL
)
4155 object
->seg_linkedit
->fileoff
= sizeof(struct mach_header
) +
4158 object
->seg_linkedit64
->fileoff
= sizeof(struct mach_header_64
) +
4161 #endif /* !(NMEDIT) */
4164 * private_extern_reference_by_module() is passed a symbol_index of a private
4165 * extern symbol and the module table. If the symbol_index appears in the
4166 * module symbol table this returns TRUE else it returns FALSE.
4170 private_extern_reference_by_module(
4171 uint32_t symbol_index
,
4172 struct dylib_reference
*refs
,
4173 uint32_t nextrefsyms
)
4177 for(i
= 0; i
< nextrefsyms
; i
++){
4178 if(refs
[i
].isym
== symbol_index
){
4179 if(refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
||
4180 refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
){
4189 * symbol_pointer_used() is passed a symbol_index and the indirect table. If
4190 * the symbol_index appears in the indirect symbol table this returns TRUE else
4195 symbol_pointer_used(
4196 uint32_t symbol_index
,
4197 uint32_t *indirectsyms
,
4198 uint32_t nindirectsyms
)
4202 for(i
= 0; i
< nindirectsyms
; i
++){
4203 if(indirectsyms
[i
] == symbol_index
)
4210 * Function for qsort for comparing undefined map entries.
4214 cmp_qsort_undef_map(
4215 const struct undef_map
*sym1
,
4216 const struct undef_map
*sym2
)
4218 return(strcmp(qsort_strings
+ sym1
->symbol
.n_un
.n_strx
,
4219 qsort_strings
+ sym2
->symbol
.n_un
.n_strx
));
4224 cmp_qsort_undef_map_64(
4225 const struct undef_map64
*sym1
,
4226 const struct undef_map64
*sym2
)
4228 return(strcmp(qsort_strings
+ sym1
->symbol64
.n_un
.n_strx
,
4229 qsort_strings
+ sym2
->symbol64
.n_un
.n_strx
));
4231 #endif /* !defined(NMEDIT) */
4235 * Function for qsort for comparing object names.
4243 return(strcmp(*name1
, *name2
));
4247 * Function for bsearch for finding a object name.
4251 cmp_bsearch_filename(
4255 return(strcmp(name1
, *name2
));
4257 #endif /* !defined(NMEDIT) */
4264 struct member
*member
,
4265 struct object
*object
,
4266 struct nlist
*symbols
,
4267 struct nlist_64
*symbols64
,
4271 struct dylib_table_of_contents
*tocs
,
4273 struct dylib_module
*mods
,
4274 struct dylib_module_64
*mods64
,
4276 struct dylib_reference
*refs
,
4277 uint32_t nextrefsyms
)
4280 unsigned char data_n_sect
, nsects
;
4281 struct load_command
*lc
;
4282 struct segment_command
*sg
;
4283 struct segment_command_64
*sg64
;
4284 struct section
*s
, **sections
;
4285 struct section_64
*s64
, **sections64
;
4287 uint32_t missing_syms
;
4288 struct symbol_list
*sp
;
4289 struct nlist
**global_symbol
;
4290 struct nlist_64
**global_symbol64
;
4291 enum bool global_symbol_found
;
4292 char *global_name
, save_char
;
4293 enum bool dwarf_debug_map
;
4294 enum byte_sex host_byte_sex
;
4295 int32_t missing_reloc_symbols
;
4296 enum bool edit_symtab_return
;
4299 uint32_t new_ext_strsize
, len
, inew_syms
;
4301 struct nlist
**changed_globals
;
4302 struct nlist_64
**changed_globals64
;
4303 uint32_t nchanged_globals
;
4304 uint32_t ncmds
, s_flags
, n_strx
, module_name
, ilocalsym
, nlocalsym
;
4305 uint32_t iextdefsym
, nextdefsym
;
4306 uint8_t n_type
, n_sect
, global_symbol_n_sect
;
4308 enum bool warned_about_global_coalesced_symbols
;
4310 edit_symtab_return
= TRUE
;
4311 host_byte_sex
= get_host_byte_sex();
4312 missing_reloc_symbols
= 0;
4313 warned_about_global_coalesced_symbols
= FALSE
;
4317 nmedits
= allocate(nsyms
* sizeof(enum bool));
4318 for(i
= 0; i
< nsyms
; i
++)
4322 * If nmedit is operating on a dynamic library then symbols are turned
4323 * into private externs with the extern bit off not into static symbols.
4325 if(object
->mh_filetype
== MH_DYLIB
&& pflag
== TRUE
){
4326 error_arch(arch
, member
, "can't use -p with dynamic libraries");
4331 * As part of the MAJOR guess for the second pass to fix stabs for the
4332 * globals symbols that get turned into non-global symbols. We need to
4333 * change the stabs. To do this we to know if a N_GSYM is for a data
4334 * symbol or not to know to turn it into an N_STSYM or a N_FUN.
4335 * This logic as determined by compiling test cases with and without
4336 * the key word 'static' and looking at the difference between the STABS
4337 * the compiler generates and trying to match that here.
4339 * We also use this loop and the next to gather an array of section
4340 * struct pointers so we can later determine if we run into a global
4341 * symbol in a coalesced section and not turn those symbols into
4347 data_n_sect
= NO_SECT
;
4348 lc
= object
->load_commands
;
4349 if(object
->mh
!= NULL
)
4350 ncmds
= object
->mh
->ncmds
;
4352 ncmds
= object
->mh64
->ncmds
;
4353 for(i
= 0; i
< ncmds
; i
++){
4354 if(lc
->cmd
== LC_SEGMENT
){
4355 sg
= (struct segment_command
*)lc
;
4356 s
= (struct section
*)((char *)sg
+
4357 sizeof(struct segment_command
));
4358 nsects
+= sg
->nsects
;
4359 for(j
= 0; j
< sg
->nsects
; j
++){
4360 if(strcmp(s
->segname
, SEG_DATA
) == 0 &&
4361 strcmp(s
->sectname
, SECT_DATA
) == 0 &&
4362 data_n_sect
== NO_SECT
){
4363 data_n_sect
= n_sect
;
4370 else if(lc
->cmd
== LC_SEGMENT_64
){
4371 sg64
= (struct segment_command_64
*)lc
;
4372 s64
= (struct section_64
*)((char *)sg64
+
4373 sizeof(struct segment_command_64
));
4374 nsects
+= sg64
->nsects
;
4375 for(j
= 0; j
< sg64
->nsects
; j
++){
4376 if(strcmp(s64
->segname
, SEG_DATA
) == 0 &&
4377 strcmp(s64
->sectname
, SECT_DATA
) == 0 &&
4378 data_n_sect
== NO_SECT
){
4379 data_n_sect
= n_sect
;
4386 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
4388 if(object
->mh
!= NULL
){
4389 sections
= allocate(nsects
* sizeof(struct section
*));
4394 sections64
= allocate(nsects
* sizeof(struct section_64
*));
4397 lc
= object
->load_commands
;
4398 for(i
= 0; i
< ncmds
; i
++){
4399 if(lc
->cmd
== LC_SEGMENT
){
4400 sg
= (struct segment_command
*)lc
;
4401 s
= (struct section
*)((char *)sg
+
4402 sizeof(struct segment_command
));
4403 for(j
= 0; j
< sg
->nsects
; j
++){
4404 sections
[nsects
++] = s
++;
4407 else if(lc
->cmd
== LC_SEGMENT_64
){
4408 sg64
= (struct segment_command_64
*)lc
;
4409 s64
= (struct section_64
*)((char *)sg64
+
4410 sizeof(struct segment_command_64
));
4411 for(j
= 0; j
< sg64
->nsects
; j
++){
4412 sections64
[nsects
++] = s64
++;
4415 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
4419 * Zero out the saved symbols so they can be recorded for this file.
4421 for(i
= 0; i
< nsave_symbols
; i
++)
4422 save_symbols
[i
].sym
= NULL
;
4423 for(i
= 0; i
< nremove_symbols
; i
++)
4424 remove_symbols
[i
].sym
= NULL
;
4426 for(i
= 0; i
< nsave_symbols
; i
++)
4427 save_symbols
[i
].seen
= FALSE
;
4428 for(i
= 0; i
< nremove_symbols
; i
++)
4429 remove_symbols
[i
].seen
= FALSE
;
4432 nchanged_globals
= 0;
4433 if(object
->mh
!= NULL
){
4434 changed_globals
= allocate(nsyms
* sizeof(struct nlist
*));
4435 changed_globals64
= NULL
;
4436 for(i
= 0; i
< nsyms
; i
++)
4437 changed_globals
[i
] = NULL
;
4440 changed_globals
= NULL
;
4441 changed_globals64
= allocate(nsyms
* sizeof(struct nlist_64
*));
4442 for(i
= 0; i
< nsyms
; i
++)
4443 changed_globals64
[i
] = NULL
;
4447 * These are the variables for the new symbol table and new string
4448 * table. Since this routine only turns globals into non-globals the
4449 * number of symbols does not change. But the count of local, defined
4450 * external symbols does change.
4457 new_strsize
= sizeof(int32_t);
4458 new_ext_strsize
= 0;
4461 * First pass: turn the globals symbols into non-global symbols.
4463 for(i
= 0; i
< nsyms
; i
++){
4466 if(object
->mh
!= NULL
){
4467 n_strx
= symbols
[i
].n_un
.n_strx
;
4468 n_type
= symbols
[i
].n_type
;
4469 n_sect
= symbols
[i
].n_sect
;
4470 if((n_type
& N_TYPE
) == N_SECT
)
4471 s_flags
= sections
[n_sect
- 1]->flags
;
4472 n_value
= symbols
[i
].n_value
;
4475 n_strx
= symbols64
[i
].n_un
.n_strx
;
4476 n_type
= symbols64
[i
].n_type
;
4477 n_sect
= symbols64
[i
].n_sect
;
4478 if((n_type
& N_TYPE
) == N_SECT
)
4479 s_flags
= sections64
[n_sect
- 1]->flags
;
4480 n_value
= symbols64
[i
].n_value
;
4483 if(n_strx
> strsize
){
4484 error_arch(arch
, member
, "bad string index for symbol "
4485 "table entry %u in: ", i
);
4488 len
= strlen(strings
+ n_strx
) + 1;
4491 if((n_type
& N_TYPE
) != N_UNDF
&&
4492 (n_type
& N_TYPE
) != N_PBUD
){
4493 if((n_type
& N_TYPE
) == N_SECT
){
4494 if(n_sect
> nsects
){
4495 error_arch(arch
, member
, "bad n_sect for symbol "
4496 "table entry %u in: ", i
);
4499 if(((s_flags
& SECTION_TYPE
) == S_COALESCED
) &&
4501 object
->mh_filetype
!= MH_OBJECT
){
4502 /* this remains a global defined symbol */
4503 if(warned_about_global_coalesced_symbols
== FALSE
){
4504 warning_arch(arch
, member
, "can't make global "
4505 "coalesced symbols (like %s) into static "
4506 "symbols (use ld(1)'s "
4507 "-exported_symbols_list option) in a final "
4508 "linked image: ", strings
+ n_strx
);
4509 warned_about_global_coalesced_symbols
= TRUE
;
4512 new_ext_strsize
+= len
;
4514 sp
= bsearch(strings
+ n_strx
,
4515 remove_symbols
, nremove_symbols
,
4516 sizeof(struct symbol_list
),
4517 (int (*)(const void *, const void *))
4518 symbol_list_bsearch
);
4520 if(sp
->sym
!= NULL
){
4521 error_arch(arch
, member
, "more than one "
4522 "symbol for: %s found in: ", sp
->name
);
4526 if(object
->mh
!= NULL
)
4527 sp
->sym
= &(symbols
[i
]);
4529 sp
->sym
= &(symbols64
[i
]);
4531 warning_arch(arch
, member
, "can't make "
4532 "global coalesced symbol: %s into a "
4533 "static symbol in: ", sp
->name
);
4537 * In case the user has listed this coalesced
4538 * symbol in the save list look for it and mark it
4539 * as seen so we don't complain about not seeing it.
4541 sp
= bsearch(strings
+ n_strx
,
4542 save_symbols
, nsave_symbols
,
4543 sizeof(struct symbol_list
),
4544 (int (*)(const void *, const void *))
4545 symbol_list_bsearch
);
4547 if(sp
->sym
!= NULL
){
4548 error_arch(arch
, member
, "more than one "
4549 "symbol for: %s found in: ", sp
->name
);
4553 if(object
->mh
!= NULL
)
4554 sp
->sym
= &(symbols
[i
]);
4556 sp
->sym
= &(symbols64
[i
]);
4560 continue; /* leave this symbol unchanged */
4563 sp
= bsearch(strings
+ n_strx
,
4564 remove_symbols
, nremove_symbols
,
4565 sizeof(struct symbol_list
),
4566 (int (*)(const void *, const void *))
4567 symbol_list_bsearch
);
4569 if(sp
->sym
!= NULL
){
4570 error_arch(arch
, member
, "more than one symbol "
4571 "for: %s found in: ", sp
->name
);
4575 if(object
->mh
!= NULL
)
4576 sp
->sym
= &(symbols
[i
]);
4578 sp
->sym
= &(symbols64
[i
]);
4585 * If there is no list of saved symbols, then all
4586 * symbols will be saved unless listed in the remove
4591 * There is no save list, so if there is also no
4592 * remove list but the -p flag is specified or it is
4593 * a dynamic library then change all symbols.
4595 if((pflag
|| object
->mh_filetype
== MH_DYLIB
)
4596 && nremove_symbols
== 0)
4598 /* this remains a global defined symbol */
4600 new_ext_strsize
+= len
;
4602 continue; /* leave this symbol unchanged */
4605 sp
= bsearch(strings
+ n_strx
,
4606 save_symbols
, nsave_symbols
,
4607 sizeof(struct symbol_list
),
4608 (int (*)(const void *, const void *))
4609 symbol_list_bsearch
);
4611 if(sp
->sym
!= NULL
){
4612 error_arch(arch
, member
, "more than one symbol "
4613 "for: %s found in: ", sp
->name
);
4617 if(object
->mh
!= NULL
)
4618 sp
->sym
= &(symbols
[i
]);
4620 sp
->sym
= &(symbols64
[i
]);
4622 /* this remains a global defined symbol */
4624 new_ext_strsize
+= len
;
4629 if(Aflag
&& n_type
== (N_EXT
| N_ABS
) &&
4632 strncmp(strings
+ n_strx
,
4633 ".objc_class_name_",
4634 sizeof(".objc_class_name_") - 1) == 0))){
4635 /* this remains a global defined symbol */
4637 new_ext_strsize
+= len
;
4642 if((n_type
& N_TYPE
) != N_INDR
){
4644 if(object
->mh
!= NULL
)
4645 changed_globals
[nchanged_globals
++] =
4648 changed_globals64
[nchanged_globals
++] =
4651 /* this remains a global defined symbol */
4653 new_ext_strsize
+= len
;
4657 /* this will become a non-global symbol */
4663 /* this remains a global defined symbol */
4665 new_ext_strsize
+= len
;
4672 /* this is an undefined symbol */
4674 new_ext_strsize
+= len
;
4679 /* this is a local symbol */
4686 * The module table's module names are placed with the external
4687 * strings. So size them and add this to the external string size.
4689 for(i
= 0; i
< nmodtab
; i
++){
4690 if(object
->mh
!= NULL
)
4691 module_name
= mods
[i
].module_name
;
4693 module_name
= mods64
[i
].module_name
;
4694 if(module_name
== 0 || module_name
> strsize
){
4695 error_arch(arch
, member
, "bad string index for module_name "
4696 "of module table entry %d in: ", i
);
4699 len
= strlen(strings
+ module_name
) + 1;
4701 new_ext_strsize
+= len
;
4705 * Warn about symbols to be saved that were missing.
4710 for(i
= 0; i
< nsave_symbols
; i
++){
4711 if(save_symbols
[i
].sym
== NULL
){
4712 if(missing_syms
== 0){
4713 error_arch(arch
, member
, "symbols names listed "
4714 "in: %s not in: ", sfile
);
4717 fprintf(stderr
, "%s\n", save_symbols
[i
].name
);
4720 for(i
= 0; i
< nremove_symbols
; i
++){
4721 if(remove_symbols
[i
].sym
== NULL
){
4722 if(missing_syms
== 0){
4723 error_arch(arch
, member
, "symbols names listed "
4724 "in: %s not in: ", Rfile
);
4727 fprintf(stderr
, "%s\n", remove_symbols
[i
].name
);
4734 * Second pass: fix stabs for the globals symbols that got turned into
4735 * non-global symbols. This is a MAJOR guess. The specific changes
4736 * to do here were determined by compiling test cases with and without
4737 * the key word 'static' and looking at the difference between the STABS
4738 * the compiler generates and trying to match that here.
4740 global_strings
= strings
;
4741 if(object
->mh
!= NULL
)
4742 qsort(changed_globals
, nchanged_globals
, sizeof(struct nlist
*),
4743 (int (*)(const void *, const void *))cmp_qsort_global
);
4745 qsort(changed_globals64
, nchanged_globals
,sizeof(struct nlist_64
*),
4746 (int (*)(const void *, const void *))cmp_qsort_global_64
);
4747 dwarf_debug_map
= FALSE
;
4748 for(i
= 0; i
< nsyms
; i
++){
4750 if(object
->mh
!= NULL
){
4751 n_strx
= symbols
[i
].n_un
.n_strx
;
4752 n_type
= symbols
[i
].n_type
;
4753 n_desc
= symbols
[i
].n_desc
;
4756 n_strx
= symbols64
[i
].n_un
.n_strx
;
4757 n_type
= symbols64
[i
].n_type
;
4758 n_desc
= symbols64
[i
].n_desc
;
4761 dwarf_debug_map
= FALSE
;
4762 else if (n_type
== N_OSO
)
4763 dwarf_debug_map
= n_desc
!= 0;
4764 else if (dwarf_debug_map
&& n_type
== N_GSYM
){
4765 global_name
= strings
+ n_strx
;
4766 if(object
->mh
!= NULL
){
4767 global_symbol
= bsearch(global_name
, changed_globals
,
4768 nchanged_globals
,sizeof(struct nlist
*),
4769 (int (*)(const void *, const void *))
4770 cmp_bsearch_global
);
4771 if(global_symbol
!= NULL
){
4772 symbols
[i
].n_type
= N_STSYM
;
4773 symbols
[i
].n_sect
= (*global_symbol
)->n_sect
;
4774 symbols
[i
].n_value
= (*global_symbol
)->n_value
;
4778 global_symbol64
= bsearch(global_name
, changed_globals64
,
4780 sizeof(struct nlist_64
*),
4781 (int (*)(const void *, const void *))
4782 cmp_bsearch_global_64
);
4783 if(global_symbol64
!= NULL
){
4784 symbols64
[i
].n_type
= N_STSYM
;
4785 symbols64
[i
].n_sect
= (*global_symbol64
)->n_sect
;
4786 symbols64
[i
].n_value
= (*global_symbol64
)->n_value
;
4790 else if(! dwarf_debug_map
&&
4791 (n_type
== N_GSYM
|| n_type
== N_FUN
) &&
4792 (n_strx
!= 0 && strings
[n_strx
] != '\0')){
4793 global_name
= strings
+ n_strx
;
4794 if((global_name
[0] == '+' || global_name
[0] == '-') &&
4795 global_name
[1] == '['){
4797 while(j
+ n_strx
< strsize
&& global_name
[j
] != ']')
4799 if(j
+ n_strx
< strsize
&& global_name
[j
] == ']')
4804 while(j
+ n_strx
< strsize
&& global_name
[j
] != ':')
4806 if(j
+ n_strx
>= strsize
){
4807 error_arch(arch
, member
, "bad N_STAB symbol name for entry "
4808 "%u (does not contain ':' separating name from type) "
4812 save_char
= global_name
[j
];
4813 global_name
[j
] = '\0';
4815 global_symbol_found
= FALSE
;
4816 global_symbol_n_sect
= 0;
4817 if(object
->mh
!= NULL
){
4818 global_symbol
= bsearch(global_name
, changed_globals
,
4819 nchanged_globals
,sizeof(struct nlist
*),
4820 (int (*)(const void *, const void *))
4821 cmp_bsearch_global_stab
);
4822 global_symbol64
= NULL
;
4823 if(global_symbol
!= NULL
){
4824 global_symbol_found
= TRUE
;
4825 global_symbol_n_sect
= (*global_symbol
)->n_sect
;
4829 global_symbol64
= bsearch(global_name
, changed_globals64
,
4831 sizeof(struct nlist_64
*),
4832 (int (*)(const void *, const void *))
4833 cmp_bsearch_global_stab_64
);
4834 global_symbol
= NULL
;
4835 if(global_symbol64
!= NULL
){
4836 global_symbol_found
= TRUE
;
4837 global_symbol_n_sect
= (*global_symbol64
)->n_sect
;
4840 global_name
[j
] = save_char
;
4841 if(global_symbol_found
== TRUE
){
4842 if(n_type
== N_GSYM
){
4843 if(global_symbol_n_sect
== data_n_sect
){
4844 if(object
->mh
!= NULL
)
4845 symbols
[i
].n_type
= N_STSYM
;
4847 symbols64
[i
].n_type
= N_STSYM
;
4850 if(object
->mh
!= NULL
)
4851 symbols
[i
].n_type
= N_FUN
;
4853 symbols64
[i
].n_type
= N_FUN
;
4855 if(object
->mh
!= NULL
){
4856 symbols
[i
].n_sect
= (*global_symbol
)->n_sect
;
4857 symbols
[i
].n_value
= (*global_symbol
)->n_value
;
4858 symbols
[i
].n_desc
= (*global_symbol
)->n_desc
;
4861 symbols64
[i
].n_sect
= (*global_symbol64
)->n_sect
;
4862 symbols64
[i
].n_value
= (*global_symbol64
)->n_value
;
4863 symbols64
[i
].n_desc
= (*global_symbol64
)->n_desc
;
4865 if(j
+ 1 + n_strx
>= strsize
||
4866 global_name
[j
+1] != 'G'){
4867 error_arch(arch
, member
, "bad N_GSYM symbol name "
4868 "for entry %u (does not have type 'G' after "
4869 "':' in name) in: ", i
);
4872 global_name
[j
+1] = 'S';
4874 else{ /* n_type == N_FUN */
4875 if(j
+ 1 + n_strx
>= strsize
||
4876 global_name
[j
+1] == 'F'){
4877 global_name
[j
+1] = 'f';
4883 global_strings
= NULL
;
4886 * Now what needs to be done is to create the new symbol table moving
4887 * those global symbols being changed into non-globals into the areas
4888 * in the symbol table for local symbols. The symbol table and string
4889 * table must be in this order:
4893 * external defined symbols
4901 saves
= (int32_t *)allocate(nsyms
* sizeof(int32_t));
4902 bzero(saves
, nsyms
* sizeof(int32_t));
4904 if(object
->mh
!= NULL
){
4905 new_symbols
= (struct nlist
*)
4906 allocate(new_nsyms
* sizeof(struct nlist
));
4907 new_symbols64
= NULL
;
4911 new_symbols64
= (struct nlist_64
*)
4912 allocate(new_nsyms
* sizeof(struct nlist_64
));
4914 new_strsize
= round(new_strsize
, sizeof(int32_t));
4915 new_strings
= (char *)allocate(new_strsize
);
4916 new_strings
[new_strsize
- 3] = '\0';
4917 new_strings
[new_strsize
- 2] = '\0';
4918 new_strings
[new_strsize
- 1] = '\0';
4920 memset(new_strings
, '\0', sizeof(int32_t));
4921 p
= new_strings
+ sizeof(int32_t);
4922 q
= p
+ new_ext_strsize
;
4925 * If this is a dynamic library the movement of the symbols has to be
4926 * done with respect to the modules. As the local symbols, and external
4927 * defined symbols are grouped together for each module. Then a new
4928 * module table needs to be created with the new indexes into the symbol
4929 * table for each module.
4931 new_nmodtab
= nmodtab
;
4933 new_nextrefsyms
= nextrefsyms
;
4934 if(object
->mh_filetype
== MH_DYLIB
&& nmodtab
!= 0){
4935 if(object
->mh
!= NULL
){
4936 new_mods
= allocate(nmodtab
* sizeof(struct dylib_module
));
4941 new_mods64
= allocate(nmodtab
* sizeof(struct dylib_module_64
));
4946 * This first loop through the module table sets the index and
4947 * counts of the local symbols for each module.
4949 for(i
= 0; i
< nmodtab
; i
++){
4951 * First put the existing local symbols into the new symbol
4954 if(object
->mh
!= NULL
){
4955 new_mods
[i
].ilocalsym
= inew_syms
;
4956 new_mods
[i
].nlocalsym
= 0;
4957 ilocalsym
= mods
[i
].ilocalsym
;
4958 nlocalsym
= mods
[i
].nlocalsym
;
4961 new_mods64
[i
].ilocalsym
= inew_syms
;
4962 new_mods64
[i
].nlocalsym
= 0;
4963 ilocalsym
= mods64
[i
].ilocalsym
;
4964 nlocalsym
= mods64
[i
].nlocalsym
;
4966 for(j
= ilocalsym
; j
< ilocalsym
+ nlocalsym
; j
++){
4967 if(object
->mh
!= NULL
){
4968 n_strx
= symbols
[j
].n_un
.n_strx
;
4969 n_type
= symbols
[j
].n_type
;
4972 n_strx
= symbols64
[j
].n_un
.n_strx
;
4973 n_type
= symbols64
[j
].n_type
;
4975 if((n_type
& N_EXT
) == 0){
4976 if(object
->mh
!= NULL
)
4977 new_symbols
[inew_syms
] = symbols
[j
];
4979 new_symbols64
[inew_syms
] = symbols64
[j
];
4981 strcpy(q
, strings
+ n_strx
);
4982 if(object
->mh
!= NULL
)
4983 new_symbols
[inew_syms
].n_un
.n_strx
=
4986 new_symbols64
[inew_syms
].n_un
.n_strx
=
4991 saves
[j
] = inew_syms
;
4992 if(object
->mh
!= NULL
)
4993 new_mods
[i
].nlocalsym
++;
4995 new_mods64
[i
].nlocalsym
++;
4999 * Next put the global symbols that were changed into
5000 * non-global symbols into the new symbol table and moved their
5001 * counts to the local symbol counts.
5003 if(object
->mh
!= NULL
){
5004 iextdefsym
= mods
[i
].iextdefsym
;
5005 nextdefsym
= mods
[i
].nextdefsym
;
5008 iextdefsym
= mods64
[i
].iextdefsym
;
5009 nextdefsym
= mods64
[i
].nextdefsym
;
5011 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
5012 if(object
->mh
!= NULL
){
5013 n_strx
= symbols
[j
].n_un
.n_strx
;
5014 n_type
= symbols
[j
].n_type
;
5017 n_strx
= symbols64
[j
].n_un
.n_strx
;
5018 n_type
= symbols64
[j
].n_type
;
5020 if((n_type
& N_EXT
) != 0){
5021 if(nmedits
[j
] == TRUE
){
5023 * Change the new symbol to a private extern symbol
5024 * with the extern bit off.
5026 if(object
->mh
!= NULL
){
5027 new_symbols
[inew_syms
] = symbols
[j
];
5028 new_symbols
[inew_syms
].n_type
|= N_PEXT
;
5029 new_symbols
[inew_syms
].n_type
&= ~N_EXT
;
5032 new_symbols64
[inew_syms
] = symbols64
[j
];
5033 new_symbols64
[inew_syms
].n_type
|= N_PEXT
;
5034 new_symbols64
[inew_syms
].n_type
&= ~N_EXT
;
5037 strcpy(q
, strings
+ n_strx
);
5038 if(object
->mh
!= NULL
)
5039 new_symbols
[inew_syms
].n_un
.n_strx
=
5042 new_symbols64
[inew_syms
].n_un
.n_strx
=
5047 saves
[j
] = inew_syms
;
5048 if(object
->mh
!= NULL
)
5049 new_mods
[i
].nlocalsym
++;
5051 new_mods64
[i
].nlocalsym
++;
5057 * Next put the unchanged defined global symbols into the new
5060 for(i
= 0; i
< nmodtab
; i
++){
5061 if(object
->mh
!= NULL
){
5062 new_mods
[i
].iextdefsym
= inew_syms
;
5063 new_mods
[i
].nextdefsym
= 0;
5064 iextdefsym
= mods
[i
].iextdefsym
;
5065 nextdefsym
= mods
[i
].nextdefsym
;
5068 new_mods64
[i
].iextdefsym
= inew_syms
;
5069 new_mods64
[i
].nextdefsym
= 0;
5070 iextdefsym
= mods64
[i
].iextdefsym
;
5071 nextdefsym
= mods64
[i
].nextdefsym
;
5073 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
5074 if(object
->mh
!= NULL
){
5075 n_strx
= symbols
[j
].n_un
.n_strx
;
5076 n_type
= symbols
[j
].n_type
;
5079 n_strx
= symbols64
[j
].n_un
.n_strx
;
5080 n_type
= symbols64
[j
].n_type
;
5082 if((n_type
& N_EXT
) != 0){
5083 if(nmedits
[j
] == FALSE
){
5084 if(object
->mh
!= NULL
)
5085 new_symbols
[inew_syms
] = symbols
[j
];
5087 new_symbols64
[inew_syms
] = symbols64
[j
];
5089 strcpy(p
, strings
+ n_strx
);
5090 if(object
->mh
!= NULL
)
5091 new_symbols
[inew_syms
].n_un
.n_strx
=
5094 new_symbols64
[inew_syms
].n_un
.n_strx
=
5099 saves
[j
] = inew_syms
;
5100 if(object
->mh
!= NULL
)
5101 new_mods
[i
].nextdefsym
++;
5103 new_mods64
[i
].nextdefsym
++;
5109 * Last put the undefined symbols into the new symbol table.
5111 for(i
= 0; i
< nsyms
; i
++){
5112 if(object
->mh
!= NULL
){
5113 n_strx
= symbols
[i
].n_un
.n_strx
;
5114 n_type
= symbols
[i
].n_type
;
5117 n_strx
= symbols64
[i
].n_un
.n_strx
;
5118 n_type
= symbols64
[i
].n_type
;
5120 if((n_type
& N_EXT
) != 0 &&
5121 ((n_type
& N_TYPE
) == N_UNDF
||
5122 (n_type
& N_TYPE
) == N_PBUD
)){
5123 if(object
->mh
!= NULL
)
5124 new_symbols
[inew_syms
] = symbols
[i
];
5126 new_symbols64
[inew_syms
] = symbols64
[i
];
5128 strcpy(p
, strings
+ n_strx
);
5129 if(object
->mh
!= NULL
)
5130 new_symbols
[inew_syms
].n_un
.n_strx
=
5133 new_symbols64
[inew_syms
].n_un
.n_strx
=
5138 saves
[i
] = inew_syms
;
5143 * Place the module table's module names with the external strings
5144 * and set the names in the new module table. And then copy the
5145 * other unchanged fields.
5147 for(i
= 0; i
< nmodtab
; i
++){
5148 if(object
->mh
!= NULL
){
5149 strcpy(p
, strings
+ mods
[i
].module_name
);
5150 new_mods
[i
].module_name
= p
- new_strings
;
5153 new_mods
[i
].irefsym
= mods
[i
].irefsym
;
5154 new_mods
[i
].nrefsym
= mods
[i
].nrefsym
;
5155 new_mods
[i
].iextrel
= mods
[i
].iextrel
;
5156 new_mods
[i
].nextrel
= mods
[i
].nextrel
;
5157 new_mods
[i
].iinit_iterm
= mods
[i
].iinit_iterm
;
5158 new_mods
[i
].ninit_nterm
= mods
[i
].ninit_nterm
;
5159 new_mods
[i
].objc_module_info_addr
=
5160 mods
[i
].objc_module_info_addr
;
5161 new_mods
[i
].objc_module_info_size
=
5162 mods
[i
].objc_module_info_size
;
5165 strcpy(p
, strings
+ mods64
[i
].module_name
);
5166 new_mods64
[i
].module_name
= p
- new_strings
;
5169 new_mods64
[i
].irefsym
= mods64
[i
].irefsym
;
5170 new_mods64
[i
].nrefsym
= mods64
[i
].nrefsym
;
5171 new_mods64
[i
].iextrel
= mods64
[i
].iextrel
;
5172 new_mods64
[i
].nextrel
= mods64
[i
].nextrel
;
5173 new_mods64
[i
].iinit_iterm
= mods64
[i
].iinit_iterm
;
5174 new_mods64
[i
].ninit_nterm
= mods64
[i
].ninit_nterm
;
5175 new_mods64
[i
].objc_module_info_addr
=
5176 mods64
[i
].objc_module_info_addr
;
5177 new_mods64
[i
].objc_module_info_size
=
5178 mods64
[i
].objc_module_info_size
;
5183 * Update the reference table with the new symbol indexes for all
5184 * entries and change type of reference (the flags field) for those
5185 * symbols that got changed from globals to non-globals.
5187 new_nextrefsyms
= nextrefsyms
;
5188 new_refs
= allocate(new_nextrefsyms
*
5189 sizeof(struct dylib_reference
));
5191 for(i
= 0; i
< nextrefsyms
; i
++){
5192 if(nmedits
[refs
[i
].isym
] == TRUE
){
5193 if(refs
[i
].flags
== REFERENCE_FLAG_DEFINED
)
5195 REFERENCE_FLAG_PRIVATE_DEFINED
;
5196 else if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
)
5198 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
;
5199 else if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
)
5201 REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
;
5203 new_refs
[i
].flags
= refs
[i
].flags
;
5206 new_refs
[i
].flags
= refs
[i
].flags
;
5208 new_refs
[i
].isym
= saves
[refs
[i
].isym
] - 1;
5212 * Create a new dylib table of contents without the global symbols
5213 * that got turned into non-globals.
5215 new_ntoc
= ntoc
- nchanged_globals
;
5216 new_tocs
= allocate(new_ntoc
*
5217 sizeof(struct dylib_table_of_contents
));
5219 for(i
= 0; i
< ntoc
; i
++){
5220 if(tocs
[i
].symbol_index
>= nsyms
){
5221 error_arch(arch
, member
, "bad symbol index for table of "
5222 "contents table entry %d in: ", i
);
5225 if(nmedits
[tocs
[i
].symbol_index
] == FALSE
){
5226 new_tocs
[k
].symbol_index
= saves
[tocs
[i
].symbol_index
] - 1;
5227 new_tocs
[k
].module_index
= tocs
[i
].module_index
;
5233 * If is not a dynamic library so all global symbols changed into
5234 * statics can be moved to the end of the local symbols. If the pflag
5235 * is set then the changed symbols remain global and just get the
5236 * private extern bit set.
5240 * First put the existing local symbols into the new symbol table.
5243 for(i
= 0; i
< nsyms
; i
++){
5244 if(object
->mh
!= NULL
){
5245 n_strx
= symbols
[i
].n_un
.n_strx
;
5246 n_type
= symbols
[i
].n_type
;
5249 n_strx
= symbols64
[i
].n_un
.n_strx
;
5250 n_type
= symbols64
[i
].n_type
;
5252 if((n_type
& N_EXT
) == 0){
5253 if(object
->mh
!= NULL
)
5254 new_symbols
[inew_syms
] = symbols
[i
];
5256 new_symbols64
[inew_syms
] = symbols64
[i
];
5258 strcpy(q
, strings
+ n_strx
);
5259 if(object
->mh
!= NULL
)
5260 new_symbols
[inew_syms
].n_un
.n_strx
=
5263 new_symbols64
[inew_syms
].n_un
.n_strx
=
5268 saves
[i
] = inew_syms
;
5272 * Next put the global symbols that were changed into statics
5273 * symbols into the new symbol table.
5276 for(i
= 0; i
< nsyms
; i
++){
5277 if(object
->mh
!= NULL
){
5278 n_strx
= symbols
[i
].n_un
.n_strx
;
5279 n_type
= symbols
[i
].n_type
;
5282 n_strx
= symbols64
[i
].n_un
.n_strx
;
5283 n_type
= symbols64
[i
].n_type
;
5285 if((n_type
& N_EXT
) != 0){
5286 if(nmedits
[i
] == TRUE
){
5288 * Change the new symbol to not be an extern symbol
5289 * by turning off the extern bit.
5291 if(object
->mh
!= NULL
){
5292 new_symbols
[inew_syms
] = symbols
[i
];
5293 new_symbols
[inew_syms
].n_type
&= ~N_EXT
;
5294 new_symbols
[inew_syms
].n_desc
&= ~N_WEAK_DEF
;
5297 new_symbols64
[inew_syms
] = symbols64
[i
];
5298 new_symbols64
[inew_syms
].n_type
&= ~N_EXT
;
5299 new_symbols64
[inew_syms
].n_desc
&= ~N_WEAK_DEF
;
5302 strcpy(q
, strings
+ n_strx
);
5303 if(object
->mh
!= NULL
)
5304 new_symbols
[inew_syms
].n_un
.n_strx
=
5307 new_symbols64
[inew_syms
].n_un
.n_strx
=
5312 saves
[i
] = inew_syms
;
5318 * Last put the unchanged global symbols into the new symbol table
5319 * and symbols changed into private externs.
5321 for(i
= 0; i
< nsyms
; i
++){
5322 if(object
->mh
!= NULL
){
5323 n_strx
= symbols
[i
].n_un
.n_strx
;
5324 n_type
= symbols
[i
].n_type
;
5327 n_strx
= symbols64
[i
].n_un
.n_strx
;
5328 n_type
= symbols64
[i
].n_type
;
5330 if((n_type
& N_EXT
) != 0){
5331 if(nmedits
[i
] == FALSE
|| pflag
== TRUE
){
5332 if(object
->mh
!= NULL
)
5333 new_symbols
[inew_syms
] = symbols
[i
];
5335 new_symbols64
[inew_syms
] = symbols64
[i
];
5336 if(nmedits
[i
] == TRUE
&& pflag
== TRUE
){
5338 * Change the new symbol to be a private extern
5339 * symbol by turning on the private extern bit.
5341 if(object
->mh
!= NULL
)
5342 new_symbols
[inew_syms
].n_type
|= N_PEXT
;
5344 new_symbols64
[inew_syms
].n_type
|= N_PEXT
;
5347 strcpy(p
, strings
+ n_strx
);
5348 if(object
->mh
!= NULL
)
5349 new_symbols
[inew_syms
].n_un
.n_strx
=
5352 new_symbols64
[inew_syms
].n_un
.n_strx
=
5357 saves
[i
] = inew_syms
;
5363 if(sections
!= NULL
)
5365 if(sections64
!= NULL
)
5375 * Function for qsort for comparing global symbol names.
5380 const struct nlist
**sym1
,
5381 const struct nlist
**sym2
)
5383 return(strcmp(global_strings
+ (*sym1
)->n_un
.n_strx
,
5384 global_strings
+ (*sym2
)->n_un
.n_strx
));
5389 cmp_qsort_global_64(
5390 const struct nlist_64
**sym1
,
5391 const struct nlist_64
**sym2
)
5393 return(strcmp(global_strings
+ (*sym1
)->n_un
.n_strx
,
5394 global_strings
+ (*sym2
)->n_un
.n_strx
));
5398 * Function for bsearch for finding a global symbol that matches a stab name.
5402 cmp_bsearch_global_stab(
5404 const struct nlist
**sym
)
5407 * The +1 is for the '_' on the global symbol that is not on the
5408 * stab string that is trying to be matched.
5410 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
+ 1));
5415 cmp_bsearch_global_stab_64(
5417 const struct nlist_64
**sym
)
5420 * The +1 is for the '_' on the global symbol that is not on the
5421 * stab string that is trying to be matched.
5423 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
+ 1));
5427 * Function for bsearch for finding a global symbol that matches a stab name
5434 const struct nlist
**sym
)
5436 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
));
5441 cmp_bsearch_global_64(
5443 const struct nlist_64
**sym
)
5445 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
));
5447 #endif /* defined(NMEDIT) */