2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * The strip(1) and nmedit(l) program. This understands only Mach-O format
25 * files (with the restriction the symbol table is at the end of the file) and
26 * fat files with Mach-O files in them.
34 #include <sys/types.h>
36 #include <mach-o/loader.h>
37 #include <mach-o/reloc.h>
38 #include <mach-o/nlist.h>
39 #include <mach-o/stab.h>
40 #include "stuff/breakout.h"
41 #include "stuff/allocate.h"
42 #include "stuff/errors.h"
43 #include "stuff/rnd.h"
44 #include "stuff/reloc.h"
45 #include "stuff/reloc.h"
46 #include "stuff/symbol_list.h"
47 #include "stuff/unix_standard_mode.h"
48 #include "stuff/execute.h"
50 #include <mach-o/prune_trie.h>
51 #endif /* TRIE_SUPPORT */
53 typedef struct dylib_name_s
{
54 struct dylib_name_s
*next
;
58 /* These are set from the command line arguments */
60 char *progname
= NULL
; /* name of the program for error messages (argv[0]) */
61 static char *output_file
;/* name of the output file */
62 static char *sfile
; /* filename of global symbol names to keep */
63 static char *Rfile
; /* filename of global symbol names to remove */
64 static uint32_t Aflag
; /* save only absolute symbols with non-zero value and
65 .objc_class_name_* symbols */
66 static uint32_t aflag
; /* -a save all symbols, just regenerate symbol table */
67 static uint32_t iflag
; /* -i ignore symbols in -s file not in object */
69 static uint32_t pflag
; /* make all defined global symbols private extern */
70 #else /* !defined(NMEDIT) */
71 static char *dfile
; /* filename of filenames of debugger symbols to keep */
72 static uint32_t uflag
; /* save undefined symbols */
73 static uint32_t rflag
; /* save symbols referenced dynamically */
74 static uint32_t nflag
; /* save N_SECT global symbols */
75 static uint32_t Sflag
; /* -S strip only debugger symbols N_STAB */
76 static uint32_t xflag
; /* -x strip non-globals */
77 static uint32_t Xflag
; /* -X strip local symbols with 'L' names */
78 static uint32_t tflag
; /* -t strip local symbols except those in the text
79 section with names that don't begin with 'L' */
80 static uint32_t cflag
; /* -c strip section contents from dynamic libraries
81 files to create stub libraries */
82 static uint32_t no_uuid
;/* -no_uuid strip LC_UUID load commands */
83 static uint32_t no_code_signature
;
84 /* -no_code_signature strip LC_CODE_SIGNATURE cmds */
85 static dylib_name
*no_dylib
;
86 /* -no_dylib options (zero or more) */
87 static uint32_t no_dylib_unused
;
88 /* strip unused dylib references */
89 static uint32_t vflag
; /* -v for verbose debugging ld -r executions */
90 static uint32_t lflag
; /* -l do ld -r executions even if it has bugs */
91 static uint32_t strip_all
= 1;
93 * This is set on an object by object basis if the strip_all flag is still set
94 * and the object is an executable that is for use with the dynamic linker.
95 * This has the same effect as -r and -u.
97 static enum bool default_dyld_executable
= FALSE
;
101 * Data structures to perform selective stripping of symbol table entries.
102 * save_symbols is the names of the symbols from the -s <file> argument.
103 * remove_symbols is the names of the symbols from the -R <file> argument.
105 static struct symbol_list
*save_symbols
= NULL
;
106 static uint32_t nsave_symbols
= 0;
107 static struct symbol_list
*remove_symbols
= NULL
;
108 static uint32_t nremove_symbols
= 0;
111 * saves points to an array of uint32_t's that is allocated. This array is a
112 * map of old symbol indexes to new symbol indexes. The new symbol indexes are
113 * plus 1 and zero value means that old symbol is not in the new symbol table.
114 * ref_saves is used in the same way but for the reference table.
115 * nmedits is an array and indexed by the symbol index the value indicates if
116 * the symbol was edited and turned into a non-global.
118 static int32_t *saves
= NULL
;
120 static int32_t *ref_saves
= NULL
;
122 static enum bool *nmedits
= NULL
;
126 * These hold pointers to the symbol, string and indirect tables being worked on
127 * by strip_object and strip_symtab() from an input object file or possiblity
128 * changed to an ld -r (-S or -x) file by make_ld_r_object().
130 static struct nlist
*symbols
= NULL
;
131 static struct nlist_64
*symbols64
= NULL
;
132 static uint32_t nsyms
= 0;
133 static char *strings
= NULL
;
134 static uint32_t strsize
= 0;
135 static uint32_t *indirectsyms
= NULL
;
136 static uint32_t nindirectsyms
= 0;
139 * These hold the new symbol and string table created by strip_symtab()
140 * and the new counts of local, defined external and undefined symbols.
142 static struct nlist
*new_symbols
= NULL
;
143 static struct nlist_64
*new_symbols64
= NULL
;
144 static uint32_t new_nsyms
= 0;
145 static char *new_strings
= NULL
;
146 static uint32_t new_strsize
= 0;
147 static uint32_t new_nlocalsym
= 0;
148 static uint32_t new_nextdefsym
= 0;
149 static uint32_t new_nundefsym
= 0;
150 #if defined(TRIE_SUPPORT) && !defined(NMEDIT)
152 * The index into the new symbols where the defined external start.
154 static uint32_t inew_nextdefsym
= 0;
158 * These hold the new table of contents, reference table and module table for
161 static struct dylib_table_of_contents
*new_tocs
= NULL
;
162 static uint32_t new_ntoc
= 0;
163 static struct dylib_reference
*new_refs
= NULL
;
164 static uint32_t new_nextrefsyms
= 0;
166 static struct dylib_module
*new_mods
= NULL
;
167 static struct dylib_module_64
*new_mods64
= NULL
;
168 static uint32_t new_nmodtab
= 0;
173 * The list of file names to save debugging symbols from.
175 static char **debug_filenames
= NULL
;
176 static uint32_t ndebug_filenames
= 0;
183 struct nlist_64 symbol64
;
185 static char *qsort_strings
= NULL
;
186 #endif /* !defined(NMEDIT) */
189 /* Internal routines */
193 static void strip_file(
195 struct arch_flag
*arch_flags
,
196 uint32_t narch_flags
,
197 enum bool all_archs
);
199 static void strip_arch(
202 struct arch_flag
*arch_flags
,
203 uint32_t narch_flags
,
204 enum bool all_archs
);
206 static void strip_object(
208 struct member
*member
,
209 struct object
*object
);
211 static uint32_t get_starting_syminfo_offset(
212 struct object
*object
);
214 static void check_object_relocs(
216 struct member
*member
,
217 struct object
*object
,
222 struct relocation_info
*relocs
,
224 struct nlist
*symbols
,
225 struct nlist_64
*symbols64
,
228 int32_t *missing_reloc_symbols
,
229 enum byte_sex host_byte_sex
);
231 static void check_indirect_symtab(
233 struct member
*member
,
234 struct object
*object
,
237 uint32_t section_type
,
239 struct nlist
*symbols
,
240 struct nlist_64
*symbols64
,
243 int32_t *missing_reloc_symbols
,
244 enum byte_sex host_byte_sex
);
247 static enum bool strip_symtab(
249 struct member
*member
,
250 struct object
*object
,
251 struct dylib_table_of_contents
*tocs
,
253 struct dylib_module
*mods
,
254 struct dylib_module_64
*mods64
,
256 struct dylib_reference
*refs
,
257 uint32_t nextrefsyms
);
262 #endif /* TRIE_SUPPORT */
264 static void make_ld_r_object(
266 struct member
*member
,
267 struct object
*object
);
269 static void strip_LC_UUID_commands(
271 struct member
*member
,
272 struct object
*object
);
274 static void strip_LC_DYLIB_commands(
276 struct member
*member
,
277 struct object
*object
);
280 static void strip_LC_CODE_SIGNATURE_commands(
282 struct member
*member
,
283 struct object
*object
);
284 #endif /* !(NMEDIT) */
286 static enum bool private_extern_reference_by_module(
287 uint32_t symbol_index
,
288 struct dylib_reference
*refs
,
289 uint32_t nextrefsyms
);
291 static enum bool symbol_pointer_used(
292 uint32_t symbol_index
,
293 uint32_t *indirectsyms
,
294 uint32_t nindirectsyms
);
296 static int cmp_qsort_undef_map(
297 const struct undef_map
*sym1
,
298 const struct undef_map
*sym2
);
300 static int cmp_qsort_undef_map_64(
301 const struct undef_map64
*sym1
,
302 const struct undef_map64
*sym2
);
303 #endif /* !defined(NMEDIT) */
306 static enum bool edit_symtab(
308 struct member
*member
,
309 struct object
*object
,
310 struct nlist
*symbols
,
311 struct nlist_64
*symbols64
,
315 struct dylib_table_of_contents
*tocs
,
317 struct dylib_module
*mods
,
318 struct dylib_module_64
*mods64
,
320 struct dylib_reference
*refs
,
321 uint32_t nextrefsyms
);
325 static void setup_debug_filenames(
328 static int cmp_qsort_filename(
332 static int cmp_bsearch_filename(
339 * This variable and routines are used for nmedit(1) only.
341 static char *global_strings
= NULL
;
343 static int cmp_qsort_global(
344 const struct nlist
**sym1
,
345 const struct nlist
**sym2
);
347 static int cmp_qsort_global_64(
348 const struct nlist_64
**sym1
,
349 const struct nlist_64
**sym2
);
351 static int cmp_bsearch_global_stab(
353 const struct nlist
**sym
);
355 static int cmp_bsearch_global_stab_64(
357 const struct nlist_64
**sym
);
359 static int cmp_bsearch_global(
361 const struct nlist
**sym
);
363 static int cmp_bsearch_global_64(
365 const struct nlist_64
**sym
);
368 /* apple_version is created by the libstuff/Makefile */
369 extern char apple_version
[];
370 char *version
= apple_version
;
379 uint32_t j
, args_left
, files_specified
;
380 struct arch_flag
*arch_flags
;
381 uint32_t narch_flags
;
383 struct symbol_list
*sp
;
393 for (i
= 1; i
< argc
; i
++){
394 if(argv
[i
][0] == '-'){
395 if(argv
[i
][1] == '\0'){
399 if(strcmp(argv
[i
], "-o") == 0){
401 fatal("-o requires an argument");
402 if(output_file
!= NULL
)
403 fatal("only one -o option allowed");
404 output_file
= argv
[i
+ 1];
407 else if(strcmp(argv
[i
], "-s") == 0){
409 fatal("-s requires an argument");
411 fatal("only one -s option allowed");
415 else if(strcmp(argv
[i
], "-R") == 0){
417 fatal("-R requires an argument");
419 fatal("only one -R option allowed");
424 else if(strcmp(argv
[i
], "-d") == 0){
426 fatal("-d requires an argument");
428 fatal("only one -d option allowed");
432 else if(strcmp(argv
[i
], "-no_uuid") == 0){
435 else if(strcmp(argv
[i
], "-no_dylib") == 0){
438 fatal("-no_dylib requires an argument");
439 dname
= (dylib_name
*)malloc(sizeof(dylib_name
));
441 fatal("out of memory (malloc failed)");
442 dname
->next
= no_dylib
;
443 dname
->name
= argv
[i
+ 1];
447 else if(strcmp(argv
[i
], "-no_dylib_unused") == 0){
450 else if(strcmp(argv
[i
], "-no_code_signature") == 0){
451 no_code_signature
= 1;
453 #endif /* !defined(NMEDIT) */
454 else if(strcmp(argv
[i
], "-arch") == 0){
456 error("missing argument(s) to %s option", argv
[i
]);
459 if(strcmp("all", argv
[i
+1]) == 0){
463 arch_flags
= reallocate(arch_flags
,
464 (narch_flags
+ 1) * sizeof(struct arch_flag
));
465 if(get_arch_from_flag(argv
[i
+1],
466 arch_flags
+ narch_flags
) == 0){
467 error("unknown architecture specification flag: "
468 "%s %s", argv
[i
], argv
[i
+1]);
472 for(j
= 0; j
< narch_flags
; j
++){
473 if(arch_flags
[j
].cputype
==
474 arch_flags
[narch_flags
].cputype
&&
475 (arch_flags
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
476 (arch_flags
[narch_flags
].cpusubtype
&
477 ~CPU_SUBTYPE_MASK
) &&
478 strcmp(arch_flags
[j
].name
,
479 arch_flags
[narch_flags
].name
) == 0)
488 for(j
= 1; argv
[i
][j
] != '\0'; j
++){
494 #else /* !defined(NMEDIT) */
526 #endif /* !defined(NMEDIT) */
531 #endif /* !defined(NMEDIT) */
550 error("unrecognized option: %s", argv
[i
]);
560 files_specified
+= argc
- (i
+ 1);
562 if(files_specified
> 1 && output_file
!= NULL
){
563 error("-o <filename> can only be used when one file is specified");
568 setup_symbol_list(sfile
, &save_symbols
, &nsave_symbols
);
572 if(Rfile
== NULL
&& pflag
== 0){
573 error("-s <filename>, -R <filename> or -p argument required");
580 setup_symbol_list(Rfile
, &remove_symbols
, &nremove_symbols
);
582 for(j
= 0; j
< nremove_symbols
; j
++){
583 sp
= bsearch(remove_symbols
[j
].name
,
584 save_symbols
, nsave_symbols
,
585 sizeof(struct symbol_list
),
586 (int (*)(const void *, const void *))
587 symbol_list_bsearch
);
589 error("symbol name: %s is listed in both -s %s and -R "
590 "%s files (can't be both saved and removed)",
591 remove_symbols
[j
].name
, sfile
, Rfile
);
599 /* the default when no -arch flags is present is to strip all archs */
605 setup_debug_filenames(dfile
);
607 #endif /* !defined(NMEDIT) */
611 for (i
= 1; i
< argc
; i
++) {
612 if(args_left
&& argv
[i
][0] == '-'){
613 if(argv
[i
][1] == '\0')
615 else if(strcmp(argv
[i
], "-o") == 0 ||
616 strcmp(argv
[i
], "-s") == 0 ||
617 strcmp(argv
[i
], "-R") == 0 ||
619 strcmp(argv
[i
], "-d") == 0 ||
620 strcmp(argv
[i
], "-no_dylib") == 0 ||
621 #endif /* !defined(NMEDIT) */
622 strcmp(argv
[i
], "-arch") == 0)
626 char resolved_path
[PATH_MAX
+ 1];
628 if(realpath(argv
[i
], resolved_path
) == NULL
)
629 strip_file(argv
[i
], arch_flags
, narch_flags
, all_archs
);
631 strip_file(resolved_path
, arch_flags
,narch_flags
,all_archs
);
635 if(files_specified
== 0)
636 fatal("no files specified");
639 return(EXIT_FAILURE
);
641 return(EXIT_SUCCESS
);
650 fprintf(stderr
, "Usage: %s [-AanuStXx] [-no_uuid] [-no_code_signature] "
651 "[-no_dylib filename] [-no_dylib_unused] [-] [-d filename] "
652 "[-s filename] [-R filename] [-o output] file [...]\n",
654 #else /* defined(NMEDIT) */
655 fprintf(stderr
, "Usage: %s -s filename [-R filename] [-p] [-A] [-] "
656 "[-o output] file [...] \n",
666 struct arch_flag
*arch_flags
,
667 uint32_t narch_flags
,
673 struct stat stat_buf
;
674 uint32_t previous_errors
;
675 enum bool unix_standard_mode
;
684 previous_errors
= errors
;
687 /* breakout the file for processing */
688 ofile
= breakout(input_file
, &archs
, &narchs
, FALSE
);
692 /* checkout the file for symbol table replacement processing */
693 checkout(archs
, narchs
);
695 /* process the symbols in the input file */
696 strip_arch(archs
, narchs
, arch_flags
, narch_flags
, all_archs
);
698 free_archs(archs
, narchs
);
703 /* create the output file */
704 if(stat(input_file
, &stat_buf
) == -1)
705 system_error("can't stat input file: %s", input_file
);
706 if(output_file
!= NULL
){
707 writeout(archs
, narchs
, output_file
, stat_buf
.st_mode
& 0777,
708 TRUE
, FALSE
, FALSE
, NULL
);
711 unix_standard_mode
= get_unix_standard_mode();
715 output_file
= makestr(input_file
, ".nmedit", NULL
);
716 #else /* !defined(NMEDIT) */
718 * In UNIX standard conformance mode we are not allowed to replace
719 * a file that is not writeable.
721 if(unix_standard_mode
== TRUE
&&
722 access(input_file
, W_OK
) == -1){
723 system_error("file: %s is not writable", input_file
);
724 goto strip_file_return
;
726 output_file
= makestr(input_file
, ".strip", NULL
);
729 * The UNIX standard conformance test suite expects files of
730 * MAXPATHLEN to work.
732 if(strlen(output_file
) >= MAXPATHLEN
){
734 * If there is a directory path in the name try to change
735 * the current working directory to that path.
737 if((p
= rindex(output_file
, '/')) != NULL
){
738 if((cwd_fd
= open(".", O_RDONLY
, 0)) == -1){
739 system_error("can't open current working directory");
740 goto strip_file_return
;
743 if(chdir(output_file
) == -1){
744 system_error("can't change current working directory "
745 "to: %s", output_file
);
746 goto strip_file_return
;
748 p
= rindex(input_file
, '/');
749 rename_file
= makestr(p
+ 1, NULL
);
752 * Create what might be a short enough name.
755 output_file
= makestr("strip.XXXXXX", NULL
);
756 output_file
= mktemp(output_file
);
759 writeout(archs
, narchs
, output_file
, stat_buf
.st_mode
& 0777,
760 TRUE
, FALSE
, FALSE
, NULL
);
761 if(rename_file
!= NULL
){
762 if(rename(output_file
, rename_file
) == -1)
763 system_error("can't move temporary file: %s to file: %s",
764 output_file
, rename_file
);
768 if(rename(output_file
, input_file
) == -1)
769 system_error("can't move temporary file: %s to input "
770 "file: %s", output_file
, input_file
);
776 * If we changed the current working directory change back to
777 * the previous working directory.
780 if(fchdir(cwd_fd
) == -1)
781 system_error("can't change back to previous working "
783 if(close(cwd_fd
) == -1)
784 system_error("can't close previous working directory");
790 #endif /* !defined(NMEDIT) */
791 /* clean-up data structures */
792 free_archs(archs
, narchs
);
795 errors
+= previous_errors
;
803 struct arch_flag
*arch_flags
,
804 uint32_t narch_flags
,
807 uint32_t i
, j
, k
, offset
, size
, missing_syms
;
809 cpu_subtype_t cpusubtype
;
810 struct arch_flag host_arch_flag
;
811 enum bool arch_process
, any_processing
, *arch_flag_processed
, family
;
812 const struct arch_flag
*family_arch_flag
;
815 * Using the specified arch_flags process specified objects for those
818 any_processing
= FALSE
;
819 arch_flag_processed
= NULL
;
821 arch_flag_processed
= allocate(narch_flags
* sizeof(enum bool));
822 memset(arch_flag_processed
, '\0', narch_flags
* sizeof(enum bool));
823 for(i
= 0; i
< narchs
; i
++){
825 * Determine the architecture (cputype and cpusubtype) of arch[i]
829 if(archs
[i
].type
== OFILE_ARCHIVE
){
830 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
831 if(archs
[i
].members
[j
].type
== OFILE_Mach_O
){
832 cputype
= archs
[i
].members
[j
].object
->mh_cputype
;
833 cpusubtype
= archs
[i
].members
[j
].object
->mh_cpusubtype
;
838 else if(archs
[i
].type
== OFILE_Mach_O
){
839 cputype
= archs
[i
].object
->mh_cputype
;
840 cpusubtype
= archs
[i
].object
->mh_cpusubtype
;
842 else if(archs
[i
].fat_arch
!= NULL
){
843 cputype
= archs
[i
].fat_arch
->cputype
;
844 cpusubtype
= archs
[i
].fat_arch
->cpusubtype
;
846 arch_process
= FALSE
;
847 if(all_archs
== TRUE
){
850 else if(narch_flags
!= 0){
852 if(narch_flags
== 1){
854 get_arch_family_from_cputype(arch_flags
[0].cputype
);
855 if(family_arch_flag
!= NULL
)
857 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
858 (arch_flags
[0].cpusubtype
& ~CPU_SUBTYPE_MASK
));
860 for(j
= 0; j
< narch_flags
; j
++){
861 if(arch_flags
[j
].cputype
== cputype
&&
862 ((arch_flags
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
863 (cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
866 arch_flag_processed
[j
] = TRUE
;
872 (void)get_arch_from_host(&host_arch_flag
, NULL
);
873 if(host_arch_flag
.cputype
== cputype
&&
874 (host_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
875 (cpusubtype
& ~CPU_SUBTYPE_MASK
))
878 if(narchs
!= 1 && arch_process
== FALSE
)
880 any_processing
= TRUE
;
883 * Now this arch[i] has been selected to be processed so process it
884 * according to its type.
886 if(archs
[i
].type
== OFILE_ARCHIVE
){
887 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
888 if(archs
[i
].members
[j
].type
== OFILE_Mach_O
){
889 strip_object(archs
+ i
, archs
[i
].members
+ j
,
890 archs
[i
].members
[j
].object
);
895 for(k
= 0; k
< nsave_symbols
; k
++){
896 if(save_symbols
[k
].seen
== FALSE
){
897 if(missing_syms
== 0){
898 error_arch(archs
+ i
, NULL
, "symbols names "
899 "listed in: %s not in: ", sfile
);
902 fprintf(stderr
, "%s\n", save_symbols
[k
].name
);
906 for(k
= 0; k
< nsave_symbols
; k
++){
907 save_symbols
[k
].seen
= FALSE
;
911 for(k
= 0; k
< nremove_symbols
; k
++){
912 if(remove_symbols
[k
].seen
== FALSE
){
913 if(missing_syms
== 0){
914 error_arch(archs
+ i
, NULL
, "symbols names "
915 "listed in: %s not defined in: ",
919 fprintf(stderr
, "%s\n", remove_symbols
[k
].name
);
923 for(k
= 0; k
< nremove_symbols
; k
++){
924 remove_symbols
[k
].seen
= FALSE
;
927 * Reset the library offsets and size.
930 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
931 archs
[i
].members
[j
].offset
= offset
;
933 if(archs
[i
].members
[j
].member_long_name
== TRUE
){
934 size
= rnd(archs
[i
].members
[j
].member_name_size
, 8) +
935 (rnd(sizeof(struct ar_hdr
), 8) -
936 sizeof(struct ar_hdr
));
937 archs
[i
].toc_long_name
= TRUE
;
939 if(archs
[i
].members
[j
].object
!= NULL
){
941 rnd(archs
[i
].members
[j
].object
->object_size
-
942 archs
[i
].members
[j
].object
->input_sym_info_size
+
943 archs
[i
].members
[j
].object
->output_sym_info_size
,
945 sprintf(archs
[i
].members
[j
].ar_hdr
->ar_size
, "%-*ld",
946 (int)sizeof(archs
[i
].members
[j
].ar_hdr
->ar_size
),
949 * This has to be done by hand because sprintf puts a
950 * null at the end of the buffer.
952 memcpy(archs
[i
].members
[j
].ar_hdr
->ar_fmag
, ARFMAG
,
953 (int)sizeof(archs
[i
].members
[j
].ar_hdr
->ar_fmag
));
956 size
+= archs
[i
].members
[j
].unknown_size
;
958 offset
+= sizeof(struct ar_hdr
) + size
;
960 archs
[i
].library_size
= offset
;
962 else if(archs
[i
].type
== OFILE_Mach_O
){
963 strip_object(archs
+ i
, NULL
, archs
[i
].object
);
966 warning_arch(archs
+ i
, NULL
, "can't process non-object and "
967 "non-archive file: ");
971 if(all_archs
== FALSE
&& narch_flags
!= 0){
972 for(i
= 0; i
< narch_flags
; i
++){
973 if(arch_flag_processed
[i
] == FALSE
)
974 error("file: %s does not contain architecture: %s",
975 archs
[0].file_name
, arch_flags
[i
].name
);
977 free(arch_flag_processed
);
979 if(any_processing
== FALSE
)
980 fatal("no processing done on input file: %s (specify a -arch flag)",
988 struct member
*member
,
989 struct object
*object
)
991 enum byte_sex host_byte_sex
;
993 struct dylib_table_of_contents
*tocs
;
995 struct dylib_module
*mods
;
996 struct dylib_module_64
*mods64
;
998 struct dylib_reference
*refs
;
999 uint32_t nextrefsyms
;
1001 struct load_command
*lc
;
1002 struct segment_command
*sg
;
1003 struct segment_command_64
*sg64
;
1005 struct section_64
*s64
;
1006 struct relocation_info
*relocs
;
1007 struct scattered_relocation_info
*sreloc
;
1008 int32_t missing_reloc_symbols
;
1009 uint32_t stride
, section_type
, nitems
;
1011 uint32_t dyld_info_start
;
1012 uint32_t dyld_info_end
;
1019 host_byte_sex
= get_host_byte_sex();
1021 /* Don't do anything to stub dylibs which have no load commands. */
1022 if(object
->mh_filetype
== MH_DYLIB_STUB
){
1023 if((object
->mh
!= NULL
&& object
->mh
->ncmds
== 0) ||
1024 (object
->mh64
!= NULL
&& object
->mh64
->ncmds
== 0)){
1028 if(object
->mh_filetype
== MH_DSYM
)
1029 fatal_arch(arch
, member
, "can't process dSYM companion file: ");
1030 if(object
->st
== NULL
|| object
->st
->nsyms
== 0){
1031 warning_arch(arch
, member
, "input object file stripped: ");
1035 nsyms
= object
->st
->nsyms
;
1036 if(object
->mh
!= NULL
){
1037 symbols
= (struct nlist
*)
1038 (object
->object_addr
+ object
->st
->symoff
);
1039 if(object
->object_byte_sex
!= host_byte_sex
)
1040 swap_nlist(symbols
, nsyms
, host_byte_sex
);
1045 symbols64
= (struct nlist_64
*)
1046 (object
->object_addr
+ object
->st
->symoff
);
1047 if(object
->object_byte_sex
!= host_byte_sex
)
1048 swap_nlist_64(symbols64
, nsyms
, host_byte_sex
);
1050 strings
= object
->object_addr
+ object
->st
->stroff
;
1051 strsize
= object
->st
->strsize
;
1054 if(object
->mh
!= NULL
)
1055 flags
= object
->mh
->flags
;
1057 flags
= object
->mh64
->flags
;
1058 if(object
->mh_filetype
== MH_DYLIB
&&
1059 (flags
& MH_PREBOUND
) != MH_PREBOUND
){
1060 arch
->dont_update_LC_ID_DYLIB_timestamp
= TRUE
;
1062 if(object
->mh_filetype
!= MH_DYLIB
&& cflag
)
1063 fatal_arch(arch
, member
, "-c can't be used on non-dynamic "
1065 #endif /* !(NMEDIT) */
1066 if(object
->mh_filetype
== MH_DYLIB_STUB
)
1067 fatal_arch(arch
, member
, "dynamic stub library can't be changed "
1070 if(object
->mh_filetype
== MH_DYLIB
){
1071 tocs
= (struct dylib_table_of_contents
*)
1072 (object
->object_addr
+ object
->dyst
->tocoff
);
1073 ntoc
= object
->dyst
->ntoc
;
1074 nmodtab
= object
->dyst
->nmodtab
;
1075 if(object
->mh
!= NULL
){
1076 mods
= (struct dylib_module
*)
1077 (object
->object_addr
+ object
->dyst
->modtaboff
);
1078 if(object
->object_byte_sex
!= host_byte_sex
)
1079 swap_dylib_module(mods
, nmodtab
, host_byte_sex
);
1084 mods64
= (struct dylib_module_64
*)
1085 (object
->object_addr
+ object
->dyst
->modtaboff
);
1086 if(object
->object_byte_sex
!= host_byte_sex
)
1087 swap_dylib_module_64(mods64
, nmodtab
, host_byte_sex
);
1089 refs
= (struct dylib_reference
*)
1090 (object
->object_addr
+ object
->dyst
->extrefsymoff
);
1091 nextrefsyms
= object
->dyst
->nextrefsyms
;
1092 if(object
->object_byte_sex
!= host_byte_sex
){
1093 swap_dylib_table_of_contents(tocs
, ntoc
, host_byte_sex
);
1094 swap_dylib_reference(refs
, nextrefsyms
, host_byte_sex
);
1098 * In the -c flag is specified then strip the section contents of
1099 * this dynamic library and change it into a stub library. When
1100 * creating a stub library the timestamp is not changed.
1103 arch
->dont_update_LC_ID_DYLIB_timestamp
= TRUE
;
1105 lc
= object
->load_commands
;
1106 if(object
->mh
!= NULL
){
1107 ncmds
= object
->mh
->ncmds
;
1108 object
->mh_filetype
= MH_DYLIB_STUB
;
1109 object
->mh
->filetype
= MH_DYLIB_STUB
;
1112 ncmds
= object
->mh64
->ncmds
;
1113 object
->mh_filetype
= MH_DYLIB_STUB
;
1114 object
->mh64
->filetype
= MH_DYLIB_STUB
;
1116 for(i
= 0; i
< ncmds
; i
++){
1117 if(lc
->cmd
== LC_SEGMENT
){
1118 sg
= (struct segment_command
*)lc
;
1119 if(strcmp(sg
->segname
, SEG_LINKEDIT
) != 0){
1121 * Zero out the section offset, reloff, and size
1122 * fields as the section contents are being removed.
1124 s
= (struct section
*)
1125 ((char *)sg
+ sizeof(struct segment_command
));
1126 for(j
= 0; j
< sg
->nsects
; j
++){
1128 * For section types with indirect tables we
1129 * do not zero out the section size in a stub
1130 * library. As the section size is needed to
1131 * know now many indirect table entries the
1132 * section has. This is a bit odd but programs
1133 * dealing with MH_DYLIB_STUB filetypes special
1136 section_type
= s
[j
].flags
& SECTION_TYPE
;
1137 if(section_type
!= S_SYMBOL_STUBS
&&
1138 section_type
!= S_LAZY_SYMBOL_POINTERS
&&
1139 section_type
!= S_LAZY_DYLIB_SYMBOL_POINTERS
&&
1140 section_type
!= S_NON_LAZY_SYMBOL_POINTERS
){
1147 /* zero out file offset and size in the segment */
1152 else if(lc
->cmd
== LC_SEGMENT_64
){
1153 sg64
= (struct segment_command_64
*)lc
;
1154 if(strcmp(sg64
->segname
, SEG_LINKEDIT
) != 0){
1156 * Zero out the section offset, reloff, and size
1157 * fields as the section contents are being removed.
1159 s64
= (struct section_64
*)
1161 sizeof(struct segment_command_64
));
1162 for(j
= 0; j
< sg64
->nsects
; j
++){
1164 * For section types with indirect tables we
1165 * do not zero out the section size in a stub
1166 * library. As the section size is needed to
1167 * know now many indirect table entries the
1168 * section has. This is a bit odd but programs
1169 * dealing with MH_DYLIB_STUB filetypes special
1172 section_type
= s64
[j
].flags
& SECTION_TYPE
;
1173 if(section_type
!= S_SYMBOL_STUBS
&&
1174 section_type
!= S_LAZY_SYMBOL_POINTERS
&&
1175 section_type
!= S_LAZY_DYLIB_SYMBOL_POINTERS
&&
1176 section_type
!= S_NON_LAZY_SYMBOL_POINTERS
){
1183 /* zero out file offset and size in the segment */
1188 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1191 * To get the right amount of the file copied out by writeout()
1192 * for the case when we are stripping out the section contents
1193 * we reduce the object size by the size of the section contents
1194 * including the padding after the load commands. Then this
1195 * size minus the size of the input symbolic information is
1198 if(object
->mh
!= NULL
){
1199 object
->object_size
-= (object
->seg_linkedit
->fileoff
-
1200 (sizeof(struct mach_header
) +
1201 object
->mh
->sizeofcmds
));
1203 * Set the file offset to the link edit information to be
1204 * right after the load commands.
1206 object
->seg_linkedit
->fileoff
=
1207 sizeof(struct mach_header
) +
1208 object
->mh
->sizeofcmds
;
1211 object
->object_size
-= (object
->seg_linkedit64
->fileoff
-
1212 (sizeof(struct mach_header_64
) +
1213 object
->mh64
->sizeofcmds
));
1215 * Set the file offset to the link edit information to be
1216 * right after the load commands.
1218 object
->seg_linkedit64
->fileoff
=
1219 sizeof(struct mach_header_64
) +
1220 object
->mh64
->sizeofcmds
;
1223 #endif /* !(NMEDIT) */
1236 * coalesced symbols can be stripped only if they are not used via an
1237 * symbol pointer. So to know that strip_symtab() needs to be passed
1238 * the indirect symbol table.
1240 if(object
->dyst
!= NULL
&& object
->dyst
->nindirectsyms
!= 0){
1241 nindirectsyms
= object
->dyst
->nindirectsyms
;
1242 indirectsyms
= (uint32_t *)
1243 (object
->object_addr
+ object
->dyst
->indirectsymoff
);
1244 if(object
->object_byte_sex
!= host_byte_sex
)
1245 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
1249 indirectsyms
= NULL
;
1253 if(object
->mh
!= NULL
)
1254 object
->input_sym_info_size
=
1255 nsyms
* sizeof(struct nlist
) +
1258 object
->input_sym_info_size
=
1259 nsyms
* sizeof(struct nlist_64
) +
1262 if(object
->mh
!= NULL
)
1263 flags
= object
->mh
->flags
;
1265 flags
= object
->mh64
->flags
;
1267 (flags
& MH_DYLDLINK
) == MH_DYLDLINK
&&
1268 object
->mh_filetype
== MH_EXECUTE
)
1269 default_dyld_executable
= TRUE
;
1271 default_dyld_executable
= FALSE
;
1272 #endif /* !defined(NMEDIT) */
1275 if(sfile
!= NULL
|| Rfile
!= NULL
|| dfile
!= NULL
|| Aflag
|| aflag
||
1276 uflag
|| Sflag
|| xflag
|| Xflag
|| tflag
|| nflag
|| rflag
||
1277 default_dyld_executable
|| object
->mh_filetype
== MH_DYLIB
||
1278 object
->mh_filetype
== MH_DYLINKER
)
1279 #endif /* !defined(NMEDIT) */
1282 if(edit_symtab(arch
, member
, object
, symbols
, symbols64
, nsyms
,
1283 strings
, strsize
, tocs
, ntoc
, mods
, mods64
, nmodtab
, refs
,
1284 nextrefsyms
) == FALSE
)
1286 #else /* !defined(NMEDIT) */
1287 if(strip_symtab(arch
, member
, object
, tocs
, ntoc
, mods
, mods64
,
1288 nmodtab
, refs
, nextrefsyms
) == FALSE
)
1291 strip_LC_UUID_commands(arch
, member
, object
);
1292 if(no_dylib
|| no_dylib_unused
)
1293 strip_LC_DYLIB_commands(arch
, member
, object
);
1294 #endif /* !defined(NMEDIT) */
1296 * The parts that make up output_sym_info_size must be added up in
1297 * the output order so that when the sizes of things are rounded up
1298 * before parts that must be aligned the final output_sym_info_size
1301 * Also the parts that make up input_sym_info_size must be added up
1302 * in the same way. And must be done here as the input file may
1303 * have been changed to and "ld -r" file and may not be the
1304 * the original input file.
1306 object
->output_sym_info_size
= 0;
1307 object
->input_sym_info_size
= 0;
1308 if(object
->dyld_info
!= NULL
){
1309 /* there are five parts to the dyld info, but
1310 strip does not alter them, so copy as a block */
1311 dyld_info_start
= 0;
1312 if (object
->dyld_info
->rebase_off
!= 0)
1313 dyld_info_start
= object
->dyld_info
->rebase_off
;
1314 else if (object
->dyld_info
->bind_off
!= 0)
1315 dyld_info_start
= object
->dyld_info
->bind_off
;
1316 else if (object
->dyld_info
->weak_bind_off
!= 0)
1317 dyld_info_start
= object
->dyld_info
->weak_bind_off
;
1318 else if (object
->dyld_info
->lazy_bind_off
!= 0)
1319 dyld_info_start
= object
->dyld_info
->lazy_bind_off
;
1320 else if (object
->dyld_info
->export_off
!= 0)
1321 dyld_info_start
= object
->dyld_info
->export_off
;
1323 if (object
->dyld_info
->export_size
!= 0)
1324 dyld_info_end
= object
->dyld_info
->export_off
1325 + object
->dyld_info
->export_size
;
1326 else if (object
->dyld_info
->lazy_bind_size
!= 0)
1327 dyld_info_end
= object
->dyld_info
->lazy_bind_off
1328 + object
->dyld_info
->lazy_bind_size
;
1329 else if (object
->dyld_info
->weak_bind_size
!= 0)
1330 dyld_info_end
= object
->dyld_info
->weak_bind_off
1331 + object
->dyld_info
->weak_bind_size
;
1332 else if (object
->dyld_info
->bind_size
!= 0)
1333 dyld_info_end
= object
->dyld_info
->bind_off
1334 + object
->dyld_info
->bind_size
;
1335 else if (object
->dyld_info
->rebase_size
!= 0)
1336 dyld_info_end
= object
->dyld_info
->rebase_off
1337 + object
->dyld_info
->rebase_size
;
1338 object
->output_dyld_info
= object
->object_addr
+dyld_info_start
;
1339 object
->output_dyld_info_size
= dyld_info_end
- dyld_info_start
;
1340 object
->output_sym_info_size
+= object
->output_dyld_info_size
;
1342 * Warn about strip -s or -R on a final linked image with
1345 if(nsave_symbols
!= 0){
1346 warning_arch(arch
, NULL
, "removing global symbols from a "
1347 "final linked no longer supported. Use "
1348 "-exported_symbols_list at link time when "
1351 object
->input_sym_info_size
+= object
->dyld_info
->rebase_size
1352 + object
->dyld_info
->bind_size
1353 + object
->dyld_info
->weak_bind_size
1354 + object
->dyld_info
->lazy_bind_size
1355 + object
->dyld_info
->export_size
;
1358 if(object
->dyst
!= NULL
){
1361 * When stripping out the section contents to create a
1362 * dynamic library stub the relocation info also gets
1366 #endif /* !(NMEDIT) */
1368 object
->output_sym_info_size
+=
1369 object
->dyst
->nlocrel
* sizeof(struct relocation_info
);
1371 object
->input_sym_info_size
+=
1372 object
->dyst
->nlocrel
* sizeof(struct relocation_info
);
1375 if(object
->split_info_cmd
!= NULL
){
1376 object
->output_split_info_data
= object
->object_addr
+
1377 object
->split_info_cmd
->dataoff
;
1378 object
->output_split_info_data_size
=
1379 object
->split_info_cmd
->datasize
;
1380 object
->input_sym_info_size
+= object
->split_info_cmd
->datasize
;
1381 object
->output_sym_info_size
+=
1382 object
->split_info_cmd
->datasize
;
1385 if(object
->func_starts_info_cmd
!= NULL
){
1386 object
->output_func_start_info_data
= object
->object_addr
+
1387 object
->func_starts_info_cmd
->dataoff
;
1388 object
->output_func_start_info_data_size
=
1389 object
->func_starts_info_cmd
->datasize
;
1390 object
->input_sym_info_size
+=
1391 object
->func_starts_info_cmd
->datasize
;
1392 object
->output_sym_info_size
+=
1393 object
->func_starts_info_cmd
->datasize
;
1396 if(object
->data_in_code_cmd
!= NULL
){
1397 object
->output_data_in_code_info_data
= object
->object_addr
+
1398 object
->data_in_code_cmd
->dataoff
;
1399 object
->output_data_in_code_info_data_size
=
1400 object
->data_in_code_cmd
->datasize
;
1401 object
->input_sym_info_size
+=
1402 object
->data_in_code_cmd
->datasize
;
1403 object
->output_sym_info_size
+=
1404 object
->data_in_code_cmd
->datasize
;
1407 if(object
->code_sign_drs_cmd
!= NULL
){
1408 object
->output_code_sign_drs_info_data
= object
->object_addr
+
1409 object
->code_sign_drs_cmd
->dataoff
;
1410 object
->output_code_sign_drs_info_data_size
=
1411 object
->code_sign_drs_cmd
->datasize
;
1412 object
->input_sym_info_size
+=
1413 object
->code_sign_drs_cmd
->datasize
;
1414 object
->output_sym_info_size
+=
1415 object
->code_sign_drs_cmd
->datasize
;
1418 if(object
->mh
!= NULL
){
1419 object
->input_sym_info_size
+= nsyms
* sizeof(struct nlist
);
1420 object
->output_symbols
= new_symbols
;
1421 object
->output_sym_info_size
+=
1422 new_nsyms
* sizeof(struct nlist
);
1425 object
->input_sym_info_size
+= nsyms
* sizeof(struct nlist_64
);
1426 object
->output_symbols64
= new_symbols64
;
1427 object
->output_sym_info_size
+=
1428 new_nsyms
* sizeof(struct nlist_64
);
1430 object
->output_nsymbols
= new_nsyms
;
1431 object
->st
->nsyms
= new_nsyms
;
1433 if(object
->hints_cmd
!= NULL
){
1434 object
->input_sym_info_size
+=
1435 object
->hints_cmd
->nhints
*
1436 sizeof(struct twolevel_hint
);
1437 object
->output_sym_info_size
+=
1438 object
->hints_cmd
->nhints
*
1439 sizeof(struct twolevel_hint
);
1442 if(object
->dyst
!= NULL
){
1445 * When stripping out the section contents to create a
1446 * dynamic library stub the relocation info also gets
1450 #endif /* !(NMEDIT) */
1452 object
->output_sym_info_size
+=
1453 object
->dyst
->nextrel
* sizeof(struct relocation_info
);
1455 object
->input_sym_info_size
+=
1456 object
->dyst
->nextrel
* sizeof(struct relocation_info
);
1459 if(object
->dyst
!= NULL
){
1460 object
->output_sym_info_size
+=
1461 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1462 object
->input_indirectsym_pad
;
1463 if(object
->mh
!= NULL
){
1464 object
->input_sym_info_size
+=
1465 object
->dyst
->nindirectsyms
* sizeof(uint32_t);
1468 object
->input_sym_info_size
+=
1469 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1470 object
->input_indirectsym_pad
;
1474 if(object
->dyst
!= NULL
){
1475 object
->output_sym_info_size
+=
1476 new_ntoc
* sizeof(struct dylib_table_of_contents
);
1477 object
->input_sym_info_size
+=
1478 object
->dyst
->ntoc
* sizeof(struct dylib_table_of_contents
);
1481 if(object
->dyst
!= NULL
){
1482 if(object
->mh
!= NULL
){
1483 object
->output_sym_info_size
+=
1484 object
->dyst
->nmodtab
* sizeof(struct dylib_module
);
1485 object
->input_sym_info_size
+=
1486 object
->dyst
->nmodtab
* sizeof(struct dylib_module
);
1489 object
->output_sym_info_size
+=
1490 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
);
1491 object
->input_sym_info_size
+=
1492 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
);
1496 if(object
->dyst
!= NULL
){
1497 object
->output_sym_info_size
+=
1498 new_nextrefsyms
* sizeof(struct dylib_reference
);
1499 object
->input_sym_info_size
+=
1500 object
->dyst
->nextrefsyms
* sizeof(struct dylib_reference
);
1503 object
->output_strings
= new_strings
;
1504 object
->output_strings_size
= new_strsize
;
1505 object
->output_sym_info_size
+= new_strsize
;
1506 object
->input_sym_info_size
+= strsize
;
1507 object
->st
->strsize
= new_strsize
;
1509 if(object
->code_sig_cmd
!= NULL
){
1511 if(!cflag
&& !no_code_signature
)
1512 #endif /* !(NMEDIT) */
1514 object
->output_code_sig_data
= object
->object_addr
+
1515 object
->code_sig_cmd
->dataoff
;
1516 object
->output_code_sig_data_size
=
1517 object
->code_sig_cmd
->datasize
;
1519 object
->input_sym_info_size
=
1520 rnd(object
->input_sym_info_size
, 16);
1521 object
->input_sym_info_size
+=
1522 object
->code_sig_cmd
->datasize
;
1524 if(cflag
|| no_code_signature
){
1525 strip_LC_CODE_SIGNATURE_commands(arch
, member
, object
);
1528 #endif /* !(NMEDIT) */
1530 object
->output_sym_info_size
=
1531 rnd(object
->output_sym_info_size
, 16);
1532 object
->output_sym_info_size
+=
1533 object
->code_sig_cmd
->datasize
;
1537 if(object
->dyst
!= NULL
){
1538 object
->dyst
->ilocalsym
= 0;
1539 object
->dyst
->nlocalsym
= new_nlocalsym
;
1540 object
->dyst
->iextdefsym
= new_nlocalsym
;
1541 object
->dyst
->nextdefsym
= new_nextdefsym
;
1542 object
->dyst
->iundefsym
= new_nlocalsym
+ new_nextdefsym
;
1543 object
->dyst
->nundefsym
= new_nundefsym
;
1544 if(object
->dyst
->nindirectsyms
!= 0){
1545 object
->output_indirect_symtab
= indirectsyms
;
1546 if(object
->object_byte_sex
!= host_byte_sex
)
1547 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
1548 object
->object_byte_sex
);
1552 * If the -c option is specified the object's filetype will
1553 * have been changed from MH_DYLIB to MH_DYLIB_STUB above.
1555 if(object
->mh_filetype
== MH_DYLIB
||
1556 object
->mh_filetype
== MH_DYLIB_STUB
){
1557 object
->output_tocs
= new_tocs
;
1558 object
->output_ntoc
= new_ntoc
;
1560 if(object
->mh
!= NULL
)
1561 object
->output_mods
= new_mods
;
1563 object
->output_mods64
= new_mods64
;
1564 object
->output_nmodtab
= new_nmodtab
;
1566 object
->output_mods
= mods
;
1567 object
->output_nmodtab
= nmodtab
;
1569 object
->output_refs
= new_refs
;
1570 object
->output_nextrefsyms
= new_nextrefsyms
;
1571 if(object
->object_byte_sex
!= host_byte_sex
){
1572 swap_dylib_table_of_contents(new_tocs
, new_ntoc
,
1573 object
->object_byte_sex
);
1575 if(object
->mh
!= NULL
)
1576 swap_dylib_module(new_mods
, new_nmodtab
,
1577 object
->object_byte_sex
);
1579 swap_dylib_module_64(new_mods64
, new_nmodtab
,
1580 object
->object_byte_sex
);
1582 if(object
->mh
!= NULL
)
1583 swap_dylib_module(mods
, nmodtab
,
1584 object
->object_byte_sex
);
1586 swap_dylib_module_64(mods64
, nmodtab
,
1587 object
->object_byte_sex
);
1589 swap_dylib_reference(new_refs
, new_nextrefsyms
,
1590 object
->object_byte_sex
);
1593 object
->dyst
->ntoc
= new_ntoc
;
1594 object
->dyst
->nextrefsyms
= new_nextrefsyms
;
1596 offset
= get_starting_syminfo_offset(object
);
1598 if(object
->dyld_info
!= 0){
1599 if (object
->dyld_info
->rebase_off
!= 0){
1600 object
->dyld_info
->rebase_off
= offset
;
1601 offset
+= object
->dyld_info
->rebase_size
;
1603 if (object
->dyld_info
->bind_off
!= 0){
1604 object
->dyld_info
->bind_off
= offset
;
1605 offset
+= object
->dyld_info
->bind_size
;
1607 if (object
->dyld_info
->weak_bind_off
!= 0){
1608 object
->dyld_info
->weak_bind_off
= offset
;
1609 offset
+= object
->dyld_info
->weak_bind_size
;
1611 if (object
->dyld_info
->lazy_bind_off
!= 0){
1612 object
->dyld_info
->lazy_bind_off
= offset
;
1613 offset
+= object
->dyld_info
->lazy_bind_size
;
1615 if (object
->dyld_info
->export_off
!= 0){
1616 object
->dyld_info
->export_off
= offset
;
1617 offset
+= object
->dyld_info
->export_size
;
1621 if(object
->dyst
->nlocrel
!= 0){
1622 object
->output_loc_relocs
= (struct relocation_info
*)
1623 (object
->object_addr
+ object
->dyst
->locreloff
);
1626 * When stripping out the section contents to create a
1627 * dynamic library stub the relocation info also gets
1631 object
->dyst
->nlocrel
= 0;
1632 object
->dyst
->locreloff
= 0;
1635 #endif /* defined(NMEDIT) */
1637 object
->dyst
->locreloff
= offset
;
1638 offset
+= object
->dyst
->nlocrel
*
1639 sizeof(struct relocation_info
);
1643 object
->dyst
->locreloff
= 0;
1645 if(object
->split_info_cmd
!= NULL
){
1646 object
->split_info_cmd
->dataoff
= offset
;
1647 offset
+= object
->split_info_cmd
->datasize
;
1650 if(object
->func_starts_info_cmd
!= NULL
){
1651 object
->func_starts_info_cmd
->dataoff
= offset
;
1652 offset
+= object
->func_starts_info_cmd
->datasize
;
1655 if(object
->data_in_code_cmd
!= NULL
){
1656 object
->data_in_code_cmd
->dataoff
= offset
;
1657 offset
+= object
->data_in_code_cmd
->datasize
;
1660 if(object
->code_sign_drs_cmd
!= NULL
){
1661 object
->code_sign_drs_cmd
->dataoff
= offset
;
1662 offset
+= object
->code_sign_drs_cmd
->datasize
;
1665 if(object
->st
->nsyms
!= 0){
1666 object
->st
->symoff
= offset
;
1667 if(object
->mh
!= NULL
)
1668 offset
+= object
->st
->nsyms
* sizeof(struct nlist
);
1670 offset
+= object
->st
->nsyms
* sizeof(struct nlist_64
);
1673 object
->st
->symoff
= 0;
1675 if(object
->hints_cmd
!= NULL
){
1676 if(object
->hints_cmd
->nhints
!= 0){
1677 object
->output_hints
= (struct twolevel_hint
*)
1678 (object
->object_addr
+ object
->hints_cmd
->offset
);
1679 object
->hints_cmd
->offset
= offset
;
1680 offset
+= object
->hints_cmd
->nhints
*
1681 sizeof(struct twolevel_hint
);
1684 object
->hints_cmd
->offset
= 0;
1687 if(object
->dyst
->nextrel
!= 0){
1688 object
->output_ext_relocs
= (struct relocation_info
*)
1689 (object
->object_addr
+ object
->dyst
->extreloff
);
1692 * When stripping out the section contents to create a
1693 * dynamic library stub the relocation info also gets
1697 object
->dyst
->nextrel
= 0;
1698 object
->dyst
->extreloff
= 0;
1701 #endif /* defined(NMEDIT) */
1703 object
->dyst
->extreloff
= offset
;
1704 offset
+= object
->dyst
->nextrel
*
1705 sizeof(struct relocation_info
);
1709 object
->dyst
->extreloff
= 0;
1711 if(object
->dyst
->nindirectsyms
!= 0){
1712 object
->dyst
->indirectsymoff
= offset
;
1713 offset
+= object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1714 object
->input_indirectsym_pad
;
1717 object
->dyst
->indirectsymoff
= 0;;
1719 if(object
->dyst
->ntoc
!= 0){
1720 object
->dyst
->tocoff
= offset
;
1721 offset
+= object
->dyst
->ntoc
*
1722 sizeof(struct dylib_table_of_contents
);
1725 object
->dyst
->tocoff
= 0;
1727 if(object
->dyst
->nmodtab
!= 0){
1730 * When stripping out the section contents to create a
1731 * dynamic library stub zero out the fields in the module
1732 * table for the sections and relocation information and
1733 * clear Objective-C address and size from modules.
1736 if(object
->mh
!= NULL
){
1737 for(k
= 0; k
< object
->dyst
->nmodtab
; k
++){
1738 mods
[k
].iinit_iterm
= 0;
1739 mods
[k
].ninit_nterm
= 0;
1740 mods
[k
].iextrel
= 0;
1741 mods
[k
].nextrel
= 0;
1742 mods
[k
].objc_module_info_addr
= 0;
1743 mods
[k
].objc_module_info_size
= 0;
1747 for(k
= 0; k
< object
->dyst
->nmodtab
; k
++){
1748 mods64
[k
].iinit_iterm
= 0;
1749 mods64
[k
].ninit_nterm
= 0;
1750 mods64
[k
].iextrel
= 0;
1751 mods64
[k
].nextrel
= 0;
1752 mods64
[k
].objc_module_info_addr
= 0;
1753 mods64
[k
].objc_module_info_size
= 0;
1757 #endif /* !(NMEDIT) */
1758 object
->dyst
->modtaboff
= offset
;
1759 if(object
->mh
!= NULL
)
1760 offset
+= object
->dyst
->nmodtab
*
1761 sizeof(struct dylib_module
);
1763 offset
+= object
->dyst
->nmodtab
*
1764 sizeof(struct dylib_module_64
);
1767 object
->dyst
->modtaboff
= 0;
1769 if(object
->dyst
->nextrefsyms
!= 0){
1770 object
->dyst
->extrefsymoff
= offset
;
1771 offset
+= object
->dyst
->nextrefsyms
*
1772 sizeof(struct dylib_reference
);
1775 object
->dyst
->extrefsymoff
= 0;
1777 if(object
->st
->strsize
!= 0){
1778 object
->st
->stroff
= offset
;
1779 offset
+= object
->st
->strsize
;
1782 object
->st
->stroff
= 0;
1784 if(object
->code_sig_cmd
!= NULL
){
1785 offset
= rnd(offset
, 16);
1786 object
->code_sig_cmd
->dataoff
= offset
;
1787 offset
+= object
->code_sig_cmd
->datasize
;
1791 if(new_strsize
!= 0){
1792 if(object
->mh
!= NULL
)
1793 object
->st
->stroff
= object
->st
->symoff
+
1794 new_nsyms
* sizeof(struct nlist
);
1796 object
->st
->stroff
= object
->st
->symoff
+
1797 new_nsyms
* sizeof(struct nlist_64
);
1800 object
->st
->stroff
= 0;
1802 object
->st
->symoff
= 0;
1808 * Here we are doing a full symbol strip. In some cases it may
1809 * leave the local relocation entries as well as LOCAL indirect
1810 * symbol table entries.
1814 saves
= (int32_t *)allocate(object
->st
->nsyms
* sizeof(int32_t));
1815 bzero(saves
, object
->st
->nsyms
* sizeof(int32_t));
1818 * Account for the symbolic info in the input file.
1820 if(object
->dyst
!= NULL
){
1821 object
->input_sym_info_size
+=
1822 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1823 object
->dyst
->nextrel
* sizeof(struct relocation_info
) +
1824 object
->dyst
->ntoc
* sizeof(struct dylib_table_of_contents
)+
1825 object
->dyst
->nextrefsyms
* sizeof(struct dylib_reference
);
1826 if(object
->mh
!= NULL
){
1827 object
->input_sym_info_size
+=
1828 object
->dyst
->nmodtab
* sizeof(struct dylib_module
) +
1829 object
->dyst
->nindirectsyms
* sizeof(uint32_t);
1832 object
->input_sym_info_size
+=
1833 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
) +
1834 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1835 object
->input_indirectsym_pad
;
1840 * Determine the offset where the remaining symbolic info will start
1841 * in the output file (if any).
1843 offset
= get_starting_syminfo_offset(object
);
1846 * For a full symbol strip all these values in the output file are
1849 object
->st
->symoff
= 0;
1850 object
->st
->nsyms
= 0;
1851 object
->st
->stroff
= 0;
1852 object
->st
->strsize
= 0;
1853 if(object
->dyst
!= NULL
){
1854 object
->dyst
->ilocalsym
= 0;
1855 object
->dyst
->nlocalsym
= 0;
1856 object
->dyst
->iextdefsym
= 0;
1857 object
->dyst
->nextdefsym
= 0;
1858 object
->dyst
->iundefsym
= 0;
1859 object
->dyst
->nundefsym
= 0;
1863 * This will accumulate any remaining symbolic info size in the
1866 object
->output_sym_info_size
= 0;
1869 * We set these so that checking can be done below to report the
1870 * symbols that can't be stripped because of relocation entries
1871 * or indirect symbol table entries. Normally if these table have a
1872 * non-zero number of entries it will be an error as we are trying
1873 * to strip everything. But it maybe that there are only LOCAL
1874 * indirect entries which is odd but will be OK.
1876 if(object
->dyst
!= NULL
){
1877 if(object
->dyst
->nextrel
!= 0){
1878 object
->output_ext_relocs
= (struct relocation_info
*)
1879 (object
->object_addr
+ object
->dyst
->extreloff
);
1882 * Since this file has a dynamic symbol table and if this file
1883 * has local relocation entries on input make sure they are
1884 * there on output. This is a rare case that it will not have
1885 * external relocs or indirect symbols but can happen as is the
1886 * case with the dynamic linker itself.
1888 if(object
->dyst
->nlocrel
!= 0){
1889 object
->output_loc_relocs
= (struct relocation_info
*)
1890 (object
->object_addr
+ object
->dyst
->locreloff
);
1891 object
->output_sym_info_size
+=
1892 object
->dyst
->nlocrel
* sizeof(struct relocation_info
);
1894 object
->dyst
->locreloff
= offset
;
1895 offset
+= object
->dyst
->nlocrel
*
1896 sizeof(struct relocation_info
);
1899 if(object
->dyst
->nindirectsyms
!= 0){
1900 object
->output_indirect_symtab
= (uint32_t *)
1901 (object
->object_addr
+
1902 object
->dyst
->indirectsymoff
);
1903 if(object
->object_byte_sex
!= host_byte_sex
)
1904 swap_indirect_symbols(
1905 object
->output_indirect_symtab
,
1906 object
->dyst
->nindirectsyms
,
1907 object
->object_byte_sex
);
1909 object
->output_sym_info_size
+=
1910 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1911 object
->input_indirectsym_pad
;
1913 object
->dyst
->indirectsymoff
= offset
;
1914 offset
+= object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1915 object
->input_indirectsym_pad
;
1919 #endif /* !defined(NMEDIT) */
1922 * Always clear the prebind checksum if any when creating a new file.
1924 if(object
->cs
!= NULL
)
1925 object
->cs
->cksum
= 0;
1927 if(object
->seg_linkedit
!= NULL
){
1928 object
->seg_linkedit
->filesize
+= object
->output_sym_info_size
-
1929 object
->input_sym_info_size
;
1930 object
->seg_linkedit
->vmsize
= object
->seg_linkedit
->filesize
;
1932 else if(object
->seg_linkedit64
!= NULL
){
1933 /* Do this in two steps to avoid 32/64-bit casting problems. */
1934 object
->seg_linkedit64
->filesize
-= object
->input_sym_info_size
;
1935 object
->seg_linkedit64
->filesize
+= object
->output_sym_info_size
;
1936 object
->seg_linkedit64
->vmsize
= object
->seg_linkedit64
->filesize
;
1940 * Check and update the external relocation entries to make sure
1941 * referenced symbols are not stripped and refer to the new symbol
1944 * The external relocation entries can be located in one of two places,
1945 * first off of the sections or second off of the dynamic symtab.
1947 missing_reloc_symbols
= 0;
1948 lc
= object
->load_commands
;
1949 if(object
->mh
!= NULL
)
1950 ncmds
= object
->mh
->ncmds
;
1952 ncmds
= object
->mh64
->ncmds
;
1953 for(i
= 0; i
< ncmds
; i
++){
1954 if(lc
->cmd
== LC_SEGMENT
&&
1955 object
->seg_linkedit
!= (struct segment_command
*)lc
){
1956 sg
= (struct segment_command
*)lc
;
1957 s
= (struct section
*)((char *)sg
+
1958 sizeof(struct segment_command
));
1959 for(j
= 0; j
< sg
->nsects
; j
++){
1961 if(s
->reloff
+ s
->nreloc
*
1962 sizeof(struct relocation_info
) >
1963 object
->object_size
){
1964 fatal_arch(arch
, member
, "truncated or malformed "
1965 "object (relocation entries for section (%.16s,"
1966 "%.16s) extends past the end of the file)",
1967 s
->segname
, s
->sectname
);
1969 relocs
= (struct relocation_info
*)
1970 (object
->object_addr
+ s
->reloff
);
1971 if(object
->object_byte_sex
!= host_byte_sex
)
1972 swap_relocation_info(relocs
, s
->nreloc
,
1974 if(s
->offset
+ s
->size
> object
->object_size
){
1975 fatal_arch(arch
, member
, "truncated or malformed "
1976 "object (contents of section (%.16s,"
1977 "%.16s) extends past the end of the file)",
1978 s
->segname
, s
->sectname
);
1980 contents
= object
->object_addr
+ s
->offset
;
1981 check_object_relocs(arch
, member
, object
, s
->segname
,
1982 s
->sectname
, s
->size
, contents
, relocs
, s
->nreloc
,
1983 symbols
, symbols64
, nsyms
, strings
,
1984 &missing_reloc_symbols
, host_byte_sex
);
1985 if(object
->object_byte_sex
!= host_byte_sex
)
1986 swap_relocation_info(relocs
, s
->nreloc
,
1987 object
->object_byte_sex
);
1992 else if(lc
->cmd
== LC_SEGMENT_64
&&
1993 object
->seg_linkedit64
!= (struct segment_command_64
*)lc
){
1994 sg64
= (struct segment_command_64
*)lc
;
1995 s64
= (struct section_64
*)((char *)sg64
+
1996 sizeof(struct segment_command_64
));
1997 for(j
= 0; j
< sg64
->nsects
; j
++){
1998 if(s64
->nreloc
!= 0){
1999 if(s64
->reloff
+ s64
->nreloc
*
2000 sizeof(struct relocation_info
) >
2001 object
->object_size
){
2002 fatal_arch(arch
, member
, "truncated or malformed "
2003 "object (relocation entries for section (%.16s,"
2004 "%.16s) extends past the end of the file)",
2005 s64
->segname
, s64
->sectname
);
2007 relocs
= (struct relocation_info
*)
2008 (object
->object_addr
+ s64
->reloff
);
2009 if(object
->object_byte_sex
!= host_byte_sex
)
2010 swap_relocation_info(relocs
, s64
->nreloc
,
2012 if(s64
->offset
+ s64
->size
> object
->object_size
){
2013 fatal_arch(arch
, member
, "truncated or malformed "
2014 "object (contents of section (%.16s,"
2015 "%.16s) extends past the end of the file)",
2016 s64
->segname
, s64
->sectname
);
2018 contents
= object
->object_addr
+ s64
->offset
;
2019 check_object_relocs(arch
, member
, object
, s64
->segname
,
2020 s64
->sectname
, s64
->size
, contents
, relocs
,
2021 s64
->nreloc
, symbols
, symbols64
, nsyms
, strings
,
2022 &missing_reloc_symbols
, host_byte_sex
);
2023 if(object
->object_byte_sex
!= host_byte_sex
)
2024 swap_relocation_info(relocs
, s64
->nreloc
,
2025 object
->object_byte_sex
);
2030 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2032 if(object
->dyst
!= NULL
&& object
->dyst
->nextrel
!= 0){
2033 relocs
= object
->output_ext_relocs
;
2034 if(object
->object_byte_sex
!= host_byte_sex
)
2035 swap_relocation_info(relocs
, object
->dyst
->nextrel
,
2038 for(i
= 0; i
< object
->dyst
->nextrel
; i
++){
2039 if((relocs
[i
].r_address
& R_SCATTERED
) == 0 &&
2040 relocs
[i
].r_extern
== 1){
2041 if(relocs
[i
].r_symbolnum
> nsyms
){
2042 fatal_arch(arch
, member
, "bad r_symbolnum for external "
2043 "relocation entry %d in: ", i
);
2045 if(saves
[relocs
[i
].r_symbolnum
] == 0){
2046 if(missing_reloc_symbols
== 0){
2047 error_arch(arch
, member
, "symbols referenced by "
2048 "relocation entries that can't be stripped in: ");
2049 missing_reloc_symbols
= 1;
2051 if(object
->mh
!= NULL
){
2052 fprintf(stderr
, "%s\n", strings
+ symbols
2053 [relocs
[i
].r_symbolnum
].n_un
.n_strx
);
2056 fprintf(stderr
, "%s\n", strings
+ symbols64
2057 [relocs
[i
].r_symbolnum
].n_un
.n_strx
);
2059 saves
[relocs
[i
].r_symbolnum
] = -1;
2061 if(saves
[relocs
[i
].r_symbolnum
] != -1){
2062 relocs
[i
].r_symbolnum
=
2063 saves
[relocs
[i
].r_symbolnum
] - 1;
2067 fatal_arch(arch
, member
, "bad external relocation entry "
2068 "%d (not external) in: ", i
);
2070 if((relocs
[i
].r_address
& R_SCATTERED
) == 0){
2071 if(reloc_has_pair(object
->mh_cputype
, relocs
[i
].r_type
))
2075 sreloc
= (struct scattered_relocation_info
*)relocs
+ i
;
2076 if(reloc_has_pair(object
->mh_cputype
, sreloc
->r_type
))
2080 if(object
->object_byte_sex
!= host_byte_sex
)
2081 swap_relocation_info(relocs
, object
->dyst
->nextrel
,
2082 object
->object_byte_sex
);
2086 * Check and update the indirect symbol table entries to make sure
2087 * referenced symbols are not stripped and refer to the new symbol
2090 if(object
->dyst
!= NULL
&& object
->dyst
->nindirectsyms
!= 0){
2091 if(object
->object_byte_sex
!= host_byte_sex
)
2092 swap_indirect_symbols(object
->output_indirect_symtab
,
2093 object
->dyst
->nindirectsyms
, host_byte_sex
);
2095 lc
= object
->load_commands
;
2096 if(object
->mh
!= NULL
)
2097 ncmds
= object
->mh
->ncmds
;
2099 ncmds
= object
->mh64
->ncmds
;
2100 for(i
= 0; i
< ncmds
; i
++){
2101 if(lc
->cmd
== LC_SEGMENT
&&
2102 object
->seg_linkedit
!= (struct segment_command
*)lc
){
2103 sg
= (struct segment_command
*)lc
;
2104 s
= (struct section
*)((char *)sg
+
2105 sizeof(struct segment_command
));
2106 for(j
= 0; j
< sg
->nsects
; j
++){
2107 section_type
= s
->flags
& SECTION_TYPE
;
2108 if(section_type
== S_LAZY_SYMBOL_POINTERS
||
2109 section_type
== S_LAZY_DYLIB_SYMBOL_POINTERS
||
2110 section_type
== S_NON_LAZY_SYMBOL_POINTERS
)
2112 else if(section_type
== S_SYMBOL_STUBS
)
2113 stride
= s
->reserved2
;
2118 nitems
= s
->size
/ stride
;
2119 contents
= object
->object_addr
+ s
->offset
;
2120 check_indirect_symtab(arch
, member
, object
, nitems
,
2121 s
->reserved1
, section_type
, contents
, symbols
,
2122 symbols64
, nsyms
, strings
, &missing_reloc_symbols
,
2127 else if(lc
->cmd
== LC_SEGMENT_64
&&
2128 object
->seg_linkedit64
!= (struct segment_command_64
*)lc
){
2129 sg64
= (struct segment_command_64
*)lc
;
2130 s64
= (struct section_64
*)((char *)sg64
+
2131 sizeof(struct segment_command_64
));
2132 for(j
= 0; j
< sg64
->nsects
; j
++){
2133 section_type
= s64
->flags
& SECTION_TYPE
;
2134 if(section_type
== S_LAZY_SYMBOL_POINTERS
||
2135 section_type
== S_LAZY_DYLIB_SYMBOL_POINTERS
||
2136 section_type
== S_NON_LAZY_SYMBOL_POINTERS
)
2138 else if(section_type
== S_SYMBOL_STUBS
)
2139 stride
= s64
->reserved2
;
2144 nitems
= s64
->size
/ stride
;
2145 contents
= object
->object_addr
+ s64
->offset
;
2146 check_indirect_symtab(arch
, member
, object
, nitems
,
2147 s64
->reserved1
, section_type
, contents
, symbols
,
2148 symbols64
, nsyms
, strings
, &missing_reloc_symbols
,
2153 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2156 if(object
->object_byte_sex
!= host_byte_sex
)
2157 swap_indirect_symbols(object
->output_indirect_symtab
,
2158 object
->dyst
->nindirectsyms
, object
->object_byte_sex
);
2162 * Issue a warning if object file has a code signature that the
2163 * operation will invalidate it.
2165 if(object
->code_sig_cmd
!= NULL
)
2166 warning_arch(arch
, member
, "changes being made to the file will "
2167 "invalidate the code signature in: ");
2171 * get_starting_syminfo_offset() returns the starting offset of the symbolic
2172 * info in the object file.
2176 get_starting_syminfo_offset(
2177 struct object
*object
)
2181 if(object
->seg_linkedit
!= NULL
||
2182 object
->seg_linkedit64
!= NULL
){
2183 if(object
->mh
!= NULL
)
2184 offset
= object
->seg_linkedit
->fileoff
;
2186 offset
= object
->seg_linkedit64
->fileoff
;
2190 if(object
->dyst
!= NULL
&&
2191 object
->dyst
->nlocrel
!= 0 &&
2192 object
->dyst
->locreloff
< offset
)
2193 offset
= object
->dyst
->locreloff
;
2194 if(object
->st
->nsyms
!= 0 &&
2195 object
->st
->symoff
< offset
)
2196 offset
= object
->st
->symoff
;
2197 if(object
->dyst
!= NULL
&&
2198 object
->dyst
->nextrel
!= 0 &&
2199 object
->dyst
->extreloff
< offset
)
2200 offset
= object
->dyst
->extreloff
;
2201 if(object
->dyst
!= NULL
&&
2202 object
->dyst
->nindirectsyms
!= 0 &&
2203 object
->dyst
->indirectsymoff
< offset
)
2204 offset
= object
->dyst
->indirectsymoff
;
2205 if(object
->dyst
!= NULL
&&
2206 object
->dyst
->ntoc
!= 0 &&
2207 object
->dyst
->tocoff
< offset
)
2208 offset
= object
->dyst
->tocoff
;
2209 if(object
->dyst
!= NULL
&&
2210 object
->dyst
->nmodtab
!= 0 &&
2211 object
->dyst
->modtaboff
< offset
)
2212 offset
= object
->dyst
->modtaboff
;
2213 if(object
->dyst
!= NULL
&&
2214 object
->dyst
->nextrefsyms
!= 0 &&
2215 object
->dyst
->extrefsymoff
< offset
)
2216 offset
= object
->dyst
->extrefsymoff
;
2217 if(object
->st
->strsize
!= 0 &&
2218 object
->st
->stroff
< offset
)
2219 offset
= object
->st
->stroff
;
2225 * check_object_relocs() is used to check and update the external relocation
2226 * entries from a section in an object file, to make sure referenced symbols
2227 * are not stripped and are changed to refer to the new symbol table indexes.
2231 check_object_relocs(
2233 struct member
*member
,
2234 struct object
*object
,
2239 struct relocation_info
*relocs
,
2241 struct nlist
*symbols
,
2242 struct nlist_64
*symbols64
,
2245 int32_t *missing_reloc_symbols
,
2246 enum byte_sex host_byte_sex
)
2251 uint32_t value
, n_ext
;
2254 struct scattered_relocation_info
*sreloc
;
2256 for(k
= 0; k
< nreloc
; k
++){
2257 if((relocs
[k
].r_address
& R_SCATTERED
) == 0 &&
2258 relocs
[k
].r_extern
== 1){
2259 if(relocs
[k
].r_symbolnum
> nsyms
){
2260 fatal_arch(arch
, member
, "bad r_symbolnum for relocation "
2261 "entry %d in section (%.16s,%.16s) in: ", k
, segname
,
2264 if(object
->mh
!= NULL
){
2265 n_strx
= symbols
[relocs
[k
].r_symbolnum
].n_un
.n_strx
;
2266 n_value
= symbols
[relocs
[k
].r_symbolnum
].n_value
;
2269 n_strx
= symbols64
[relocs
[k
].r_symbolnum
].n_un
.n_strx
;
2270 n_value
= symbols64
[relocs
[k
].r_symbolnum
].n_value
;
2273 if(saves
[relocs
[k
].r_symbolnum
] == 0){
2274 if(*missing_reloc_symbols
== 0){
2275 error_arch(arch
, member
, "symbols referenced by "
2276 "relocation entries that can't be stripped in: ");
2277 *missing_reloc_symbols
= 1;
2279 fprintf(stderr
, "%s\n", strings
+ n_strx
);
2280 saves
[relocs
[k
].r_symbolnum
] = -1;
2282 #else /* defined(NMEDIT) */
2284 * We are letting nmedit change global coalesed symbols into
2285 * statics in MH_OBJECT file types only. Relocation entries to
2286 * global coalesced symbols are external relocs.
2288 if(object
->mh
!= NULL
)
2289 n_ext
= new_symbols
[saves
[relocs
[k
].r_symbolnum
] - 1].
2292 n_ext
= new_symbols64
[saves
[relocs
[k
].r_symbolnum
] - 1].
2294 if(n_ext
!= N_EXT
&&
2295 object
->mh_cputype
!= CPU_TYPE_X86_64
){
2297 * We need to do the relocation for this external relocation
2298 * entry so the item to be relocated is correct for a local
2299 * relocation entry. We don't need to do this for x86-64.
2301 if(relocs
[k
].r_address
+ sizeof(int32_t) > sectsize
){
2302 fatal_arch(arch
, member
, "truncated or malformed "
2303 "object (r_address of relocation entry %u of "
2304 "section (%.16s,%.16s) extends past the end "
2305 "of the section)", k
, segname
, sectname
);
2307 if(object
->mh
!= NULL
){
2308 value
= *(uint32_t *)
2309 (contents
+ relocs
[k
].r_address
);
2310 if(object
->object_byte_sex
!= host_byte_sex
)
2311 value
= SWAP_INT(value
);
2313 * We handle a very limited form here. Only VANILLA
2314 * (r_type == 0) long (r_length==2) absolute or pcrel
2315 * that won't need a scattered relocation entry.
2317 if(relocs
[k
].r_type
!= 0 ||
2318 relocs
[k
].r_length
!= 2){
2319 fatal_arch(arch
, member
, "don't have "
2320 "code to convert external relocation "
2321 "entry %d in section (%.16s,%.16s) "
2322 "for global coalesced symbol: %s "
2323 "in: ", k
, segname
, sectname
,
2327 if(object
->object_byte_sex
!= host_byte_sex
)
2328 value
= SWAP_INT(value
);
2329 *(uint32_t *)(contents
+ relocs
[k
].r_address
) =
2333 value64
= *(uint64_t *)(contents
+ relocs
[k
].r_address
);
2334 if(object
->object_byte_sex
!= host_byte_sex
)
2335 value64
= SWAP_LONG_LONG(value64
);
2337 * We handle a very limited form here. Only VANILLA
2338 * (r_type == 0) quad (r_length==3) absolute or pcrel
2339 * that won't need a scattered relocation entry.
2341 if(relocs
[k
].r_type
!= 0 ||
2342 relocs
[k
].r_length
!= 3){
2343 fatal_arch(arch
, member
, "don't have "
2344 "code to convert external relocation "
2345 "entry %d in section (%.16s,%.16s) "
2346 "for global coalesced symbol: %s "
2347 "in: ", k
, segname
, sectname
,
2351 if(object
->object_byte_sex
!= host_byte_sex
)
2352 value64
= SWAP_LONG_LONG(value64
);
2353 *(uint64_t *)(contents
+ relocs
[k
].r_address
) = value64
;
2356 * Turn the extern reloc into a local.
2358 if(object
->mh
!= NULL
)
2359 relocs
[k
].r_symbolnum
=
2360 new_symbols
[saves
[relocs
[k
].r_symbolnum
] - 1].n_sect
;
2362 relocs
[k
].r_symbolnum
=
2363 new_symbols64
[saves
[relocs
[k
].r_symbolnum
] - 1].n_sect
;
2364 relocs
[k
].r_extern
= 0;
2367 if(relocs
[k
].r_extern
== 1 &&
2368 saves
[relocs
[k
].r_symbolnum
] != -1){
2369 relocs
[k
].r_symbolnum
= saves
[relocs
[k
].r_symbolnum
] - 1;
2372 if((relocs
[k
].r_address
& R_SCATTERED
) == 0){
2373 if(reloc_has_pair(object
->mh_cputype
, relocs
[k
].r_type
) == TRUE
)
2377 sreloc
= (struct scattered_relocation_info
*)relocs
+ k
;
2378 if(reloc_has_pair(object
->mh_cputype
, sreloc
->r_type
) == TRUE
)
2385 * check_indirect_symtab() checks and updates the indirect symbol table entries
2386 * to make sure referenced symbols are not stripped and refer to the new symbol
2391 check_indirect_symtab(
2393 struct member
*member
,
2394 struct object
*object
,
2397 uint32_t section_type
,
2399 struct nlist
*symbols
,
2400 struct nlist_64
*symbols64
,
2403 int32_t *missing_reloc_symbols
,
2404 enum byte_sex host_byte_sex
)
2408 uint32_t n_strx
, value
;
2410 enum bool made_local
;
2412 for(k
= 0; k
< nitems
; k
++){
2414 index
= object
->output_indirect_symtab
[reserved1
+ k
];
2415 if(index
== INDIRECT_SYMBOL_LOCAL
||
2416 index
== INDIRECT_SYMBOL_ABS
||
2417 index
== (INDIRECT_SYMBOL_LOCAL
| INDIRECT_SYMBOL_ABS
))
2420 fatal_arch(arch
, member
,"indirect symbol table entry %d (past " "the end of the symbol table) in: ", reserved1
+ k
);
2422 if(pflag
== 0 && nmedits
[index
] == TRUE
&& saves
[index
] != -1)
2424 if(saves
[index
] == 0)
2428 * Indirect symbol table entries for defined symbols in a
2429 * non-lazy pointer section that are not saved are changed to
2430 * INDIRECT_SYMBOL_LOCAL which their values just have to be
2431 * slid if the are not absolute symbols.
2433 if(object
->mh
!= NULL
){
2434 n_type
= symbols
[index
].n_type
;
2435 n_strx
= symbols
[index
].n_un
.n_strx
;
2438 n_type
= symbols64
[index
].n_type
;
2439 n_strx
= symbols64
[index
].n_un
.n_strx
;
2441 if((n_type
& N_TYPE
) != N_UNDF
&&
2442 (n_type
& N_TYPE
) != N_PBUD
&&
2443 section_type
== S_NON_LAZY_SYMBOL_POINTERS
){
2444 object
->output_indirect_symtab
[reserved1
+ k
] =
2445 INDIRECT_SYMBOL_LOCAL
;
2446 if((n_type
& N_TYPE
) == N_ABS
)
2447 object
->output_indirect_symtab
[reserved1
+ k
] |=
2448 INDIRECT_SYMBOL_ABS
;
2451 * When creating a stub shared library the section contents
2452 * are not updated since they will be stripped.
2454 if(object
->mh_filetype
!= MH_DYLIB_STUB
){
2455 if(object
->mh
!= NULL
){
2456 value
= symbols
[index
].n_value
;
2457 if (symbols
[index
].n_desc
& N_ARM_THUMB_DEF
)
2459 if(object
->object_byte_sex
!= host_byte_sex
)
2460 value
= SWAP_INT(value
);
2461 *(uint32_t *)(contents
+ k
* 4) = value
;
2464 value64
= symbols64
[index
].n_value
;
2465 if(object
->object_byte_sex
!= host_byte_sex
)
2466 value64
= SWAP_LONG_LONG(value64
);
2467 *(uint64_t *)(contents
+ k
* 8) = value64
;
2473 object
->output_indirect_symtab
[reserved1
+ k
] =
2476 #else /* !defined(NMEDIT) */
2478 if(*missing_reloc_symbols
== 0){
2479 error_arch(arch
, member
, "symbols referenced by "
2480 "indirect symbol table entries that can't be "
2482 *missing_reloc_symbols
= 1;
2484 fprintf(stderr
, "%s\n", strings
+ n_strx
);
2487 #endif /* !defined(NMEDIT) */
2491 #else /* !defined(NMEDIT) */
2492 if(made_local
== FALSE
&& saves
[index
] != -1)
2493 #endif /* !defined(NMEDIT) */
2495 object
->output_indirect_symtab
[reserved1
+k
] = saves
[index
] - 1;
2502 * This is called if there is a -d option specified. It reads the file with
2503 * the strings in it and places them in the array debug_filenames and sorts
2504 * them by name. The file that contains the file names must have names one
2505 * per line with no white space (except the newlines).
2509 setup_debug_filenames(
2512 int fd
, i
, strings_size
;
2513 struct stat stat_buf
;
2516 if((fd
= open(dfile
, O_RDONLY
)) < 0){
2517 system_error("can't open: %s", dfile
);
2520 if(fstat(fd
, &stat_buf
) == -1){
2521 system_error("can't stat: %s", dfile
);
2525 strings_size
= stat_buf
.st_size
;
2526 strings
= (char *)allocate(strings_size
+ 1);
2527 strings
[strings_size
] = '\0';
2528 if(read(fd
, strings
, strings_size
) != strings_size
){
2529 system_error("can't read: %s", dfile
);
2534 for(i
= 0; i
< strings_size
; i
++){
2541 debug_filenames
= (char **)allocate(ndebug_filenames
* sizeof(char *));
2543 for(i
= 0; i
< ndebug_filenames
; i
++){
2544 debug_filenames
[i
] = p
;
2547 qsort(debug_filenames
, ndebug_filenames
, sizeof(char *),
2548 (int (*)(const void *, const void *))cmp_qsort_filename
);
2551 printf("Debug filenames:\n");
2552 for(i
= 0; i
< ndebug_filenames
; i
++){
2553 printf("filename = %s\n", debug_filenames
[i
]);
2559 * Strip the symbol table to the level specified by the command line arguments.
2560 * The new symbol table is built and new_symbols is left pointing to it. The
2561 * number of new symbols is left in new_nsyms, the new string table is built
2562 * and new_stings is left pointing to it and new_strsize is left containing it.
2563 * This routine returns zero if successfull and non-zero otherwise.
2569 struct member
*member
,
2570 struct object
*object
,
2571 struct dylib_table_of_contents
*tocs
,
2573 struct dylib_module
*mods
,
2574 struct dylib_module_64
*mods64
,
2576 struct dylib_reference
*refs
,
2577 uint32_t nextrefsyms
)
2579 uint32_t i
, j
, k
, n
, inew_syms
, save_debug
, missing_syms
;
2580 uint32_t missing_symbols
;
2581 char *p
, *q
, **pp
, *basename
;
2582 struct symbol_list
*sp
;
2583 uint32_t new_ext_strsize
, len
, *changes
, inew_undefsyms
;
2584 unsigned char nsects
;
2585 struct load_command
*lc
;
2586 struct segment_command
*sg
;
2587 struct segment_command_64
*sg64
;
2588 struct section
*s
, **sections
;
2589 struct section_64
*s64
, **sections64
;
2590 uint32_t ncmds
, mh_flags
, s_flags
, n_strx
;
2592 struct undef_map
*undef_map
;
2593 struct undef_map64
*undef_map64
;
2594 uint8_t n_type
, n_sect
;
2597 uint32_t module_name
, iextdefsym
, nextdefsym
, ilocalsym
, nlocalsym
;
2598 uint32_t irefsym
, nrefsym
;
2599 unsigned char text_nsect
;
2600 enum bool has_dwarf
, hack_5614542
;
2606 for(i
= 0; i
< nsave_symbols
; i
++)
2607 save_symbols
[i
].sym
= NULL
;
2608 for(i
= 0; i
< nremove_symbols
; i
++)
2609 remove_symbols
[i
].sym
= NULL
;
2611 for(i
= 0; i
< nsave_symbols
; i
++)
2612 save_symbols
[i
].seen
= FALSE
;
2613 for(i
= 0; i
< nremove_symbols
; i
++)
2614 remove_symbols
[i
].seen
= FALSE
;
2618 if(object
->mh
!= NULL
)
2619 new_strsize
= sizeof(int32_t);
2621 new_strsize
= sizeof(int64_t);
2625 new_ext_strsize
= 0;
2628 * If this an object file that has DWARF debugging sections to strip
2629 * then we have to run ld -r on it.
2631 if(object
->mh_filetype
== MH_OBJECT
&& (Sflag
|| xflag
)){
2633 lc
= object
->load_commands
;
2634 if(object
->mh
!= NULL
)
2635 ncmds
= object
->mh
->ncmds
;
2637 ncmds
= object
->mh64
->ncmds
;
2638 for(i
= 0; i
< ncmds
&& has_dwarf
== FALSE
; i
++){
2639 if(lc
->cmd
== LC_SEGMENT
){
2640 sg
= (struct segment_command
*)lc
;
2641 s
= (struct section
*)((char *)sg
+
2642 sizeof(struct segment_command
));
2643 for(j
= 0; j
< sg
->nsects
; j
++){
2644 if(s
->flags
& S_ATTR_DEBUG
){
2651 else if(lc
->cmd
== LC_SEGMENT_64
){
2652 sg64
= (struct segment_command_64
*)lc
;
2653 s64
= (struct section_64
*)((char *)sg64
+
2654 sizeof(struct segment_command_64
));
2655 for(j
= 0; j
< sg64
->nsects
; j
++){
2656 if(s64
->flags
& S_ATTR_DEBUG
){
2663 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2665 if(has_dwarf
== TRUE
)
2666 make_ld_r_object(arch
, member
, object
);
2669 * Because of the "design" of 64-bit object files and the lack of
2670 * local relocation entries it is not possible for strip(1) to do its
2671 * job without becoming a static link editor. The "design" does not
2672 * actually strip the symbols it simply renames them to things like
2673 * "l1000". And they become static symbols but still have external
2674 * relocation entries. Thus can never actually be stripped. Also some
2675 * symbols, *.eh, symbols are not even changed to these names if there
2676 * corresponding global symbol is not stripped. So strip(1) only
2677 * recourse is to use the unified linker to create an ld -r object then
2678 * save all resulting symbols (both static and global) and hope the user
2679 * does not notice the stripping is not what they asked for.
2681 if(object
->mh_filetype
== MH_OBJECT
&&
2682 (object
->mh64
!= NULL
&& object
->ld_r_ofile
== NULL
))
2683 make_ld_r_object(arch
, member
, object
);
2686 * Since make_ld_r_object() may create an object with more symbols
2687 * this has to be done after make_ld_r_object() and nsyms is updated.
2689 saves
= (int32_t *)allocate(nsyms
* sizeof(int32_t));
2690 bzero(saves
, nsyms
* sizeof(int32_t));
2693 * Gather an array of section struct pointers so we can later determine
2694 * if we run into a global symbol in a coalesced section and not strip
2699 text_nsect
= NO_SECT
;
2700 lc
= object
->load_commands
;
2701 if(object
->mh
!= NULL
)
2702 ncmds
= object
->mh
->ncmds
;
2704 ncmds
= object
->mh64
->ncmds
;
2705 for(i
= 0; i
< ncmds
; i
++){
2706 if(lc
->cmd
== LC_SEGMENT
){
2707 sg
= (struct segment_command
*)lc
;
2708 nsects
+= sg
->nsects
;
2710 else if(lc
->cmd
== LC_SEGMENT_64
){
2711 sg64
= (struct segment_command_64
*)lc
;
2712 nsects
+= sg64
->nsects
;
2714 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2716 if(object
->mh
!= NULL
){
2717 sections
= allocate(nsects
* sizeof(struct section
*));
2722 sections64
= allocate(nsects
* sizeof(struct section_64
*));
2725 lc
= object
->load_commands
;
2726 for(i
= 0; i
< ncmds
; i
++){
2727 if(lc
->cmd
== LC_SEGMENT
){
2728 sg
= (struct segment_command
*)lc
;
2729 s
= (struct section
*)((char *)sg
+
2730 sizeof(struct segment_command
));
2731 for(j
= 0; j
< sg
->nsects
; j
++){
2732 if(strcmp((s
+ j
)->sectname
, SECT_TEXT
) == 0 &&
2733 strcmp((s
+ j
)->segname
, SEG_TEXT
) == 0)
2734 text_nsect
= nsects
+ 1;
2735 sections
[nsects
++] = s
++;
2738 else if(lc
->cmd
== LC_SEGMENT_64
){
2739 sg64
= (struct segment_command_64
*)lc
;
2740 s64
= (struct section_64
*)((char *)sg64
+
2741 sizeof(struct segment_command_64
));
2742 for(j
= 0; j
< sg64
->nsects
; j
++){
2743 if(strcmp((s64
+ j
)->sectname
, SECT_TEXT
) == 0 &&
2744 strcmp((s64
+ j
)->segname
, SEG_TEXT
) == 0)
2745 text_nsect
= nsects
+ 1;
2746 sections64
[nsects
++] = s64
++;
2749 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2752 for(i
= 0; i
< nsyms
; i
++){
2754 if(object
->mh
!= NULL
){
2755 mh_flags
= object
->mh
->flags
;
2756 n_strx
= symbols
[i
].n_un
.n_strx
;
2757 n_type
= symbols
[i
].n_type
;
2758 n_sect
= symbols
[i
].n_sect
;
2759 if((n_type
& N_TYPE
) == N_SECT
){
2760 if(n_sect
== 0 || n_sect
> nsects
){
2761 error_arch(arch
, member
, "bad n_sect for symbol "
2762 "table entry %d in: ", i
);
2765 s_flags
= sections
[n_sect
- 1]->flags
;
2767 n_desc
= symbols
[i
].n_desc
;
2768 n_value
= symbols
[i
].n_value
;
2771 mh_flags
= object
->mh64
->flags
;
2772 n_strx
= symbols64
[i
].n_un
.n_strx
;
2773 n_type
= symbols64
[i
].n_type
;
2774 n_sect
= symbols64
[i
].n_sect
;
2775 if((n_type
& N_TYPE
) == N_SECT
){
2776 if(n_sect
== 0 || n_sect
> nsects
){
2777 error_arch(arch
, member
, "bad n_sect for symbol "
2778 "table entry %d in: ", i
);
2781 s_flags
= sections64
[n_sect
- 1]->flags
;
2783 n_desc
= symbols64
[i
].n_desc
;
2784 n_value
= symbols64
[i
].n_value
;
2787 if(n_strx
> strsize
){
2788 error_arch(arch
, member
, "bad string index for symbol "
2789 "table entry %d in: ", i
);
2793 if((n_type
& N_TYPE
) == N_INDR
){
2795 if(n_value
> strsize
){
2796 error_arch(arch
, member
, "bad string index for "
2797 "indirect symbol table entry %d in: ", i
);
2802 if((n_type
& N_EXT
) == 0){ /* local symbol */
2805 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2808 saves
[i
] = new_nsyms
;
2811 * For x86_64 .o files we have run ld -r on them and are stuck
2812 * keeping all resulting symbols.
2814 else if(object
->mh
== NULL
&& (
2815 object
->mh64
->cputype
== CPU_TYPE_X86_64
) &&
2816 object
->mh64
->filetype
== MH_OBJECT
){
2818 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2821 saves
[i
] = new_nsyms
;
2824 * The cases a local symbol might be saved are with -X, -S, -t,
2825 * or with -d filename.
2827 else if((!strip_all
&& (Xflag
|| tflag
|| Sflag
)) || dfile
){
2828 if(n_type
& N_STAB
){ /* debug symbol */
2829 if(dfile
&& n_type
== N_SO
){
2831 basename
= strrchr(strings
+ n_strx
, '/');
2832 if(basename
!= NULL
)
2835 basename
= strings
+ n_strx
;
2836 pp
= bsearch(basename
, debug_filenames
,
2837 ndebug_filenames
, sizeof(char *),
2838 (int (*)(const void *, const void *)
2839 )cmp_bsearch_filename
);
2841 * Save the bracketing N_SO. For each N_SO that
2842 * has a filename there is an N_SO that has a
2843 * name of "" which ends the stabs for that file
2845 if(*basename
!= '\0'){
2853 * This is a bracketing SO so if we are
2854 * currently saving debug symbols save this
2855 * last one and turn off saving debug syms.
2859 new_strsize
+= strlen(strings
+
2863 saves
[i
] = new_nsyms
;
2872 if(saves
[i
] == 0 && (!Sflag
|| save_debug
)){
2874 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2877 saves
[i
] = new_nsyms
;
2880 else{ /* non-debug local symbol */
2881 if(xflag
== 0 && (Sflag
|| Xflag
|| tflag
)){
2883 * No -x (strip all local), and one of -S (strip
2884 * debug), -X (strip 'L' local), or -t (strip
2885 * local except non-'L' text) was given.
2887 if((Xflag
&& n_strx
!= 0 &&
2888 strings
[n_strx
] != 'L') ||
2889 (tflag
&& (n_type
& N_TYPE
) == N_SECT
&&
2890 n_sect
== text_nsect
&& n_strx
!= 0 &&
2891 strings
[n_strx
] != 'L') ||
2892 (Sflag
&& !Xflag
&& !tflag
)) {
2894 * If this file is a for the dynamic linker and
2895 * this symbol is in a section marked so that
2896 * static symbols are stripped then don't
2899 if((mh_flags
& MH_DYLDLINK
) != MH_DYLDLINK
||
2900 (n_type
& N_TYPE
) != N_SECT
||
2901 (s_flags
& S_ATTR_STRIP_STATIC_SYMS
) !=
2902 S_ATTR_STRIP_STATIC_SYMS
){
2903 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2906 saves
[i
] = new_nsyms
;
2911 * Treat a local symbol that was a private extern as if
2912 * were global if it is referenced by a module and save
2915 if((n_type
& N_PEXT
) == N_PEXT
){
2917 private_extern_reference_by_module(
2918 i
, refs
,nextrefsyms
) == TRUE
){
2920 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2923 saves
[i
] = new_nsyms
;
2926 * We need to save symbols that were private externs
2927 * that are used with indirect symbols.
2930 symbol_pointer_used(i
, indirectsyms
,
2931 nindirectsyms
) == TRUE
){
2933 len
= strlen(strings
+ n_strx
) + 1;
2938 saves
[i
] = new_nsyms
;
2944 * Treat a local symbol that was a private extern as if were
2945 * global if it is not referenced by a module.
2947 else if((n_type
& N_PEXT
) == N_PEXT
){
2948 if(saves
[i
] == 0 && sfile
){
2949 sp
= bsearch(strings
+ n_strx
,
2950 save_symbols
, nsave_symbols
,
2951 sizeof(struct symbol_list
),
2952 (int (*)(const void *, const void *))
2953 symbol_list_bsearch
);
2955 if(sp
->sym
== NULL
){
2956 if(object
->mh
!= NULL
)
2957 sp
->sym
= &(symbols
[i
]);
2959 sp
->sym
= &(symbols64
[i
]);
2963 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2966 saves
[i
] = new_nsyms
;
2970 private_extern_reference_by_module(
2971 i
, refs
,nextrefsyms
) == TRUE
){
2973 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2976 saves
[i
] = new_nsyms
;
2979 * We need to save symbols that were private externs that
2980 * are used with indirect symbols.
2983 symbol_pointer_used(i
, indirectsyms
, nindirectsyms
) ==
2986 len
= strlen(strings
+ n_strx
) + 1;
2991 saves
[i
] = new_nsyms
;
2995 else{ /* global symbol */
2997 * strip -R on an x86_64 .o file should do nothing.
3000 (object
->mh
!= NULL
||
3001 object
->mh64
->cputype
!= CPU_TYPE_X86_64
||
3002 object
->mh64
->filetype
!= MH_OBJECT
)){
3003 sp
= bsearch(strings
+ n_strx
,
3004 remove_symbols
, nremove_symbols
,
3005 sizeof(struct symbol_list
),
3006 (int (*)(const void *, const void *))
3007 symbol_list_bsearch
);
3009 if((n_type
& N_TYPE
) == N_UNDF
||
3010 (n_type
& N_TYPE
) == N_PBUD
){
3011 error_arch(arch
, member
, "symbol: %s undefined"
3012 " and can't be stripped from: ",
3015 else if(sp
->sym
!= NULL
){
3016 sym
= (struct nlist
*)sp
->sym
;
3017 if((sym
->n_type
& N_PEXT
) != N_PEXT
)
3018 error_arch(arch
, member
, "more than one symbol "
3019 "for: %s found in: ", sp
->name
);
3022 if(object
->mh
!= NULL
)
3023 sp
->sym
= &(symbols
[i
]);
3025 sp
->sym
= &(symbols64
[i
]);
3028 if(n_desc
& REFERENCED_DYNAMICALLY
){
3029 error_arch(arch
, member
, "symbol: %s is dynamically"
3030 " referenced and can't be stripped "
3031 "from: ", sp
->name
);
3033 if((n_type
& N_TYPE
) == N_SECT
&&
3034 (s_flags
& SECTION_TYPE
) == S_COALESCED
){
3035 error_arch(arch
, member
, "symbol: %s is a global "
3036 "coalesced symbol and can't be "
3037 "stripped from: ", sp
->name
);
3039 /* don't save this symbol */
3043 if(Aflag
&& (n_type
& N_TYPE
) == N_ABS
&&
3046 strncmp(strings
+ n_strx
,
3047 ".objc_class_name_",
3048 sizeof(".objc_class_name_") - 1) == 0))){
3049 len
= strlen(strings
+ n_strx
) + 1;
3051 new_ext_strsize
+= len
;
3054 saves
[i
] = new_nsyms
;
3056 if(saves
[i
] == 0 && (uflag
|| default_dyld_executable
) &&
3057 ((((n_type
& N_TYPE
) == N_UNDF
) &&
3059 (n_type
& N_TYPE
) == N_PBUD
)){
3061 len
= strlen(strings
+ n_strx
) + 1;
3063 new_ext_strsize
+= len
;
3067 saves
[i
] = new_nsyms
;
3069 if(saves
[i
] == 0 && nflag
&&
3070 (n_type
& N_TYPE
) == N_SECT
){
3072 len
= strlen(strings
+ n_strx
) + 1;
3074 new_ext_strsize
+= len
;
3078 saves
[i
] = new_nsyms
;
3080 if(saves
[i
] == 0 && sfile
){
3081 sp
= bsearch(strings
+ n_strx
,
3082 save_symbols
, nsave_symbols
,
3083 sizeof(struct symbol_list
),
3084 (int (*)(const void *, const void *))
3085 symbol_list_bsearch
);
3087 if(sp
->sym
!= NULL
){
3088 sym
= (struct nlist
*)sp
->sym
;
3089 if((sym
->n_type
& N_PEXT
) != N_PEXT
)
3090 error_arch(arch
, member
, "more than one symbol "
3091 "for: %s found in: ", sp
->name
);
3094 if(object
->mh
!= NULL
)
3095 sp
->sym
= &(symbols
[i
]);
3097 sp
->sym
= &(symbols64
[i
]);
3099 len
= strlen(strings
+ n_strx
) + 1;
3101 new_ext_strsize
+= len
;
3102 if((n_type
& N_TYPE
) == N_UNDF
||
3103 (n_type
& N_TYPE
) == N_PBUD
)
3108 saves
[i
] = new_nsyms
;
3113 * We only need to save coalesced symbols that are used as
3114 * indirect symbols in 32-bit applications.
3116 * In 64-bit applications, we only need to save coalesced
3117 * symbols that are used as weak definitions.
3119 if(object
->mh
!= NULL
&&
3121 (n_type
& N_TYPE
) == N_SECT
&&
3122 (s_flags
& SECTION_TYPE
) == S_COALESCED
&&
3123 symbol_pointer_used(i
, indirectsyms
, nindirectsyms
) == TRUE
){
3125 len
= strlen(strings
+ n_strx
) + 1;
3127 new_ext_strsize
+= len
;
3131 saves
[i
] = new_nsyms
;
3134 (n_type
& N_TYPE
) == N_SECT
&&
3135 (n_desc
& N_WEAK_DEF
) != 0){
3137 len
= strlen(strings
+ n_strx
) + 1;
3139 new_ext_strsize
+= len
;
3143 saves
[i
] = new_nsyms
;
3146 ((Xflag
|| Sflag
|| xflag
|| tflag
|| aflag
) ||
3147 ((rflag
|| default_dyld_executable
) &&
3148 n_desc
& REFERENCED_DYNAMICALLY
))){
3149 len
= strlen(strings
+ n_strx
) + 1;
3151 new_ext_strsize
+= len
;
3152 if((n_type
& N_TYPE
) == N_INDR
){
3153 len
= strlen(strings
+ n_value
) + 1;
3155 new_ext_strsize
+= len
;
3157 if((n_type
& N_TYPE
) == N_UNDF
||
3158 (n_type
& N_TYPE
) == N_PBUD
)
3163 saves
[i
] = new_nsyms
;
3166 * For x86_64 .o files we have run ld -r on them and are stuck
3167 * keeping all resulting symbols.
3170 object
->mh
== NULL
&&
3171 object
->mh64
->cputype
== CPU_TYPE_X86_64
&&
3172 object
->mh64
->filetype
== MH_OBJECT
){
3173 len
= strlen(strings
+ n_strx
) + 1;
3175 new_ext_strsize
+= len
;
3176 if((n_type
& N_TYPE
) == N_INDR
){
3177 len
= strlen(strings
+ n_value
) + 1;
3179 new_ext_strsize
+= len
;
3181 if((n_type
& N_TYPE
) == N_UNDF
||
3182 (n_type
& N_TYPE
) == N_PBUD
)
3187 saves
[i
] = new_nsyms
;
3192 * The module table's module names are placed with the external strings.
3193 * So size them and add this to the external string size.
3195 for(i
= 0; i
< nmodtab
; i
++){
3196 if(object
->mh
!= NULL
)
3197 module_name
= mods
[i
].module_name
;
3199 module_name
= mods64
[i
].module_name
;
3200 if(module_name
== 0 || module_name
> strsize
){
3201 error_arch(arch
, member
, "bad string index for module_name "
3202 "of module table entry %d in: ", i
);
3205 len
= strlen(strings
+ module_name
) + 1;
3207 new_ext_strsize
+= len
;
3211 * Updating the reference table may require a symbol not yet listed as
3212 * as saved to be present in the output file. If a defined external
3213 * symbol is removed and there is a undefined reference to it in the
3214 * reference table an undefined symbol needs to be created for it in
3215 * the output file. If this happens the number of new symbols and size
3216 * of the new strings are adjusted. And the array changes[] is set to
3217 * map the old symbol index to the new symbol index for the symbol that
3218 * is changed to an undefined symbol.
3220 missing_symbols
= 0;
3221 if(ref_saves
!= NULL
)
3223 ref_saves
= (int32_t *)allocate(nextrefsyms
* sizeof(int32_t));
3224 bzero(ref_saves
, nextrefsyms
* sizeof(int32_t));
3225 changes
= (uint32_t *)allocate(nsyms
* sizeof(int32_t));
3226 bzero(changes
, nsyms
* sizeof(int32_t));
3227 new_nextrefsyms
= 0;
3228 for(i
= 0; i
< nextrefsyms
; i
++){
3229 if(refs
[i
].isym
> nsyms
){
3230 error_arch(arch
, member
, "bad symbol table index for "
3231 "reference table entry %d in: ", i
);
3234 if(saves
[refs
[i
].isym
]){
3236 ref_saves
[i
] = new_nextrefsyms
;
3239 if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
||
3240 refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
){
3241 if(changes
[refs
[i
].isym
] == 0){
3242 if(object
->mh
!= NULL
)
3243 n_strx
= symbols
[refs
[i
].isym
].n_un
.n_strx
;
3245 n_strx
= symbols64
[refs
[i
].isym
].n_un
.n_strx
;
3246 len
= strlen(strings
+ n_strx
) + 1;
3248 new_ext_strsize
+= len
;
3251 changes
[refs
[i
].isym
] = new_nsyms
;
3253 ref_saves
[i
] = new_nextrefsyms
;
3258 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
||
3259 refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
){
3260 if(missing_symbols
== 0){
3261 error_arch(arch
, member
, "private extern symbols "
3262 "referenced by modules can't be stripped in: ");
3263 missing_symbols
= 1;
3265 if(object
->mh
!= NULL
)
3266 n_strx
= symbols
[refs
[i
].isym
].n_un
.n_strx
;
3268 n_strx
= symbols64
[refs
[i
].isym
].n_un
.n_strx
;
3269 fprintf(stderr
, "%s\n", strings
+ n_strx
);
3270 saves
[refs
[i
].isym
] = -1;
3275 if(missing_symbols
== 1)
3281 for(i
= 0; i
< nsave_symbols
; i
++){
3282 if(save_symbols
[i
].sym
== NULL
){
3283 if(missing_syms
== 0){
3284 error_arch(arch
, member
, "symbols names listed "
3285 "in: %s not in: ", sfile
);
3288 fprintf(stderr
, "%s\n", save_symbols
[i
].name
);
3294 * strip -R on an x86_64 .o file should do nothing.
3297 (object
->mh
!= NULL
||
3298 object
->mh64
->cputype
!= CPU_TYPE_X86_64
||
3299 object
->mh64
->filetype
!= MH_OBJECT
)){
3300 for(i
= 0; i
< nremove_symbols
; i
++){
3301 if(remove_symbols
[i
].sym
== NULL
){
3302 if(missing_syms
== 0){
3303 error_arch(arch
, member
, "symbols names listed "
3304 "in: %s not in: ", Rfile
);
3307 fprintf(stderr
, "%s\n", remove_symbols
[i
].name
);
3314 * If there is a chance that we could end up with an indirect symbol
3315 * with an index of zero we need to avoid that due to a work around
3316 * in the dynamic linker for a bug it is working around that was in
3317 * the old classic static linker. See radar bug 5614542 and the
3318 * related bugs 3685312 and 3534709.
3320 * A reasonable way to do this to know that local symbols are first in
3321 * the symbol table. So if we have any local symbols this won't happen
3322 * and if there are no indirect symbols it will also not happen. Past
3323 * that we'll just add a local symbol so it will end up at symbol index
3324 * zero and avoid any indirect symbol having that index.
3326 * If one really wanted they could build up the new symbol table then
3327 * look at all the indirect symbol table entries to see if any of them
3328 * have an index of zero then in that case throw that new symbol table
3329 * away and rebuild the symbol and string table once again after adding
3330 * a local symbol. This seems not all that resonable to save one symbol
3331 * table entry and a few bytes in the string table for the complexity it
3332 * would add and what it would save.
3334 if(new_nlocalsym
== 0 && nindirectsyms
!= 0){
3335 len
= strlen("radr://5614542") + 1;
3339 hack_5614542
= TRUE
;
3342 hack_5614542
= FALSE
;
3345 if(object
->mh
!= NULL
){
3346 new_symbols
= (struct nlist
*)
3347 allocate(new_nsyms
* sizeof(struct nlist
));
3348 new_symbols64
= NULL
;
3352 new_symbols64
= (struct nlist_64
*)
3353 allocate(new_nsyms
* sizeof(struct nlist_64
));
3355 if(object
->mh
!= NULL
)
3356 new_strsize
= rnd(new_strsize
, sizeof(int32_t));
3358 new_strsize
= rnd(new_strsize
, sizeof(int64_t));
3359 new_strings
= (char *)allocate(new_strsize
);
3360 if(object
->mh
!= NULL
){
3361 new_strings
[new_strsize
- 3] = '\0';
3362 new_strings
[new_strsize
- 2] = '\0';
3363 new_strings
[new_strsize
- 1] = '\0';
3366 new_strings
[new_strsize
- 7] = '\0';
3367 new_strings
[new_strsize
- 6] = '\0';
3368 new_strings
[new_strsize
- 5] = '\0';
3369 new_strings
[new_strsize
- 4] = '\0';
3370 new_strings
[new_strsize
- 3] = '\0';
3371 new_strings
[new_strsize
- 2] = '\0';
3372 new_strings
[new_strsize
- 1] = '\0';
3375 memset(new_strings
, '\0', sizeof(int32_t));
3376 p
= new_strings
+ sizeof(int32_t);
3377 q
= p
+ new_ext_strsize
;
3380 * If all strings were stripped set the size to zero but only for 32-bit
3381 * because the unified linker seems to set the filesize of empty .o
3382 * files to include the string table.
3384 if(object
->mh
!= NULL
&& new_strsize
== sizeof(int32_t))
3388 * Now create a symbol table and string table in this order
3391 * external defined symbols
3400 * If we are doing the hack for radar bug 5614542 (see above) add the
3401 * one local symbol and string.
3403 * We use an N_OPT stab which should be safe to use and not mess any
3404 * thing up. In Mac OS X, gcc(1) writes one N_OPT stab saying the file
3405 * is compiled with gcc(1). Then gdb(1) looks for that stab, but it
3406 * also looks at the name. If the name string is "gcc_compiled" or
3407 * "gcc2_compiled" gdb(1) sets its "compiled by gcc flag. If the N_OPT
3408 * is emitted INSIDE an N_SO section, then gdb(1) thinks that object
3409 * module was compiled by Sun's compiler, which apparently sticks one
3410 * outermost N_LBRAC/N_RBRAC pair, which gdb(1) strips off. But if the
3411 * N_OPT comes before any N_SO stabs, then gdb(1) will just ignore it.
3412 * Since this N_OPT is the first local symbol, it will always come
3413 * before any N_SO stabs that might be around and should be fine.
3415 if(hack_5614542
== TRUE
){
3416 if(object
->mh
!= NULL
){
3417 new_symbols
[inew_syms
].n_type
= N_OPT
;
3418 new_symbols
[inew_syms
].n_sect
= NO_SECT
;
3419 new_symbols
[inew_syms
].n_desc
= 0;
3420 new_symbols
[inew_syms
].n_value
= 0x05614542;
3423 new_symbols64
[inew_syms
].n_type
= N_OPT
;
3424 new_symbols64
[inew_syms
].n_sect
= NO_SECT
;
3425 new_symbols64
[inew_syms
].n_desc
= 0;
3426 new_symbols64
[inew_syms
].n_value
= 0x05614542;
3428 strcpy(q
, "radr://5614542");
3429 if(object
->mh
!= NULL
)
3430 new_symbols
[inew_syms
].n_un
.n_strx
=
3433 new_symbols64
[inew_syms
].n_un
.n_strx
=
3439 for(i
= 0; i
< nsyms
; i
++){
3441 if(object
->mh
!= NULL
){
3442 n_strx
= symbols
[i
].n_un
.n_strx
;
3443 n_type
= symbols
[i
].n_type
;
3446 n_strx
= symbols64
[i
].n_un
.n_strx
;
3447 n_type
= symbols64
[i
].n_type
;
3449 if((n_type
& N_EXT
) == 0){
3450 if(object
->mh
!= NULL
)
3451 new_symbols
[inew_syms
] = symbols
[i
];
3453 new_symbols64
[inew_syms
] = symbols64
[i
];
3455 strcpy(q
, strings
+ n_strx
);
3456 if(object
->mh
!= NULL
)
3457 new_symbols
[inew_syms
].n_un
.n_strx
=
3460 new_symbols64
[inew_syms
].n_un
.n_strx
=
3465 saves
[i
] = inew_syms
;
3470 inew_nextdefsym
= inew_syms
;
3471 #endif /* TRIE_SUPPORT */
3472 for(i
= 0; i
< nsyms
; i
++){
3474 if(object
->mh
!= NULL
){
3475 n_strx
= symbols
[i
].n_un
.n_strx
;
3476 n_type
= symbols
[i
].n_type
;
3477 n_value
= symbols
[i
].n_value
;
3480 n_strx
= symbols64
[i
].n_un
.n_strx
;
3481 n_type
= symbols64
[i
].n_type
;
3482 n_value
= symbols64
[i
].n_value
;
3484 if((n_type
& N_EXT
) == N_EXT
&&
3485 ((n_type
& N_TYPE
) != N_UNDF
&&
3486 (n_type
& N_TYPE
) != N_PBUD
)){
3487 if(object
->mh
!= NULL
)
3488 new_symbols
[inew_syms
] = symbols
[i
];
3490 new_symbols64
[inew_syms
] = symbols64
[i
];
3492 strcpy(p
, strings
+ n_strx
);
3493 if(object
->mh
!= NULL
)
3494 new_symbols
[inew_syms
].n_un
.n_strx
=
3497 new_symbols64
[inew_syms
].n_un
.n_strx
=
3501 if((n_type
& N_TYPE
) == N_INDR
){
3503 strcpy(p
, strings
+ n_value
);
3504 if(object
->mh
!= NULL
)
3505 new_symbols
[inew_syms
].n_value
=
3508 new_symbols64
[inew_syms
].n_value
=
3514 saves
[i
] = inew_syms
;
3519 * Build the new undefined symbols into a map and sort it.
3522 if(object
->mh
!= NULL
){
3523 undef_map
= (struct undef_map
*)allocate(new_nundefsym
*
3524 sizeof(struct undef_map
));
3529 undef_map64
= (struct undef_map64
*)allocate(new_nundefsym
*
3530 sizeof(struct undef_map64
));
3532 for(i
= 0; i
< nsyms
; i
++){
3534 if(object
->mh
!= NULL
){
3535 n_strx
= symbols
[i
].n_un
.n_strx
;
3536 n_type
= symbols
[i
].n_type
;
3539 n_strx
= symbols64
[i
].n_un
.n_strx
;
3540 n_type
= symbols64
[i
].n_type
;
3542 if((n_type
& N_EXT
) == N_EXT
&&
3543 ((n_type
& N_TYPE
) == N_UNDF
||
3544 (n_type
& N_TYPE
) == N_PBUD
)){
3545 if(object
->mh
!= NULL
)
3546 undef_map
[inew_undefsyms
].symbol
= symbols
[i
];
3548 undef_map64
[inew_undefsyms
].symbol64
= symbols64
[i
];
3550 strcpy(p
, strings
+ n_strx
);
3551 if(object
->mh
!= NULL
)
3552 undef_map
[inew_undefsyms
].symbol
.n_un
.n_strx
=
3555 undef_map64
[inew_undefsyms
].symbol64
.n_un
.n_strx
=
3559 if(object
->mh
!= NULL
)
3560 undef_map
[inew_undefsyms
].index
= i
;
3562 undef_map64
[inew_undefsyms
].index
= i
;
3567 for(i
= 0; i
< nsyms
; i
++){
3569 if(object
->mh
!= NULL
)
3570 n_strx
= symbols
[i
].n_un
.n_strx
;
3572 n_strx
= symbols64
[i
].n_un
.n_strx
;
3574 strcpy(p
, strings
+ n_strx
);
3575 if(object
->mh
!= NULL
)
3576 undef_map
[inew_undefsyms
].symbol
.n_un
.n_strx
=
3579 undef_map64
[inew_undefsyms
].symbol64
.n_un
.n_strx
=
3583 if(object
->mh
!= NULL
){
3584 undef_map
[inew_undefsyms
].symbol
.n_type
= N_UNDF
| N_EXT
;
3585 undef_map
[inew_undefsyms
].symbol
.n_sect
= NO_SECT
;
3586 undef_map
[inew_undefsyms
].symbol
.n_desc
= 0;
3587 undef_map
[inew_undefsyms
].symbol
.n_value
= 0;
3588 undef_map
[inew_undefsyms
].index
= i
;
3591 undef_map64
[inew_undefsyms
].symbol64
.n_type
= N_UNDF
|N_EXT
;
3592 undef_map64
[inew_undefsyms
].symbol64
.n_sect
= NO_SECT
;
3593 undef_map64
[inew_undefsyms
].symbol64
.n_desc
= 0;
3594 undef_map64
[inew_undefsyms
].symbol64
.n_value
= 0;
3595 undef_map64
[inew_undefsyms
].index
= i
;
3600 /* Sort the undefined symbols by name */
3601 qsort_strings
= new_strings
;
3602 if(object
->mh
!= NULL
)
3603 qsort(undef_map
, new_nundefsym
, sizeof(struct undef_map
),
3604 (int (*)(const void *, const void *))cmp_qsort_undef_map
);
3606 qsort(undef_map64
, new_nundefsym
, sizeof(struct undef_map64
),
3607 (int (*)(const void *, const void *))cmp_qsort_undef_map_64
);
3608 /* Copy the symbols now in sorted order into new_symbols */
3609 for(i
= 0; i
< new_nundefsym
; i
++){
3610 if(object
->mh
!= NULL
){
3611 new_symbols
[inew_syms
] = undef_map
[i
].symbol
;
3613 saves
[undef_map
[i
].index
] = inew_syms
;
3616 new_symbols64
[inew_syms
] = undef_map64
[i
].symbol64
;
3618 saves
[undef_map64
[i
].index
] = inew_syms
;
3623 * Fixup the module table's module name strings adding them to the
3624 * string table. Also fix the indexes into the symbol table for
3625 * external and local symbols. And fix up the indexes into the
3628 for(i
= 0; i
< nmodtab
; i
++){
3629 if(object
->mh
!= NULL
){
3630 strcpy(p
, strings
+ mods
[i
].module_name
);
3631 mods
[i
].module_name
= p
- new_strings
;
3632 iextdefsym
= mods
[i
].iextdefsym
;
3633 nextdefsym
= mods
[i
].nextdefsym
;
3634 ilocalsym
= mods
[i
].ilocalsym
;
3635 nlocalsym
= mods
[i
].nlocalsym
;
3636 irefsym
= mods
[i
].irefsym
;
3637 nrefsym
= mods
[i
].nrefsym
;
3640 strcpy(p
, strings
+ mods64
[i
].module_name
);
3641 mods64
[i
].module_name
= p
- new_strings
;
3642 iextdefsym
= mods64
[i
].iextdefsym
;
3643 nextdefsym
= mods64
[i
].nextdefsym
;
3644 ilocalsym
= mods64
[i
].ilocalsym
;
3645 nlocalsym
= mods64
[i
].nlocalsym
;
3646 irefsym
= mods64
[i
].irefsym
;
3647 nrefsym
= mods64
[i
].nrefsym
;
3651 if(iextdefsym
> nsyms
){
3652 error_arch(arch
, member
, "bad index into externally defined "
3653 "symbols of module table entry %d in: ", i
);
3656 if(iextdefsym
+ nextdefsym
> nsyms
){
3657 error_arch(arch
, member
, "bad number of externally defined "
3658 "symbols of module table entry %d in: ", i
);
3661 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
3662 if(saves
[j
] != 0 && changes
[j
] == 0)
3666 for(k
= j
; k
< iextdefsym
+ nextdefsym
; k
++){
3667 if(saves
[k
] != 0 && changes
[k
] == 0)
3671 if(object
->mh
!= NULL
){
3672 mods
[i
].iextdefsym
= 0;
3673 mods
[i
].nextdefsym
= 0;
3676 mods64
[i
].iextdefsym
= 0;
3677 mods64
[i
].nextdefsym
= 0;
3681 if(object
->mh
!= NULL
){
3682 mods
[i
].iextdefsym
= saves
[j
] - 1;
3683 mods
[i
].nextdefsym
= n
;
3686 mods64
[i
].iextdefsym
= saves
[j
] - 1;
3687 mods64
[i
].nextdefsym
= n
;
3691 if(ilocalsym
> nsyms
){
3692 error_arch(arch
, member
, "bad index into symbols for local "
3693 "symbols of module table entry %d in: ", i
);
3696 if(ilocalsym
+ nlocalsym
> nsyms
){
3697 error_arch(arch
, member
, "bad number of local "
3698 "symbols of module table entry %d in: ", i
);
3701 for(j
= ilocalsym
; j
< ilocalsym
+ nlocalsym
; j
++){
3706 for(k
= j
; k
< ilocalsym
+ nlocalsym
; k
++){
3711 if(object
->mh
!= NULL
){
3712 mods
[i
].ilocalsym
= 0;
3713 mods
[i
].nlocalsym
= 0;
3716 mods64
[i
].ilocalsym
= 0;
3717 mods64
[i
].nlocalsym
= 0;
3721 if(object
->mh
!= NULL
){
3722 mods
[i
].ilocalsym
= saves
[j
] - 1;
3723 mods
[i
].nlocalsym
= n
;
3726 mods64
[i
].ilocalsym
= saves
[j
] - 1;
3727 mods64
[i
].nlocalsym
= n
;
3731 if(irefsym
> nextrefsyms
){
3732 error_arch(arch
, member
, "bad index into reference table "
3733 "of module table entry %d in: ", i
);
3736 if(irefsym
+ nrefsym
> nextrefsyms
){
3737 error_arch(arch
, member
, "bad number of reference table "
3738 "entries of module table entry %d in: ", i
);
3741 for(j
= irefsym
; j
< irefsym
+ nrefsym
; j
++){
3742 if(ref_saves
[j
] != 0)
3746 for(k
= j
; k
< irefsym
+ nrefsym
; k
++){
3747 if(ref_saves
[k
] != 0)
3751 if(object
->mh
!= NULL
){
3752 mods
[i
].irefsym
= 0;
3753 mods
[i
].nrefsym
= 0;
3756 mods64
[i
].irefsym
= 0;
3757 mods64
[i
].nrefsym
= 0;
3761 if(object
->mh
!= NULL
){
3762 mods
[i
].irefsym
= ref_saves
[j
] - 1;
3763 mods
[i
].nrefsym
= n
;
3766 mods64
[i
].irefsym
= ref_saves
[j
] - 1;
3767 mods64
[i
].nrefsym
= n
;
3773 * Create a new reference table.
3775 new_refs
= allocate(new_nextrefsyms
* sizeof(struct dylib_reference
));
3777 for(i
= 0; i
< nextrefsyms
; i
++){
3779 if(saves
[refs
[i
].isym
]){
3780 new_refs
[j
].isym
= saves
[refs
[i
].isym
] - 1;
3781 new_refs
[j
].flags
= refs
[i
].flags
;
3784 if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
||
3785 refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
){
3786 new_refs
[j
].isym
= changes
[refs
[i
].isym
] - 1;
3787 new_refs
[j
].flags
= refs
[i
].flags
;
3795 * Create a new dylib table of contents.
3798 for(i
= 0; i
< ntoc
; i
++){
3799 if(tocs
[i
].symbol_index
>= nsyms
){
3800 error_arch(arch
, member
, "bad symbol index for table of "
3801 "contents table entry %d in: ", i
);
3804 if(saves
[tocs
[i
].symbol_index
] != 0 &&
3805 changes
[tocs
[i
].symbol_index
] == 0)
3808 new_tocs
= allocate(new_ntoc
* sizeof(struct dylib_table_of_contents
));
3810 for(i
= 0; i
< ntoc
; i
++){
3811 if(saves
[tocs
[i
].symbol_index
] != 0 &&
3812 changes
[tocs
[i
].symbol_index
] == 0){
3813 new_tocs
[j
].symbol_index
= saves
[tocs
[i
].symbol_index
] - 1;
3814 new_tocs
[j
].module_index
= tocs
[i
].module_index
;
3820 * Update the export trie if it has one but only call the the
3821 * prune_trie() routine when we are removing global symbols as is
3822 * done with default stripping of a dyld executable or with the -s
3825 if(object
->dyld_info
!= NULL
&&
3826 object
->dyld_info
->export_size
!= 0 &&
3827 (default_dyld_executable
|| sfile
!= NULL
|| Rfile
!= NULL
)){
3828 const char *error_string
;
3829 uint32_t trie_new_size
;
3831 error_string
= prune_trie((uint8_t *)(object
->object_addr
+
3832 object
->dyld_info
->export_off
),
3833 object
->dyld_info
->export_size
,
3836 if(error_string
!= NULL
){
3837 error_arch(arch
, member
, "%s", error_string
);
3841 #endif /* TRIE_SUPPORT */
3843 if(undef_map
!= NULL
)
3845 if(undef_map64
!= NULL
)
3849 if(sections
!= NULL
)
3851 if(sections64
!= NULL
)
3862 * prune() is called by prune_trie() and passed a name of an external symbol
3863 * in the trie. It returns 1 if the symbols is to be pruned out and 0 if the
3864 * symbol is to be kept.
3866 * Note that it may seem like a linear search of the new symbols would not be
3867 * the best approach but in 10.6 the only defined global symbol left in a
3868 * stripped executable is __mh_execute_header and new_nextdefsym is usually 1
3869 * so this never actually loops in practice.
3878 for(i
= 0; i
< new_nextdefsym
; i
++){
3879 if(new_symbols
!= NULL
){
3880 if(strcmp(name
, new_strings
+ new_symbols
[inew_nextdefsym
+ i
]
3885 if(strcmp(name
, new_strings
+ new_symbols64
[inew_nextdefsym
+ i
]
3892 #endif /* TRIE_SUPPORT */
3895 * make_ld_r_object() takes the object file contents referenced by the passed
3896 * data structures, writes that to a temporary file, runs "ld -r" plus the
3897 * specified stripping option creating a second temporary file, reads that file
3898 * in and replaces the object file contents with that and resets the variables
3899 * pointing to the symbol, string and indirect tables.
3905 struct member
*member
,
3906 struct object
*object
)
3908 enum byte_sex host_byte_sex
;
3909 char *input_file
, *output_file
;
3911 struct ofile
*ld_r_ofile
;
3912 struct arch
*ld_r_archs
;
3913 uint32_t ld_r_narchs
, save_errors
;
3915 host_byte_sex
= get_host_byte_sex();
3918 * Swap the object file back into its bytesex before writing it to the
3919 * temporary file if needed.
3921 if(object
->object_byte_sex
!= host_byte_sex
){
3922 if(object
->mh
!= NULL
){
3923 if(swap_object_headers(object
->mh
, object
->load_commands
) ==
3925 fatal("internal error: swap_object_headers() failed");
3926 swap_nlist(symbols
, nsyms
, object
->object_byte_sex
);
3929 if(swap_object_headers(object
->mh64
, object
->load_commands
) ==
3931 fatal("internal error: swap_object_headers() failed");
3932 swap_nlist_64(symbols64
, nsyms
, object
->object_byte_sex
);
3934 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
3935 object
->object_byte_sex
);
3939 * Create an input object file for the ld -r command from the bytes
3940 * of this arch's object file.
3942 input_file
= makestr("/tmp/strip.XXXXXX", NULL
);
3943 input_file
= mktemp(input_file
);
3945 if((fd
= open(input_file
, O_WRONLY
|O_CREAT
, 0600)) < 0)
3946 system_fatal("can't open temporary file: %s", input_file
);
3948 if(write(fd
, object
->object_addr
, object
->object_size
) !=
3949 object
->object_size
)
3950 system_fatal("can't write temporary file: %s", input_file
);
3953 system_fatal("can't close temporary file: %s", input_file
);
3956 * Create a temporary name for the output file of the ld -r
3958 output_file
= makestr("/tmp/strip.XXXXXX", NULL
);
3959 output_file
= mktemp(output_file
);
3962 * Create the ld -r command line and execute it.
3964 reset_execute_list();
3965 add_execute_list_with_prefix("ld");
3966 add_execute_list("-keep_private_externs");
3967 add_execute_list("-r");
3969 add_execute_list("-S");
3971 add_execute_list("-x");
3972 add_execute_list(input_file
);
3973 add_execute_list("-o");
3974 add_execute_list(output_file
);
3976 add_execute_list("-x");
3977 add_execute_list("-exported_symbols_list");
3978 add_execute_list(sfile
);
3981 add_execute_list("-unexported_symbols_list");
3982 add_execute_list(Rfile
);
3984 if(execute_list(vflag
) == 0)
3985 fatal("internal link edit command failed");
3987 save_errors
= errors
;
3989 /* breakout the output file of the ld -f for processing */
3990 ld_r_ofile
= breakout(output_file
, &ld_r_archs
, &ld_r_narchs
, FALSE
);
3992 goto make_ld_r_object_cleanup
;
3994 /* checkout the file for symbol table replacement processing */
3995 checkout(ld_r_archs
, ld_r_narchs
);
3998 * Make sure the output of the ld -r is an object file with one arch.
4000 if(ld_r_narchs
!= 1 ||
4001 ld_r_archs
->type
!= OFILE_Mach_O
||
4002 ld_r_archs
->object
== NULL
||
4003 ld_r_archs
->object
->mh_filetype
!= MH_OBJECT
)
4004 fatal("internal link edit command failed to produce a thin Mach-O "
4008 * Now reset all the data of the input object with the ld -r output
4011 nsyms
= ld_r_archs
->object
->st
->nsyms
;
4012 if(ld_r_archs
->object
->mh
!= NULL
){
4013 symbols
= (struct nlist
*)
4014 (ld_r_archs
->object
->object_addr
+
4015 ld_r_archs
->object
->st
->symoff
);
4016 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
4017 swap_nlist(symbols
, nsyms
, host_byte_sex
);
4022 symbols64
= (struct nlist_64
*)
4023 (ld_r_archs
->object
->object_addr
+
4024 ld_r_archs
->object
->st
->symoff
);
4025 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
4026 swap_nlist_64(symbols64
, nsyms
, host_byte_sex
);
4028 strings
= ld_r_archs
->object
->object_addr
+
4029 ld_r_archs
->object
->st
->stroff
;
4030 strsize
= ld_r_archs
->object
->st
->strsize
;
4032 if(ld_r_archs
->object
->dyst
!= NULL
&&
4033 ld_r_archs
->object
->dyst
->nindirectsyms
!= 0){
4034 nindirectsyms
= ld_r_archs
->object
->dyst
->nindirectsyms
;
4035 indirectsyms
= (uint32_t *)
4036 (ld_r_archs
->object
->object_addr
+
4037 ld_r_archs
->object
->dyst
->indirectsymoff
);
4038 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
4039 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
4043 indirectsyms
= NULL
;
4047 if(ld_r_archs
->object
->mh
!= NULL
)
4048 ld_r_archs
->object
->input_sym_info_size
=
4049 nsyms
* sizeof(struct nlist
) +
4052 ld_r_archs
->object
->input_sym_info_size
=
4053 nsyms
* sizeof(struct nlist_64
) +
4057 * Copy over the object struct from the ld -r object file onto the
4058 * input object file.
4060 *object
= *ld_r_archs
->object
;
4063 * Save the ofile struct for the ld -r output so it can be umapped when
4064 * we are done. And free up the ld_r_archs now that we are done with
4067 object
->ld_r_ofile
= ld_r_ofile
;
4068 free_archs(ld_r_archs
, ld_r_narchs
);
4070 make_ld_r_object_cleanup
:
4071 errors
+= save_errors
;
4073 * Remove the input and output files and clean up.
4075 if(unlink(input_file
) == -1)
4076 system_fatal("can't remove temporary file: %s", input_file
);
4077 if(unlink(output_file
) == -1)
4078 system_fatal("can't remove temporary file: %s", output_file
);
4084 * strip_LC_UUID_commands() is called when -no_uuid is specified to remove any
4085 * LC_UUID load commands from the object's load commands.
4089 strip_LC_UUID_commands(
4091 struct member
*member
,
4092 struct object
*object
)
4094 uint32_t i
, ncmds
, nuuids
, mh_sizeofcmds
, sizeofcmds
;
4095 struct load_command
*lc1
, *lc2
, *new_load_commands
;
4096 struct segment_command
*sg
;
4099 * See if there are any LC_UUID load commands.
4102 lc1
= arch
->object
->load_commands
;
4103 if(arch
->object
->mh
!= NULL
){
4104 ncmds
= arch
->object
->mh
->ncmds
;
4105 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
4108 ncmds
= arch
->object
->mh64
->ncmds
;
4109 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
4111 for(i
= 0; i
< ncmds
; i
++){
4112 if(lc1
->cmd
== LC_UUID
){
4115 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4117 /* if no LC_UUID load commands just return */
4122 * Allocate space for the new load commands as zero it out so any holes
4123 * will be zero bytes.
4125 new_load_commands
= allocate(mh_sizeofcmds
);
4126 memset(new_load_commands
, '\0', mh_sizeofcmds
);
4129 * Copy all the load commands except the LC_UUID load commands into the
4130 * allocated space for the new load commands.
4132 lc1
= arch
->object
->load_commands
;
4133 lc2
= new_load_commands
;
4135 for(i
= 0; i
< ncmds
; i
++){
4136 if(lc1
->cmd
!= LC_UUID
){
4137 memcpy(lc2
, lc1
, lc1
->cmdsize
);
4138 sizeofcmds
+= lc2
->cmdsize
;
4139 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
4141 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4145 * Finally copy the updated load commands over the existing load
4148 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
4149 if(mh_sizeofcmds
> sizeofcmds
){
4150 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
4151 (mh_sizeofcmds
- sizeofcmds
));
4154 if(arch
->object
->mh
!= NULL
) {
4155 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
4156 arch
->object
->mh
->ncmds
= ncmds
;
4158 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
4159 arch
->object
->mh64
->ncmds
= ncmds
;
4161 free(new_load_commands
);
4163 /* reset the pointers into the load commands */
4164 lc1
= arch
->object
->load_commands
;
4165 for(i
= 0; i
< ncmds
; i
++){
4168 arch
->object
->st
= (struct symtab_command
*)lc1
;
4171 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
4173 case LC_TWOLEVEL_HINTS
:
4174 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
4176 case LC_PREBIND_CKSUM
:
4177 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
4180 sg
= (struct segment_command
*)lc1
;
4181 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
4182 arch
->object
->seg_linkedit
= sg
;
4184 case LC_SEGMENT_SPLIT_INFO
:
4185 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
4187 case LC_FUNCTION_STARTS
:
4188 object
->func_starts_info_cmd
=
4189 (struct linkedit_data_command
*)lc1
;
4191 case LC_DATA_IN_CODE
:
4192 object
->data_in_code_cmd
=
4193 (struct linkedit_data_command
*)lc1
;
4195 case LC_DYLIB_CODE_SIGN_DRS
:
4196 object
->code_sign_drs_cmd
=
4197 (struct linkedit_data_command
*)lc1
;
4199 case LC_CODE_SIGNATURE
:
4200 object
->code_sig_cmd
= (struct linkedit_data_command
*)lc1
;
4202 case LC_DYLD_INFO_ONLY
:
4204 object
->dyld_info
= (struct dyld_info_command
*)lc1
;
4206 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4211 * strip_LC_DYLIB_commands() is called when -no_dylib is specified to remove any
4212 * LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB or LC_REEXPORT_DYLIB load commands from the
4213 * object's load commands that reference any of the -no_dylib shared libraries.
4217 strip_LC_DYLIB_commands(
4219 struct member
*member
,
4220 struct object
*object
)
4222 uint32_t i
, ncmds
, ndylibs
, dyidx
, newnum
, mh_sizeofcmds
, sizeofcmds
;
4223 struct load_command
*lc1
, *lc2
, *new_load_commands
;
4224 struct segment_command
*sg
;
4225 uint8_t inuse
[256], renum
[256];
4228 * See if there are any DYLIB load commands.
4231 lc1
= arch
->object
->load_commands
;
4232 if(arch
->object
->mh
!= NULL
){
4233 ncmds
= arch
->object
->mh
->ncmds
;
4234 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
4237 ncmds
= arch
->object
->mh64
->ncmds
;
4238 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
4240 for(i
= 0; i
< ncmds
; i
++){
4241 if(lc1
->cmd
== LC_LOAD_DYLIB
||
4242 lc1
->cmd
== LC_LOAD_WEAK_DYLIB
||
4243 lc1
->cmd
== LC_REEXPORT_DYLIB
||
4244 lc1
->cmd
== LC_LAZY_LOAD_DYLIB
||
4245 lc1
->cmd
== LC_LOAD_UPWARD_DYLIB
){
4248 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4250 /* if no DYLIB load commands just return */
4255 * Allocate space for the new load commands as zero it out so any holes
4256 * will be zero bytes.
4258 new_load_commands
= allocate(mh_sizeofcmds
);
4259 memset(new_load_commands
, '\0', mh_sizeofcmds
);
4262 * Find dylib references currently in use by undefined symbols
4264 memset(inuse
, 0, sizeof(inuse
));
4265 memset(renum
, 0, sizeof(renum
));
4267 for (i
=0; i
<new_nsyms
; ++i
) {
4268 if ((new_symbols
[i
].n_type
& N_TYPE
) == N_UNDF
) {
4269 uint8_t ordn
= GET_LIBRARY_ORDINAL(new_symbols
[i
].n_desc
);
4270 if (1 <= ordn
&& ordn
<= MAX_LIBRARY_ORDINAL
)
4275 else if (new_symbols64
) {
4276 for (i
=0; i
<new_nsyms
; ++i
) {
4277 if ((new_symbols64
[i
].n_type
& N_TYPE
) == N_UNDF
) {
4278 uint8_t ordn
= GET_LIBRARY_ORDINAL(new_symbols64
[i
].n_desc
);
4279 if (1 <= ordn
&& ordn
<= MAX_LIBRARY_ORDINAL
)
4286 * Copy all the load commands except the matching DYLIB load commands
4287 * into the allocated space for the new load commands.
4289 lc1
= arch
->object
->load_commands
;
4290 lc2
= new_load_commands
;
4295 for(i
= 0; i
< ncmds
; i
++){
4297 if(lc1
->cmd
== LC_LOAD_DYLIB
||
4298 lc1
->cmd
== LC_LOAD_WEAK_DYLIB
||
4299 lc1
->cmd
== LC_REEXPORT_DYLIB
||
4300 lc1
->cmd
== LC_LAZY_LOAD_DYLIB
||
4301 lc1
->cmd
== LC_LOAD_UPWARD_DYLIB
){
4302 struct dylib_command
*dlc
= (struct dylib_command
*)lc1
;
4303 char *name
= (char *)lc1
+ dlc
->dylib
.name
.offset
;
4306 if (no_dylib_unused
)
4307 ignore
= !inuse
[dyidx
];
4308 for (ptr
= no_dylib
; !ignore
&& ptr
; ptr
= ptr
->next
) {
4309 if (strcmp(ptr
->name
, name
) == 0) {
4311 fatal_arch(arch
, member
, "can't remove inuse "
4312 "dylib reference %s from: ", name
);
4323 renum
[dyidx
] = ++newnum
;
4326 memcpy(lc2
, lc1
, lc1
->cmdsize
);
4327 sizeofcmds
+= lc2
->cmdsize
;
4328 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
4330 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4334 * Finally copy the updated load commands over the existing load
4337 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
4338 if(mh_sizeofcmds
> sizeofcmds
){
4339 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
4340 (mh_sizeofcmds
- sizeofcmds
));
4343 if(arch
->object
->mh
!= NULL
) {
4344 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
4345 arch
->object
->mh
->ncmds
= ncmds
;
4347 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
4348 arch
->object
->mh64
->ncmds
= ncmds
;
4350 free(new_load_commands
);
4352 /* reset the pointers into the load commands */
4353 lc1
= arch
->object
->load_commands
;
4354 for(i
= 0; i
< ncmds
; i
++){
4357 arch
->object
->st
= (struct symtab_command
*)lc1
;
4360 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
4362 case LC_TWOLEVEL_HINTS
:
4363 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
4365 case LC_PREBIND_CKSUM
:
4366 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
4369 sg
= (struct segment_command
*)lc1
;
4370 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
4371 arch
->object
->seg_linkedit
= sg
;
4373 case LC_SEGMENT_SPLIT_INFO
:
4374 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
4376 case LC_FUNCTION_STARTS
:
4377 object
->func_starts_info_cmd
=
4378 (struct linkedit_data_command
*)lc1
;
4380 case LC_DATA_IN_CODE
:
4381 object
->data_in_code_cmd
=
4382 (struct linkedit_data_command
*)lc1
;
4384 case LC_DYLIB_CODE_SIGN_DRS
:
4385 object
->code_sign_drs_cmd
=
4386 (struct linkedit_data_command
*)lc1
;
4388 case LC_CODE_SIGNATURE
:
4389 object
->code_sig_cmd
= (struct linkedit_data_command
*)lc1
;
4391 case LC_DYLD_INFO_ONLY
:
4393 object
->dyld_info
= (struct dyld_info_command
*)lc1
;
4395 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4399 * Renumber symbol dylib references
4402 for (i
=0; i
<new_nsyms
; ++i
) {
4403 if ((new_symbols
[i
].n_type
& N_TYPE
) == N_UNDF
) {
4404 uint8_t n
= GET_LIBRARY_ORDINAL(new_symbols
[i
].n_desc
);
4405 if (1 <= n
&& n
<= MAX_LIBRARY_ORDINAL
)
4406 SET_LIBRARY_ORDINAL(new_symbols
[i
].n_desc
, renum
[n
]);
4410 else if (new_symbols64
) {
4411 for (i
=0; i
<new_nsyms
; ++i
) {
4412 if ((new_symbols64
[i
].n_type
& N_TYPE
) == N_UNDF
) {
4413 uint8_t n
= GET_LIBRARY_ORDINAL(new_symbols64
[i
].n_desc
);
4414 if (1 <= n
&& n
<= MAX_LIBRARY_ORDINAL
)
4415 SET_LIBRARY_ORDINAL(new_symbols64
[i
].n_desc
, renum
[n
]);
4423 * strip_LC_CODE_SIGNATURE_commands() is called when -c is specified to remove
4424 * any LC_CODE_SIGNATURE load commands from the object's load commands.
4428 strip_LC_CODE_SIGNATURE_commands(
4430 struct member
*member
,
4431 struct object
*object
)
4433 uint32_t i
, ncmds
, mh_sizeofcmds
, sizeofcmds
;
4434 struct load_command
*lc1
, *lc2
, *new_load_commands
;
4435 struct segment_command
*sg
;
4438 * See if there is an LC_CODE_SIGNATURE load command and if no command
4441 if(object
->code_sig_cmd
== NULL
)
4445 * Allocate space for the new load commands and zero it out so any holes
4446 * will be zero bytes.
4448 if(arch
->object
->mh
!= NULL
){
4449 ncmds
= arch
->object
->mh
->ncmds
;
4450 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
4453 ncmds
= arch
->object
->mh64
->ncmds
;
4454 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
4456 new_load_commands
= allocate(mh_sizeofcmds
);
4457 memset(new_load_commands
, '\0', mh_sizeofcmds
);
4460 * Copy all the load commands except the LC_CODE_SIGNATURE load commands
4461 * into the allocated space for the new load commands.
4463 lc1
= arch
->object
->load_commands
;
4464 lc2
= new_load_commands
;
4466 for(i
= 0; i
< ncmds
; i
++){
4467 if(lc1
->cmd
!= LC_CODE_SIGNATURE
){
4468 memcpy(lc2
, lc1
, lc1
->cmdsize
);
4469 sizeofcmds
+= lc2
->cmdsize
;
4470 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
4472 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4476 * Finally copy the updated load commands over the existing load
4479 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
4480 if(mh_sizeofcmds
> sizeofcmds
){
4481 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
4482 (mh_sizeofcmds
- sizeofcmds
));
4485 if(arch
->object
->mh
!= NULL
) {
4486 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
4487 arch
->object
->mh
->ncmds
= ncmds
;
4489 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
4490 arch
->object
->mh64
->ncmds
= ncmds
;
4492 free(new_load_commands
);
4494 /* reset the pointers into the load commands */
4495 object
->code_sig_cmd
= NULL
;
4496 lc1
= arch
->object
->load_commands
;
4497 for(i
= 0; i
< ncmds
; i
++){
4500 arch
->object
->st
= (struct symtab_command
*)lc1
;
4503 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
4505 case LC_TWOLEVEL_HINTS
:
4506 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
4508 case LC_PREBIND_CKSUM
:
4509 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
4512 sg
= (struct segment_command
*)lc1
;
4513 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
4514 arch
->object
->seg_linkedit
= sg
;
4516 case LC_SEGMENT_SPLIT_INFO
:
4517 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
4519 case LC_FUNCTION_STARTS
:
4520 object
->func_starts_info_cmd
=
4521 (struct linkedit_data_command
*)lc1
;
4523 case LC_DATA_IN_CODE
:
4524 object
->data_in_code_cmd
=
4525 (struct linkedit_data_command
*)lc1
;
4527 case LC_DYLIB_CODE_SIGN_DRS
:
4528 object
->code_sign_drs_cmd
=
4529 (struct linkedit_data_command
*)lc1
;
4531 case LC_DYLD_INFO_ONLY
:
4533 object
->dyld_info
= (struct dyld_info_command
*)lc1
;
4535 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4540 * To get the right amount of the file copied out by writeout() for
4541 * the case when we are stripping out the section contents we
4542 * already reduce the object size by the size of the section
4543 * contents including the padding after the load commands. So here
4544 * we need to further reduce it by the load command for the
4545 * LC_CODE_SIGNATURE (a struct linkedit_data_command) we are
4548 object
->object_size
-= sizeof(struct linkedit_data_command
);
4550 * Then this size minus the size of the input symbolic information
4551 * is what is copied out from the file by writeout(). Which in this
4552 * case is just the new headers.
4556 * Finally for -c the file offset to the link edit information is to
4557 * be right after the load commands. So reset this for the updated
4558 * size of the load commands without the LC_CODE_SIGNATURE.
4560 if(object
->mh
!= NULL
)
4561 object
->seg_linkedit
->fileoff
= sizeof(struct mach_header
) +
4564 object
->seg_linkedit64
->fileoff
=
4565 sizeof(struct mach_header_64
) + sizeofcmds
;
4568 #endif /* !(NMEDIT) */
4571 * private_extern_reference_by_module() is passed a symbol_index of a private
4572 * extern symbol and the module table. If the symbol_index appears in the
4573 * module symbol table this returns TRUE else it returns FALSE.
4577 private_extern_reference_by_module(
4578 uint32_t symbol_index
,
4579 struct dylib_reference
*refs
,
4580 uint32_t nextrefsyms
)
4584 for(i
= 0; i
< nextrefsyms
; i
++){
4585 if(refs
[i
].isym
== symbol_index
){
4586 if(refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
||
4587 refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
){
4596 * symbol_pointer_used() is passed a symbol_index and the indirect table. If
4597 * the symbol_index appears in the indirect symbol table this returns TRUE else
4602 symbol_pointer_used(
4603 uint32_t symbol_index
,
4604 uint32_t *indirectsyms
,
4605 uint32_t nindirectsyms
)
4609 for(i
= 0; i
< nindirectsyms
; i
++){
4610 if(indirectsyms
[i
] == symbol_index
)
4617 * Function for qsort for comparing undefined map entries.
4621 cmp_qsort_undef_map(
4622 const struct undef_map
*sym1
,
4623 const struct undef_map
*sym2
)
4625 return(strcmp(qsort_strings
+ sym1
->symbol
.n_un
.n_strx
,
4626 qsort_strings
+ sym2
->symbol
.n_un
.n_strx
));
4631 cmp_qsort_undef_map_64(
4632 const struct undef_map64
*sym1
,
4633 const struct undef_map64
*sym2
)
4635 return(strcmp(qsort_strings
+ sym1
->symbol64
.n_un
.n_strx
,
4636 qsort_strings
+ sym2
->symbol64
.n_un
.n_strx
));
4638 #endif /* !defined(NMEDIT) */
4642 * Function for qsort for comparing object names.
4650 return(strcmp(*name1
, *name2
));
4654 * Function for bsearch for finding a object name.
4658 cmp_bsearch_filename(
4662 return(strcmp(name1
, *name2
));
4664 #endif /* !defined(NMEDIT) */
4671 struct member
*member
,
4672 struct object
*object
,
4673 struct nlist
*symbols
,
4674 struct nlist_64
*symbols64
,
4678 struct dylib_table_of_contents
*tocs
,
4680 struct dylib_module
*mods
,
4681 struct dylib_module_64
*mods64
,
4683 struct dylib_reference
*refs
,
4684 uint32_t nextrefsyms
)
4687 unsigned char data_n_sect
, nsects
;
4688 struct load_command
*lc
;
4689 struct segment_command
*sg
;
4690 struct segment_command_64
*sg64
;
4691 struct section
*s
, **sections
;
4692 struct section_64
*s64
, **sections64
;
4694 uint32_t missing_syms
;
4695 struct symbol_list
*sp
;
4696 struct nlist
**global_symbol
;
4697 struct nlist_64
**global_symbol64
;
4698 enum bool global_symbol_found
;
4699 char *global_name
, save_char
;
4700 enum bool dwarf_debug_map
;
4701 enum byte_sex host_byte_sex
;
4702 int32_t missing_reloc_symbols
;
4703 enum bool edit_symtab_return
;
4706 uint32_t new_ext_strsize
, len
, inew_syms
;
4708 struct nlist
**changed_globals
;
4709 struct nlist_64
**changed_globals64
;
4710 uint32_t nchanged_globals
;
4711 uint32_t ncmds
, s_flags
, n_strx
, module_name
, ilocalsym
, nlocalsym
;
4712 uint32_t iextdefsym
, nextdefsym
;
4713 uint8_t n_type
, n_sect
, global_symbol_n_sect
;
4715 enum bool warned_about_global_coalesced_symbols
;
4717 edit_symtab_return
= TRUE
;
4718 host_byte_sex
= get_host_byte_sex();
4719 missing_reloc_symbols
= 0;
4720 warned_about_global_coalesced_symbols
= FALSE
;
4724 nmedits
= allocate(nsyms
* sizeof(enum bool));
4725 for(i
= 0; i
< nsyms
; i
++)
4729 * If nmedit is operating on a dynamic library then symbols are turned
4730 * into private externs with the extern bit off not into static symbols.
4732 if(object
->mh_filetype
== MH_DYLIB
&& pflag
== TRUE
){
4733 error_arch(arch
, member
, "can't use -p with dynamic libraries");
4738 * As part of the MAJOR guess for the second pass to fix stabs for the
4739 * globals symbols that get turned into non-global symbols. We need to
4740 * change the stabs. To do this we to know if a N_GSYM is for a data
4741 * symbol or not to know to turn it into an N_STSYM or a N_FUN.
4742 * This logic as determined by compiling test cases with and without
4743 * the key word 'static' and looking at the difference between the STABS
4744 * the compiler generates and trying to match that here.
4746 * We also use this loop and the next to gather an array of section
4747 * struct pointers so we can later determine if we run into a global
4748 * symbol in a coalesced section and not turn those symbols into
4754 data_n_sect
= NO_SECT
;
4755 lc
= object
->load_commands
;
4756 if(object
->mh
!= NULL
)
4757 ncmds
= object
->mh
->ncmds
;
4759 ncmds
= object
->mh64
->ncmds
;
4760 for(i
= 0; i
< ncmds
; i
++){
4761 if(lc
->cmd
== LC_SEGMENT
){
4762 sg
= (struct segment_command
*)lc
;
4763 s
= (struct section
*)((char *)sg
+
4764 sizeof(struct segment_command
));
4765 nsects
+= sg
->nsects
;
4766 for(j
= 0; j
< sg
->nsects
; j
++){
4767 if(strcmp(s
->segname
, SEG_DATA
) == 0 &&
4768 strcmp(s
->sectname
, SECT_DATA
) == 0 &&
4769 data_n_sect
== NO_SECT
){
4770 data_n_sect
= n_sect
;
4777 else if(lc
->cmd
== LC_SEGMENT_64
){
4778 sg64
= (struct segment_command_64
*)lc
;
4779 s64
= (struct section_64
*)((char *)sg64
+
4780 sizeof(struct segment_command_64
));
4781 nsects
+= sg64
->nsects
;
4782 for(j
= 0; j
< sg64
->nsects
; j
++){
4783 if(strcmp(s64
->segname
, SEG_DATA
) == 0 &&
4784 strcmp(s64
->sectname
, SECT_DATA
) == 0 &&
4785 data_n_sect
== NO_SECT
){
4786 data_n_sect
= n_sect
;
4793 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
4795 if(object
->mh
!= NULL
){
4796 sections
= allocate(nsects
* sizeof(struct section
*));
4801 sections64
= allocate(nsects
* sizeof(struct section_64
*));
4804 lc
= object
->load_commands
;
4805 for(i
= 0; i
< ncmds
; i
++){
4806 if(lc
->cmd
== LC_SEGMENT
){
4807 sg
= (struct segment_command
*)lc
;
4808 s
= (struct section
*)((char *)sg
+
4809 sizeof(struct segment_command
));
4810 for(j
= 0; j
< sg
->nsects
; j
++){
4811 sections
[nsects
++] = s
++;
4814 else if(lc
->cmd
== LC_SEGMENT_64
){
4815 sg64
= (struct segment_command_64
*)lc
;
4816 s64
= (struct section_64
*)((char *)sg64
+
4817 sizeof(struct segment_command_64
));
4818 for(j
= 0; j
< sg64
->nsects
; j
++){
4819 sections64
[nsects
++] = s64
++;
4822 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
4826 * Zero out the saved symbols so they can be recorded for this file.
4828 for(i
= 0; i
< nsave_symbols
; i
++)
4829 save_symbols
[i
].sym
= NULL
;
4830 for(i
= 0; i
< nremove_symbols
; i
++)
4831 remove_symbols
[i
].sym
= NULL
;
4833 for(i
= 0; i
< nsave_symbols
; i
++)
4834 save_symbols
[i
].seen
= FALSE
;
4835 for(i
= 0; i
< nremove_symbols
; i
++)
4836 remove_symbols
[i
].seen
= FALSE
;
4839 nchanged_globals
= 0;
4840 if(object
->mh
!= NULL
){
4841 changed_globals
= allocate(nsyms
* sizeof(struct nlist
*));
4842 changed_globals64
= NULL
;
4843 for(i
= 0; i
< nsyms
; i
++)
4844 changed_globals
[i
] = NULL
;
4847 changed_globals
= NULL
;
4848 changed_globals64
= allocate(nsyms
* sizeof(struct nlist_64
*));
4849 for(i
= 0; i
< nsyms
; i
++)
4850 changed_globals64
[i
] = NULL
;
4854 * These are the variables for the new symbol table and new string
4855 * table. Since this routine only turns globals into non-globals the
4856 * number of symbols does not change. But the count of local, defined
4857 * external symbols does change.
4864 new_strsize
= sizeof(int32_t);
4865 new_ext_strsize
= 0;
4868 * First pass: turn the globals symbols into non-global symbols.
4870 for(i
= 0; i
< nsyms
; i
++){
4873 if(object
->mh
!= NULL
){
4874 n_strx
= symbols
[i
].n_un
.n_strx
;
4875 n_type
= symbols
[i
].n_type
;
4876 n_sect
= symbols
[i
].n_sect
;
4877 if((n_type
& N_TYPE
) == N_SECT
)
4878 s_flags
= sections
[n_sect
- 1]->flags
;
4879 n_value
= symbols
[i
].n_value
;
4882 n_strx
= symbols64
[i
].n_un
.n_strx
;
4883 n_type
= symbols64
[i
].n_type
;
4884 n_sect
= symbols64
[i
].n_sect
;
4885 if((n_type
& N_TYPE
) == N_SECT
)
4886 s_flags
= sections64
[n_sect
- 1]->flags
;
4887 n_value
= symbols64
[i
].n_value
;
4890 if(n_strx
> strsize
){
4891 error_arch(arch
, member
, "bad string index for symbol "
4892 "table entry %u in: ", i
);
4895 len
= strlen(strings
+ n_strx
) + 1;
4898 if((n_type
& N_TYPE
) != N_UNDF
&&
4899 (n_type
& N_TYPE
) != N_PBUD
){
4900 if((n_type
& N_TYPE
) == N_SECT
){
4901 if(n_sect
> nsects
){
4902 error_arch(arch
, member
, "bad n_sect for symbol "
4903 "table entry %u in: ", i
);
4906 if(((s_flags
& SECTION_TYPE
) == S_COALESCED
) &&
4908 object
->mh_filetype
!= MH_OBJECT
){
4909 /* this remains a global defined symbol */
4910 if(warned_about_global_coalesced_symbols
== FALSE
){
4911 warning_arch(arch
, member
, "can't make global "
4912 "coalesced symbols (like %s) into static "
4913 "symbols (use ld(1)'s "
4914 "-exported_symbols_list option) in a final "
4915 "linked image: ", strings
+ n_strx
);
4916 warned_about_global_coalesced_symbols
= TRUE
;
4919 new_ext_strsize
+= len
;
4921 sp
= bsearch(strings
+ n_strx
,
4922 remove_symbols
, nremove_symbols
,
4923 sizeof(struct symbol_list
),
4924 (int (*)(const void *, const void *))
4925 symbol_list_bsearch
);
4927 if(sp
->sym
!= NULL
){
4928 error_arch(arch
, member
, "more than one "
4929 "symbol for: %s found in: ", sp
->name
);
4933 if(object
->mh
!= NULL
)
4934 sp
->sym
= &(symbols
[i
]);
4936 sp
->sym
= &(symbols64
[i
]);
4938 warning_arch(arch
, member
, "can't make "
4939 "global coalesced symbol: %s into a "
4940 "static symbol in: ", sp
->name
);
4944 * In case the user has listed this coalesced
4945 * symbol in the save list look for it and mark it
4946 * as seen so we don't complain about not seeing it.
4948 sp
= bsearch(strings
+ n_strx
,
4949 save_symbols
, nsave_symbols
,
4950 sizeof(struct symbol_list
),
4951 (int (*)(const void *, const void *))
4952 symbol_list_bsearch
);
4954 if(sp
->sym
!= NULL
){
4955 error_arch(arch
, member
, "more than one "
4956 "symbol for: %s found in: ", sp
->name
);
4960 if(object
->mh
!= NULL
)
4961 sp
->sym
= &(symbols
[i
]);
4963 sp
->sym
= &(symbols64
[i
]);
4967 continue; /* leave this symbol unchanged */
4970 sp
= bsearch(strings
+ n_strx
,
4971 remove_symbols
, nremove_symbols
,
4972 sizeof(struct symbol_list
),
4973 (int (*)(const void *, const void *))
4974 symbol_list_bsearch
);
4976 if(sp
->sym
!= NULL
){
4977 error_arch(arch
, member
, "more than one symbol "
4978 "for: %s found in: ", sp
->name
);
4982 if(object
->mh
!= NULL
)
4983 sp
->sym
= &(symbols
[i
]);
4985 sp
->sym
= &(symbols64
[i
]);
4992 * If there is no list of saved symbols, then all
4993 * symbols will be saved unless listed in the remove
4998 * There is no save list, so if there is also no
4999 * remove list but the -p flag is specified or it is
5000 * a dynamic library then change all symbols.
5002 if((pflag
|| object
->mh_filetype
== MH_DYLIB
)
5003 && nremove_symbols
== 0)
5005 /* this remains a global defined symbol */
5007 new_ext_strsize
+= len
;
5009 continue; /* leave this symbol unchanged */
5012 sp
= bsearch(strings
+ n_strx
,
5013 save_symbols
, nsave_symbols
,
5014 sizeof(struct symbol_list
),
5015 (int (*)(const void *, const void *))
5016 symbol_list_bsearch
);
5018 if(sp
->sym
!= NULL
){
5019 error_arch(arch
, member
, "more than one symbol "
5020 "for: %s found in: ", sp
->name
);
5024 if(object
->mh
!= NULL
)
5025 sp
->sym
= &(symbols
[i
]);
5027 sp
->sym
= &(symbols64
[i
]);
5029 /* this remains a global defined symbol */
5031 new_ext_strsize
+= len
;
5036 if(Aflag
&& n_type
== (N_EXT
| N_ABS
) &&
5039 strncmp(strings
+ n_strx
,
5040 ".objc_class_name_",
5041 sizeof(".objc_class_name_") - 1) == 0))){
5042 /* this remains a global defined symbol */
5044 new_ext_strsize
+= len
;
5049 if((n_type
& N_TYPE
) != N_INDR
){
5051 if(object
->mh
!= NULL
)
5052 changed_globals
[nchanged_globals
++] =
5055 changed_globals64
[nchanged_globals
++] =
5058 /* this remains a global defined symbol */
5060 new_ext_strsize
+= len
;
5064 /* this will become a non-global symbol */
5070 /* this remains a global defined symbol */
5072 new_ext_strsize
+= len
;
5079 /* this is an undefined symbol */
5081 new_ext_strsize
+= len
;
5086 /* this is a local symbol */
5093 * The module table's module names are placed with the external
5094 * strings. So size them and add this to the external string size.
5096 for(i
= 0; i
< nmodtab
; i
++){
5097 if(object
->mh
!= NULL
)
5098 module_name
= mods
[i
].module_name
;
5100 module_name
= mods64
[i
].module_name
;
5101 if(module_name
== 0 || module_name
> strsize
){
5102 error_arch(arch
, member
, "bad string index for module_name "
5103 "of module table entry %d in: ", i
);
5106 len
= strlen(strings
+ module_name
) + 1;
5108 new_ext_strsize
+= len
;
5112 * Warn about symbols to be saved that were missing.
5117 for(i
= 0; i
< nsave_symbols
; i
++){
5118 if(save_symbols
[i
].sym
== NULL
){
5119 if(missing_syms
== 0){
5120 error_arch(arch
, member
, "symbols names listed "
5121 "in: %s not in: ", sfile
);
5124 fprintf(stderr
, "%s\n", save_symbols
[i
].name
);
5127 for(i
= 0; i
< nremove_symbols
; i
++){
5128 if(remove_symbols
[i
].sym
== NULL
){
5129 if(missing_syms
== 0){
5130 error_arch(arch
, member
, "symbols names listed "
5131 "in: %s not in: ", Rfile
);
5134 fprintf(stderr
, "%s\n", remove_symbols
[i
].name
);
5141 * Second pass: fix stabs for the globals symbols that got turned into
5142 * non-global symbols. This is a MAJOR guess. The specific changes
5143 * to do here were determined by compiling test cases with and without
5144 * the key word 'static' and looking at the difference between the STABS
5145 * the compiler generates and trying to match that here.
5147 global_strings
= strings
;
5148 if(object
->mh
!= NULL
)
5149 qsort(changed_globals
, nchanged_globals
, sizeof(struct nlist
*),
5150 (int (*)(const void *, const void *))cmp_qsort_global
);
5152 qsort(changed_globals64
, nchanged_globals
,sizeof(struct nlist_64
*),
5153 (int (*)(const void *, const void *))cmp_qsort_global_64
);
5154 dwarf_debug_map
= FALSE
;
5155 for(i
= 0; i
< nsyms
; i
++){
5157 if(object
->mh
!= NULL
){
5158 n_strx
= symbols
[i
].n_un
.n_strx
;
5159 n_type
= symbols
[i
].n_type
;
5160 n_desc
= symbols
[i
].n_desc
;
5163 n_strx
= symbols64
[i
].n_un
.n_strx
;
5164 n_type
= symbols64
[i
].n_type
;
5165 n_desc
= symbols64
[i
].n_desc
;
5168 dwarf_debug_map
= FALSE
;
5169 else if (n_type
== N_OSO
)
5170 dwarf_debug_map
= n_desc
!= 0;
5171 else if (dwarf_debug_map
&& n_type
== N_GSYM
){
5172 global_name
= strings
+ n_strx
;
5173 if(object
->mh
!= NULL
){
5174 global_symbol
= bsearch(global_name
, changed_globals
,
5175 nchanged_globals
,sizeof(struct nlist
*),
5176 (int (*)(const void *, const void *))
5177 cmp_bsearch_global
);
5178 if(global_symbol
!= NULL
){
5179 symbols
[i
].n_type
= N_STSYM
;
5180 symbols
[i
].n_sect
= (*global_symbol
)->n_sect
;
5181 symbols
[i
].n_value
= (*global_symbol
)->n_value
;
5185 global_symbol64
= bsearch(global_name
, changed_globals64
,
5187 sizeof(struct nlist_64
*),
5188 (int (*)(const void *, const void *))
5189 cmp_bsearch_global_64
);
5190 if(global_symbol64
!= NULL
){
5191 symbols64
[i
].n_type
= N_STSYM
;
5192 symbols64
[i
].n_sect
= (*global_symbol64
)->n_sect
;
5193 symbols64
[i
].n_value
= (*global_symbol64
)->n_value
;
5197 else if(! dwarf_debug_map
&&
5198 (n_type
== N_GSYM
|| n_type
== N_FUN
) &&
5199 (n_strx
!= 0 && strings
[n_strx
] != '\0')){
5200 global_name
= strings
+ n_strx
;
5201 if((global_name
[0] == '+' || global_name
[0] == '-') &&
5202 global_name
[1] == '['){
5204 while(j
+ n_strx
< strsize
&& global_name
[j
] != ']')
5206 if(j
+ n_strx
< strsize
&& global_name
[j
] == ']')
5211 while(j
+ n_strx
< strsize
&& global_name
[j
] != ':')
5213 if(j
+ n_strx
>= strsize
){
5214 error_arch(arch
, member
, "bad N_STAB symbol name for entry "
5215 "%u (does not contain ':' separating name from type) "
5219 save_char
= global_name
[j
];
5220 global_name
[j
] = '\0';
5222 global_symbol_found
= FALSE
;
5223 global_symbol_n_sect
= 0;
5224 if(object
->mh
!= NULL
){
5225 global_symbol
= bsearch(global_name
, changed_globals
,
5226 nchanged_globals
,sizeof(struct nlist
*),
5227 (int (*)(const void *, const void *))
5228 cmp_bsearch_global_stab
);
5229 global_symbol64
= NULL
;
5230 if(global_symbol
!= NULL
){
5231 global_symbol_found
= TRUE
;
5232 global_symbol_n_sect
= (*global_symbol
)->n_sect
;
5236 global_symbol64
= bsearch(global_name
, changed_globals64
,
5238 sizeof(struct nlist_64
*),
5239 (int (*)(const void *, const void *))
5240 cmp_bsearch_global_stab_64
);
5241 global_symbol
= NULL
;
5242 if(global_symbol64
!= NULL
){
5243 global_symbol_found
= TRUE
;
5244 global_symbol_n_sect
= (*global_symbol64
)->n_sect
;
5247 global_name
[j
] = save_char
;
5248 if(global_symbol_found
== TRUE
){
5249 if(n_type
== N_GSYM
){
5250 if(global_symbol_n_sect
== data_n_sect
){
5251 if(object
->mh
!= NULL
)
5252 symbols
[i
].n_type
= N_STSYM
;
5254 symbols64
[i
].n_type
= N_STSYM
;
5257 if(object
->mh
!= NULL
)
5258 symbols
[i
].n_type
= N_FUN
;
5260 symbols64
[i
].n_type
= N_FUN
;
5262 if(object
->mh
!= NULL
){
5263 symbols
[i
].n_sect
= (*global_symbol
)->n_sect
;
5264 symbols
[i
].n_value
= (*global_symbol
)->n_value
;
5265 symbols
[i
].n_desc
= (*global_symbol
)->n_desc
;
5268 symbols64
[i
].n_sect
= (*global_symbol64
)->n_sect
;
5269 symbols64
[i
].n_value
= (*global_symbol64
)->n_value
;
5270 symbols64
[i
].n_desc
= (*global_symbol64
)->n_desc
;
5272 if(j
+ 1 + n_strx
>= strsize
||
5273 global_name
[j
+1] != 'G'){
5274 error_arch(arch
, member
, "bad N_GSYM symbol name "
5275 "for entry %u (does not have type 'G' after "
5276 "':' in name) in: ", i
);
5279 global_name
[j
+1] = 'S';
5281 else{ /* n_type == N_FUN */
5282 if(j
+ 1 + n_strx
>= strsize
||
5283 global_name
[j
+1] == 'F'){
5284 global_name
[j
+1] = 'f';
5290 global_strings
= NULL
;
5293 * Now what needs to be done is to create the new symbol table moving
5294 * those global symbols being changed into non-globals into the areas
5295 * in the symbol table for local symbols. The symbol table and string
5296 * table must be in this order:
5300 * external defined symbols
5308 saves
= (int32_t *)allocate(nsyms
* sizeof(int32_t));
5309 bzero(saves
, nsyms
* sizeof(int32_t));
5311 if(object
->mh
!= NULL
){
5312 new_symbols
= (struct nlist
*)
5313 allocate(new_nsyms
* sizeof(struct nlist
));
5314 new_symbols64
= NULL
;
5318 new_symbols64
= (struct nlist_64
*)
5319 allocate(new_nsyms
* sizeof(struct nlist_64
));
5321 new_strsize
= rnd(new_strsize
, sizeof(int32_t));
5322 new_strings
= (char *)allocate(new_strsize
);
5323 new_strings
[new_strsize
- 3] = '\0';
5324 new_strings
[new_strsize
- 2] = '\0';
5325 new_strings
[new_strsize
- 1] = '\0';
5327 memset(new_strings
, '\0', sizeof(int32_t));
5328 p
= new_strings
+ sizeof(int32_t);
5329 q
= p
+ new_ext_strsize
;
5332 * If this is a dynamic library the movement of the symbols has to be
5333 * done with respect to the modules. As the local symbols, and external
5334 * defined symbols are grouped together for each module. Then a new
5335 * module table needs to be created with the new indexes into the symbol
5336 * table for each module.
5338 new_nmodtab
= nmodtab
;
5340 new_nextrefsyms
= nextrefsyms
;
5341 if(object
->mh_filetype
== MH_DYLIB
&& nmodtab
!= 0){
5342 if(object
->mh
!= NULL
){
5343 new_mods
= allocate(nmodtab
* sizeof(struct dylib_module
));
5348 new_mods64
= allocate(nmodtab
* sizeof(struct dylib_module_64
));
5353 * This first loop through the module table sets the index and
5354 * counts of the local symbols for each module.
5356 for(i
= 0; i
< nmodtab
; i
++){
5358 * First put the existing local symbols into the new symbol
5361 if(object
->mh
!= NULL
){
5362 new_mods
[i
].ilocalsym
= inew_syms
;
5363 new_mods
[i
].nlocalsym
= 0;
5364 ilocalsym
= mods
[i
].ilocalsym
;
5365 nlocalsym
= mods
[i
].nlocalsym
;
5368 new_mods64
[i
].ilocalsym
= inew_syms
;
5369 new_mods64
[i
].nlocalsym
= 0;
5370 ilocalsym
= mods64
[i
].ilocalsym
;
5371 nlocalsym
= mods64
[i
].nlocalsym
;
5373 for(j
= ilocalsym
; j
< ilocalsym
+ nlocalsym
; j
++){
5374 if(object
->mh
!= NULL
){
5375 n_strx
= symbols
[j
].n_un
.n_strx
;
5376 n_type
= symbols
[j
].n_type
;
5379 n_strx
= symbols64
[j
].n_un
.n_strx
;
5380 n_type
= symbols64
[j
].n_type
;
5382 if((n_type
& N_EXT
) == 0){
5383 if(object
->mh
!= NULL
)
5384 new_symbols
[inew_syms
] = symbols
[j
];
5386 new_symbols64
[inew_syms
] = symbols64
[j
];
5388 strcpy(q
, strings
+ n_strx
);
5389 if(object
->mh
!= NULL
)
5390 new_symbols
[inew_syms
].n_un
.n_strx
=
5393 new_symbols64
[inew_syms
].n_un
.n_strx
=
5398 saves
[j
] = inew_syms
;
5399 if(object
->mh
!= NULL
)
5400 new_mods
[i
].nlocalsym
++;
5402 new_mods64
[i
].nlocalsym
++;
5406 * Next put the global symbols that were changed into
5407 * non-global symbols into the new symbol table and moved their
5408 * counts to the local symbol counts.
5410 if(object
->mh
!= NULL
){
5411 iextdefsym
= mods
[i
].iextdefsym
;
5412 nextdefsym
= mods
[i
].nextdefsym
;
5415 iextdefsym
= mods64
[i
].iextdefsym
;
5416 nextdefsym
= mods64
[i
].nextdefsym
;
5418 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
5419 if(object
->mh
!= NULL
){
5420 n_strx
= symbols
[j
].n_un
.n_strx
;
5421 n_type
= symbols
[j
].n_type
;
5424 n_strx
= symbols64
[j
].n_un
.n_strx
;
5425 n_type
= symbols64
[j
].n_type
;
5427 if((n_type
& N_EXT
) != 0){
5428 if(nmedits
[j
] == TRUE
){
5430 * Change the new symbol to a private extern symbol
5431 * with the extern bit off.
5433 if(object
->mh
!= NULL
){
5434 new_symbols
[inew_syms
] = symbols
[j
];
5435 new_symbols
[inew_syms
].n_type
|= N_PEXT
;
5436 new_symbols
[inew_syms
].n_type
&= ~N_EXT
;
5439 new_symbols64
[inew_syms
] = symbols64
[j
];
5440 new_symbols64
[inew_syms
].n_type
|= N_PEXT
;
5441 new_symbols64
[inew_syms
].n_type
&= ~N_EXT
;
5444 strcpy(q
, strings
+ n_strx
);
5445 if(object
->mh
!= NULL
)
5446 new_symbols
[inew_syms
].n_un
.n_strx
=
5449 new_symbols64
[inew_syms
].n_un
.n_strx
=
5454 saves
[j
] = inew_syms
;
5455 if(object
->mh
!= NULL
)
5456 new_mods
[i
].nlocalsym
++;
5458 new_mods64
[i
].nlocalsym
++;
5464 * Next put the unchanged defined global symbols into the new
5467 for(i
= 0; i
< nmodtab
; i
++){
5468 if(object
->mh
!= NULL
){
5469 new_mods
[i
].iextdefsym
= inew_syms
;
5470 new_mods
[i
].nextdefsym
= 0;
5471 iextdefsym
= mods
[i
].iextdefsym
;
5472 nextdefsym
= mods
[i
].nextdefsym
;
5475 new_mods64
[i
].iextdefsym
= inew_syms
;
5476 new_mods64
[i
].nextdefsym
= 0;
5477 iextdefsym
= mods64
[i
].iextdefsym
;
5478 nextdefsym
= mods64
[i
].nextdefsym
;
5480 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
5481 if(object
->mh
!= NULL
){
5482 n_strx
= symbols
[j
].n_un
.n_strx
;
5483 n_type
= symbols
[j
].n_type
;
5486 n_strx
= symbols64
[j
].n_un
.n_strx
;
5487 n_type
= symbols64
[j
].n_type
;
5489 if((n_type
& N_EXT
) != 0){
5490 if(nmedits
[j
] == FALSE
){
5491 if(object
->mh
!= NULL
)
5492 new_symbols
[inew_syms
] = symbols
[j
];
5494 new_symbols64
[inew_syms
] = symbols64
[j
];
5496 strcpy(p
, strings
+ n_strx
);
5497 if(object
->mh
!= NULL
)
5498 new_symbols
[inew_syms
].n_un
.n_strx
=
5501 new_symbols64
[inew_syms
].n_un
.n_strx
=
5506 saves
[j
] = inew_syms
;
5507 if(object
->mh
!= NULL
)
5508 new_mods
[i
].nextdefsym
++;
5510 new_mods64
[i
].nextdefsym
++;
5516 * Last put the undefined symbols into the new symbol table.
5518 for(i
= 0; i
< nsyms
; i
++){
5519 if(object
->mh
!= NULL
){
5520 n_strx
= symbols
[i
].n_un
.n_strx
;
5521 n_type
= symbols
[i
].n_type
;
5524 n_strx
= symbols64
[i
].n_un
.n_strx
;
5525 n_type
= symbols64
[i
].n_type
;
5527 if((n_type
& N_EXT
) != 0 &&
5528 ((n_type
& N_TYPE
) == N_UNDF
||
5529 (n_type
& N_TYPE
) == N_PBUD
)){
5530 if(object
->mh
!= NULL
)
5531 new_symbols
[inew_syms
] = symbols
[i
];
5533 new_symbols64
[inew_syms
] = symbols64
[i
];
5535 strcpy(p
, strings
+ n_strx
);
5536 if(object
->mh
!= NULL
)
5537 new_symbols
[inew_syms
].n_un
.n_strx
=
5540 new_symbols64
[inew_syms
].n_un
.n_strx
=
5545 saves
[i
] = inew_syms
;
5550 * Place the module table's module names with the external strings
5551 * and set the names in the new module table. And then copy the
5552 * other unchanged fields.
5554 for(i
= 0; i
< nmodtab
; i
++){
5555 if(object
->mh
!= NULL
){
5556 strcpy(p
, strings
+ mods
[i
].module_name
);
5557 new_mods
[i
].module_name
= p
- new_strings
;
5560 new_mods
[i
].irefsym
= mods
[i
].irefsym
;
5561 new_mods
[i
].nrefsym
= mods
[i
].nrefsym
;
5562 new_mods
[i
].iextrel
= mods
[i
].iextrel
;
5563 new_mods
[i
].nextrel
= mods
[i
].nextrel
;
5564 new_mods
[i
].iinit_iterm
= mods
[i
].iinit_iterm
;
5565 new_mods
[i
].ninit_nterm
= mods
[i
].ninit_nterm
;
5566 new_mods
[i
].objc_module_info_addr
=
5567 mods
[i
].objc_module_info_addr
;
5568 new_mods
[i
].objc_module_info_size
=
5569 mods
[i
].objc_module_info_size
;
5572 strcpy(p
, strings
+ mods64
[i
].module_name
);
5573 new_mods64
[i
].module_name
= p
- new_strings
;
5576 new_mods64
[i
].irefsym
= mods64
[i
].irefsym
;
5577 new_mods64
[i
].nrefsym
= mods64
[i
].nrefsym
;
5578 new_mods64
[i
].iextrel
= mods64
[i
].iextrel
;
5579 new_mods64
[i
].nextrel
= mods64
[i
].nextrel
;
5580 new_mods64
[i
].iinit_iterm
= mods64
[i
].iinit_iterm
;
5581 new_mods64
[i
].ninit_nterm
= mods64
[i
].ninit_nterm
;
5582 new_mods64
[i
].objc_module_info_addr
=
5583 mods64
[i
].objc_module_info_addr
;
5584 new_mods64
[i
].objc_module_info_size
=
5585 mods64
[i
].objc_module_info_size
;
5590 * Update the reference table with the new symbol indexes for all
5591 * entries and change type of reference (the flags field) for those
5592 * symbols that got changed from globals to non-globals.
5594 new_nextrefsyms
= nextrefsyms
;
5595 new_refs
= allocate(new_nextrefsyms
*
5596 sizeof(struct dylib_reference
));
5598 for(i
= 0; i
< nextrefsyms
; i
++){
5599 if(nmedits
[refs
[i
].isym
] == TRUE
){
5600 if(refs
[i
].flags
== REFERENCE_FLAG_DEFINED
)
5602 REFERENCE_FLAG_PRIVATE_DEFINED
;
5603 else if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
)
5605 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
;
5606 else if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
)
5608 REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
;
5610 new_refs
[i
].flags
= refs
[i
].flags
;
5613 new_refs
[i
].flags
= refs
[i
].flags
;
5615 new_refs
[i
].isym
= saves
[refs
[i
].isym
] - 1;
5619 * Create a new dylib table of contents without the global symbols
5620 * that got turned into non-globals.
5622 new_ntoc
= ntoc
- nchanged_globals
;
5623 new_tocs
= allocate(new_ntoc
*
5624 sizeof(struct dylib_table_of_contents
));
5626 for(i
= 0; i
< ntoc
; i
++){
5627 if(tocs
[i
].symbol_index
>= nsyms
){
5628 error_arch(arch
, member
, "bad symbol index for table of "
5629 "contents table entry %d in: ", i
);
5632 if(nmedits
[tocs
[i
].symbol_index
] == FALSE
){
5633 new_tocs
[k
].symbol_index
= saves
[tocs
[i
].symbol_index
] - 1;
5634 new_tocs
[k
].module_index
= tocs
[i
].module_index
;
5640 * If is not a dynamic library so all global symbols changed into
5641 * statics can be moved to the end of the local symbols. If the pflag
5642 * is set then the changed symbols remain global and just get the
5643 * private extern bit set.
5647 * First put the existing local symbols into the new symbol table.
5650 for(i
= 0; i
< nsyms
; i
++){
5651 if(object
->mh
!= NULL
){
5652 n_strx
= symbols
[i
].n_un
.n_strx
;
5653 n_type
= symbols
[i
].n_type
;
5656 n_strx
= symbols64
[i
].n_un
.n_strx
;
5657 n_type
= symbols64
[i
].n_type
;
5659 if((n_type
& N_EXT
) == 0){
5660 if(object
->mh
!= NULL
)
5661 new_symbols
[inew_syms
] = symbols
[i
];
5663 new_symbols64
[inew_syms
] = symbols64
[i
];
5665 strcpy(q
, strings
+ n_strx
);
5666 if(object
->mh
!= NULL
)
5667 new_symbols
[inew_syms
].n_un
.n_strx
=
5670 new_symbols64
[inew_syms
].n_un
.n_strx
=
5675 saves
[i
] = inew_syms
;
5679 * Next put the global symbols that were changed into statics
5680 * symbols into the new symbol table.
5683 for(i
= 0; i
< nsyms
; i
++){
5684 if(object
->mh
!= NULL
){
5685 n_strx
= symbols
[i
].n_un
.n_strx
;
5686 n_type
= symbols
[i
].n_type
;
5689 n_strx
= symbols64
[i
].n_un
.n_strx
;
5690 n_type
= symbols64
[i
].n_type
;
5692 if((n_type
& N_EXT
) != 0){
5693 if(nmedits
[i
] == TRUE
){
5695 * Change the new symbol to not be an extern symbol
5696 * by turning off the extern bit.
5698 if(object
->mh
!= NULL
){
5699 new_symbols
[inew_syms
] = symbols
[i
];
5700 new_symbols
[inew_syms
].n_type
&= ~N_EXT
;
5701 new_symbols
[inew_syms
].n_desc
&= ~N_WEAK_DEF
;
5704 new_symbols64
[inew_syms
] = symbols64
[i
];
5705 new_symbols64
[inew_syms
].n_type
&= ~N_EXT
;
5706 new_symbols64
[inew_syms
].n_desc
&= ~N_WEAK_DEF
;
5709 strcpy(q
, strings
+ n_strx
);
5710 if(object
->mh
!= NULL
)
5711 new_symbols
[inew_syms
].n_un
.n_strx
=
5714 new_symbols64
[inew_syms
].n_un
.n_strx
=
5719 saves
[i
] = inew_syms
;
5725 * Last put the unchanged global symbols into the new symbol table
5726 * and symbols changed into private externs.
5728 for(i
= 0; i
< nsyms
; i
++){
5729 if(object
->mh
!= NULL
){
5730 n_strx
= symbols
[i
].n_un
.n_strx
;
5731 n_type
= symbols
[i
].n_type
;
5734 n_strx
= symbols64
[i
].n_un
.n_strx
;
5735 n_type
= symbols64
[i
].n_type
;
5737 if((n_type
& N_EXT
) != 0){
5738 if(nmedits
[i
] == FALSE
|| pflag
== TRUE
){
5739 if(object
->mh
!= NULL
)
5740 new_symbols
[inew_syms
] = symbols
[i
];
5742 new_symbols64
[inew_syms
] = symbols64
[i
];
5743 if(nmedits
[i
] == TRUE
&& pflag
== TRUE
){
5745 * Change the new symbol to be a private extern
5746 * symbol by turning on the private extern bit.
5748 if(object
->mh
!= NULL
)
5749 new_symbols
[inew_syms
].n_type
|= N_PEXT
;
5751 new_symbols64
[inew_syms
].n_type
|= N_PEXT
;
5754 strcpy(p
, strings
+ n_strx
);
5755 if(object
->mh
!= NULL
)
5756 new_symbols
[inew_syms
].n_un
.n_strx
=
5759 new_symbols64
[inew_syms
].n_un
.n_strx
=
5764 saves
[i
] = inew_syms
;
5770 if(sections
!= NULL
)
5772 if(sections64
!= NULL
)
5782 * Function for qsort for comparing global symbol names.
5787 const struct nlist
**sym1
,
5788 const struct nlist
**sym2
)
5790 return(strcmp(global_strings
+ (*sym1
)->n_un
.n_strx
,
5791 global_strings
+ (*sym2
)->n_un
.n_strx
));
5796 cmp_qsort_global_64(
5797 const struct nlist_64
**sym1
,
5798 const struct nlist_64
**sym2
)
5800 return(strcmp(global_strings
+ (*sym1
)->n_un
.n_strx
,
5801 global_strings
+ (*sym2
)->n_un
.n_strx
));
5805 * Function for bsearch for finding a global symbol that matches a stab name.
5809 cmp_bsearch_global_stab(
5811 const struct nlist
**sym
)
5814 * The +1 is for the '_' on the global symbol that is not on the
5815 * stab string that is trying to be matched.
5817 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
+ 1));
5822 cmp_bsearch_global_stab_64(
5824 const struct nlist_64
**sym
)
5827 * The +1 is for the '_' on the global symbol that is not on the
5828 * stab string that is trying to be matched.
5830 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
+ 1));
5834 * Function for bsearch for finding a global symbol that matches a stab name
5841 const struct nlist
**sym
)
5843 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
));
5848 cmp_bsearch_global_64(
5850 const struct nlist_64
**sym
)
5852 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
));
5854 #endif /* defined(NMEDIT) */