2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * The strip(1) and nmedit(l) program. This understands only Mach-O format
25 * files (with the restriction the symbol table is at the end of the file) and
26 * fat files with Mach-O files in them.
34 #include <sys/types.h>
36 #include <mach-o/loader.h>
37 #include <mach-o/reloc.h>
38 #include <mach-o/nlist.h>
39 #include <mach-o/stab.h>
40 #include "stuff/breakout.h"
41 #include "stuff/allocate.h"
42 #include "stuff/errors.h"
43 #include "stuff/rnd.h"
44 #include "stuff/reloc.h"
45 #include "stuff/reloc.h"
46 #include "stuff/symbol_list.h"
47 #include "stuff/unix_standard_mode.h"
48 #include "stuff/execute.h"
50 #include <mach-o/prune_trie.h>
51 #endif /* TRIE_SUPPORT */
53 /* These are set from the command line arguments */
55 char *progname
= NULL
; /* name of the program for error messages (argv[0]) */
56 static char *output_file
;/* name of the output file */
57 static char *sfile
; /* filename of global symbol names to keep */
58 static char *Rfile
; /* filename of global symbol names to remove */
59 static uint32_t Aflag
; /* save only absolute symbols with non-zero value and
60 .objc_class_name_* symbols */
61 static uint32_t aflag
; /* -a save all symbols, just regenerate symbol table */
62 static uint32_t iflag
; /* -i ignore symbols in -s file not in object */
64 static uint32_t pflag
; /* make all defined global symbols private extern */
65 #else /* !defined(NMEDIT) */
66 static char *dfile
; /* filename of filenames of debugger symbols to keep */
67 static uint32_t uflag
; /* save undefined symbols */
68 static uint32_t rflag
; /* save symbols referenced dynamically */
69 static uint32_t nflag
; /* save N_SECT global symbols */
70 static uint32_t Sflag
; /* -S strip only debugger symbols N_STAB */
71 static uint32_t xflag
; /* -x strip non-globals */
72 static uint32_t Xflag
; /* -X strip local symbols with 'L' names */
73 static uint32_t tflag
; /* -t strip local symbols except those in the text
74 section with names that don't begin with 'L' */
75 static uint32_t cflag
; /* -c strip section contents from dynamic libraries
76 files to create stub libraries */
77 static uint32_t no_uuid
;/* -no_uuid strip LC_UUID load commands */
78 static uint32_t no_code_signature
;
79 /* -no_code_signature strip LC_CODE_SIGNATURE cmds */
80 static uint32_t vflag
; /* -v for verbose debugging ld -r executions */
81 static uint32_t lflag
; /* -l do ld -r executions even if it has bugs */
82 static uint32_t strip_all
= 1;
84 * This is set on an object by object basis if the strip_all flag is still set
85 * and the object is an executable that is for use with the dynamic linker.
86 * This has the same effect as -r and -u.
88 static enum bool default_dyld_executable
= FALSE
;
92 * Data structures to perform selective stripping of symbol table entries.
93 * save_symbols is the names of the symbols from the -s <file> argument.
94 * remove_symbols is the names of the symbols from the -R <file> argument.
96 static struct symbol_list
*save_symbols
= NULL
;
97 static uint32_t nsave_symbols
= 0;
98 static struct symbol_list
*remove_symbols
= NULL
;
99 static uint32_t nremove_symbols
= 0;
102 * saves points to an array of uint32_t's that is allocated. This array is a
103 * map of old symbol indexes to new symbol indexes. The new symbol indexes are
104 * plus 1 and zero value means that old symbol is not in the new symbol table.
105 * ref_saves is used in the same way but for the reference table.
106 * nmedits is an array and indexed by the symbol index the value indicates if
107 * the symbol was edited and turned into a non-global.
109 static int32_t *saves
= NULL
;
111 static int32_t *ref_saves
= NULL
;
113 static enum bool *nmedits
= NULL
;
117 * These hold pointers to the symbol, string and indirect tables being worked on
118 * by strip_object and strip_symtab() from an input object file or possiblity
119 * changed to an ld -r (-S or -x) file by make_ld_r_object().
121 static struct nlist
*symbols
= NULL
;
122 static struct nlist_64
*symbols64
= NULL
;
123 static uint32_t nsyms
= 0;
124 static char *strings
= NULL
;
125 static uint32_t strsize
= 0;
126 static uint32_t *indirectsyms
= NULL
;
127 static uint32_t nindirectsyms
= 0;
130 * These hold the new symbol and string table created by strip_symtab()
131 * and the new counts of local, defined external and undefined symbols.
133 static struct nlist
*new_symbols
= NULL
;
134 static struct nlist_64
*new_symbols64
= NULL
;
135 static uint32_t new_nsyms
= 0;
136 static char *new_strings
= NULL
;
137 static uint32_t new_strsize
= 0;
138 static uint32_t new_nlocalsym
= 0;
139 static uint32_t new_nextdefsym
= 0;
140 static uint32_t new_nundefsym
= 0;
141 #if defined(TRIE_SUPPORT) && !defined(NMEDIT)
143 * The index into the new symbols where the defined external start.
145 static uint32_t inew_nextdefsym
= 0;
149 * These hold the new table of contents, reference table and module table for
152 static struct dylib_table_of_contents
*new_tocs
= NULL
;
153 static uint32_t new_ntoc
= 0;
154 static struct dylib_reference
*new_refs
= NULL
;
155 static uint32_t new_nextrefsyms
= 0;
157 static struct dylib_module
*new_mods
= NULL
;
158 static struct dylib_module_64
*new_mods64
= NULL
;
159 static uint32_t new_nmodtab
= 0;
164 * The list of file names to save debugging symbols from.
166 static char **debug_filenames
= NULL
;
167 static uint32_t ndebug_filenames
= 0;
174 struct nlist_64 symbol64
;
176 static char *qsort_strings
= NULL
;
177 #endif /* !defined(NMEDIT) */
180 /* Internal routines */
184 static void strip_file(
186 struct arch_flag
*arch_flags
,
187 uint32_t narch_flags
,
188 enum bool all_archs
);
190 static void strip_arch(
193 struct arch_flag
*arch_flags
,
194 uint32_t narch_flags
,
195 enum bool all_archs
);
197 static void strip_object(
199 struct member
*member
,
200 struct object
*object
);
202 static uint32_t get_starting_syminfo_offset(
203 struct object
*object
);
205 static void check_object_relocs(
207 struct member
*member
,
208 struct object
*object
,
213 struct relocation_info
*relocs
,
215 struct nlist
*symbols
,
216 struct nlist_64
*symbols64
,
219 int32_t *missing_reloc_symbols
,
220 enum byte_sex host_byte_sex
);
222 static void check_indirect_symtab(
224 struct member
*member
,
225 struct object
*object
,
228 uint32_t section_type
,
230 struct nlist
*symbols
,
231 struct nlist_64
*symbols64
,
234 int32_t *missing_reloc_symbols
,
235 enum byte_sex host_byte_sex
);
238 static enum bool strip_symtab(
240 struct member
*member
,
241 struct object
*object
,
242 struct dylib_table_of_contents
*tocs
,
244 struct dylib_module
*mods
,
245 struct dylib_module_64
*mods64
,
247 struct dylib_reference
*refs
,
248 uint32_t nextrefsyms
);
253 #endif /* TRIE_SUPPORT */
255 static void make_ld_r_object(
257 struct member
*member
,
258 struct object
*object
);
260 static void strip_LC_UUID_commands(
262 struct member
*member
,
263 struct object
*object
);
266 static void strip_LC_CODE_SIGNATURE_commands(
268 struct member
*member
,
269 struct object
*object
);
270 #endif /* !(NMEDIT) */
272 static enum bool private_extern_reference_by_module(
273 uint32_t symbol_index
,
274 struct dylib_reference
*refs
,
275 uint32_t nextrefsyms
);
277 static enum bool symbol_pointer_used(
278 uint32_t symbol_index
,
279 uint32_t *indirectsyms
,
280 uint32_t nindirectsyms
);
282 static int cmp_qsort_undef_map(
283 const struct undef_map
*sym1
,
284 const struct undef_map
*sym2
);
286 static int cmp_qsort_undef_map_64(
287 const struct undef_map64
*sym1
,
288 const struct undef_map64
*sym2
);
289 #endif /* !defined(NMEDIT) */
292 static enum bool edit_symtab(
294 struct member
*member
,
295 struct object
*object
,
296 struct nlist
*symbols
,
297 struct nlist_64
*symbols64
,
301 struct dylib_table_of_contents
*tocs
,
303 struct dylib_module
*mods
,
304 struct dylib_module_64
*mods64
,
306 struct dylib_reference
*refs
,
307 uint32_t nextrefsyms
);
311 static void setup_debug_filenames(
314 static int cmp_qsort_filename(
318 static int cmp_bsearch_filename(
325 * This variable and routines are used for nmedit(1) only.
327 static char *global_strings
= NULL
;
329 static int cmp_qsort_global(
330 const struct nlist
**sym1
,
331 const struct nlist
**sym2
);
333 static int cmp_qsort_global_64(
334 const struct nlist_64
**sym1
,
335 const struct nlist_64
**sym2
);
337 static int cmp_bsearch_global_stab(
339 const struct nlist
**sym
);
341 static int cmp_bsearch_global_stab_64(
343 const struct nlist_64
**sym
);
345 static int cmp_bsearch_global(
347 const struct nlist
**sym
);
349 static int cmp_bsearch_global_64(
351 const struct nlist_64
**sym
);
354 /* apple_version is created by the libstuff/Makefile */
355 extern char apple_version
[];
356 char *version
= apple_version
;
365 uint32_t j
, args_left
, files_specified
;
366 struct arch_flag
*arch_flags
;
367 uint32_t narch_flags
;
369 struct symbol_list
*sp
;
379 for (i
= 1; i
< argc
; i
++){
380 if(argv
[i
][0] == '-'){
381 if(argv
[i
][1] == '\0'){
385 if(strcmp(argv
[i
], "-o") == 0){
387 fatal("-o requires an argument");
388 if(output_file
!= NULL
)
389 fatal("only one -o option allowed");
390 output_file
= argv
[i
+ 1];
393 else if(strcmp(argv
[i
], "-s") == 0){
395 fatal("-s requires an argument");
397 fatal("only one -s option allowed");
401 else if(strcmp(argv
[i
], "-R") == 0){
403 fatal("-R requires an argument");
405 fatal("only one -R option allowed");
410 else if(strcmp(argv
[i
], "-d") == 0){
412 fatal("-d requires an argument");
414 fatal("only one -d option allowed");
418 else if(strcmp(argv
[i
], "-no_uuid") == 0){
421 else if(strcmp(argv
[i
], "-no_code_signature") == 0){
422 no_code_signature
= 1;
424 #endif /* !defined(NMEDIT) */
425 else if(strcmp(argv
[i
], "-arch") == 0){
427 error("missing argument(s) to %s option", argv
[i
]);
430 if(strcmp("all", argv
[i
+1]) == 0){
434 arch_flags
= reallocate(arch_flags
,
435 (narch_flags
+ 1) * sizeof(struct arch_flag
));
436 if(get_arch_from_flag(argv
[i
+1],
437 arch_flags
+ narch_flags
) == 0){
438 error("unknown architecture specification flag: "
439 "%s %s", argv
[i
], argv
[i
+1]);
443 for(j
= 0; j
< narch_flags
; j
++){
444 if(arch_flags
[j
].cputype
==
445 arch_flags
[narch_flags
].cputype
&&
446 (arch_flags
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
447 (arch_flags
[narch_flags
].cpusubtype
&
448 ~CPU_SUBTYPE_MASK
) &&
449 strcmp(arch_flags
[j
].name
,
450 arch_flags
[narch_flags
].name
) == 0)
459 for(j
= 1; argv
[i
][j
] != '\0'; j
++){
465 #else /* !defined(NMEDIT) */
497 #endif /* !defined(NMEDIT) */
502 #endif /* !defined(NMEDIT) */
521 error("unrecognized option: %s", argv
[i
]);
531 files_specified
+= argc
- (i
+ 1);
533 if(files_specified
> 1 && output_file
!= NULL
){
534 error("-o <filename> can only be used when one file is specified");
539 setup_symbol_list(sfile
, &save_symbols
, &nsave_symbols
);
543 if(Rfile
== NULL
&& pflag
== 0){
544 error("-s <filename>, -R <filename> or -p argument required");
551 setup_symbol_list(Rfile
, &remove_symbols
, &nremove_symbols
);
553 for(j
= 0; j
< nremove_symbols
; j
++){
554 sp
= bsearch(remove_symbols
[j
].name
,
555 save_symbols
, nsave_symbols
,
556 sizeof(struct symbol_list
),
557 (int (*)(const void *, const void *))
558 symbol_list_bsearch
);
560 error("symbol name: %s is listed in both -s %s and -R "
561 "%s files (can't be both saved and removed)",
562 remove_symbols
[j
].name
, sfile
, Rfile
);
570 /* the default when no -arch flags is present is to strip all archs */
576 setup_debug_filenames(dfile
);
578 #endif /* !defined(NMEDIT) */
582 for (i
= 1; i
< argc
; i
++) {
583 if(args_left
&& argv
[i
][0] == '-'){
584 if(argv
[i
][1] == '\0')
586 else if(strcmp(argv
[i
], "-o") == 0 ||
587 strcmp(argv
[i
], "-s") == 0 ||
588 strcmp(argv
[i
], "-R") == 0 ||
590 strcmp(argv
[i
], "-d") == 0 ||
591 #endif /* !defined(NMEDIT) */
592 strcmp(argv
[i
], "-arch") == 0)
596 char resolved_path
[PATH_MAX
+ 1];
598 if(realpath(argv
[i
], resolved_path
) == NULL
)
599 strip_file(argv
[i
], arch_flags
, narch_flags
, all_archs
);
601 strip_file(resolved_path
, arch_flags
,narch_flags
,all_archs
);
605 if(files_specified
== 0)
606 fatal("no files specified");
609 return(EXIT_FAILURE
);
611 return(EXIT_SUCCESS
);
620 fprintf(stderr
, "Usage: %s [-AanuStXx] [-no_uuid] [-no_code_signature] "
621 "[-] [-d filename] [-s filename] [-R filename] [-o output] "
622 "file [...]\n", progname
);
623 #else /* defined(NMEDIT) */
624 fprintf(stderr
, "Usage: %s -s filename [-R filename] [-p] [-A] [-] "
625 "[-o output] file [...] \n",
635 struct arch_flag
*arch_flags
,
636 uint32_t narch_flags
,
642 struct stat stat_buf
;
643 uint32_t previous_errors
;
644 enum bool unix_standard_mode
;
653 previous_errors
= errors
;
656 /* breakout the file for processing */
657 ofile
= breakout(input_file
, &archs
, &narchs
, FALSE
);
661 /* checkout the file for symbol table replacement processing */
662 checkout(archs
, narchs
);
664 /* process the symbols in the input file */
665 strip_arch(archs
, narchs
, arch_flags
, narch_flags
, all_archs
);
667 free_archs(archs
, narchs
);
672 /* create the output file */
673 if(stat(input_file
, &stat_buf
) == -1)
674 system_error("can't stat input file: %s", input_file
);
675 if(output_file
!= NULL
){
676 writeout(archs
, narchs
, output_file
, stat_buf
.st_mode
& 0777,
677 TRUE
, FALSE
, FALSE
, NULL
);
680 unix_standard_mode
= get_unix_standard_mode();
684 output_file
= makestr(input_file
, ".nmedit", NULL
);
685 #else /* !defined(NMEDIT) */
687 * In UNIX standard conformance mode we are not allowed to replace
688 * a file that is not writeable.
690 if(unix_standard_mode
== TRUE
&&
691 access(input_file
, W_OK
) == -1){
692 system_error("file: %s is not writable", input_file
);
693 goto strip_file_return
;
695 output_file
= makestr(input_file
, ".strip", NULL
);
698 * The UNIX standard conformance test suite expects files of
699 * MAXPATHLEN to work.
701 if(strlen(output_file
) >= MAXPATHLEN
){
703 * If there is a directory path in the name try to change
704 * the current working directory to that path.
706 if((p
= rindex(output_file
, '/')) != NULL
){
707 if((cwd_fd
= open(".", O_RDONLY
, 0)) == -1){
708 system_error("can't open current working directory");
709 goto strip_file_return
;
712 if(chdir(output_file
) == -1){
713 system_error("can't change current working directory "
714 "to: %s", output_file
);
715 goto strip_file_return
;
717 p
= rindex(input_file
, '/');
718 rename_file
= makestr(p
+ 1, NULL
);
721 * Create what might be a short enough name.
724 output_file
= makestr("strip.XXXXXX", NULL
);
725 output_file
= mktemp(output_file
);
728 writeout(archs
, narchs
, output_file
, stat_buf
.st_mode
& 0777,
729 TRUE
, FALSE
, FALSE
, NULL
);
730 if(rename_file
!= NULL
){
731 if(rename(output_file
, rename_file
) == -1)
732 system_error("can't move temporary file: %s to file: %s",
733 output_file
, rename_file
);
737 if(rename(output_file
, input_file
) == -1)
738 system_error("can't move temporary file: %s to input "
739 "file: %s", output_file
, input_file
);
745 * If we changed the current working directory change back to
746 * the previous working directory.
749 if(fchdir(cwd_fd
) == -1)
750 system_error("can't change back to previous working "
752 if(close(cwd_fd
) == -1)
753 system_error("can't close previous working directory");
759 #endif /* !defined(NMEDIT) */
760 /* clean-up data structures */
761 free_archs(archs
, narchs
);
764 errors
+= previous_errors
;
772 struct arch_flag
*arch_flags
,
773 uint32_t narch_flags
,
776 uint32_t i
, j
, k
, offset
, size
, missing_syms
;
778 cpu_subtype_t cpusubtype
;
779 struct arch_flag host_arch_flag
;
780 enum bool arch_process
, any_processing
, *arch_flag_processed
, family
;
781 const struct arch_flag
*family_arch_flag
;
784 * Using the specified arch_flags process specified objects for those
787 any_processing
= FALSE
;
788 arch_flag_processed
= NULL
;
790 arch_flag_processed
= allocate(narch_flags
* sizeof(enum bool));
791 memset(arch_flag_processed
, '\0', narch_flags
* sizeof(enum bool));
792 for(i
= 0; i
< narchs
; i
++){
794 * Determine the architecture (cputype and cpusubtype) of arch[i]
798 if(archs
[i
].type
== OFILE_ARCHIVE
){
799 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
800 if(archs
[i
].members
[j
].type
== OFILE_Mach_O
){
801 cputype
= archs
[i
].members
[j
].object
->mh_cputype
;
802 cpusubtype
= archs
[i
].members
[j
].object
->mh_cpusubtype
;
807 else if(archs
[i
].type
== OFILE_Mach_O
){
808 cputype
= archs
[i
].object
->mh_cputype
;
809 cpusubtype
= archs
[i
].object
->mh_cpusubtype
;
811 else if(archs
[i
].fat_arch
!= NULL
){
812 cputype
= archs
[i
].fat_arch
->cputype
;
813 cpusubtype
= archs
[i
].fat_arch
->cpusubtype
;
815 arch_process
= FALSE
;
816 if(all_archs
== TRUE
){
819 else if(narch_flags
!= 0){
821 if(narch_flags
== 1){
823 get_arch_family_from_cputype(arch_flags
[0].cputype
);
824 if(family_arch_flag
!= NULL
)
826 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
827 (arch_flags
[0].cpusubtype
& ~CPU_SUBTYPE_MASK
));
829 for(j
= 0; j
< narch_flags
; j
++){
830 if(arch_flags
[j
].cputype
== cputype
&&
831 ((arch_flags
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
832 (cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
835 arch_flag_processed
[j
] = TRUE
;
841 (void)get_arch_from_host(&host_arch_flag
, NULL
);
842 if(host_arch_flag
.cputype
== cputype
&&
843 (host_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
844 (cpusubtype
& ~CPU_SUBTYPE_MASK
))
847 if(narchs
!= 1 && arch_process
== FALSE
)
849 any_processing
= TRUE
;
852 * Now this arch[i] has been selected to be processed so process it
853 * according to its type.
855 if(archs
[i
].type
== OFILE_ARCHIVE
){
856 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
857 if(archs
[i
].members
[j
].type
== OFILE_Mach_O
){
858 strip_object(archs
+ i
, archs
[i
].members
+ j
,
859 archs
[i
].members
[j
].object
);
864 for(k
= 0; k
< nsave_symbols
; k
++){
865 if(save_symbols
[k
].seen
== FALSE
){
866 if(missing_syms
== 0){
867 error_arch(archs
+ i
, NULL
, "symbols names "
868 "listed in: %s not in: ", sfile
);
871 fprintf(stderr
, "%s\n", save_symbols
[k
].name
);
875 for(k
= 0; k
< nsave_symbols
; k
++){
876 save_symbols
[k
].seen
= FALSE
;
880 for(k
= 0; k
< nremove_symbols
; k
++){
881 if(remove_symbols
[k
].seen
== FALSE
){
882 if(missing_syms
== 0){
883 error_arch(archs
+ i
, NULL
, "symbols names "
884 "listed in: %s not defined in: ",
888 fprintf(stderr
, "%s\n", remove_symbols
[k
].name
);
892 for(k
= 0; k
< nremove_symbols
; k
++){
893 remove_symbols
[k
].seen
= FALSE
;
896 * Reset the library offsets and size.
899 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
900 archs
[i
].members
[j
].offset
= offset
;
902 if(archs
[i
].members
[j
].member_long_name
== TRUE
){
903 size
= rnd(archs
[i
].members
[j
].member_name_size
, 8) +
904 (rnd(sizeof(struct ar_hdr
), 8) -
905 sizeof(struct ar_hdr
));
906 archs
[i
].toc_long_name
= TRUE
;
908 if(archs
[i
].members
[j
].object
!= NULL
){
910 rnd(archs
[i
].members
[j
].object
->object_size
-
911 archs
[i
].members
[j
].object
->input_sym_info_size
+
912 archs
[i
].members
[j
].object
->output_sym_info_size
,
914 sprintf(archs
[i
].members
[j
].ar_hdr
->ar_size
, "%-*ld",
915 (int)sizeof(archs
[i
].members
[j
].ar_hdr
->ar_size
),
918 * This has to be done by hand because sprintf puts a
919 * null at the end of the buffer.
921 memcpy(archs
[i
].members
[j
].ar_hdr
->ar_fmag
, ARFMAG
,
922 (int)sizeof(archs
[i
].members
[j
].ar_hdr
->ar_fmag
));
925 size
+= archs
[i
].members
[j
].unknown_size
;
927 offset
+= sizeof(struct ar_hdr
) + size
;
929 archs
[i
].library_size
= offset
;
931 else if(archs
[i
].type
== OFILE_Mach_O
){
932 strip_object(archs
+ i
, NULL
, archs
[i
].object
);
935 warning_arch(archs
+ i
, NULL
, "can't process non-object and "
936 "non-archive file: ");
940 if(all_archs
== FALSE
&& narch_flags
!= 0){
941 for(i
= 0; i
< narch_flags
; i
++){
942 if(arch_flag_processed
[i
] == FALSE
)
943 error("file: %s does not contain architecture: %s",
944 archs
[0].file_name
, arch_flags
[i
].name
);
946 free(arch_flag_processed
);
948 if(any_processing
== FALSE
)
949 fatal("no processing done on input file: %s (specify a -arch flag)",
957 struct member
*member
,
958 struct object
*object
)
960 enum byte_sex host_byte_sex
;
962 struct dylib_table_of_contents
*tocs
;
964 struct dylib_module
*mods
;
965 struct dylib_module_64
*mods64
;
967 struct dylib_reference
*refs
;
968 uint32_t nextrefsyms
;
970 struct load_command
*lc
;
971 struct segment_command
*sg
;
972 struct segment_command_64
*sg64
;
974 struct section_64
*s64
;
975 struct relocation_info
*relocs
;
976 struct scattered_relocation_info
*sreloc
;
977 int32_t missing_reloc_symbols
;
978 uint32_t stride
, section_type
, nitems
;
980 uint32_t dyld_info_start
;
981 uint32_t dyld_info_end
;
988 host_byte_sex
= get_host_byte_sex();
990 /* Don't do anything to stub dylibs which have no load commands. */
991 if(object
->mh_filetype
== MH_DYLIB_STUB
){
992 if((object
->mh
!= NULL
&& object
->mh
->ncmds
== 0) ||
993 (object
->mh64
!= NULL
&& object
->mh64
->ncmds
== 0)){
997 if(object
->mh_filetype
== MH_DSYM
)
998 fatal_arch(arch
, member
, "can't process dSYM companion file: ");
999 if(object
->st
== NULL
|| object
->st
->nsyms
== 0){
1000 warning_arch(arch
, member
, "input object file stripped: ");
1004 nsyms
= object
->st
->nsyms
;
1005 if(object
->mh
!= NULL
){
1006 symbols
= (struct nlist
*)
1007 (object
->object_addr
+ object
->st
->symoff
);
1008 if(object
->object_byte_sex
!= host_byte_sex
)
1009 swap_nlist(symbols
, nsyms
, host_byte_sex
);
1014 symbols64
= (struct nlist_64
*)
1015 (object
->object_addr
+ object
->st
->symoff
);
1016 if(object
->object_byte_sex
!= host_byte_sex
)
1017 swap_nlist_64(symbols64
, nsyms
, host_byte_sex
);
1019 strings
= object
->object_addr
+ object
->st
->stroff
;
1020 strsize
= object
->st
->strsize
;
1023 if(object
->mh
!= NULL
)
1024 flags
= object
->mh
->flags
;
1026 flags
= object
->mh64
->flags
;
1027 if(object
->mh_filetype
== MH_DYLIB
&&
1028 (flags
& MH_PREBOUND
) != MH_PREBOUND
){
1029 arch
->dont_update_LC_ID_DYLIB_timestamp
= TRUE
;
1031 if(object
->mh_filetype
!= MH_DYLIB
&& cflag
)
1032 fatal_arch(arch
, member
, "-c can't be used on non-dynamic "
1034 #endif /* !(NMEDIT) */
1035 if(object
->mh_filetype
== MH_DYLIB_STUB
)
1036 fatal_arch(arch
, member
, "dynamic stub library can't be changed "
1039 if(object
->mh_filetype
== MH_DYLIB
){
1040 tocs
= (struct dylib_table_of_contents
*)
1041 (object
->object_addr
+ object
->dyst
->tocoff
);
1042 ntoc
= object
->dyst
->ntoc
;
1043 nmodtab
= object
->dyst
->nmodtab
;
1044 if(object
->mh
!= NULL
){
1045 mods
= (struct dylib_module
*)
1046 (object
->object_addr
+ object
->dyst
->modtaboff
);
1047 if(object
->object_byte_sex
!= host_byte_sex
)
1048 swap_dylib_module(mods
, nmodtab
, host_byte_sex
);
1053 mods64
= (struct dylib_module_64
*)
1054 (object
->object_addr
+ object
->dyst
->modtaboff
);
1055 if(object
->object_byte_sex
!= host_byte_sex
)
1056 swap_dylib_module_64(mods64
, nmodtab
, host_byte_sex
);
1058 refs
= (struct dylib_reference
*)
1059 (object
->object_addr
+ object
->dyst
->extrefsymoff
);
1060 nextrefsyms
= object
->dyst
->nextrefsyms
;
1061 if(object
->object_byte_sex
!= host_byte_sex
){
1062 swap_dylib_table_of_contents(tocs
, ntoc
, host_byte_sex
);
1063 swap_dylib_reference(refs
, nextrefsyms
, host_byte_sex
);
1067 * In the -c flag is specified then strip the section contents of
1068 * this dynamic library and change it into a stub library. When
1069 * creating a stub library the timestamp is not changed.
1072 arch
->dont_update_LC_ID_DYLIB_timestamp
= TRUE
;
1074 lc
= object
->load_commands
;
1075 if(object
->mh
!= NULL
){
1076 ncmds
= object
->mh
->ncmds
;
1077 object
->mh_filetype
= MH_DYLIB_STUB
;
1078 object
->mh
->filetype
= MH_DYLIB_STUB
;
1081 ncmds
= object
->mh64
->ncmds
;
1082 object
->mh_filetype
= MH_DYLIB_STUB
;
1083 object
->mh64
->filetype
= MH_DYLIB_STUB
;
1085 for(i
= 0; i
< ncmds
; i
++){
1086 if(lc
->cmd
== LC_SEGMENT
){
1087 sg
= (struct segment_command
*)lc
;
1088 if(strcmp(sg
->segname
, SEG_LINKEDIT
) != 0){
1090 * Zero out the section offset, reloff, and size
1091 * fields as the section contents are being removed.
1093 s
= (struct section
*)
1094 ((char *)sg
+ sizeof(struct segment_command
));
1095 for(j
= 0; j
< sg
->nsects
; j
++){
1097 * For section types with indirect tables we
1098 * do not zero out the section size in a stub
1099 * library. As the section size is needed to
1100 * know now many indirect table entries the
1101 * section has. This is a bit odd but programs
1102 * dealing with MH_DYLIB_STUB filetypes special
1105 section_type
= s
[j
].flags
& SECTION_TYPE
;
1106 if(section_type
!= S_SYMBOL_STUBS
&&
1107 section_type
!= S_LAZY_SYMBOL_POINTERS
&&
1108 section_type
!= S_LAZY_DYLIB_SYMBOL_POINTERS
&&
1109 section_type
!= S_NON_LAZY_SYMBOL_POINTERS
){
1116 /* zero out file offset and size in the segment */
1121 else if(lc
->cmd
== LC_SEGMENT_64
){
1122 sg64
= (struct segment_command_64
*)lc
;
1123 if(strcmp(sg64
->segname
, SEG_LINKEDIT
) != 0){
1125 * Zero out the section offset, reloff, and size
1126 * fields as the section contents are being removed.
1128 s64
= (struct section_64
*)
1130 sizeof(struct segment_command_64
));
1131 for(j
= 0; j
< sg64
->nsects
; j
++){
1133 * For section types with indirect tables we
1134 * do not zero out the section size in a stub
1135 * library. As the section size is needed to
1136 * know now many indirect table entries the
1137 * section has. This is a bit odd but programs
1138 * dealing with MH_DYLIB_STUB filetypes special
1141 section_type
= s64
[j
].flags
& SECTION_TYPE
;
1142 if(section_type
!= S_SYMBOL_STUBS
&&
1143 section_type
!= S_LAZY_SYMBOL_POINTERS
&&
1144 section_type
!= S_LAZY_DYLIB_SYMBOL_POINTERS
&&
1145 section_type
!= S_NON_LAZY_SYMBOL_POINTERS
){
1152 /* zero out file offset and size in the segment */
1157 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1160 * To get the right amount of the file copied out by writeout()
1161 * for the case when we are stripping out the section contents
1162 * we reduce the object size by the size of the section contents
1163 * including the padding after the load commands. Then this
1164 * size minus the size of the input symbolic information is
1167 if(object
->mh
!= NULL
){
1168 object
->object_size
-= (object
->seg_linkedit
->fileoff
-
1169 (sizeof(struct mach_header
) +
1170 object
->mh
->sizeofcmds
));
1172 * Set the file offset to the link edit information to be
1173 * right after the load commands.
1175 object
->seg_linkedit
->fileoff
=
1176 sizeof(struct mach_header
) +
1177 object
->mh
->sizeofcmds
;
1180 object
->object_size
-= (object
->seg_linkedit64
->fileoff
-
1181 (sizeof(struct mach_header_64
) +
1182 object
->mh64
->sizeofcmds
));
1184 * Set the file offset to the link edit information to be
1185 * right after the load commands.
1187 object
->seg_linkedit64
->fileoff
=
1188 sizeof(struct mach_header_64
) +
1189 object
->mh64
->sizeofcmds
;
1192 #endif /* !(NMEDIT) */
1205 * coalesced symbols can be stripped only if they are not used via an
1206 * symbol pointer. So to know that strip_symtab() needs to be passed
1207 * the indirect symbol table.
1209 if(object
->dyst
!= NULL
&& object
->dyst
->nindirectsyms
!= 0){
1210 nindirectsyms
= object
->dyst
->nindirectsyms
;
1211 indirectsyms
= (uint32_t *)
1212 (object
->object_addr
+ object
->dyst
->indirectsymoff
);
1213 if(object
->object_byte_sex
!= host_byte_sex
)
1214 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
1218 indirectsyms
= NULL
;
1222 if(object
->mh
!= NULL
)
1223 object
->input_sym_info_size
=
1224 nsyms
* sizeof(struct nlist
) +
1227 object
->input_sym_info_size
=
1228 nsyms
* sizeof(struct nlist_64
) +
1231 if(object
->mh
!= NULL
)
1232 flags
= object
->mh
->flags
;
1234 flags
= object
->mh64
->flags
;
1236 (flags
& MH_DYLDLINK
) == MH_DYLDLINK
&&
1237 object
->mh_filetype
== MH_EXECUTE
)
1238 default_dyld_executable
= TRUE
;
1240 default_dyld_executable
= FALSE
;
1241 #endif /* !defined(NMEDIT) */
1244 if(sfile
!= NULL
|| Rfile
!= NULL
|| dfile
!= NULL
|| Aflag
|| aflag
||
1245 uflag
|| Sflag
|| xflag
|| Xflag
|| tflag
|| nflag
|| rflag
||
1246 default_dyld_executable
|| object
->mh_filetype
== MH_DYLIB
||
1247 object
->mh_filetype
== MH_DYLINKER
)
1248 #endif /* !defined(NMEDIT) */
1251 if(edit_symtab(arch
, member
, object
, symbols
, symbols64
, nsyms
,
1252 strings
, strsize
, tocs
, ntoc
, mods
, mods64
, nmodtab
, refs
,
1253 nextrefsyms
) == FALSE
)
1255 #else /* !defined(NMEDIT) */
1256 if(strip_symtab(arch
, member
, object
, tocs
, ntoc
, mods
, mods64
,
1257 nmodtab
, refs
, nextrefsyms
) == FALSE
)
1260 strip_LC_UUID_commands(arch
, member
, object
);
1261 #endif /* !defined(NMEDIT) */
1263 * The parts that make up output_sym_info_size must be added up in
1264 * the output order so that when the sizes of things are rounded up
1265 * before parts that must be aligned the final output_sym_info_size
1268 * Also the parts that make up input_sym_info_size must be added up
1269 * in the same way. And must be done here as the input file may
1270 * have been changed to and "ld -r" file and may not be the
1271 * the original input file.
1273 object
->output_sym_info_size
= 0;
1274 object
->input_sym_info_size
= 0;
1275 if(object
->dyld_info
!= NULL
){
1276 /* there are five parts to the dyld info, but
1277 strip does not alter them, so copy as a block */
1278 dyld_info_start
= 0;
1279 if (object
->dyld_info
->rebase_off
!= 0)
1280 dyld_info_start
= object
->dyld_info
->rebase_off
;
1281 else if (object
->dyld_info
->bind_off
!= 0)
1282 dyld_info_start
= object
->dyld_info
->bind_off
;
1283 else if (object
->dyld_info
->weak_bind_off
!= 0)
1284 dyld_info_start
= object
->dyld_info
->weak_bind_off
;
1285 else if (object
->dyld_info
->lazy_bind_off
!= 0)
1286 dyld_info_start
= object
->dyld_info
->lazy_bind_off
;
1287 else if (object
->dyld_info
->export_off
!= 0)
1288 dyld_info_start
= object
->dyld_info
->export_off
;
1290 if (object
->dyld_info
->export_size
!= 0)
1291 dyld_info_end
= object
->dyld_info
->export_off
1292 + object
->dyld_info
->export_size
;
1293 else if (object
->dyld_info
->lazy_bind_size
!= 0)
1294 dyld_info_end
= object
->dyld_info
->lazy_bind_off
1295 + object
->dyld_info
->lazy_bind_size
;
1296 else if (object
->dyld_info
->weak_bind_size
!= 0)
1297 dyld_info_end
= object
->dyld_info
->weak_bind_off
1298 + object
->dyld_info
->weak_bind_size
;
1299 else if (object
->dyld_info
->bind_size
!= 0)
1300 dyld_info_end
= object
->dyld_info
->bind_off
1301 + object
->dyld_info
->bind_size
;
1302 else if (object
->dyld_info
->rebase_size
!= 0)
1303 dyld_info_end
= object
->dyld_info
->rebase_off
1304 + object
->dyld_info
->rebase_size
;
1305 object
->output_dyld_info
= object
->object_addr
+dyld_info_start
;
1306 object
->output_dyld_info_size
= dyld_info_end
- dyld_info_start
;
1307 object
->output_sym_info_size
+= object
->output_dyld_info_size
;
1309 * Warn about strip -s or -R on a final linked image with
1312 if(nsave_symbols
!= 0){
1313 warning_arch(arch
, NULL
, "removing global symbols from a "
1314 "final linked no longer supported. Use "
1315 "-exported_symbols_list at link time when "
1318 object
->input_sym_info_size
+= object
->dyld_info
->rebase_size
1319 + object
->dyld_info
->bind_size
1320 + object
->dyld_info
->weak_bind_size
1321 + object
->dyld_info
->lazy_bind_size
1322 + object
->dyld_info
->export_size
;
1325 if(object
->dyst
!= NULL
){
1328 * When stripping out the section contents to create a
1329 * dynamic library stub the relocation info also gets
1333 #endif /* !(NMEDIT) */
1335 object
->output_sym_info_size
+=
1336 object
->dyst
->nlocrel
* sizeof(struct relocation_info
);
1338 object
->input_sym_info_size
+=
1339 object
->dyst
->nlocrel
* sizeof(struct relocation_info
);
1342 if(object
->split_info_cmd
!= NULL
){
1343 object
->output_split_info_data
= object
->object_addr
+
1344 object
->split_info_cmd
->dataoff
;
1345 object
->output_split_info_data_size
=
1346 object
->split_info_cmd
->datasize
;
1347 object
->input_sym_info_size
+= object
->split_info_cmd
->datasize
;
1348 object
->output_sym_info_size
+=
1349 object
->split_info_cmd
->datasize
;
1352 if(object
->func_starts_info_cmd
!= NULL
){
1353 object
->output_func_start_info_data
= object
->object_addr
+
1354 object
->func_starts_info_cmd
->dataoff
;
1355 object
->output_func_start_info_data_size
=
1356 object
->func_starts_info_cmd
->datasize
;
1357 object
->input_sym_info_size
+=
1358 object
->func_starts_info_cmd
->datasize
;
1359 object
->output_sym_info_size
+=
1360 object
->func_starts_info_cmd
->datasize
;
1363 if(object
->data_in_code_cmd
!= NULL
){
1364 object
->output_data_in_code_info_data
= object
->object_addr
+
1365 object
->data_in_code_cmd
->dataoff
;
1366 object
->output_data_in_code_info_data_size
=
1367 object
->data_in_code_cmd
->datasize
;
1368 object
->input_sym_info_size
+=
1369 object
->data_in_code_cmd
->datasize
;
1370 object
->output_sym_info_size
+=
1371 object
->data_in_code_cmd
->datasize
;
1374 if(object
->code_sign_drs_cmd
!= NULL
){
1375 object
->output_code_sign_drs_info_data
= object
->object_addr
+
1376 object
->code_sign_drs_cmd
->dataoff
;
1377 object
->output_code_sign_drs_info_data_size
=
1378 object
->code_sign_drs_cmd
->datasize
;
1379 object
->input_sym_info_size
+=
1380 object
->code_sign_drs_cmd
->datasize
;
1381 object
->output_sym_info_size
+=
1382 object
->code_sign_drs_cmd
->datasize
;
1385 if(object
->mh
!= NULL
){
1386 object
->input_sym_info_size
+= nsyms
* sizeof(struct nlist
);
1387 object
->output_symbols
= new_symbols
;
1388 object
->output_sym_info_size
+=
1389 new_nsyms
* sizeof(struct nlist
);
1392 object
->input_sym_info_size
+= nsyms
* sizeof(struct nlist_64
);
1393 object
->output_symbols64
= new_symbols64
;
1394 object
->output_sym_info_size
+=
1395 new_nsyms
* sizeof(struct nlist_64
);
1397 object
->output_nsymbols
= new_nsyms
;
1398 object
->st
->nsyms
= new_nsyms
;
1400 if(object
->hints_cmd
!= NULL
){
1401 object
->input_sym_info_size
+=
1402 object
->hints_cmd
->nhints
*
1403 sizeof(struct twolevel_hint
);
1404 object
->output_sym_info_size
+=
1405 object
->hints_cmd
->nhints
*
1406 sizeof(struct twolevel_hint
);
1409 if(object
->dyst
!= NULL
){
1412 * When stripping out the section contents to create a
1413 * dynamic library stub the relocation info also gets
1417 #endif /* !(NMEDIT) */
1419 object
->output_sym_info_size
+=
1420 object
->dyst
->nextrel
* sizeof(struct relocation_info
);
1422 object
->input_sym_info_size
+=
1423 object
->dyst
->nextrel
* sizeof(struct relocation_info
);
1426 if(object
->dyst
!= NULL
){
1427 object
->output_sym_info_size
+=
1428 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1429 object
->input_indirectsym_pad
;
1430 if(object
->mh
!= NULL
){
1431 object
->input_sym_info_size
+=
1432 object
->dyst
->nindirectsyms
* sizeof(uint32_t);
1435 object
->input_sym_info_size
+=
1436 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1437 object
->input_indirectsym_pad
;
1441 if(object
->dyst
!= NULL
){
1442 object
->output_sym_info_size
+=
1443 new_ntoc
* sizeof(struct dylib_table_of_contents
);
1444 object
->input_sym_info_size
+=
1445 object
->dyst
->ntoc
* sizeof(struct dylib_table_of_contents
);
1448 if(object
->dyst
!= NULL
){
1449 if(object
->mh
!= NULL
){
1450 object
->output_sym_info_size
+=
1451 object
->dyst
->nmodtab
* sizeof(struct dylib_module
);
1452 object
->input_sym_info_size
+=
1453 object
->dyst
->nmodtab
* sizeof(struct dylib_module
);
1456 object
->output_sym_info_size
+=
1457 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
);
1458 object
->input_sym_info_size
+=
1459 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
);
1463 if(object
->dyst
!= NULL
){
1464 object
->output_sym_info_size
+=
1465 new_nextrefsyms
* sizeof(struct dylib_reference
);
1466 object
->input_sym_info_size
+=
1467 object
->dyst
->nextrefsyms
* sizeof(struct dylib_reference
);
1470 object
->output_strings
= new_strings
;
1471 object
->output_strings_size
= new_strsize
;
1472 object
->output_sym_info_size
+= new_strsize
;
1473 object
->input_sym_info_size
+= strsize
;
1474 object
->st
->strsize
= new_strsize
;
1476 if(object
->code_sig_cmd
!= NULL
){
1478 if(!cflag
&& !no_code_signature
)
1479 #endif /* !(NMEDIT) */
1481 object
->output_code_sig_data
= object
->object_addr
+
1482 object
->code_sig_cmd
->dataoff
;
1483 object
->output_code_sig_data_size
=
1484 object
->code_sig_cmd
->datasize
;
1486 object
->input_sym_info_size
=
1487 rnd(object
->input_sym_info_size
, 16);
1488 object
->input_sym_info_size
+=
1489 object
->code_sig_cmd
->datasize
;
1491 if(cflag
|| no_code_signature
){
1492 strip_LC_CODE_SIGNATURE_commands(arch
, member
, object
);
1495 #endif /* !(NMEDIT) */
1497 object
->output_sym_info_size
=
1498 rnd(object
->output_sym_info_size
, 16);
1499 object
->output_sym_info_size
+=
1500 object
->code_sig_cmd
->datasize
;
1504 if(object
->dyst
!= NULL
){
1505 object
->dyst
->ilocalsym
= 0;
1506 object
->dyst
->nlocalsym
= new_nlocalsym
;
1507 object
->dyst
->iextdefsym
= new_nlocalsym
;
1508 object
->dyst
->nextdefsym
= new_nextdefsym
;
1509 object
->dyst
->iundefsym
= new_nlocalsym
+ new_nextdefsym
;
1510 object
->dyst
->nundefsym
= new_nundefsym
;
1511 if(object
->dyst
->nindirectsyms
!= 0){
1512 object
->output_indirect_symtab
= indirectsyms
;
1513 if(object
->object_byte_sex
!= host_byte_sex
)
1514 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
1515 object
->object_byte_sex
);
1519 * If the -c option is specified the object's filetype will
1520 * have been changed from MH_DYLIB to MH_DYLIB_STUB above.
1522 if(object
->mh_filetype
== MH_DYLIB
||
1523 object
->mh_filetype
== MH_DYLIB_STUB
){
1524 object
->output_tocs
= new_tocs
;
1525 object
->output_ntoc
= new_ntoc
;
1527 if(object
->mh
!= NULL
)
1528 object
->output_mods
= new_mods
;
1530 object
->output_mods64
= new_mods64
;
1531 object
->output_nmodtab
= new_nmodtab
;
1533 object
->output_mods
= mods
;
1534 object
->output_nmodtab
= nmodtab
;
1536 object
->output_refs
= new_refs
;
1537 object
->output_nextrefsyms
= new_nextrefsyms
;
1538 if(object
->object_byte_sex
!= host_byte_sex
){
1539 swap_dylib_table_of_contents(new_tocs
, new_ntoc
,
1540 object
->object_byte_sex
);
1542 if(object
->mh
!= NULL
)
1543 swap_dylib_module(new_mods
, new_nmodtab
,
1544 object
->object_byte_sex
);
1546 swap_dylib_module_64(new_mods64
, new_nmodtab
,
1547 object
->object_byte_sex
);
1549 if(object
->mh
!= NULL
)
1550 swap_dylib_module(mods
, nmodtab
,
1551 object
->object_byte_sex
);
1553 swap_dylib_module_64(mods64
, nmodtab
,
1554 object
->object_byte_sex
);
1556 swap_dylib_reference(new_refs
, new_nextrefsyms
,
1557 object
->object_byte_sex
);
1560 object
->dyst
->ntoc
= new_ntoc
;
1561 object
->dyst
->nextrefsyms
= new_nextrefsyms
;
1563 offset
= get_starting_syminfo_offset(object
);
1565 if(object
->dyld_info
!= 0){
1566 if (object
->dyld_info
->rebase_off
!= 0){
1567 object
->dyld_info
->rebase_off
= offset
;
1568 offset
+= object
->dyld_info
->rebase_size
;
1570 if (object
->dyld_info
->bind_off
!= 0){
1571 object
->dyld_info
->bind_off
= offset
;
1572 offset
+= object
->dyld_info
->bind_size
;
1574 if (object
->dyld_info
->weak_bind_off
!= 0){
1575 object
->dyld_info
->weak_bind_off
= offset
;
1576 offset
+= object
->dyld_info
->weak_bind_size
;
1578 if (object
->dyld_info
->lazy_bind_off
!= 0){
1579 object
->dyld_info
->lazy_bind_off
= offset
;
1580 offset
+= object
->dyld_info
->lazy_bind_size
;
1582 if (object
->dyld_info
->export_off
!= 0){
1583 object
->dyld_info
->export_off
= offset
;
1584 offset
+= object
->dyld_info
->export_size
;
1588 if(object
->dyst
->nlocrel
!= 0){
1589 object
->output_loc_relocs
= (struct relocation_info
*)
1590 (object
->object_addr
+ object
->dyst
->locreloff
);
1593 * When stripping out the section contents to create a
1594 * dynamic library stub the relocation info also gets
1598 object
->dyst
->nlocrel
= 0;
1599 object
->dyst
->locreloff
= 0;
1602 #endif /* defined(NMEDIT) */
1604 object
->dyst
->locreloff
= offset
;
1605 offset
+= object
->dyst
->nlocrel
*
1606 sizeof(struct relocation_info
);
1610 object
->dyst
->locreloff
= 0;
1612 if(object
->split_info_cmd
!= NULL
){
1613 object
->split_info_cmd
->dataoff
= offset
;
1614 offset
+= object
->split_info_cmd
->datasize
;
1617 if(object
->func_starts_info_cmd
!= NULL
){
1618 object
->func_starts_info_cmd
->dataoff
= offset
;
1619 offset
+= object
->func_starts_info_cmd
->datasize
;
1622 if(object
->data_in_code_cmd
!= NULL
){
1623 object
->data_in_code_cmd
->dataoff
= offset
;
1624 offset
+= object
->data_in_code_cmd
->datasize
;
1627 if(object
->code_sign_drs_cmd
!= NULL
){
1628 object
->code_sign_drs_cmd
->dataoff
= offset
;
1629 offset
+= object
->code_sign_drs_cmd
->datasize
;
1632 if(object
->st
->nsyms
!= 0){
1633 object
->st
->symoff
= offset
;
1634 if(object
->mh
!= NULL
)
1635 offset
+= object
->st
->nsyms
* sizeof(struct nlist
);
1637 offset
+= object
->st
->nsyms
* sizeof(struct nlist_64
);
1640 object
->st
->symoff
= 0;
1642 if(object
->hints_cmd
!= NULL
){
1643 if(object
->hints_cmd
->nhints
!= 0){
1644 object
->output_hints
= (struct twolevel_hint
*)
1645 (object
->object_addr
+ object
->hints_cmd
->offset
);
1646 object
->hints_cmd
->offset
= offset
;
1647 offset
+= object
->hints_cmd
->nhints
*
1648 sizeof(struct twolevel_hint
);
1651 object
->hints_cmd
->offset
= 0;
1654 if(object
->dyst
->nextrel
!= 0){
1655 object
->output_ext_relocs
= (struct relocation_info
*)
1656 (object
->object_addr
+ object
->dyst
->extreloff
);
1659 * When stripping out the section contents to create a
1660 * dynamic library stub the relocation info also gets
1664 object
->dyst
->nextrel
= 0;
1665 object
->dyst
->extreloff
= 0;
1668 #endif /* defined(NMEDIT) */
1670 object
->dyst
->extreloff
= offset
;
1671 offset
+= object
->dyst
->nextrel
*
1672 sizeof(struct relocation_info
);
1676 object
->dyst
->extreloff
= 0;
1678 if(object
->dyst
->nindirectsyms
!= 0){
1679 object
->dyst
->indirectsymoff
= offset
;
1680 offset
+= object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1681 object
->input_indirectsym_pad
;
1684 object
->dyst
->indirectsymoff
= 0;;
1686 if(object
->dyst
->ntoc
!= 0){
1687 object
->dyst
->tocoff
= offset
;
1688 offset
+= object
->dyst
->ntoc
*
1689 sizeof(struct dylib_table_of_contents
);
1692 object
->dyst
->tocoff
= 0;
1694 if(object
->dyst
->nmodtab
!= 0){
1697 * When stripping out the section contents to create a
1698 * dynamic library stub zero out the fields in the module
1699 * table for the sections and relocation information and
1700 * clear Objective-C address and size from modules.
1703 if(object
->mh
!= NULL
){
1704 for(k
= 0; k
< object
->dyst
->nmodtab
; k
++){
1705 mods
[k
].iinit_iterm
= 0;
1706 mods
[k
].ninit_nterm
= 0;
1707 mods
[k
].iextrel
= 0;
1708 mods
[k
].nextrel
= 0;
1709 mods
[k
].objc_module_info_addr
= 0;
1710 mods
[k
].objc_module_info_size
= 0;
1714 for(k
= 0; k
< object
->dyst
->nmodtab
; k
++){
1715 mods64
[k
].iinit_iterm
= 0;
1716 mods64
[k
].ninit_nterm
= 0;
1717 mods64
[k
].iextrel
= 0;
1718 mods64
[k
].nextrel
= 0;
1719 mods64
[k
].objc_module_info_addr
= 0;
1720 mods64
[k
].objc_module_info_size
= 0;
1724 #endif /* !(NMEDIT) */
1725 object
->dyst
->modtaboff
= offset
;
1726 if(object
->mh
!= NULL
)
1727 offset
+= object
->dyst
->nmodtab
*
1728 sizeof(struct dylib_module
);
1730 offset
+= object
->dyst
->nmodtab
*
1731 sizeof(struct dylib_module_64
);
1734 object
->dyst
->modtaboff
= 0;
1736 if(object
->dyst
->nextrefsyms
!= 0){
1737 object
->dyst
->extrefsymoff
= offset
;
1738 offset
+= object
->dyst
->nextrefsyms
*
1739 sizeof(struct dylib_reference
);
1742 object
->dyst
->extrefsymoff
= 0;
1744 if(object
->st
->strsize
!= 0){
1745 object
->st
->stroff
= offset
;
1746 offset
+= object
->st
->strsize
;
1749 object
->st
->stroff
= 0;
1751 if(object
->code_sig_cmd
!= NULL
){
1752 offset
= rnd(offset
, 16);
1753 object
->code_sig_cmd
->dataoff
= offset
;
1754 offset
+= object
->code_sig_cmd
->datasize
;
1758 if(new_strsize
!= 0){
1759 if(object
->mh
!= NULL
)
1760 object
->st
->stroff
= object
->st
->symoff
+
1761 new_nsyms
* sizeof(struct nlist
);
1763 object
->st
->stroff
= object
->st
->symoff
+
1764 new_nsyms
* sizeof(struct nlist_64
);
1767 object
->st
->stroff
= 0;
1769 object
->st
->symoff
= 0;
1775 * Here we are doing a full symbol strip. In some cases it may
1776 * leave the local relocation entries as well as LOCAL indirect
1777 * symbol table entries.
1781 saves
= (int32_t *)allocate(object
->st
->nsyms
* sizeof(int32_t));
1782 bzero(saves
, object
->st
->nsyms
* sizeof(int32_t));
1785 * Account for the symbolic info in the input file.
1787 if(object
->dyst
!= NULL
){
1788 object
->input_sym_info_size
+=
1789 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1790 object
->dyst
->nextrel
* sizeof(struct relocation_info
) +
1791 object
->dyst
->ntoc
* sizeof(struct dylib_table_of_contents
)+
1792 object
->dyst
->nextrefsyms
* sizeof(struct dylib_reference
);
1793 if(object
->mh
!= NULL
){
1794 object
->input_sym_info_size
+=
1795 object
->dyst
->nmodtab
* sizeof(struct dylib_module
) +
1796 object
->dyst
->nindirectsyms
* sizeof(uint32_t);
1799 object
->input_sym_info_size
+=
1800 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
) +
1801 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1802 object
->input_indirectsym_pad
;
1807 * Determine the offset where the remaining symbolic info will start
1808 * in the output file (if any).
1810 offset
= get_starting_syminfo_offset(object
);
1813 * For a full symbol strip all these values in the output file are
1816 object
->st
->symoff
= 0;
1817 object
->st
->nsyms
= 0;
1818 object
->st
->stroff
= 0;
1819 object
->st
->strsize
= 0;
1820 if(object
->dyst
!= NULL
){
1821 object
->dyst
->ilocalsym
= 0;
1822 object
->dyst
->nlocalsym
= 0;
1823 object
->dyst
->iextdefsym
= 0;
1824 object
->dyst
->nextdefsym
= 0;
1825 object
->dyst
->iundefsym
= 0;
1826 object
->dyst
->nundefsym
= 0;
1830 * This will accumulate any remaining symbolic info size in the
1833 object
->output_sym_info_size
= 0;
1836 * We set these so that checking can be done below to report the
1837 * symbols that can't be stripped because of relocation entries
1838 * or indirect symbol table entries. Normally if these table have a
1839 * non-zero number of entries it will be an error as we are trying
1840 * to strip everything. But it maybe that there are only LOCAL
1841 * indirect entries which is odd but will be OK.
1843 if(object
->dyst
!= NULL
){
1844 if(object
->dyst
->nextrel
!= 0){
1845 object
->output_ext_relocs
= (struct relocation_info
*)
1846 (object
->object_addr
+ object
->dyst
->extreloff
);
1849 * Since this file has a dynamic symbol table and if this file
1850 * has local relocation entries on input make sure they are
1851 * there on output. This is a rare case that it will not have
1852 * external relocs or indirect symbols but can happen as is the
1853 * case with the dynamic linker itself.
1855 if(object
->dyst
->nlocrel
!= 0){
1856 object
->output_loc_relocs
= (struct relocation_info
*)
1857 (object
->object_addr
+ object
->dyst
->locreloff
);
1858 object
->output_sym_info_size
+=
1859 object
->dyst
->nlocrel
* sizeof(struct relocation_info
);
1861 object
->dyst
->locreloff
= offset
;
1862 offset
+= object
->dyst
->nlocrel
*
1863 sizeof(struct relocation_info
);
1866 if(object
->dyst
->nindirectsyms
!= 0){
1867 object
->output_indirect_symtab
= (uint32_t *)
1868 (object
->object_addr
+
1869 object
->dyst
->indirectsymoff
);
1870 if(object
->object_byte_sex
!= host_byte_sex
)
1871 swap_indirect_symbols(
1872 object
->output_indirect_symtab
,
1873 object
->dyst
->nindirectsyms
,
1874 object
->object_byte_sex
);
1876 object
->output_sym_info_size
+=
1877 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1878 object
->input_indirectsym_pad
;
1880 object
->dyst
->indirectsymoff
= offset
;
1881 offset
+= object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1882 object
->input_indirectsym_pad
;
1886 #endif /* !defined(NMEDIT) */
1889 * Always clear the prebind checksum if any when creating a new file.
1891 if(object
->cs
!= NULL
)
1892 object
->cs
->cksum
= 0;
1894 if(object
->seg_linkedit
!= NULL
){
1895 object
->seg_linkedit
->filesize
+= object
->output_sym_info_size
-
1896 object
->input_sym_info_size
;
1897 object
->seg_linkedit
->vmsize
= object
->seg_linkedit
->filesize
;
1899 else if(object
->seg_linkedit64
!= NULL
){
1900 /* Do this in two steps to avoid 32/64-bit casting problems. */
1901 object
->seg_linkedit64
->filesize
-= object
->input_sym_info_size
;
1902 object
->seg_linkedit64
->filesize
+= object
->output_sym_info_size
;
1903 object
->seg_linkedit64
->vmsize
= object
->seg_linkedit64
->filesize
;
1907 * Check and update the external relocation entries to make sure
1908 * referenced symbols are not stripped and refer to the new symbol
1911 * The external relocation entries can be located in one of two places,
1912 * first off of the sections or second off of the dynamic symtab.
1914 missing_reloc_symbols
= 0;
1915 lc
= object
->load_commands
;
1916 if(object
->mh
!= NULL
)
1917 ncmds
= object
->mh
->ncmds
;
1919 ncmds
= object
->mh64
->ncmds
;
1920 for(i
= 0; i
< ncmds
; i
++){
1921 if(lc
->cmd
== LC_SEGMENT
&&
1922 object
->seg_linkedit
!= (struct segment_command
*)lc
){
1923 sg
= (struct segment_command
*)lc
;
1924 s
= (struct section
*)((char *)sg
+
1925 sizeof(struct segment_command
));
1926 for(j
= 0; j
< sg
->nsects
; j
++){
1928 if(s
->reloff
+ s
->nreloc
*
1929 sizeof(struct relocation_info
) >
1930 object
->object_size
){
1931 fatal_arch(arch
, member
, "truncated or malformed "
1932 "object (relocation entries for section (%.16s,"
1933 "%.16s) extends past the end of the file)",
1934 s
->segname
, s
->sectname
);
1936 relocs
= (struct relocation_info
*)
1937 (object
->object_addr
+ s
->reloff
);
1938 if(object
->object_byte_sex
!= host_byte_sex
)
1939 swap_relocation_info(relocs
, s
->nreloc
,
1941 if(s
->offset
+ s
->size
> object
->object_size
){
1942 fatal_arch(arch
, member
, "truncated or malformed "
1943 "object (contents of section (%.16s,"
1944 "%.16s) extends past the end of the file)",
1945 s
->segname
, s
->sectname
);
1947 contents
= object
->object_addr
+ s
->offset
;
1948 check_object_relocs(arch
, member
, object
, s
->segname
,
1949 s
->sectname
, s
->size
, contents
, relocs
, s
->nreloc
,
1950 symbols
, symbols64
, nsyms
, strings
,
1951 &missing_reloc_symbols
, host_byte_sex
);
1952 if(object
->object_byte_sex
!= host_byte_sex
)
1953 swap_relocation_info(relocs
, s
->nreloc
,
1954 object
->object_byte_sex
);
1959 else if(lc
->cmd
== LC_SEGMENT_64
&&
1960 object
->seg_linkedit64
!= (struct segment_command_64
*)lc
){
1961 sg64
= (struct segment_command_64
*)lc
;
1962 s64
= (struct section_64
*)((char *)sg64
+
1963 sizeof(struct segment_command_64
));
1964 for(j
= 0; j
< sg64
->nsects
; j
++){
1965 if(s64
->nreloc
!= 0){
1966 if(s64
->reloff
+ s64
->nreloc
*
1967 sizeof(struct relocation_info
) >
1968 object
->object_size
){
1969 fatal_arch(arch
, member
, "truncated or malformed "
1970 "object (relocation entries for section (%.16s,"
1971 "%.16s) extends past the end of the file)",
1972 s64
->segname
, s64
->sectname
);
1974 relocs
= (struct relocation_info
*)
1975 (object
->object_addr
+ s64
->reloff
);
1976 if(object
->object_byte_sex
!= host_byte_sex
)
1977 swap_relocation_info(relocs
, s64
->nreloc
,
1979 if(s64
->offset
+ s64
->size
> object
->object_size
){
1980 fatal_arch(arch
, member
, "truncated or malformed "
1981 "object (contents of section (%.16s,"
1982 "%.16s) extends past the end of the file)",
1983 s64
->segname
, s64
->sectname
);
1985 contents
= object
->object_addr
+ s64
->offset
;
1986 check_object_relocs(arch
, member
, object
, s64
->segname
,
1987 s64
->sectname
, s64
->size
, contents
, relocs
,
1988 s64
->nreloc
, symbols
, symbols64
, nsyms
, strings
,
1989 &missing_reloc_symbols
, host_byte_sex
);
1990 if(object
->object_byte_sex
!= host_byte_sex
)
1991 swap_relocation_info(relocs
, s64
->nreloc
,
1992 object
->object_byte_sex
);
1997 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1999 if(object
->dyst
!= NULL
&& object
->dyst
->nextrel
!= 0){
2000 relocs
= object
->output_ext_relocs
;
2001 if(object
->object_byte_sex
!= host_byte_sex
)
2002 swap_relocation_info(relocs
, object
->dyst
->nextrel
,
2005 for(i
= 0; i
< object
->dyst
->nextrel
; i
++){
2006 if((relocs
[i
].r_address
& R_SCATTERED
) == 0 &&
2007 relocs
[i
].r_extern
== 1){
2008 if(relocs
[i
].r_symbolnum
> nsyms
){
2009 fatal_arch(arch
, member
, "bad r_symbolnum for external "
2010 "relocation entry %d in: ", i
);
2012 if(saves
[relocs
[i
].r_symbolnum
] == 0){
2013 if(missing_reloc_symbols
== 0){
2014 error_arch(arch
, member
, "symbols referenced by "
2015 "relocation entries that can't be stripped in: ");
2016 missing_reloc_symbols
= 1;
2018 if(object
->mh
!= NULL
){
2019 fprintf(stderr
, "%s\n", strings
+ symbols
2020 [relocs
[i
].r_symbolnum
].n_un
.n_strx
);
2023 fprintf(stderr
, "%s\n", strings
+ symbols64
2024 [relocs
[i
].r_symbolnum
].n_un
.n_strx
);
2026 saves
[relocs
[i
].r_symbolnum
] = -1;
2028 if(saves
[relocs
[i
].r_symbolnum
] != -1){
2029 relocs
[i
].r_symbolnum
=
2030 saves
[relocs
[i
].r_symbolnum
] - 1;
2034 fatal_arch(arch
, member
, "bad external relocation entry "
2035 "%d (not external) in: ", i
);
2037 if((relocs
[i
].r_address
& R_SCATTERED
) == 0){
2038 if(reloc_has_pair(object
->mh_cputype
, relocs
[i
].r_type
))
2042 sreloc
= (struct scattered_relocation_info
*)relocs
+ i
;
2043 if(reloc_has_pair(object
->mh_cputype
, sreloc
->r_type
))
2047 if(object
->object_byte_sex
!= host_byte_sex
)
2048 swap_relocation_info(relocs
, object
->dyst
->nextrel
,
2049 object
->object_byte_sex
);
2053 * Check and update the indirect symbol table entries to make sure
2054 * referenced symbols are not stripped and refer to the new symbol
2057 if(object
->dyst
!= NULL
&& object
->dyst
->nindirectsyms
!= 0){
2058 if(object
->object_byte_sex
!= host_byte_sex
)
2059 swap_indirect_symbols(object
->output_indirect_symtab
,
2060 object
->dyst
->nindirectsyms
, host_byte_sex
);
2062 lc
= object
->load_commands
;
2063 if(object
->mh
!= NULL
)
2064 ncmds
= object
->mh
->ncmds
;
2066 ncmds
= object
->mh64
->ncmds
;
2067 for(i
= 0; i
< ncmds
; i
++){
2068 if(lc
->cmd
== LC_SEGMENT
&&
2069 object
->seg_linkedit
!= (struct segment_command
*)lc
){
2070 sg
= (struct segment_command
*)lc
;
2071 s
= (struct section
*)((char *)sg
+
2072 sizeof(struct segment_command
));
2073 for(j
= 0; j
< sg
->nsects
; j
++){
2074 section_type
= s
->flags
& SECTION_TYPE
;
2075 if(section_type
== S_LAZY_SYMBOL_POINTERS
||
2076 section_type
== S_LAZY_DYLIB_SYMBOL_POINTERS
||
2077 section_type
== S_NON_LAZY_SYMBOL_POINTERS
)
2079 else if(section_type
== S_SYMBOL_STUBS
)
2080 stride
= s
->reserved2
;
2085 nitems
= s
->size
/ stride
;
2086 contents
= object
->object_addr
+ s
->offset
;
2087 check_indirect_symtab(arch
, member
, object
, nitems
,
2088 s
->reserved1
, section_type
, contents
, symbols
,
2089 symbols64
, nsyms
, strings
, &missing_reloc_symbols
,
2094 else if(lc
->cmd
== LC_SEGMENT_64
&&
2095 object
->seg_linkedit64
!= (struct segment_command_64
*)lc
){
2096 sg64
= (struct segment_command_64
*)lc
;
2097 s64
= (struct section_64
*)((char *)sg64
+
2098 sizeof(struct segment_command_64
));
2099 for(j
= 0; j
< sg64
->nsects
; j
++){
2100 section_type
= s64
->flags
& SECTION_TYPE
;
2101 if(section_type
== S_LAZY_SYMBOL_POINTERS
||
2102 section_type
== S_LAZY_DYLIB_SYMBOL_POINTERS
||
2103 section_type
== S_NON_LAZY_SYMBOL_POINTERS
)
2105 else if(section_type
== S_SYMBOL_STUBS
)
2106 stride
= s64
->reserved2
;
2111 nitems
= s64
->size
/ stride
;
2112 contents
= object
->object_addr
+ s64
->offset
;
2113 check_indirect_symtab(arch
, member
, object
, nitems
,
2114 s64
->reserved1
, section_type
, contents
, symbols
,
2115 symbols64
, nsyms
, strings
, &missing_reloc_symbols
,
2120 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2123 if(object
->object_byte_sex
!= host_byte_sex
)
2124 swap_indirect_symbols(object
->output_indirect_symtab
,
2125 object
->dyst
->nindirectsyms
, object
->object_byte_sex
);
2129 * Issue a warning if object file has a code signature that the
2130 * operation will invalidate it.
2132 if(object
->code_sig_cmd
!= NULL
)
2133 warning_arch(arch
, member
, "changes being made to the file will "
2134 "invalidate the code signature in: ");
2138 * get_starting_syminfo_offset() returns the starting offset of the symbolic
2139 * info in the object file.
2143 get_starting_syminfo_offset(
2144 struct object
*object
)
2148 if(object
->seg_linkedit
!= NULL
||
2149 object
->seg_linkedit64
!= NULL
){
2150 if(object
->mh
!= NULL
)
2151 offset
= object
->seg_linkedit
->fileoff
;
2153 offset
= object
->seg_linkedit64
->fileoff
;
2157 if(object
->dyst
!= NULL
&&
2158 object
->dyst
->nlocrel
!= 0 &&
2159 object
->dyst
->locreloff
< offset
)
2160 offset
= object
->dyst
->locreloff
;
2161 if(object
->st
->nsyms
!= 0 &&
2162 object
->st
->symoff
< offset
)
2163 offset
= object
->st
->symoff
;
2164 if(object
->dyst
!= NULL
&&
2165 object
->dyst
->nextrel
!= 0 &&
2166 object
->dyst
->extreloff
< offset
)
2167 offset
= object
->dyst
->extreloff
;
2168 if(object
->dyst
!= NULL
&&
2169 object
->dyst
->nindirectsyms
!= 0 &&
2170 object
->dyst
->indirectsymoff
< offset
)
2171 offset
= object
->dyst
->indirectsymoff
;
2172 if(object
->dyst
!= NULL
&&
2173 object
->dyst
->ntoc
!= 0 &&
2174 object
->dyst
->tocoff
< offset
)
2175 offset
= object
->dyst
->tocoff
;
2176 if(object
->dyst
!= NULL
&&
2177 object
->dyst
->nmodtab
!= 0 &&
2178 object
->dyst
->modtaboff
< offset
)
2179 offset
= object
->dyst
->modtaboff
;
2180 if(object
->dyst
!= NULL
&&
2181 object
->dyst
->nextrefsyms
!= 0 &&
2182 object
->dyst
->extrefsymoff
< offset
)
2183 offset
= object
->dyst
->extrefsymoff
;
2184 if(object
->st
->strsize
!= 0 &&
2185 object
->st
->stroff
< offset
)
2186 offset
= object
->st
->stroff
;
2192 * check_object_relocs() is used to check and update the external relocation
2193 * entries from a section in an object file, to make sure referenced symbols
2194 * are not stripped and are changed to refer to the new symbol table indexes.
2198 check_object_relocs(
2200 struct member
*member
,
2201 struct object
*object
,
2206 struct relocation_info
*relocs
,
2208 struct nlist
*symbols
,
2209 struct nlist_64
*symbols64
,
2212 int32_t *missing_reloc_symbols
,
2213 enum byte_sex host_byte_sex
)
2218 uint32_t value
, n_ext
;
2221 struct scattered_relocation_info
*sreloc
;
2223 for(k
= 0; k
< nreloc
; k
++){
2224 if((relocs
[k
].r_address
& R_SCATTERED
) == 0 &&
2225 relocs
[k
].r_extern
== 1){
2226 if(relocs
[k
].r_symbolnum
> nsyms
){
2227 fatal_arch(arch
, member
, "bad r_symbolnum for relocation "
2228 "entry %d in section (%.16s,%.16s) in: ", k
, segname
,
2231 if(object
->mh
!= NULL
){
2232 n_strx
= symbols
[relocs
[k
].r_symbolnum
].n_un
.n_strx
;
2233 n_value
= symbols
[relocs
[k
].r_symbolnum
].n_value
;
2236 n_strx
= symbols64
[relocs
[k
].r_symbolnum
].n_un
.n_strx
;
2237 n_value
= symbols64
[relocs
[k
].r_symbolnum
].n_value
;
2240 if(saves
[relocs
[k
].r_symbolnum
] == 0){
2241 if(*missing_reloc_symbols
== 0){
2242 error_arch(arch
, member
, "symbols referenced by "
2243 "relocation entries that can't be stripped in: ");
2244 *missing_reloc_symbols
= 1;
2246 fprintf(stderr
, "%s\n", strings
+ n_strx
);
2247 saves
[relocs
[k
].r_symbolnum
] = -1;
2249 #else /* defined(NMEDIT) */
2251 * We are letting nmedit change global coalesed symbols into
2252 * statics in MH_OBJECT file types only. Relocation entries to
2253 * global coalesced symbols are external relocs.
2255 if(object
->mh
!= NULL
)
2256 n_ext
= new_symbols
[saves
[relocs
[k
].r_symbolnum
] - 1].
2259 n_ext
= new_symbols64
[saves
[relocs
[k
].r_symbolnum
] - 1].
2261 if(n_ext
!= N_EXT
&&
2262 object
->mh_cputype
!= CPU_TYPE_X86_64
){
2264 * We need to do the relocation for this external relocation
2265 * entry so the item to be relocated is correct for a local
2266 * relocation entry. We don't need to do this for x86-64.
2268 if(relocs
[k
].r_address
+ sizeof(int32_t) > sectsize
){
2269 fatal_arch(arch
, member
, "truncated or malformed "
2270 "object (r_address of relocation entry %u of "
2271 "section (%.16s,%.16s) extends past the end "
2272 "of the section)", k
, segname
, sectname
);
2274 if(object
->mh
!= NULL
){
2275 value
= *(uint32_t *)
2276 (contents
+ relocs
[k
].r_address
);
2277 if(object
->object_byte_sex
!= host_byte_sex
)
2278 value
= SWAP_INT(value
);
2280 * We handle a very limited form here. Only VANILLA
2281 * (r_type == 0) long (r_length==2) absolute or pcrel
2282 * that won't need a scattered relocation entry.
2284 if(relocs
[k
].r_type
!= 0 ||
2285 relocs
[k
].r_length
!= 2){
2286 fatal_arch(arch
, member
, "don't have "
2287 "code to convert external relocation "
2288 "entry %d in section (%.16s,%.16s) "
2289 "for global coalesced symbol: %s "
2290 "in: ", k
, segname
, sectname
,
2294 if(object
->object_byte_sex
!= host_byte_sex
)
2295 value
= SWAP_INT(value
);
2296 *(uint32_t *)(contents
+ relocs
[k
].r_address
) =
2300 value64
= *(uint64_t *)(contents
+ relocs
[k
].r_address
);
2301 if(object
->object_byte_sex
!= host_byte_sex
)
2302 value64
= SWAP_LONG_LONG(value64
);
2304 * We handle a very limited form here. Only VANILLA
2305 * (r_type == 0) quad (r_length==3) absolute or pcrel
2306 * that won't need a scattered relocation entry.
2308 if(relocs
[k
].r_type
!= 0 ||
2309 relocs
[k
].r_length
!= 3){
2310 fatal_arch(arch
, member
, "don't have "
2311 "code to convert external relocation "
2312 "entry %d in section (%.16s,%.16s) "
2313 "for global coalesced symbol: %s "
2314 "in: ", k
, segname
, sectname
,
2318 if(object
->object_byte_sex
!= host_byte_sex
)
2319 value64
= SWAP_LONG_LONG(value64
);
2320 *(uint64_t *)(contents
+ relocs
[k
].r_address
) = value64
;
2323 * Turn the extern reloc into a local.
2325 if(object
->mh
!= NULL
)
2326 relocs
[k
].r_symbolnum
=
2327 new_symbols
[saves
[relocs
[k
].r_symbolnum
] - 1].n_sect
;
2329 relocs
[k
].r_symbolnum
=
2330 new_symbols64
[saves
[relocs
[k
].r_symbolnum
] - 1].n_sect
;
2331 relocs
[k
].r_extern
= 0;
2334 if(relocs
[k
].r_extern
== 1 &&
2335 saves
[relocs
[k
].r_symbolnum
] != -1){
2336 relocs
[k
].r_symbolnum
= saves
[relocs
[k
].r_symbolnum
] - 1;
2339 if((relocs
[k
].r_address
& R_SCATTERED
) == 0){
2340 if(reloc_has_pair(object
->mh_cputype
, relocs
[k
].r_type
) == TRUE
)
2344 sreloc
= (struct scattered_relocation_info
*)relocs
+ k
;
2345 if(reloc_has_pair(object
->mh_cputype
, sreloc
->r_type
) == TRUE
)
2352 * check_indirect_symtab() checks and updates the indirect symbol table entries
2353 * to make sure referenced symbols are not stripped and refer to the new symbol
2358 check_indirect_symtab(
2360 struct member
*member
,
2361 struct object
*object
,
2364 uint32_t section_type
,
2366 struct nlist
*symbols
,
2367 struct nlist_64
*symbols64
,
2370 int32_t *missing_reloc_symbols
,
2371 enum byte_sex host_byte_sex
)
2375 uint32_t n_strx
, value
;
2377 enum bool made_local
;
2379 for(k
= 0; k
< nitems
; k
++){
2381 index
= object
->output_indirect_symtab
[reserved1
+ k
];
2382 if(index
== INDIRECT_SYMBOL_LOCAL
||
2383 index
== INDIRECT_SYMBOL_ABS
||
2384 index
== (INDIRECT_SYMBOL_LOCAL
| INDIRECT_SYMBOL_ABS
))
2387 fatal_arch(arch
, member
,"indirect symbol table entry %d (past " "the end of the symbol table) in: ", reserved1
+ k
);
2389 if(pflag
== 0 && nmedits
[index
] == TRUE
&& saves
[index
] != -1)
2391 if(saves
[index
] == 0)
2395 * Indirect symbol table entries for defined symbols in a
2396 * non-lazy pointer section that are not saved are changed to
2397 * INDIRECT_SYMBOL_LOCAL which their values just have to be
2398 * slid if the are not absolute symbols.
2400 if(object
->mh
!= NULL
){
2401 n_type
= symbols
[index
].n_type
;
2402 n_strx
= symbols
[index
].n_un
.n_strx
;
2405 n_type
= symbols64
[index
].n_type
;
2406 n_strx
= symbols64
[index
].n_un
.n_strx
;
2408 if((n_type
& N_TYPE
) != N_UNDF
&&
2409 (n_type
& N_TYPE
) != N_PBUD
&&
2410 section_type
== S_NON_LAZY_SYMBOL_POINTERS
){
2411 object
->output_indirect_symtab
[reserved1
+ k
] =
2412 INDIRECT_SYMBOL_LOCAL
;
2413 if((n_type
& N_TYPE
) == N_ABS
)
2414 object
->output_indirect_symtab
[reserved1
+ k
] |=
2415 INDIRECT_SYMBOL_ABS
;
2418 * When creating a stub shared library the section contents
2419 * are not updated since they will be stripped.
2421 if(object
->mh_filetype
!= MH_DYLIB_STUB
){
2422 if(object
->mh
!= NULL
){
2423 value
= symbols
[index
].n_value
;
2424 if (symbols
[index
].n_desc
& N_ARM_THUMB_DEF
)
2426 if(object
->object_byte_sex
!= host_byte_sex
)
2427 value
= SWAP_INT(value
);
2428 *(uint32_t *)(contents
+ k
* 4) = value
;
2431 value64
= symbols64
[index
].n_value
;
2432 if(object
->object_byte_sex
!= host_byte_sex
)
2433 value64
= SWAP_LONG_LONG(value64
);
2434 *(uint64_t *)(contents
+ k
* 8) = value64
;
2440 object
->output_indirect_symtab
[reserved1
+ k
] =
2443 #else /* !defined(NMEDIT) */
2445 if(*missing_reloc_symbols
== 0){
2446 error_arch(arch
, member
, "symbols referenced by "
2447 "indirect symbol table entries that can't be "
2449 *missing_reloc_symbols
= 1;
2451 fprintf(stderr
, "%s\n", strings
+ n_strx
);
2454 #endif /* !defined(NMEDIT) */
2458 #else /* !defined(NMEDIT) */
2459 if(made_local
== FALSE
&& saves
[index
] != -1)
2460 #endif /* !defined(NMEDIT) */
2462 object
->output_indirect_symtab
[reserved1
+k
] = saves
[index
] - 1;
2469 * This is called if there is a -d option specified. It reads the file with
2470 * the strings in it and places them in the array debug_filenames and sorts
2471 * them by name. The file that contains the file names must have names one
2472 * per line with no white space (except the newlines).
2476 setup_debug_filenames(
2479 int fd
, i
, strings_size
;
2480 struct stat stat_buf
;
2483 if((fd
= open(dfile
, O_RDONLY
)) < 0){
2484 system_error("can't open: %s", dfile
);
2487 if(fstat(fd
, &stat_buf
) == -1){
2488 system_error("can't stat: %s", dfile
);
2492 strings_size
= stat_buf
.st_size
;
2493 strings
= (char *)allocate(strings_size
+ 1);
2494 strings
[strings_size
] = '\0';
2495 if(read(fd
, strings
, strings_size
) != strings_size
){
2496 system_error("can't read: %s", dfile
);
2501 for(i
= 0; i
< strings_size
; i
++){
2508 debug_filenames
= (char **)allocate(ndebug_filenames
* sizeof(char *));
2510 for(i
= 0; i
< ndebug_filenames
; i
++){
2511 debug_filenames
[i
] = p
;
2514 qsort(debug_filenames
, ndebug_filenames
, sizeof(char *),
2515 (int (*)(const void *, const void *))cmp_qsort_filename
);
2518 printf("Debug filenames:\n");
2519 for(i
= 0; i
< ndebug_filenames
; i
++){
2520 printf("filename = %s\n", debug_filenames
[i
]);
2526 * Strip the symbol table to the level specified by the command line arguments.
2527 * The new symbol table is built and new_symbols is left pointing to it. The
2528 * number of new symbols is left in new_nsyms, the new string table is built
2529 * and new_stings is left pointing to it and new_strsize is left containing it.
2530 * This routine returns zero if successfull and non-zero otherwise.
2536 struct member
*member
,
2537 struct object
*object
,
2538 struct dylib_table_of_contents
*tocs
,
2540 struct dylib_module
*mods
,
2541 struct dylib_module_64
*mods64
,
2543 struct dylib_reference
*refs
,
2544 uint32_t nextrefsyms
)
2546 uint32_t i
, j
, k
, n
, inew_syms
, save_debug
, missing_syms
;
2547 uint32_t missing_symbols
;
2548 char *p
, *q
, **pp
, *basename
;
2549 struct symbol_list
*sp
;
2550 uint32_t new_ext_strsize
, len
, *changes
, inew_undefsyms
;
2551 unsigned char nsects
;
2552 struct load_command
*lc
;
2553 struct segment_command
*sg
;
2554 struct segment_command_64
*sg64
;
2555 struct section
*s
, **sections
;
2556 struct section_64
*s64
, **sections64
;
2557 uint32_t ncmds
, mh_flags
, s_flags
, n_strx
;
2559 struct undef_map
*undef_map
;
2560 struct undef_map64
*undef_map64
;
2561 uint8_t n_type
, n_sect
;
2564 uint32_t module_name
, iextdefsym
, nextdefsym
, ilocalsym
, nlocalsym
;
2565 uint32_t irefsym
, nrefsym
;
2566 unsigned char text_nsect
;
2567 enum bool has_dwarf
, hack_5614542
;
2573 for(i
= 0; i
< nsave_symbols
; i
++)
2574 save_symbols
[i
].sym
= NULL
;
2575 for(i
= 0; i
< nremove_symbols
; i
++)
2576 remove_symbols
[i
].sym
= NULL
;
2578 for(i
= 0; i
< nsave_symbols
; i
++)
2579 save_symbols
[i
].seen
= FALSE
;
2580 for(i
= 0; i
< nremove_symbols
; i
++)
2581 remove_symbols
[i
].seen
= FALSE
;
2585 if(object
->mh
!= NULL
)
2586 new_strsize
= sizeof(int32_t);
2588 new_strsize
= sizeof(int64_t);
2592 new_ext_strsize
= 0;
2595 * If this an object file that has DWARF debugging sections to strip
2596 * then we have to run ld -r on it.
2598 if(object
->mh_filetype
== MH_OBJECT
&& (Sflag
|| xflag
)){
2600 lc
= object
->load_commands
;
2601 if(object
->mh
!= NULL
)
2602 ncmds
= object
->mh
->ncmds
;
2604 ncmds
= object
->mh64
->ncmds
;
2605 for(i
= 0; i
< ncmds
&& has_dwarf
== FALSE
; i
++){
2606 if(lc
->cmd
== LC_SEGMENT
){
2607 sg
= (struct segment_command
*)lc
;
2608 s
= (struct section
*)((char *)sg
+
2609 sizeof(struct segment_command
));
2610 for(j
= 0; j
< sg
->nsects
; j
++){
2611 if(s
->flags
& S_ATTR_DEBUG
){
2618 else if(lc
->cmd
== LC_SEGMENT_64
){
2619 sg64
= (struct segment_command_64
*)lc
;
2620 s64
= (struct section_64
*)((char *)sg64
+
2621 sizeof(struct segment_command_64
));
2622 for(j
= 0; j
< sg64
->nsects
; j
++){
2623 if(s64
->flags
& S_ATTR_DEBUG
){
2630 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2632 if(has_dwarf
== TRUE
)
2633 make_ld_r_object(arch
, member
, object
);
2636 * Because of the "design" of 64-bit object files and the lack of
2637 * local relocation entries it is not possible for strip(1) to do its
2638 * job without becoming a static link editor. The "design" does not
2639 * actually strip the symbols it simply renames them to things like
2640 * "l1000". And they become static symbols but still have external
2641 * relocation entries. Thus can never actually be stripped. Also some
2642 * symbols, *.eh, symbols are not even changed to these names if there
2643 * corresponding global symbol is not stripped. So strip(1) only
2644 * recourse is to use the unified linker to create an ld -r object then
2645 * save all resulting symbols (both static and global) and hope the user
2646 * does not notice the stripping is not what they asked for.
2648 if(object
->mh_filetype
== MH_OBJECT
&&
2649 (object
->mh64
!= NULL
&& object
->ld_r_ofile
== NULL
))
2650 make_ld_r_object(arch
, member
, object
);
2653 * Since make_ld_r_object() may create an object with more symbols
2654 * this has to be done after make_ld_r_object() and nsyms is updated.
2656 saves
= (int32_t *)allocate(nsyms
* sizeof(int32_t));
2657 bzero(saves
, nsyms
* sizeof(int32_t));
2660 * Gather an array of section struct pointers so we can later determine
2661 * if we run into a global symbol in a coalesced section and not strip
2666 text_nsect
= NO_SECT
;
2667 lc
= object
->load_commands
;
2668 if(object
->mh
!= NULL
)
2669 ncmds
= object
->mh
->ncmds
;
2671 ncmds
= object
->mh64
->ncmds
;
2672 for(i
= 0; i
< ncmds
; i
++){
2673 if(lc
->cmd
== LC_SEGMENT
){
2674 sg
= (struct segment_command
*)lc
;
2675 nsects
+= sg
->nsects
;
2677 else if(lc
->cmd
== LC_SEGMENT_64
){
2678 sg64
= (struct segment_command_64
*)lc
;
2679 nsects
+= sg64
->nsects
;
2681 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2683 if(object
->mh
!= NULL
){
2684 sections
= allocate(nsects
* sizeof(struct section
*));
2689 sections64
= allocate(nsects
* sizeof(struct section_64
*));
2692 lc
= object
->load_commands
;
2693 for(i
= 0; i
< ncmds
; i
++){
2694 if(lc
->cmd
== LC_SEGMENT
){
2695 sg
= (struct segment_command
*)lc
;
2696 s
= (struct section
*)((char *)sg
+
2697 sizeof(struct segment_command
));
2698 for(j
= 0; j
< sg
->nsects
; j
++){
2699 if(strcmp((s
+ j
)->sectname
, SECT_TEXT
) == 0 &&
2700 strcmp((s
+ j
)->segname
, SEG_TEXT
) == 0)
2701 text_nsect
= nsects
+ 1;
2702 sections
[nsects
++] = s
++;
2705 else if(lc
->cmd
== LC_SEGMENT_64
){
2706 sg64
= (struct segment_command_64
*)lc
;
2707 s64
= (struct section_64
*)((char *)sg64
+
2708 sizeof(struct segment_command_64
));
2709 for(j
= 0; j
< sg64
->nsects
; j
++){
2710 if(strcmp((s64
+ j
)->sectname
, SECT_TEXT
) == 0 &&
2711 strcmp((s64
+ j
)->segname
, SEG_TEXT
) == 0)
2712 text_nsect
= nsects
+ 1;
2713 sections64
[nsects
++] = s64
++;
2716 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2719 for(i
= 0; i
< nsyms
; i
++){
2721 if(object
->mh
!= NULL
){
2722 mh_flags
= object
->mh
->flags
;
2723 n_strx
= symbols
[i
].n_un
.n_strx
;
2724 n_type
= symbols
[i
].n_type
;
2725 n_sect
= symbols
[i
].n_sect
;
2726 if((n_type
& N_TYPE
) == N_SECT
){
2727 if(n_sect
== 0 || n_sect
> nsects
){
2728 error_arch(arch
, member
, "bad n_sect for symbol "
2729 "table entry %d in: ", i
);
2732 s_flags
= sections
[n_sect
- 1]->flags
;
2734 n_desc
= symbols
[i
].n_desc
;
2735 n_value
= symbols
[i
].n_value
;
2738 mh_flags
= object
->mh64
->flags
;
2739 n_strx
= symbols64
[i
].n_un
.n_strx
;
2740 n_type
= symbols64
[i
].n_type
;
2741 n_sect
= symbols64
[i
].n_sect
;
2742 if((n_type
& N_TYPE
) == N_SECT
){
2743 if(n_sect
== 0 || n_sect
> nsects
){
2744 error_arch(arch
, member
, "bad n_sect for symbol "
2745 "table entry %d in: ", i
);
2748 s_flags
= sections64
[n_sect
- 1]->flags
;
2750 n_desc
= symbols64
[i
].n_desc
;
2751 n_value
= symbols64
[i
].n_value
;
2754 if(n_strx
> strsize
){
2755 error_arch(arch
, member
, "bad string index for symbol "
2756 "table entry %d in: ", i
);
2760 if((n_type
& N_TYPE
) == N_INDR
){
2762 if(n_value
> strsize
){
2763 error_arch(arch
, member
, "bad string index for "
2764 "indirect symbol table entry %d in: ", i
);
2769 if((n_type
& N_EXT
) == 0){ /* local symbol */
2772 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2775 saves
[i
] = new_nsyms
;
2778 * For x86_64 .o files we have run ld -r on them and are stuck
2779 * keeping all resulting symbols.
2781 else if(object
->mh
== NULL
&& (
2782 object
->mh64
->cputype
== CPU_TYPE_X86_64
) &&
2783 object
->mh64
->filetype
== MH_OBJECT
){
2785 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2788 saves
[i
] = new_nsyms
;
2791 * The cases a local symbol might be saved are with -X, -S, -t,
2792 * or with -d filename.
2794 else if((!strip_all
&& (Xflag
|| tflag
|| Sflag
)) || dfile
){
2795 if(n_type
& N_STAB
){ /* debug symbol */
2796 if(dfile
&& n_type
== N_SO
){
2798 basename
= strrchr(strings
+ n_strx
, '/');
2799 if(basename
!= NULL
)
2802 basename
= strings
+ n_strx
;
2803 pp
= bsearch(basename
, debug_filenames
,
2804 ndebug_filenames
, sizeof(char *),
2805 (int (*)(const void *, const void *)
2806 )cmp_bsearch_filename
);
2808 * Save the bracketing N_SO. For each N_SO that
2809 * has a filename there is an N_SO that has a
2810 * name of "" which ends the stabs for that file
2812 if(*basename
!= '\0'){
2820 * This is a bracketing SO so if we are
2821 * currently saving debug symbols save this
2822 * last one and turn off saving debug syms.
2826 new_strsize
+= strlen(strings
+
2830 saves
[i
] = new_nsyms
;
2839 if(saves
[i
] == 0 && (!Sflag
|| save_debug
)){
2841 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2844 saves
[i
] = new_nsyms
;
2847 else{ /* non-debug local symbol */
2848 if(xflag
== 0 && (Sflag
|| Xflag
|| tflag
)){
2850 * No -x (strip all local), and one of -S (strip
2851 * debug), -X (strip 'L' local), or -t (strip
2852 * local except non-'L' text) was given.
2854 if((Xflag
&& n_strx
!= 0 &&
2855 strings
[n_strx
] != 'L') ||
2856 (tflag
&& (n_type
& N_TYPE
) == N_SECT
&&
2857 n_sect
== text_nsect
&& n_strx
!= 0 &&
2858 strings
[n_strx
] != 'L') ||
2859 (Sflag
&& !Xflag
&& !tflag
)) {
2861 * If this file is a for the dynamic linker and
2862 * this symbol is in a section marked so that
2863 * static symbols are stripped then don't
2866 if((mh_flags
& MH_DYLDLINK
) != MH_DYLDLINK
||
2867 (n_type
& N_TYPE
) != N_SECT
||
2868 (s_flags
& S_ATTR_STRIP_STATIC_SYMS
) !=
2869 S_ATTR_STRIP_STATIC_SYMS
){
2870 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2873 saves
[i
] = new_nsyms
;
2878 * Treat a local symbol that was a private extern as if
2879 * were global if it is referenced by a module and save
2882 if((n_type
& N_PEXT
) == N_PEXT
){
2884 private_extern_reference_by_module(
2885 i
, refs
,nextrefsyms
) == TRUE
){
2887 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2890 saves
[i
] = new_nsyms
;
2893 * We need to save symbols that were private externs
2894 * that are used with indirect symbols.
2897 symbol_pointer_used(i
, indirectsyms
,
2898 nindirectsyms
) == TRUE
){
2900 len
= strlen(strings
+ n_strx
) + 1;
2905 saves
[i
] = new_nsyms
;
2911 * Treat a local symbol that was a private extern as if were
2912 * global if it is not referenced by a module.
2914 else if((n_type
& N_PEXT
) == N_PEXT
){
2915 if(saves
[i
] == 0 && sfile
){
2916 sp
= bsearch(strings
+ n_strx
,
2917 save_symbols
, nsave_symbols
,
2918 sizeof(struct symbol_list
),
2919 (int (*)(const void *, const void *))
2920 symbol_list_bsearch
);
2922 if(sp
->sym
== NULL
){
2923 if(object
->mh
!= NULL
)
2924 sp
->sym
= &(symbols
[i
]);
2926 sp
->sym
= &(symbols64
[i
]);
2930 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2933 saves
[i
] = new_nsyms
;
2937 private_extern_reference_by_module(
2938 i
, refs
,nextrefsyms
) == TRUE
){
2940 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2943 saves
[i
] = new_nsyms
;
2946 * We need to save symbols that were private externs that
2947 * are used with indirect symbols.
2950 symbol_pointer_used(i
, indirectsyms
, nindirectsyms
) ==
2953 len
= strlen(strings
+ n_strx
) + 1;
2958 saves
[i
] = new_nsyms
;
2962 else{ /* global symbol */
2964 * strip -R on an x86_64 .o file should do nothing.
2967 (object
->mh
!= NULL
||
2968 object
->mh64
->cputype
!= CPU_TYPE_X86_64
||
2969 object
->mh64
->filetype
!= MH_OBJECT
)){
2970 sp
= bsearch(strings
+ n_strx
,
2971 remove_symbols
, nremove_symbols
,
2972 sizeof(struct symbol_list
),
2973 (int (*)(const void *, const void *))
2974 symbol_list_bsearch
);
2976 if((n_type
& N_TYPE
) == N_UNDF
||
2977 (n_type
& N_TYPE
) == N_PBUD
){
2978 error_arch(arch
, member
, "symbol: %s undefined"
2979 " and can't be stripped from: ",
2982 else if(sp
->sym
!= NULL
){
2983 sym
= (struct nlist
*)sp
->sym
;
2984 if((sym
->n_type
& N_PEXT
) != N_PEXT
)
2985 error_arch(arch
, member
, "more than one symbol "
2986 "for: %s found in: ", sp
->name
);
2989 if(object
->mh
!= NULL
)
2990 sp
->sym
= &(symbols
[i
]);
2992 sp
->sym
= &(symbols64
[i
]);
2995 if(n_desc
& REFERENCED_DYNAMICALLY
){
2996 error_arch(arch
, member
, "symbol: %s is dynamically"
2997 " referenced and can't be stripped "
2998 "from: ", sp
->name
);
3000 if((n_type
& N_TYPE
) == N_SECT
&&
3001 (s_flags
& SECTION_TYPE
) == S_COALESCED
){
3002 error_arch(arch
, member
, "symbol: %s is a global "
3003 "coalesced symbol and can't be "
3004 "stripped from: ", sp
->name
);
3006 /* don't save this symbol */
3010 if(Aflag
&& (n_type
& N_TYPE
) == N_ABS
&&
3013 strncmp(strings
+ n_strx
,
3014 ".objc_class_name_",
3015 sizeof(".objc_class_name_") - 1) == 0))){
3016 len
= strlen(strings
+ n_strx
) + 1;
3018 new_ext_strsize
+= len
;
3021 saves
[i
] = new_nsyms
;
3023 if(saves
[i
] == 0 && (uflag
|| default_dyld_executable
) &&
3024 ((((n_type
& N_TYPE
) == N_UNDF
) &&
3026 (n_type
& N_TYPE
) == N_PBUD
)){
3028 len
= strlen(strings
+ n_strx
) + 1;
3030 new_ext_strsize
+= len
;
3034 saves
[i
] = new_nsyms
;
3036 if(saves
[i
] == 0 && nflag
&&
3037 (n_type
& N_TYPE
) == N_SECT
){
3039 len
= strlen(strings
+ n_strx
) + 1;
3041 new_ext_strsize
+= len
;
3045 saves
[i
] = new_nsyms
;
3047 if(saves
[i
] == 0 && sfile
){
3048 sp
= bsearch(strings
+ n_strx
,
3049 save_symbols
, nsave_symbols
,
3050 sizeof(struct symbol_list
),
3051 (int (*)(const void *, const void *))
3052 symbol_list_bsearch
);
3054 if(sp
->sym
!= NULL
){
3055 sym
= (struct nlist
*)sp
->sym
;
3056 if((sym
->n_type
& N_PEXT
) != N_PEXT
)
3057 error_arch(arch
, member
, "more than one symbol "
3058 "for: %s found in: ", sp
->name
);
3061 if(object
->mh
!= NULL
)
3062 sp
->sym
= &(symbols
[i
]);
3064 sp
->sym
= &(symbols64
[i
]);
3066 len
= strlen(strings
+ n_strx
) + 1;
3068 new_ext_strsize
+= len
;
3069 if((n_type
& N_TYPE
) == N_UNDF
||
3070 (n_type
& N_TYPE
) == N_PBUD
)
3075 saves
[i
] = new_nsyms
;
3080 * We only need to save coalesced symbols that are used as
3081 * indirect symbols in 32-bit applications.
3083 * In 64-bit applications, we only need to save coalesced
3084 * symbols that are used as weak definitions.
3086 if(object
->mh
!= NULL
&&
3088 (n_type
& N_TYPE
) == N_SECT
&&
3089 (s_flags
& SECTION_TYPE
) == S_COALESCED
&&
3090 symbol_pointer_used(i
, indirectsyms
, nindirectsyms
) == TRUE
){
3092 len
= strlen(strings
+ n_strx
) + 1;
3094 new_ext_strsize
+= len
;
3098 saves
[i
] = new_nsyms
;
3101 (n_type
& N_TYPE
) == N_SECT
&&
3102 (n_desc
& N_WEAK_DEF
) != 0){
3104 len
= strlen(strings
+ n_strx
) + 1;
3106 new_ext_strsize
+= len
;
3110 saves
[i
] = new_nsyms
;
3113 ((Xflag
|| Sflag
|| xflag
|| tflag
|| aflag
) ||
3114 ((rflag
|| default_dyld_executable
) &&
3115 n_desc
& REFERENCED_DYNAMICALLY
))){
3116 len
= strlen(strings
+ n_strx
) + 1;
3118 new_ext_strsize
+= len
;
3119 if((n_type
& N_TYPE
) == N_INDR
){
3120 len
= strlen(strings
+ n_value
) + 1;
3122 new_ext_strsize
+= len
;
3124 if((n_type
& N_TYPE
) == N_UNDF
||
3125 (n_type
& N_TYPE
) == N_PBUD
)
3130 saves
[i
] = new_nsyms
;
3133 * For x86_64 .o files we have run ld -r on them and are stuck
3134 * keeping all resulting symbols.
3137 object
->mh
== NULL
&&
3138 object
->mh64
->cputype
== CPU_TYPE_X86_64
&&
3139 object
->mh64
->filetype
== MH_OBJECT
){
3140 len
= strlen(strings
+ n_strx
) + 1;
3142 new_ext_strsize
+= len
;
3143 if((n_type
& N_TYPE
) == N_INDR
){
3144 len
= strlen(strings
+ n_value
) + 1;
3146 new_ext_strsize
+= len
;
3148 if((n_type
& N_TYPE
) == N_UNDF
||
3149 (n_type
& N_TYPE
) == N_PBUD
)
3154 saves
[i
] = new_nsyms
;
3159 * The module table's module names are placed with the external strings.
3160 * So size them and add this to the external string size.
3162 for(i
= 0; i
< nmodtab
; i
++){
3163 if(object
->mh
!= NULL
)
3164 module_name
= mods
[i
].module_name
;
3166 module_name
= mods64
[i
].module_name
;
3167 if(module_name
== 0 || module_name
> strsize
){
3168 error_arch(arch
, member
, "bad string index for module_name "
3169 "of module table entry %d in: ", i
);
3172 len
= strlen(strings
+ module_name
) + 1;
3174 new_ext_strsize
+= len
;
3178 * Updating the reference table may require a symbol not yet listed as
3179 * as saved to be present in the output file. If a defined external
3180 * symbol is removed and there is a undefined reference to it in the
3181 * reference table an undefined symbol needs to be created for it in
3182 * the output file. If this happens the number of new symbols and size
3183 * of the new strings are adjusted. And the array changes[] is set to
3184 * map the old symbol index to the new symbol index for the symbol that
3185 * is changed to an undefined symbol.
3187 missing_symbols
= 0;
3188 if(ref_saves
!= NULL
)
3190 ref_saves
= (int32_t *)allocate(nextrefsyms
* sizeof(int32_t));
3191 bzero(ref_saves
, nextrefsyms
* sizeof(int32_t));
3192 changes
= (uint32_t *)allocate(nsyms
* sizeof(int32_t));
3193 bzero(changes
, nsyms
* sizeof(int32_t));
3194 new_nextrefsyms
= 0;
3195 for(i
= 0; i
< nextrefsyms
; i
++){
3196 if(refs
[i
].isym
> nsyms
){
3197 error_arch(arch
, member
, "bad symbol table index for "
3198 "reference table entry %d in: ", i
);
3201 if(saves
[refs
[i
].isym
]){
3203 ref_saves
[i
] = new_nextrefsyms
;
3206 if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
||
3207 refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
){
3208 if(changes
[refs
[i
].isym
] == 0){
3209 if(object
->mh
!= NULL
)
3210 n_strx
= symbols
[refs
[i
].isym
].n_un
.n_strx
;
3212 n_strx
= symbols64
[refs
[i
].isym
].n_un
.n_strx
;
3213 len
= strlen(strings
+ n_strx
) + 1;
3215 new_ext_strsize
+= len
;
3218 changes
[refs
[i
].isym
] = new_nsyms
;
3220 ref_saves
[i
] = new_nextrefsyms
;
3225 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
||
3226 refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
){
3227 if(missing_symbols
== 0){
3228 error_arch(arch
, member
, "private extern symbols "
3229 "referenced by modules can't be stripped in: ");
3230 missing_symbols
= 1;
3232 if(object
->mh
!= NULL
)
3233 n_strx
= symbols
[refs
[i
].isym
].n_un
.n_strx
;
3235 n_strx
= symbols64
[refs
[i
].isym
].n_un
.n_strx
;
3236 fprintf(stderr
, "%s\n", strings
+ n_strx
);
3237 saves
[refs
[i
].isym
] = -1;
3242 if(missing_symbols
== 1)
3248 for(i
= 0; i
< nsave_symbols
; i
++){
3249 if(save_symbols
[i
].sym
== NULL
){
3250 if(missing_syms
== 0){
3251 error_arch(arch
, member
, "symbols names listed "
3252 "in: %s not in: ", sfile
);
3255 fprintf(stderr
, "%s\n", save_symbols
[i
].name
);
3261 * strip -R on an x86_64 .o file should do nothing.
3264 (object
->mh
!= NULL
||
3265 object
->mh64
->cputype
!= CPU_TYPE_X86_64
||
3266 object
->mh64
->filetype
!= MH_OBJECT
)){
3267 for(i
= 0; i
< nremove_symbols
; i
++){
3268 if(remove_symbols
[i
].sym
== NULL
){
3269 if(missing_syms
== 0){
3270 error_arch(arch
, member
, "symbols names listed "
3271 "in: %s not in: ", Rfile
);
3274 fprintf(stderr
, "%s\n", remove_symbols
[i
].name
);
3281 * If there is a chance that we could end up with an indirect symbol
3282 * with an index of zero we need to avoid that due to a work around
3283 * in the dynamic linker for a bug it is working around that was in
3284 * the old classic static linker. See radar bug 5614542 and the
3285 * related bugs 3685312 and 3534709.
3287 * A reasonable way to do this to know that local symbols are first in
3288 * the symbol table. So if we have any local symbols this won't happen
3289 * and if there are no indirect symbols it will also not happen. Past
3290 * that we'll just add a local symbol so it will end up at symbol index
3291 * zero and avoid any indirect symbol having that index.
3293 * If one really wanted they could build up the new symbol table then
3294 * look at all the indirect symbol table entries to see if any of them
3295 * have an index of zero then in that case throw that new symbol table
3296 * away and rebuild the symbol and string table once again after adding
3297 * a local symbol. This seems not all that resonable to save one symbol
3298 * table entry and a few bytes in the string table for the complexity it
3299 * would add and what it would save.
3301 if(new_nlocalsym
== 0 && nindirectsyms
!= 0){
3302 len
= strlen("radr://5614542") + 1;
3306 hack_5614542
= TRUE
;
3309 hack_5614542
= FALSE
;
3312 if(object
->mh
!= NULL
){
3313 new_symbols
= (struct nlist
*)
3314 allocate(new_nsyms
* sizeof(struct nlist
));
3315 new_symbols64
= NULL
;
3319 new_symbols64
= (struct nlist_64
*)
3320 allocate(new_nsyms
* sizeof(struct nlist_64
));
3322 if(object
->mh
!= NULL
)
3323 new_strsize
= rnd(new_strsize
, sizeof(int32_t));
3325 new_strsize
= rnd(new_strsize
, sizeof(int64_t));
3326 new_strings
= (char *)allocate(new_strsize
);
3327 if(object
->mh
!= NULL
){
3328 new_strings
[new_strsize
- 3] = '\0';
3329 new_strings
[new_strsize
- 2] = '\0';
3330 new_strings
[new_strsize
- 1] = '\0';
3333 new_strings
[new_strsize
- 7] = '\0';
3334 new_strings
[new_strsize
- 6] = '\0';
3335 new_strings
[new_strsize
- 5] = '\0';
3336 new_strings
[new_strsize
- 4] = '\0';
3337 new_strings
[new_strsize
- 3] = '\0';
3338 new_strings
[new_strsize
- 2] = '\0';
3339 new_strings
[new_strsize
- 1] = '\0';
3342 memset(new_strings
, '\0', sizeof(int32_t));
3343 p
= new_strings
+ sizeof(int32_t);
3344 q
= p
+ new_ext_strsize
;
3347 * If all strings were stripped set the size to zero but only for 32-bit
3348 * because the unified linker seems to set the filesize of empty .o
3349 * files to include the string table.
3351 if(object
->mh
!= NULL
&& new_strsize
== sizeof(int32_t))
3355 * Now create a symbol table and string table in this order
3358 * external defined symbols
3367 * If we are doing the hack for radar bug 5614542 (see above) add the
3368 * one local symbol and string.
3370 * We use an N_OPT stab which should be safe to use and not mess any
3371 * thing up. In Mac OS X, gcc(1) writes one N_OPT stab saying the file
3372 * is compiled with gcc(1). Then gdb(1) looks for that stab, but it
3373 * also looks at the name. If the name string is "gcc_compiled" or
3374 * "gcc2_compiled" gdb(1) sets its "compiled by gcc flag. If the N_OPT
3375 * is emitted INSIDE an N_SO section, then gdb(1) thinks that object
3376 * module was compiled by Sun's compiler, which apparently sticks one
3377 * outermost N_LBRAC/N_RBRAC pair, which gdb(1) strips off. But if the
3378 * N_OPT comes before any N_SO stabs, then gdb(1) will just ignore it.
3379 * Since this N_OPT is the first local symbol, it will always come
3380 * before any N_SO stabs that might be around and should be fine.
3382 if(hack_5614542
== TRUE
){
3383 if(object
->mh
!= NULL
){
3384 new_symbols
[inew_syms
].n_type
= N_OPT
;
3385 new_symbols
[inew_syms
].n_sect
= NO_SECT
;
3386 new_symbols
[inew_syms
].n_desc
= 0;
3387 new_symbols
[inew_syms
].n_value
= 0x05614542;
3390 new_symbols64
[inew_syms
].n_type
= N_OPT
;
3391 new_symbols64
[inew_syms
].n_sect
= NO_SECT
;
3392 new_symbols64
[inew_syms
].n_desc
= 0;
3393 new_symbols64
[inew_syms
].n_value
= 0x05614542;
3395 strcpy(q
, "radr://5614542");
3396 if(object
->mh
!= NULL
)
3397 new_symbols
[inew_syms
].n_un
.n_strx
=
3400 new_symbols64
[inew_syms
].n_un
.n_strx
=
3406 for(i
= 0; i
< nsyms
; i
++){
3408 if(object
->mh
!= NULL
){
3409 n_strx
= symbols
[i
].n_un
.n_strx
;
3410 n_type
= symbols
[i
].n_type
;
3413 n_strx
= symbols64
[i
].n_un
.n_strx
;
3414 n_type
= symbols64
[i
].n_type
;
3416 if((n_type
& N_EXT
) == 0){
3417 if(object
->mh
!= NULL
)
3418 new_symbols
[inew_syms
] = symbols
[i
];
3420 new_symbols64
[inew_syms
] = symbols64
[i
];
3422 strcpy(q
, strings
+ n_strx
);
3423 if(object
->mh
!= NULL
)
3424 new_symbols
[inew_syms
].n_un
.n_strx
=
3427 new_symbols64
[inew_syms
].n_un
.n_strx
=
3432 saves
[i
] = inew_syms
;
3437 inew_nextdefsym
= inew_syms
;
3438 #endif /* TRIE_SUPPORT */
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
;
3444 n_value
= symbols
[i
].n_value
;
3447 n_strx
= symbols64
[i
].n_un
.n_strx
;
3448 n_type
= symbols64
[i
].n_type
;
3449 n_value
= symbols64
[i
].n_value
;
3451 if((n_type
& N_EXT
) == N_EXT
&&
3452 ((n_type
& N_TYPE
) != N_UNDF
&&
3453 (n_type
& N_TYPE
) != N_PBUD
)){
3454 if(object
->mh
!= NULL
)
3455 new_symbols
[inew_syms
] = symbols
[i
];
3457 new_symbols64
[inew_syms
] = symbols64
[i
];
3459 strcpy(p
, strings
+ n_strx
);
3460 if(object
->mh
!= NULL
)
3461 new_symbols
[inew_syms
].n_un
.n_strx
=
3464 new_symbols64
[inew_syms
].n_un
.n_strx
=
3468 if((n_type
& N_TYPE
) == N_INDR
){
3470 strcpy(p
, strings
+ n_value
);
3471 if(object
->mh
!= NULL
)
3472 new_symbols
[inew_syms
].n_value
=
3475 new_symbols64
[inew_syms
].n_value
=
3481 saves
[i
] = inew_syms
;
3486 * Build the new undefined symbols into a map and sort it.
3489 if(object
->mh
!= NULL
){
3490 undef_map
= (struct undef_map
*)allocate(new_nundefsym
*
3491 sizeof(struct undef_map
));
3496 undef_map64
= (struct undef_map64
*)allocate(new_nundefsym
*
3497 sizeof(struct undef_map64
));
3499 for(i
= 0; i
< nsyms
; i
++){
3501 if(object
->mh
!= NULL
){
3502 n_strx
= symbols
[i
].n_un
.n_strx
;
3503 n_type
= symbols
[i
].n_type
;
3506 n_strx
= symbols64
[i
].n_un
.n_strx
;
3507 n_type
= symbols64
[i
].n_type
;
3509 if((n_type
& N_EXT
) == N_EXT
&&
3510 ((n_type
& N_TYPE
) == N_UNDF
||
3511 (n_type
& N_TYPE
) == N_PBUD
)){
3512 if(object
->mh
!= NULL
)
3513 undef_map
[inew_undefsyms
].symbol
= symbols
[i
];
3515 undef_map64
[inew_undefsyms
].symbol64
= symbols64
[i
];
3517 strcpy(p
, strings
+ n_strx
);
3518 if(object
->mh
!= NULL
)
3519 undef_map
[inew_undefsyms
].symbol
.n_un
.n_strx
=
3522 undef_map64
[inew_undefsyms
].symbol64
.n_un
.n_strx
=
3526 if(object
->mh
!= NULL
)
3527 undef_map
[inew_undefsyms
].index
= i
;
3529 undef_map64
[inew_undefsyms
].index
= i
;
3534 for(i
= 0; i
< nsyms
; i
++){
3536 if(object
->mh
!= NULL
)
3537 n_strx
= symbols
[i
].n_un
.n_strx
;
3539 n_strx
= symbols64
[i
].n_un
.n_strx
;
3541 strcpy(p
, strings
+ n_strx
);
3542 if(object
->mh
!= NULL
)
3543 undef_map
[inew_undefsyms
].symbol
.n_un
.n_strx
=
3546 undef_map64
[inew_undefsyms
].symbol64
.n_un
.n_strx
=
3550 if(object
->mh
!= NULL
){
3551 undef_map
[inew_undefsyms
].symbol
.n_type
= N_UNDF
| N_EXT
;
3552 undef_map
[inew_undefsyms
].symbol
.n_sect
= NO_SECT
;
3553 undef_map
[inew_undefsyms
].symbol
.n_desc
= 0;
3554 undef_map
[inew_undefsyms
].symbol
.n_value
= 0;
3555 undef_map
[inew_undefsyms
].index
= i
;
3558 undef_map64
[inew_undefsyms
].symbol64
.n_type
= N_UNDF
|N_EXT
;
3559 undef_map64
[inew_undefsyms
].symbol64
.n_sect
= NO_SECT
;
3560 undef_map64
[inew_undefsyms
].symbol64
.n_desc
= 0;
3561 undef_map64
[inew_undefsyms
].symbol64
.n_value
= 0;
3562 undef_map64
[inew_undefsyms
].index
= i
;
3567 /* Sort the undefined symbols by name */
3568 qsort_strings
= new_strings
;
3569 if(object
->mh
!= NULL
)
3570 qsort(undef_map
, new_nundefsym
, sizeof(struct undef_map
),
3571 (int (*)(const void *, const void *))cmp_qsort_undef_map
);
3573 qsort(undef_map64
, new_nundefsym
, sizeof(struct undef_map64
),
3574 (int (*)(const void *, const void *))cmp_qsort_undef_map_64
);
3575 /* Copy the symbols now in sorted order into new_symbols */
3576 for(i
= 0; i
< new_nundefsym
; i
++){
3577 if(object
->mh
!= NULL
){
3578 new_symbols
[inew_syms
] = undef_map
[i
].symbol
;
3580 saves
[undef_map
[i
].index
] = inew_syms
;
3583 new_symbols64
[inew_syms
] = undef_map64
[i
].symbol64
;
3585 saves
[undef_map64
[i
].index
] = inew_syms
;
3590 * Fixup the module table's module name strings adding them to the
3591 * string table. Also fix the indexes into the symbol table for
3592 * external and local symbols. And fix up the indexes into the
3595 for(i
= 0; i
< nmodtab
; i
++){
3596 if(object
->mh
!= NULL
){
3597 strcpy(p
, strings
+ mods
[i
].module_name
);
3598 mods
[i
].module_name
= p
- new_strings
;
3599 iextdefsym
= mods
[i
].iextdefsym
;
3600 nextdefsym
= mods
[i
].nextdefsym
;
3601 ilocalsym
= mods
[i
].ilocalsym
;
3602 nlocalsym
= mods
[i
].nlocalsym
;
3603 irefsym
= mods
[i
].irefsym
;
3604 nrefsym
= mods
[i
].nrefsym
;
3607 strcpy(p
, strings
+ mods64
[i
].module_name
);
3608 mods64
[i
].module_name
= p
- new_strings
;
3609 iextdefsym
= mods64
[i
].iextdefsym
;
3610 nextdefsym
= mods64
[i
].nextdefsym
;
3611 ilocalsym
= mods64
[i
].ilocalsym
;
3612 nlocalsym
= mods64
[i
].nlocalsym
;
3613 irefsym
= mods64
[i
].irefsym
;
3614 nrefsym
= mods64
[i
].nrefsym
;
3618 if(iextdefsym
> nsyms
){
3619 error_arch(arch
, member
, "bad index into externally defined "
3620 "symbols of module table entry %d in: ", i
);
3623 if(iextdefsym
+ nextdefsym
> nsyms
){
3624 error_arch(arch
, member
, "bad number of externally defined "
3625 "symbols of module table entry %d in: ", i
);
3628 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
3629 if(saves
[j
] != 0 && changes
[j
] == 0)
3633 for(k
= j
; k
< iextdefsym
+ nextdefsym
; k
++){
3634 if(saves
[k
] != 0 && changes
[k
] == 0)
3638 if(object
->mh
!= NULL
){
3639 mods
[i
].iextdefsym
= 0;
3640 mods
[i
].nextdefsym
= 0;
3643 mods64
[i
].iextdefsym
= 0;
3644 mods64
[i
].nextdefsym
= 0;
3648 if(object
->mh
!= NULL
){
3649 mods
[i
].iextdefsym
= saves
[j
] - 1;
3650 mods
[i
].nextdefsym
= n
;
3653 mods64
[i
].iextdefsym
= saves
[j
] - 1;
3654 mods64
[i
].nextdefsym
= n
;
3658 if(ilocalsym
> nsyms
){
3659 error_arch(arch
, member
, "bad index into symbols for local "
3660 "symbols of module table entry %d in: ", i
);
3663 if(ilocalsym
+ nlocalsym
> nsyms
){
3664 error_arch(arch
, member
, "bad number of local "
3665 "symbols of module table entry %d in: ", i
);
3668 for(j
= ilocalsym
; j
< ilocalsym
+ nlocalsym
; j
++){
3673 for(k
= j
; k
< ilocalsym
+ nlocalsym
; k
++){
3678 if(object
->mh
!= NULL
){
3679 mods
[i
].ilocalsym
= 0;
3680 mods
[i
].nlocalsym
= 0;
3683 mods64
[i
].ilocalsym
= 0;
3684 mods64
[i
].nlocalsym
= 0;
3688 if(object
->mh
!= NULL
){
3689 mods
[i
].ilocalsym
= saves
[j
] - 1;
3690 mods
[i
].nlocalsym
= n
;
3693 mods64
[i
].ilocalsym
= saves
[j
] - 1;
3694 mods64
[i
].nlocalsym
= n
;
3698 if(irefsym
> nextrefsyms
){
3699 error_arch(arch
, member
, "bad index into reference table "
3700 "of module table entry %d in: ", i
);
3703 if(irefsym
+ nrefsym
> nextrefsyms
){
3704 error_arch(arch
, member
, "bad number of reference table "
3705 "entries of module table entry %d in: ", i
);
3708 for(j
= irefsym
; j
< irefsym
+ nrefsym
; j
++){
3709 if(ref_saves
[j
] != 0)
3713 for(k
= j
; k
< irefsym
+ nrefsym
; k
++){
3714 if(ref_saves
[k
] != 0)
3718 if(object
->mh
!= NULL
){
3719 mods
[i
].irefsym
= 0;
3720 mods
[i
].nrefsym
= 0;
3723 mods64
[i
].irefsym
= 0;
3724 mods64
[i
].nrefsym
= 0;
3728 if(object
->mh
!= NULL
){
3729 mods
[i
].irefsym
= ref_saves
[j
] - 1;
3730 mods
[i
].nrefsym
= n
;
3733 mods64
[i
].irefsym
= ref_saves
[j
] - 1;
3734 mods64
[i
].nrefsym
= n
;
3740 * Create a new reference table.
3742 new_refs
= allocate(new_nextrefsyms
* sizeof(struct dylib_reference
));
3744 for(i
= 0; i
< nextrefsyms
; i
++){
3746 if(saves
[refs
[i
].isym
]){
3747 new_refs
[j
].isym
= saves
[refs
[i
].isym
] - 1;
3748 new_refs
[j
].flags
= refs
[i
].flags
;
3751 if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
||
3752 refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
){
3753 new_refs
[j
].isym
= changes
[refs
[i
].isym
] - 1;
3754 new_refs
[j
].flags
= refs
[i
].flags
;
3762 * Create a new dylib table of contents.
3765 for(i
= 0; i
< ntoc
; i
++){
3766 if(tocs
[i
].symbol_index
>= nsyms
){
3767 error_arch(arch
, member
, "bad symbol index for table of "
3768 "contents table entry %d in: ", i
);
3771 if(saves
[tocs
[i
].symbol_index
] != 0 &&
3772 changes
[tocs
[i
].symbol_index
] == 0)
3775 new_tocs
= allocate(new_ntoc
* sizeof(struct dylib_table_of_contents
));
3777 for(i
= 0; i
< ntoc
; i
++){
3778 if(saves
[tocs
[i
].symbol_index
] != 0 &&
3779 changes
[tocs
[i
].symbol_index
] == 0){
3780 new_tocs
[j
].symbol_index
= saves
[tocs
[i
].symbol_index
] - 1;
3781 new_tocs
[j
].module_index
= tocs
[i
].module_index
;
3787 * Update the export trie if it has one but only call the the
3788 * prune_trie() routine when we are removing global symbols as is
3789 * done with default stripping of a dyld executable or with the -s
3792 if(object
->dyld_info
!= NULL
&&
3793 object
->dyld_info
->export_size
!= 0 &&
3794 (default_dyld_executable
|| sfile
!= NULL
|| Rfile
!= NULL
)){
3795 const char *error_string
;
3796 uint32_t trie_new_size
;
3798 error_string
= prune_trie((uint8_t *)(object
->object_addr
+
3799 object
->dyld_info
->export_off
),
3800 object
->dyld_info
->export_size
,
3803 if(error_string
!= NULL
){
3804 error_arch(arch
, member
, "%s", error_string
);
3808 #endif /* TRIE_SUPPORT */
3810 if(undef_map
!= NULL
)
3812 if(undef_map64
!= NULL
)
3816 if(sections
!= NULL
)
3818 if(sections64
!= NULL
)
3829 * prune() is called by prune_trie() and passed a name of an external symbol
3830 * in the trie. It returns 1 if the symbols is to be pruned out and 0 if the
3831 * symbol is to be kept.
3833 * Note that it may seem like a linear search of the new symbols would not be
3834 * the best approach but in 10.6 the only defined global symbol left in a
3835 * stripped executable is __mh_execute_header and new_nextdefsym is usually 1
3836 * so this never actually loops in practice.
3845 for(i
= 0; i
< new_nextdefsym
; i
++){
3846 if(new_symbols
!= NULL
){
3847 if(strcmp(name
, new_strings
+ new_symbols
[inew_nextdefsym
+ i
]
3852 if(strcmp(name
, new_strings
+ new_symbols64
[inew_nextdefsym
+ i
]
3859 #endif /* TRIE_SUPPORT */
3862 * make_ld_r_object() takes the object file contents referenced by the passed
3863 * data structures, writes that to a temporary file, runs "ld -r" plus the
3864 * specified stripping option creating a second temporary file, reads that file
3865 * in and replaces the object file contents with that and resets the variables
3866 * pointing to the symbol, string and indirect tables.
3872 struct member
*member
,
3873 struct object
*object
)
3875 enum byte_sex host_byte_sex
;
3876 char *input_file
, *output_file
;
3878 struct ofile
*ld_r_ofile
;
3879 struct arch
*ld_r_archs
;
3880 uint32_t ld_r_narchs
, save_errors
;
3882 host_byte_sex
= get_host_byte_sex();
3885 * Swap the object file back into its bytesex before writing it to the
3886 * temporary file if needed.
3888 if(object
->object_byte_sex
!= host_byte_sex
){
3889 if(object
->mh
!= NULL
){
3890 if(swap_object_headers(object
->mh
, object
->load_commands
) ==
3892 fatal("internal error: swap_object_headers() failed");
3893 swap_nlist(symbols
, nsyms
, object
->object_byte_sex
);
3896 if(swap_object_headers(object
->mh64
, object
->load_commands
) ==
3898 fatal("internal error: swap_object_headers() failed");
3899 swap_nlist_64(symbols64
, nsyms
, object
->object_byte_sex
);
3901 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
3902 object
->object_byte_sex
);
3906 * Create an input object file for the ld -r command from the bytes
3907 * of this arch's object file.
3909 input_file
= makestr("/tmp/strip.XXXXXX", NULL
);
3910 input_file
= mktemp(input_file
);
3912 if((fd
= open(input_file
, O_WRONLY
|O_CREAT
, 0600)) < 0)
3913 system_fatal("can't open temporary file: %s", input_file
);
3915 if(write(fd
, object
->object_addr
, object
->object_size
) !=
3916 object
->object_size
)
3917 system_fatal("can't write temporary file: %s", input_file
);
3920 system_fatal("can't close temporary file: %s", input_file
);
3923 * Create a temporary name for the output file of the ld -r
3925 output_file
= makestr("/tmp/strip.XXXXXX", NULL
);
3926 output_file
= mktemp(output_file
);
3929 * Create the ld -r command line and execute it.
3931 reset_execute_list();
3932 add_execute_list_with_prefix("ld");
3933 add_execute_list("-keep_private_externs");
3934 add_execute_list("-r");
3936 add_execute_list("-S");
3938 add_execute_list("-x");
3939 add_execute_list(input_file
);
3940 add_execute_list("-o");
3941 add_execute_list(output_file
);
3943 add_execute_list("-x");
3944 add_execute_list("-exported_symbols_list");
3945 add_execute_list(sfile
);
3948 add_execute_list("-unexported_symbols_list");
3949 add_execute_list(Rfile
);
3951 if(execute_list(vflag
) == 0)
3952 fatal("internal link edit command failed");
3954 save_errors
= errors
;
3956 /* breakout the output file of the ld -f for processing */
3957 ld_r_ofile
= breakout(output_file
, &ld_r_archs
, &ld_r_narchs
, FALSE
);
3959 goto make_ld_r_object_cleanup
;
3961 /* checkout the file for symbol table replacement processing */
3962 checkout(ld_r_archs
, ld_r_narchs
);
3965 * Make sure the output of the ld -r is an object file with one arch.
3967 if(ld_r_narchs
!= 1 ||
3968 ld_r_archs
->type
!= OFILE_Mach_O
||
3969 ld_r_archs
->object
== NULL
||
3970 ld_r_archs
->object
->mh_filetype
!= MH_OBJECT
)
3971 fatal("internal link edit command failed to produce a thin Mach-O "
3975 * Now reset all the data of the input object with the ld -r output
3978 nsyms
= ld_r_archs
->object
->st
->nsyms
;
3979 if(ld_r_archs
->object
->mh
!= NULL
){
3980 symbols
= (struct nlist
*)
3981 (ld_r_archs
->object
->object_addr
+
3982 ld_r_archs
->object
->st
->symoff
);
3983 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3984 swap_nlist(symbols
, nsyms
, host_byte_sex
);
3989 symbols64
= (struct nlist_64
*)
3990 (ld_r_archs
->object
->object_addr
+
3991 ld_r_archs
->object
->st
->symoff
);
3992 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3993 swap_nlist_64(symbols64
, nsyms
, host_byte_sex
);
3995 strings
= ld_r_archs
->object
->object_addr
+
3996 ld_r_archs
->object
->st
->stroff
;
3997 strsize
= ld_r_archs
->object
->st
->strsize
;
3999 if(ld_r_archs
->object
->dyst
!= NULL
&&
4000 ld_r_archs
->object
->dyst
->nindirectsyms
!= 0){
4001 nindirectsyms
= ld_r_archs
->object
->dyst
->nindirectsyms
;
4002 indirectsyms
= (uint32_t *)
4003 (ld_r_archs
->object
->object_addr
+
4004 ld_r_archs
->object
->dyst
->indirectsymoff
);
4005 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
4006 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
4010 indirectsyms
= NULL
;
4014 if(ld_r_archs
->object
->mh
!= NULL
)
4015 ld_r_archs
->object
->input_sym_info_size
=
4016 nsyms
* sizeof(struct nlist
) +
4019 ld_r_archs
->object
->input_sym_info_size
=
4020 nsyms
* sizeof(struct nlist_64
) +
4024 * Copy over the object struct from the ld -r object file onto the
4025 * input object file.
4027 *object
= *ld_r_archs
->object
;
4030 * Save the ofile struct for the ld -r output so it can be umapped when
4031 * we are done. And free up the ld_r_archs now that we are done with
4034 object
->ld_r_ofile
= ld_r_ofile
;
4035 free_archs(ld_r_archs
, ld_r_narchs
);
4037 make_ld_r_object_cleanup
:
4038 errors
+= save_errors
;
4040 * Remove the input and output files and clean up.
4042 if(unlink(input_file
) == -1)
4043 system_fatal("can't remove temporary file: %s", input_file
);
4044 if(unlink(output_file
) == -1)
4045 system_fatal("can't remove temporary file: %s", output_file
);
4051 * strip_LC_UUID_commands() is called when -no_uuid is specified to remove any
4052 * LC_UUID load commands from the object's load commands.
4056 strip_LC_UUID_commands(
4058 struct member
*member
,
4059 struct object
*object
)
4061 uint32_t i
, ncmds
, nuuids
, mh_sizeofcmds
, sizeofcmds
;
4062 struct load_command
*lc1
, *lc2
, *new_load_commands
;
4063 struct segment_command
*sg
;
4066 * See if there are any LC_UUID load commands.
4069 lc1
= arch
->object
->load_commands
;
4070 if(arch
->object
->mh
!= NULL
){
4071 ncmds
= arch
->object
->mh
->ncmds
;
4072 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
4075 ncmds
= arch
->object
->mh64
->ncmds
;
4076 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
4078 for(i
= 0; i
< ncmds
; i
++){
4079 if(lc1
->cmd
== LC_UUID
){
4082 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4084 /* if no LC_UUID load commands just return */
4089 * Allocate space for the new load commands as zero it out so any holes
4090 * will be zero bytes.
4092 new_load_commands
= allocate(mh_sizeofcmds
);
4093 memset(new_load_commands
, '\0', mh_sizeofcmds
);
4096 * Copy all the load commands except the LC_UUID load commands into the
4097 * allocated space for the new load commands.
4099 lc1
= arch
->object
->load_commands
;
4100 lc2
= new_load_commands
;
4102 for(i
= 0; i
< ncmds
; i
++){
4103 if(lc1
->cmd
!= LC_UUID
){
4104 memcpy(lc2
, lc1
, lc1
->cmdsize
);
4105 sizeofcmds
+= lc2
->cmdsize
;
4106 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
4108 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4112 * Finally copy the updated load commands over the existing load
4115 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
4116 if(mh_sizeofcmds
> sizeofcmds
){
4117 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
4118 (mh_sizeofcmds
- sizeofcmds
));
4121 if(arch
->object
->mh
!= NULL
) {
4122 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
4123 arch
->object
->mh
->ncmds
= ncmds
;
4125 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
4126 arch
->object
->mh64
->ncmds
= ncmds
;
4128 free(new_load_commands
);
4130 /* reset the pointers into the load commands */
4131 lc1
= arch
->object
->load_commands
;
4132 for(i
= 0; i
< ncmds
; i
++){
4135 arch
->object
->st
= (struct symtab_command
*)lc1
;
4138 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
4140 case LC_TWOLEVEL_HINTS
:
4141 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
4143 case LC_PREBIND_CKSUM
:
4144 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
4147 sg
= (struct segment_command
*)lc1
;
4148 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
4149 arch
->object
->seg_linkedit
= sg
;
4151 case LC_SEGMENT_SPLIT_INFO
:
4152 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
4154 case LC_FUNCTION_STARTS
:
4155 object
->func_starts_info_cmd
=
4156 (struct linkedit_data_command
*)lc1
;
4158 case LC_DATA_IN_CODE
:
4159 object
->data_in_code_cmd
=
4160 (struct linkedit_data_command
*)lc1
;
4162 case LC_DYLIB_CODE_SIGN_DRS
:
4163 object
->code_sign_drs_cmd
=
4164 (struct linkedit_data_command
*)lc1
;
4166 case LC_CODE_SIGNATURE
:
4167 object
->code_sig_cmd
= (struct linkedit_data_command
*)lc1
;
4169 case LC_DYLD_INFO_ONLY
:
4171 object
->dyld_info
= (struct dyld_info_command
*)lc1
;
4173 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4179 * strip_LC_CODE_SIGNATURE_commands() is called when -c is specified to remove
4180 * any LC_CODE_SIGNATURE load commands from the object's load commands.
4184 strip_LC_CODE_SIGNATURE_commands(
4186 struct member
*member
,
4187 struct object
*object
)
4189 uint32_t i
, ncmds
, mh_sizeofcmds
, sizeofcmds
;
4190 struct load_command
*lc1
, *lc2
, *new_load_commands
;
4191 struct segment_command
*sg
;
4194 * See if there is an LC_CODE_SIGNATURE load command and if no command
4197 if(object
->code_sig_cmd
== NULL
)
4201 * Allocate space for the new load commands and zero it out so any holes
4202 * will be zero bytes.
4204 if(arch
->object
->mh
!= NULL
){
4205 ncmds
= arch
->object
->mh
->ncmds
;
4206 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
4209 ncmds
= arch
->object
->mh64
->ncmds
;
4210 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
4212 new_load_commands
= allocate(mh_sizeofcmds
);
4213 memset(new_load_commands
, '\0', mh_sizeofcmds
);
4216 * Copy all the load commands except the LC_CODE_SIGNATURE load commands
4217 * into the allocated space for the new load commands.
4219 lc1
= arch
->object
->load_commands
;
4220 lc2
= new_load_commands
;
4222 for(i
= 0; i
< ncmds
; i
++){
4223 if(lc1
->cmd
!= LC_CODE_SIGNATURE
){
4224 memcpy(lc2
, lc1
, lc1
->cmdsize
);
4225 sizeofcmds
+= lc2
->cmdsize
;
4226 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
4228 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4232 * Finally copy the updated load commands over the existing load
4235 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
4236 if(mh_sizeofcmds
> sizeofcmds
){
4237 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
4238 (mh_sizeofcmds
- sizeofcmds
));
4241 if(arch
->object
->mh
!= NULL
) {
4242 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
4243 arch
->object
->mh
->ncmds
= ncmds
;
4245 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
4246 arch
->object
->mh64
->ncmds
= ncmds
;
4248 free(new_load_commands
);
4250 /* reset the pointers into the load commands */
4251 object
->code_sig_cmd
= NULL
;
4252 lc1
= arch
->object
->load_commands
;
4253 for(i
= 0; i
< ncmds
; i
++){
4256 arch
->object
->st
= (struct symtab_command
*)lc1
;
4259 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
4261 case LC_TWOLEVEL_HINTS
:
4262 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
4264 case LC_PREBIND_CKSUM
:
4265 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
4268 sg
= (struct segment_command
*)lc1
;
4269 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
4270 arch
->object
->seg_linkedit
= sg
;
4272 case LC_SEGMENT_SPLIT_INFO
:
4273 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
4275 case LC_FUNCTION_STARTS
:
4276 object
->func_starts_info_cmd
=
4277 (struct linkedit_data_command
*)lc1
;
4279 case LC_DATA_IN_CODE
:
4280 object
->data_in_code_cmd
=
4281 (struct linkedit_data_command
*)lc1
;
4283 case LC_DYLIB_CODE_SIGN_DRS
:
4284 object
->code_sign_drs_cmd
=
4285 (struct linkedit_data_command
*)lc1
;
4287 case LC_DYLD_INFO_ONLY
:
4289 object
->dyld_info
= (struct dyld_info_command
*)lc1
;
4291 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4296 * To get the right amount of the file copied out by writeout() for
4297 * the case when we are stripping out the section contents we
4298 * already reduce the object size by the size of the section
4299 * contents including the padding after the load commands. So here
4300 * we need to further reduce it by the load command for the
4301 * LC_CODE_SIGNATURE (a struct linkedit_data_command) we are
4304 object
->object_size
-= sizeof(struct linkedit_data_command
);
4306 * Then this size minus the size of the input symbolic information
4307 * is what is copied out from the file by writeout(). Which in this
4308 * case is just the new headers.
4312 * Finally for -c the file offset to the link edit information is to
4313 * be right after the load commands. So reset this for the updated
4314 * size of the load commands without the LC_CODE_SIGNATURE.
4316 if(object
->mh
!= NULL
)
4317 object
->seg_linkedit
->fileoff
= sizeof(struct mach_header
) +
4320 object
->seg_linkedit64
->fileoff
=
4321 sizeof(struct mach_header_64
) + sizeofcmds
;
4324 #endif /* !(NMEDIT) */
4327 * private_extern_reference_by_module() is passed a symbol_index of a private
4328 * extern symbol and the module table. If the symbol_index appears in the
4329 * module symbol table this returns TRUE else it returns FALSE.
4333 private_extern_reference_by_module(
4334 uint32_t symbol_index
,
4335 struct dylib_reference
*refs
,
4336 uint32_t nextrefsyms
)
4340 for(i
= 0; i
< nextrefsyms
; i
++){
4341 if(refs
[i
].isym
== symbol_index
){
4342 if(refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
||
4343 refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
){
4352 * symbol_pointer_used() is passed a symbol_index and the indirect table. If
4353 * the symbol_index appears in the indirect symbol table this returns TRUE else
4358 symbol_pointer_used(
4359 uint32_t symbol_index
,
4360 uint32_t *indirectsyms
,
4361 uint32_t nindirectsyms
)
4365 for(i
= 0; i
< nindirectsyms
; i
++){
4366 if(indirectsyms
[i
] == symbol_index
)
4373 * Function for qsort for comparing undefined map entries.
4377 cmp_qsort_undef_map(
4378 const struct undef_map
*sym1
,
4379 const struct undef_map
*sym2
)
4381 return(strcmp(qsort_strings
+ sym1
->symbol
.n_un
.n_strx
,
4382 qsort_strings
+ sym2
->symbol
.n_un
.n_strx
));
4387 cmp_qsort_undef_map_64(
4388 const struct undef_map64
*sym1
,
4389 const struct undef_map64
*sym2
)
4391 return(strcmp(qsort_strings
+ sym1
->symbol64
.n_un
.n_strx
,
4392 qsort_strings
+ sym2
->symbol64
.n_un
.n_strx
));
4394 #endif /* !defined(NMEDIT) */
4398 * Function for qsort for comparing object names.
4406 return(strcmp(*name1
, *name2
));
4410 * Function for bsearch for finding a object name.
4414 cmp_bsearch_filename(
4418 return(strcmp(name1
, *name2
));
4420 #endif /* !defined(NMEDIT) */
4427 struct member
*member
,
4428 struct object
*object
,
4429 struct nlist
*symbols
,
4430 struct nlist_64
*symbols64
,
4434 struct dylib_table_of_contents
*tocs
,
4436 struct dylib_module
*mods
,
4437 struct dylib_module_64
*mods64
,
4439 struct dylib_reference
*refs
,
4440 uint32_t nextrefsyms
)
4443 unsigned char data_n_sect
, nsects
;
4444 struct load_command
*lc
;
4445 struct segment_command
*sg
;
4446 struct segment_command_64
*sg64
;
4447 struct section
*s
, **sections
;
4448 struct section_64
*s64
, **sections64
;
4450 uint32_t missing_syms
;
4451 struct symbol_list
*sp
;
4452 struct nlist
**global_symbol
;
4453 struct nlist_64
**global_symbol64
;
4454 enum bool global_symbol_found
;
4455 char *global_name
, save_char
;
4456 enum bool dwarf_debug_map
;
4457 enum byte_sex host_byte_sex
;
4458 int32_t missing_reloc_symbols
;
4459 enum bool edit_symtab_return
;
4462 uint32_t new_ext_strsize
, len
, inew_syms
;
4464 struct nlist
**changed_globals
;
4465 struct nlist_64
**changed_globals64
;
4466 uint32_t nchanged_globals
;
4467 uint32_t ncmds
, s_flags
, n_strx
, module_name
, ilocalsym
, nlocalsym
;
4468 uint32_t iextdefsym
, nextdefsym
;
4469 uint8_t n_type
, n_sect
, global_symbol_n_sect
;
4471 enum bool warned_about_global_coalesced_symbols
;
4473 edit_symtab_return
= TRUE
;
4474 host_byte_sex
= get_host_byte_sex();
4475 missing_reloc_symbols
= 0;
4476 warned_about_global_coalesced_symbols
= FALSE
;
4480 nmedits
= allocate(nsyms
* sizeof(enum bool));
4481 for(i
= 0; i
< nsyms
; i
++)
4485 * If nmedit is operating on a dynamic library then symbols are turned
4486 * into private externs with the extern bit off not into static symbols.
4488 if(object
->mh_filetype
== MH_DYLIB
&& pflag
== TRUE
){
4489 error_arch(arch
, member
, "can't use -p with dynamic libraries");
4494 * As part of the MAJOR guess for the second pass to fix stabs for the
4495 * globals symbols that get turned into non-global symbols. We need to
4496 * change the stabs. To do this we to know if a N_GSYM is for a data
4497 * symbol or not to know to turn it into an N_STSYM or a N_FUN.
4498 * This logic as determined by compiling test cases with and without
4499 * the key word 'static' and looking at the difference between the STABS
4500 * the compiler generates and trying to match that here.
4502 * We also use this loop and the next to gather an array of section
4503 * struct pointers so we can later determine if we run into a global
4504 * symbol in a coalesced section and not turn those symbols into
4510 data_n_sect
= NO_SECT
;
4511 lc
= object
->load_commands
;
4512 if(object
->mh
!= NULL
)
4513 ncmds
= object
->mh
->ncmds
;
4515 ncmds
= object
->mh64
->ncmds
;
4516 for(i
= 0; i
< ncmds
; i
++){
4517 if(lc
->cmd
== LC_SEGMENT
){
4518 sg
= (struct segment_command
*)lc
;
4519 s
= (struct section
*)((char *)sg
+
4520 sizeof(struct segment_command
));
4521 nsects
+= sg
->nsects
;
4522 for(j
= 0; j
< sg
->nsects
; j
++){
4523 if(strcmp(s
->segname
, SEG_DATA
) == 0 &&
4524 strcmp(s
->sectname
, SECT_DATA
) == 0 &&
4525 data_n_sect
== NO_SECT
){
4526 data_n_sect
= n_sect
;
4533 else if(lc
->cmd
== LC_SEGMENT_64
){
4534 sg64
= (struct segment_command_64
*)lc
;
4535 s64
= (struct section_64
*)((char *)sg64
+
4536 sizeof(struct segment_command_64
));
4537 nsects
+= sg64
->nsects
;
4538 for(j
= 0; j
< sg64
->nsects
; j
++){
4539 if(strcmp(s64
->segname
, SEG_DATA
) == 0 &&
4540 strcmp(s64
->sectname
, SECT_DATA
) == 0 &&
4541 data_n_sect
== NO_SECT
){
4542 data_n_sect
= n_sect
;
4549 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
4551 if(object
->mh
!= NULL
){
4552 sections
= allocate(nsects
* sizeof(struct section
*));
4557 sections64
= allocate(nsects
* sizeof(struct section_64
*));
4560 lc
= object
->load_commands
;
4561 for(i
= 0; i
< ncmds
; i
++){
4562 if(lc
->cmd
== LC_SEGMENT
){
4563 sg
= (struct segment_command
*)lc
;
4564 s
= (struct section
*)((char *)sg
+
4565 sizeof(struct segment_command
));
4566 for(j
= 0; j
< sg
->nsects
; j
++){
4567 sections
[nsects
++] = s
++;
4570 else if(lc
->cmd
== LC_SEGMENT_64
){
4571 sg64
= (struct segment_command_64
*)lc
;
4572 s64
= (struct section_64
*)((char *)sg64
+
4573 sizeof(struct segment_command_64
));
4574 for(j
= 0; j
< sg64
->nsects
; j
++){
4575 sections64
[nsects
++] = s64
++;
4578 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
4582 * Zero out the saved symbols so they can be recorded for this file.
4584 for(i
= 0; i
< nsave_symbols
; i
++)
4585 save_symbols
[i
].sym
= NULL
;
4586 for(i
= 0; i
< nremove_symbols
; i
++)
4587 remove_symbols
[i
].sym
= NULL
;
4589 for(i
= 0; i
< nsave_symbols
; i
++)
4590 save_symbols
[i
].seen
= FALSE
;
4591 for(i
= 0; i
< nremove_symbols
; i
++)
4592 remove_symbols
[i
].seen
= FALSE
;
4595 nchanged_globals
= 0;
4596 if(object
->mh
!= NULL
){
4597 changed_globals
= allocate(nsyms
* sizeof(struct nlist
*));
4598 changed_globals64
= NULL
;
4599 for(i
= 0; i
< nsyms
; i
++)
4600 changed_globals
[i
] = NULL
;
4603 changed_globals
= NULL
;
4604 changed_globals64
= allocate(nsyms
* sizeof(struct nlist_64
*));
4605 for(i
= 0; i
< nsyms
; i
++)
4606 changed_globals64
[i
] = NULL
;
4610 * These are the variables for the new symbol table and new string
4611 * table. Since this routine only turns globals into non-globals the
4612 * number of symbols does not change. But the count of local, defined
4613 * external symbols does change.
4620 new_strsize
= sizeof(int32_t);
4621 new_ext_strsize
= 0;
4624 * First pass: turn the globals symbols into non-global symbols.
4626 for(i
= 0; i
< nsyms
; i
++){
4629 if(object
->mh
!= NULL
){
4630 n_strx
= symbols
[i
].n_un
.n_strx
;
4631 n_type
= symbols
[i
].n_type
;
4632 n_sect
= symbols
[i
].n_sect
;
4633 if((n_type
& N_TYPE
) == N_SECT
)
4634 s_flags
= sections
[n_sect
- 1]->flags
;
4635 n_value
= symbols
[i
].n_value
;
4638 n_strx
= symbols64
[i
].n_un
.n_strx
;
4639 n_type
= symbols64
[i
].n_type
;
4640 n_sect
= symbols64
[i
].n_sect
;
4641 if((n_type
& N_TYPE
) == N_SECT
)
4642 s_flags
= sections64
[n_sect
- 1]->flags
;
4643 n_value
= symbols64
[i
].n_value
;
4646 if(n_strx
> strsize
){
4647 error_arch(arch
, member
, "bad string index for symbol "
4648 "table entry %u in: ", i
);
4651 len
= strlen(strings
+ n_strx
) + 1;
4654 if((n_type
& N_TYPE
) != N_UNDF
&&
4655 (n_type
& N_TYPE
) != N_PBUD
){
4656 if((n_type
& N_TYPE
) == N_SECT
){
4657 if(n_sect
> nsects
){
4658 error_arch(arch
, member
, "bad n_sect for symbol "
4659 "table entry %u in: ", i
);
4662 if(((s_flags
& SECTION_TYPE
) == S_COALESCED
) &&
4664 object
->mh_filetype
!= MH_OBJECT
){
4665 /* this remains a global defined symbol */
4666 if(warned_about_global_coalesced_symbols
== FALSE
){
4667 warning_arch(arch
, member
, "can't make global "
4668 "coalesced symbols (like %s) into static "
4669 "symbols (use ld(1)'s "
4670 "-exported_symbols_list option) in a final "
4671 "linked image: ", strings
+ n_strx
);
4672 warned_about_global_coalesced_symbols
= TRUE
;
4675 new_ext_strsize
+= len
;
4677 sp
= bsearch(strings
+ n_strx
,
4678 remove_symbols
, nremove_symbols
,
4679 sizeof(struct symbol_list
),
4680 (int (*)(const void *, const void *))
4681 symbol_list_bsearch
);
4683 if(sp
->sym
!= NULL
){
4684 error_arch(arch
, member
, "more than one "
4685 "symbol for: %s found in: ", sp
->name
);
4689 if(object
->mh
!= NULL
)
4690 sp
->sym
= &(symbols
[i
]);
4692 sp
->sym
= &(symbols64
[i
]);
4694 warning_arch(arch
, member
, "can't make "
4695 "global coalesced symbol: %s into a "
4696 "static symbol in: ", sp
->name
);
4700 * In case the user has listed this coalesced
4701 * symbol in the save list look for it and mark it
4702 * as seen so we don't complain about not seeing it.
4704 sp
= bsearch(strings
+ n_strx
,
4705 save_symbols
, nsave_symbols
,
4706 sizeof(struct symbol_list
),
4707 (int (*)(const void *, const void *))
4708 symbol_list_bsearch
);
4710 if(sp
->sym
!= NULL
){
4711 error_arch(arch
, member
, "more than one "
4712 "symbol for: %s found in: ", sp
->name
);
4716 if(object
->mh
!= NULL
)
4717 sp
->sym
= &(symbols
[i
]);
4719 sp
->sym
= &(symbols64
[i
]);
4723 continue; /* leave this symbol unchanged */
4726 sp
= bsearch(strings
+ n_strx
,
4727 remove_symbols
, nremove_symbols
,
4728 sizeof(struct symbol_list
),
4729 (int (*)(const void *, const void *))
4730 symbol_list_bsearch
);
4732 if(sp
->sym
!= NULL
){
4733 error_arch(arch
, member
, "more than one symbol "
4734 "for: %s found in: ", sp
->name
);
4738 if(object
->mh
!= NULL
)
4739 sp
->sym
= &(symbols
[i
]);
4741 sp
->sym
= &(symbols64
[i
]);
4748 * If there is no list of saved symbols, then all
4749 * symbols will be saved unless listed in the remove
4754 * There is no save list, so if there is also no
4755 * remove list but the -p flag is specified or it is
4756 * a dynamic library then change all symbols.
4758 if((pflag
|| object
->mh_filetype
== MH_DYLIB
)
4759 && nremove_symbols
== 0)
4761 /* this remains a global defined symbol */
4763 new_ext_strsize
+= len
;
4765 continue; /* leave this symbol unchanged */
4768 sp
= bsearch(strings
+ n_strx
,
4769 save_symbols
, nsave_symbols
,
4770 sizeof(struct symbol_list
),
4771 (int (*)(const void *, const void *))
4772 symbol_list_bsearch
);
4774 if(sp
->sym
!= NULL
){
4775 error_arch(arch
, member
, "more than one symbol "
4776 "for: %s found in: ", sp
->name
);
4780 if(object
->mh
!= NULL
)
4781 sp
->sym
= &(symbols
[i
]);
4783 sp
->sym
= &(symbols64
[i
]);
4785 /* this remains a global defined symbol */
4787 new_ext_strsize
+= len
;
4792 if(Aflag
&& n_type
== (N_EXT
| N_ABS
) &&
4795 strncmp(strings
+ n_strx
,
4796 ".objc_class_name_",
4797 sizeof(".objc_class_name_") - 1) == 0))){
4798 /* this remains a global defined symbol */
4800 new_ext_strsize
+= len
;
4805 if((n_type
& N_TYPE
) != N_INDR
){
4807 if(object
->mh
!= NULL
)
4808 changed_globals
[nchanged_globals
++] =
4811 changed_globals64
[nchanged_globals
++] =
4814 /* this remains a global defined symbol */
4816 new_ext_strsize
+= len
;
4820 /* this will become a non-global symbol */
4826 /* this remains a global defined symbol */
4828 new_ext_strsize
+= len
;
4835 /* this is an undefined symbol */
4837 new_ext_strsize
+= len
;
4842 /* this is a local symbol */
4849 * The module table's module names are placed with the external
4850 * strings. So size them and add this to the external string size.
4852 for(i
= 0; i
< nmodtab
; i
++){
4853 if(object
->mh
!= NULL
)
4854 module_name
= mods
[i
].module_name
;
4856 module_name
= mods64
[i
].module_name
;
4857 if(module_name
== 0 || module_name
> strsize
){
4858 error_arch(arch
, member
, "bad string index for module_name "
4859 "of module table entry %d in: ", i
);
4862 len
= strlen(strings
+ module_name
) + 1;
4864 new_ext_strsize
+= len
;
4868 * Warn about symbols to be saved that were missing.
4873 for(i
= 0; i
< nsave_symbols
; i
++){
4874 if(save_symbols
[i
].sym
== NULL
){
4875 if(missing_syms
== 0){
4876 error_arch(arch
, member
, "symbols names listed "
4877 "in: %s not in: ", sfile
);
4880 fprintf(stderr
, "%s\n", save_symbols
[i
].name
);
4883 for(i
= 0; i
< nremove_symbols
; i
++){
4884 if(remove_symbols
[i
].sym
== NULL
){
4885 if(missing_syms
== 0){
4886 error_arch(arch
, member
, "symbols names listed "
4887 "in: %s not in: ", Rfile
);
4890 fprintf(stderr
, "%s\n", remove_symbols
[i
].name
);
4897 * Second pass: fix stabs for the globals symbols that got turned into
4898 * non-global symbols. This is a MAJOR guess. The specific changes
4899 * to do here were determined by compiling test cases with and without
4900 * the key word 'static' and looking at the difference between the STABS
4901 * the compiler generates and trying to match that here.
4903 global_strings
= strings
;
4904 if(object
->mh
!= NULL
)
4905 qsort(changed_globals
, nchanged_globals
, sizeof(struct nlist
*),
4906 (int (*)(const void *, const void *))cmp_qsort_global
);
4908 qsort(changed_globals64
, nchanged_globals
,sizeof(struct nlist_64
*),
4909 (int (*)(const void *, const void *))cmp_qsort_global_64
);
4910 dwarf_debug_map
= FALSE
;
4911 for(i
= 0; i
< nsyms
; i
++){
4913 if(object
->mh
!= NULL
){
4914 n_strx
= symbols
[i
].n_un
.n_strx
;
4915 n_type
= symbols
[i
].n_type
;
4916 n_desc
= symbols
[i
].n_desc
;
4919 n_strx
= symbols64
[i
].n_un
.n_strx
;
4920 n_type
= symbols64
[i
].n_type
;
4921 n_desc
= symbols64
[i
].n_desc
;
4924 dwarf_debug_map
= FALSE
;
4925 else if (n_type
== N_OSO
)
4926 dwarf_debug_map
= n_desc
!= 0;
4927 else if (dwarf_debug_map
&& n_type
== N_GSYM
){
4928 global_name
= strings
+ n_strx
;
4929 if(object
->mh
!= NULL
){
4930 global_symbol
= bsearch(global_name
, changed_globals
,
4931 nchanged_globals
,sizeof(struct nlist
*),
4932 (int (*)(const void *, const void *))
4933 cmp_bsearch_global
);
4934 if(global_symbol
!= NULL
){
4935 symbols
[i
].n_type
= N_STSYM
;
4936 symbols
[i
].n_sect
= (*global_symbol
)->n_sect
;
4937 symbols
[i
].n_value
= (*global_symbol
)->n_value
;
4941 global_symbol64
= bsearch(global_name
, changed_globals64
,
4943 sizeof(struct nlist_64
*),
4944 (int (*)(const void *, const void *))
4945 cmp_bsearch_global_64
);
4946 if(global_symbol64
!= NULL
){
4947 symbols64
[i
].n_type
= N_STSYM
;
4948 symbols64
[i
].n_sect
= (*global_symbol64
)->n_sect
;
4949 symbols64
[i
].n_value
= (*global_symbol64
)->n_value
;
4953 else if(! dwarf_debug_map
&&
4954 (n_type
== N_GSYM
|| n_type
== N_FUN
) &&
4955 (n_strx
!= 0 && strings
[n_strx
] != '\0')){
4956 global_name
= strings
+ n_strx
;
4957 if((global_name
[0] == '+' || global_name
[0] == '-') &&
4958 global_name
[1] == '['){
4960 while(j
+ n_strx
< strsize
&& global_name
[j
] != ']')
4962 if(j
+ n_strx
< strsize
&& global_name
[j
] == ']')
4967 while(j
+ n_strx
< strsize
&& global_name
[j
] != ':')
4969 if(j
+ n_strx
>= strsize
){
4970 error_arch(arch
, member
, "bad N_STAB symbol name for entry "
4971 "%u (does not contain ':' separating name from type) "
4975 save_char
= global_name
[j
];
4976 global_name
[j
] = '\0';
4978 global_symbol_found
= FALSE
;
4979 global_symbol_n_sect
= 0;
4980 if(object
->mh
!= NULL
){
4981 global_symbol
= bsearch(global_name
, changed_globals
,
4982 nchanged_globals
,sizeof(struct nlist
*),
4983 (int (*)(const void *, const void *))
4984 cmp_bsearch_global_stab
);
4985 global_symbol64
= NULL
;
4986 if(global_symbol
!= NULL
){
4987 global_symbol_found
= TRUE
;
4988 global_symbol_n_sect
= (*global_symbol
)->n_sect
;
4992 global_symbol64
= bsearch(global_name
, changed_globals64
,
4994 sizeof(struct nlist_64
*),
4995 (int (*)(const void *, const void *))
4996 cmp_bsearch_global_stab_64
);
4997 global_symbol
= NULL
;
4998 if(global_symbol64
!= NULL
){
4999 global_symbol_found
= TRUE
;
5000 global_symbol_n_sect
= (*global_symbol64
)->n_sect
;
5003 global_name
[j
] = save_char
;
5004 if(global_symbol_found
== TRUE
){
5005 if(n_type
== N_GSYM
){
5006 if(global_symbol_n_sect
== data_n_sect
){
5007 if(object
->mh
!= NULL
)
5008 symbols
[i
].n_type
= N_STSYM
;
5010 symbols64
[i
].n_type
= N_STSYM
;
5013 if(object
->mh
!= NULL
)
5014 symbols
[i
].n_type
= N_FUN
;
5016 symbols64
[i
].n_type
= N_FUN
;
5018 if(object
->mh
!= NULL
){
5019 symbols
[i
].n_sect
= (*global_symbol
)->n_sect
;
5020 symbols
[i
].n_value
= (*global_symbol
)->n_value
;
5021 symbols
[i
].n_desc
= (*global_symbol
)->n_desc
;
5024 symbols64
[i
].n_sect
= (*global_symbol64
)->n_sect
;
5025 symbols64
[i
].n_value
= (*global_symbol64
)->n_value
;
5026 symbols64
[i
].n_desc
= (*global_symbol64
)->n_desc
;
5028 if(j
+ 1 + n_strx
>= strsize
||
5029 global_name
[j
+1] != 'G'){
5030 error_arch(arch
, member
, "bad N_GSYM symbol name "
5031 "for entry %u (does not have type 'G' after "
5032 "':' in name) in: ", i
);
5035 global_name
[j
+1] = 'S';
5037 else{ /* n_type == N_FUN */
5038 if(j
+ 1 + n_strx
>= strsize
||
5039 global_name
[j
+1] == 'F'){
5040 global_name
[j
+1] = 'f';
5046 global_strings
= NULL
;
5049 * Now what needs to be done is to create the new symbol table moving
5050 * those global symbols being changed into non-globals into the areas
5051 * in the symbol table for local symbols. The symbol table and string
5052 * table must be in this order:
5056 * external defined symbols
5064 saves
= (int32_t *)allocate(nsyms
* sizeof(int32_t));
5065 bzero(saves
, nsyms
* sizeof(int32_t));
5067 if(object
->mh
!= NULL
){
5068 new_symbols
= (struct nlist
*)
5069 allocate(new_nsyms
* sizeof(struct nlist
));
5070 new_symbols64
= NULL
;
5074 new_symbols64
= (struct nlist_64
*)
5075 allocate(new_nsyms
* sizeof(struct nlist_64
));
5077 new_strsize
= rnd(new_strsize
, sizeof(int32_t));
5078 new_strings
= (char *)allocate(new_strsize
);
5079 new_strings
[new_strsize
- 3] = '\0';
5080 new_strings
[new_strsize
- 2] = '\0';
5081 new_strings
[new_strsize
- 1] = '\0';
5083 memset(new_strings
, '\0', sizeof(int32_t));
5084 p
= new_strings
+ sizeof(int32_t);
5085 q
= p
+ new_ext_strsize
;
5088 * If this is a dynamic library the movement of the symbols has to be
5089 * done with respect to the modules. As the local symbols, and external
5090 * defined symbols are grouped together for each module. Then a new
5091 * module table needs to be created with the new indexes into the symbol
5092 * table for each module.
5094 new_nmodtab
= nmodtab
;
5096 new_nextrefsyms
= nextrefsyms
;
5097 if(object
->mh_filetype
== MH_DYLIB
&& nmodtab
!= 0){
5098 if(object
->mh
!= NULL
){
5099 new_mods
= allocate(nmodtab
* sizeof(struct dylib_module
));
5104 new_mods64
= allocate(nmodtab
* sizeof(struct dylib_module_64
));
5109 * This first loop through the module table sets the index and
5110 * counts of the local symbols for each module.
5112 for(i
= 0; i
< nmodtab
; i
++){
5114 * First put the existing local symbols into the new symbol
5117 if(object
->mh
!= NULL
){
5118 new_mods
[i
].ilocalsym
= inew_syms
;
5119 new_mods
[i
].nlocalsym
= 0;
5120 ilocalsym
= mods
[i
].ilocalsym
;
5121 nlocalsym
= mods
[i
].nlocalsym
;
5124 new_mods64
[i
].ilocalsym
= inew_syms
;
5125 new_mods64
[i
].nlocalsym
= 0;
5126 ilocalsym
= mods64
[i
].ilocalsym
;
5127 nlocalsym
= mods64
[i
].nlocalsym
;
5129 for(j
= ilocalsym
; j
< ilocalsym
+ nlocalsym
; j
++){
5130 if(object
->mh
!= NULL
){
5131 n_strx
= symbols
[j
].n_un
.n_strx
;
5132 n_type
= symbols
[j
].n_type
;
5135 n_strx
= symbols64
[j
].n_un
.n_strx
;
5136 n_type
= symbols64
[j
].n_type
;
5138 if((n_type
& N_EXT
) == 0){
5139 if(object
->mh
!= NULL
)
5140 new_symbols
[inew_syms
] = symbols
[j
];
5142 new_symbols64
[inew_syms
] = symbols64
[j
];
5144 strcpy(q
, strings
+ n_strx
);
5145 if(object
->mh
!= NULL
)
5146 new_symbols
[inew_syms
].n_un
.n_strx
=
5149 new_symbols64
[inew_syms
].n_un
.n_strx
=
5154 saves
[j
] = inew_syms
;
5155 if(object
->mh
!= NULL
)
5156 new_mods
[i
].nlocalsym
++;
5158 new_mods64
[i
].nlocalsym
++;
5162 * Next put the global symbols that were changed into
5163 * non-global symbols into the new symbol table and moved their
5164 * counts to the local symbol counts.
5166 if(object
->mh
!= NULL
){
5167 iextdefsym
= mods
[i
].iextdefsym
;
5168 nextdefsym
= mods
[i
].nextdefsym
;
5171 iextdefsym
= mods64
[i
].iextdefsym
;
5172 nextdefsym
= mods64
[i
].nextdefsym
;
5174 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
5175 if(object
->mh
!= NULL
){
5176 n_strx
= symbols
[j
].n_un
.n_strx
;
5177 n_type
= symbols
[j
].n_type
;
5180 n_strx
= symbols64
[j
].n_un
.n_strx
;
5181 n_type
= symbols64
[j
].n_type
;
5183 if((n_type
& N_EXT
) != 0){
5184 if(nmedits
[j
] == TRUE
){
5186 * Change the new symbol to a private extern symbol
5187 * with the extern bit off.
5189 if(object
->mh
!= NULL
){
5190 new_symbols
[inew_syms
] = symbols
[j
];
5191 new_symbols
[inew_syms
].n_type
|= N_PEXT
;
5192 new_symbols
[inew_syms
].n_type
&= ~N_EXT
;
5195 new_symbols64
[inew_syms
] = symbols64
[j
];
5196 new_symbols64
[inew_syms
].n_type
|= N_PEXT
;
5197 new_symbols64
[inew_syms
].n_type
&= ~N_EXT
;
5200 strcpy(q
, strings
+ n_strx
);
5201 if(object
->mh
!= NULL
)
5202 new_symbols
[inew_syms
].n_un
.n_strx
=
5205 new_symbols64
[inew_syms
].n_un
.n_strx
=
5210 saves
[j
] = inew_syms
;
5211 if(object
->mh
!= NULL
)
5212 new_mods
[i
].nlocalsym
++;
5214 new_mods64
[i
].nlocalsym
++;
5220 * Next put the unchanged defined global symbols into the new
5223 for(i
= 0; i
< nmodtab
; i
++){
5224 if(object
->mh
!= NULL
){
5225 new_mods
[i
].iextdefsym
= inew_syms
;
5226 new_mods
[i
].nextdefsym
= 0;
5227 iextdefsym
= mods
[i
].iextdefsym
;
5228 nextdefsym
= mods
[i
].nextdefsym
;
5231 new_mods64
[i
].iextdefsym
= inew_syms
;
5232 new_mods64
[i
].nextdefsym
= 0;
5233 iextdefsym
= mods64
[i
].iextdefsym
;
5234 nextdefsym
= mods64
[i
].nextdefsym
;
5236 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
5237 if(object
->mh
!= NULL
){
5238 n_strx
= symbols
[j
].n_un
.n_strx
;
5239 n_type
= symbols
[j
].n_type
;
5242 n_strx
= symbols64
[j
].n_un
.n_strx
;
5243 n_type
= symbols64
[j
].n_type
;
5245 if((n_type
& N_EXT
) != 0){
5246 if(nmedits
[j
] == FALSE
){
5247 if(object
->mh
!= NULL
)
5248 new_symbols
[inew_syms
] = symbols
[j
];
5250 new_symbols64
[inew_syms
] = symbols64
[j
];
5252 strcpy(p
, strings
+ n_strx
);
5253 if(object
->mh
!= NULL
)
5254 new_symbols
[inew_syms
].n_un
.n_strx
=
5257 new_symbols64
[inew_syms
].n_un
.n_strx
=
5262 saves
[j
] = inew_syms
;
5263 if(object
->mh
!= NULL
)
5264 new_mods
[i
].nextdefsym
++;
5266 new_mods64
[i
].nextdefsym
++;
5272 * Last put the undefined symbols into the new symbol table.
5274 for(i
= 0; i
< nsyms
; i
++){
5275 if(object
->mh
!= NULL
){
5276 n_strx
= symbols
[i
].n_un
.n_strx
;
5277 n_type
= symbols
[i
].n_type
;
5280 n_strx
= symbols64
[i
].n_un
.n_strx
;
5281 n_type
= symbols64
[i
].n_type
;
5283 if((n_type
& N_EXT
) != 0 &&
5284 ((n_type
& N_TYPE
) == N_UNDF
||
5285 (n_type
& N_TYPE
) == N_PBUD
)){
5286 if(object
->mh
!= NULL
)
5287 new_symbols
[inew_syms
] = symbols
[i
];
5289 new_symbols64
[inew_syms
] = symbols64
[i
];
5291 strcpy(p
, strings
+ n_strx
);
5292 if(object
->mh
!= NULL
)
5293 new_symbols
[inew_syms
].n_un
.n_strx
=
5296 new_symbols64
[inew_syms
].n_un
.n_strx
=
5301 saves
[i
] = inew_syms
;
5306 * Place the module table's module names with the external strings
5307 * and set the names in the new module table. And then copy the
5308 * other unchanged fields.
5310 for(i
= 0; i
< nmodtab
; i
++){
5311 if(object
->mh
!= NULL
){
5312 strcpy(p
, strings
+ mods
[i
].module_name
);
5313 new_mods
[i
].module_name
= p
- new_strings
;
5316 new_mods
[i
].irefsym
= mods
[i
].irefsym
;
5317 new_mods
[i
].nrefsym
= mods
[i
].nrefsym
;
5318 new_mods
[i
].iextrel
= mods
[i
].iextrel
;
5319 new_mods
[i
].nextrel
= mods
[i
].nextrel
;
5320 new_mods
[i
].iinit_iterm
= mods
[i
].iinit_iterm
;
5321 new_mods
[i
].ninit_nterm
= mods
[i
].ninit_nterm
;
5322 new_mods
[i
].objc_module_info_addr
=
5323 mods
[i
].objc_module_info_addr
;
5324 new_mods
[i
].objc_module_info_size
=
5325 mods
[i
].objc_module_info_size
;
5328 strcpy(p
, strings
+ mods64
[i
].module_name
);
5329 new_mods64
[i
].module_name
= p
- new_strings
;
5332 new_mods64
[i
].irefsym
= mods64
[i
].irefsym
;
5333 new_mods64
[i
].nrefsym
= mods64
[i
].nrefsym
;
5334 new_mods64
[i
].iextrel
= mods64
[i
].iextrel
;
5335 new_mods64
[i
].nextrel
= mods64
[i
].nextrel
;
5336 new_mods64
[i
].iinit_iterm
= mods64
[i
].iinit_iterm
;
5337 new_mods64
[i
].ninit_nterm
= mods64
[i
].ninit_nterm
;
5338 new_mods64
[i
].objc_module_info_addr
=
5339 mods64
[i
].objc_module_info_addr
;
5340 new_mods64
[i
].objc_module_info_size
=
5341 mods64
[i
].objc_module_info_size
;
5346 * Update the reference table with the new symbol indexes for all
5347 * entries and change type of reference (the flags field) for those
5348 * symbols that got changed from globals to non-globals.
5350 new_nextrefsyms
= nextrefsyms
;
5351 new_refs
= allocate(new_nextrefsyms
*
5352 sizeof(struct dylib_reference
));
5354 for(i
= 0; i
< nextrefsyms
; i
++){
5355 if(nmedits
[refs
[i
].isym
] == TRUE
){
5356 if(refs
[i
].flags
== REFERENCE_FLAG_DEFINED
)
5358 REFERENCE_FLAG_PRIVATE_DEFINED
;
5359 else if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
)
5361 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
;
5362 else if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
)
5364 REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
;
5366 new_refs
[i
].flags
= refs
[i
].flags
;
5369 new_refs
[i
].flags
= refs
[i
].flags
;
5371 new_refs
[i
].isym
= saves
[refs
[i
].isym
] - 1;
5375 * Create a new dylib table of contents without the global symbols
5376 * that got turned into non-globals.
5378 new_ntoc
= ntoc
- nchanged_globals
;
5379 new_tocs
= allocate(new_ntoc
*
5380 sizeof(struct dylib_table_of_contents
));
5382 for(i
= 0; i
< ntoc
; i
++){
5383 if(tocs
[i
].symbol_index
>= nsyms
){
5384 error_arch(arch
, member
, "bad symbol index for table of "
5385 "contents table entry %d in: ", i
);
5388 if(nmedits
[tocs
[i
].symbol_index
] == FALSE
){
5389 new_tocs
[k
].symbol_index
= saves
[tocs
[i
].symbol_index
] - 1;
5390 new_tocs
[k
].module_index
= tocs
[i
].module_index
;
5396 * If is not a dynamic library so all global symbols changed into
5397 * statics can be moved to the end of the local symbols. If the pflag
5398 * is set then the changed symbols remain global and just get the
5399 * private extern bit set.
5403 * First put the existing local symbols into the new symbol table.
5406 for(i
= 0; i
< nsyms
; i
++){
5407 if(object
->mh
!= NULL
){
5408 n_strx
= symbols
[i
].n_un
.n_strx
;
5409 n_type
= symbols
[i
].n_type
;
5412 n_strx
= symbols64
[i
].n_un
.n_strx
;
5413 n_type
= symbols64
[i
].n_type
;
5415 if((n_type
& N_EXT
) == 0){
5416 if(object
->mh
!= NULL
)
5417 new_symbols
[inew_syms
] = symbols
[i
];
5419 new_symbols64
[inew_syms
] = symbols64
[i
];
5421 strcpy(q
, strings
+ n_strx
);
5422 if(object
->mh
!= NULL
)
5423 new_symbols
[inew_syms
].n_un
.n_strx
=
5426 new_symbols64
[inew_syms
].n_un
.n_strx
=
5431 saves
[i
] = inew_syms
;
5435 * Next put the global symbols that were changed into statics
5436 * symbols into the new symbol table.
5439 for(i
= 0; i
< nsyms
; i
++){
5440 if(object
->mh
!= NULL
){
5441 n_strx
= symbols
[i
].n_un
.n_strx
;
5442 n_type
= symbols
[i
].n_type
;
5445 n_strx
= symbols64
[i
].n_un
.n_strx
;
5446 n_type
= symbols64
[i
].n_type
;
5448 if((n_type
& N_EXT
) != 0){
5449 if(nmedits
[i
] == TRUE
){
5451 * Change the new symbol to not be an extern symbol
5452 * by turning off the extern bit.
5454 if(object
->mh
!= NULL
){
5455 new_symbols
[inew_syms
] = symbols
[i
];
5456 new_symbols
[inew_syms
].n_type
&= ~N_EXT
;
5457 new_symbols
[inew_syms
].n_desc
&= ~N_WEAK_DEF
;
5460 new_symbols64
[inew_syms
] = symbols64
[i
];
5461 new_symbols64
[inew_syms
].n_type
&= ~N_EXT
;
5462 new_symbols64
[inew_syms
].n_desc
&= ~N_WEAK_DEF
;
5465 strcpy(q
, strings
+ n_strx
);
5466 if(object
->mh
!= NULL
)
5467 new_symbols
[inew_syms
].n_un
.n_strx
=
5470 new_symbols64
[inew_syms
].n_un
.n_strx
=
5475 saves
[i
] = inew_syms
;
5481 * Last put the unchanged global symbols into the new symbol table
5482 * and symbols changed into private externs.
5484 for(i
= 0; i
< nsyms
; i
++){
5485 if(object
->mh
!= NULL
){
5486 n_strx
= symbols
[i
].n_un
.n_strx
;
5487 n_type
= symbols
[i
].n_type
;
5490 n_strx
= symbols64
[i
].n_un
.n_strx
;
5491 n_type
= symbols64
[i
].n_type
;
5493 if((n_type
& N_EXT
) != 0){
5494 if(nmedits
[i
] == FALSE
|| pflag
== TRUE
){
5495 if(object
->mh
!= NULL
)
5496 new_symbols
[inew_syms
] = symbols
[i
];
5498 new_symbols64
[inew_syms
] = symbols64
[i
];
5499 if(nmedits
[i
] == TRUE
&& pflag
== TRUE
){
5501 * Change the new symbol to be a private extern
5502 * symbol by turning on the private extern bit.
5504 if(object
->mh
!= NULL
)
5505 new_symbols
[inew_syms
].n_type
|= N_PEXT
;
5507 new_symbols64
[inew_syms
].n_type
|= N_PEXT
;
5510 strcpy(p
, strings
+ n_strx
);
5511 if(object
->mh
!= NULL
)
5512 new_symbols
[inew_syms
].n_un
.n_strx
=
5515 new_symbols64
[inew_syms
].n_un
.n_strx
=
5520 saves
[i
] = inew_syms
;
5526 if(sections
!= NULL
)
5528 if(sections64
!= NULL
)
5538 * Function for qsort for comparing global symbol names.
5543 const struct nlist
**sym1
,
5544 const struct nlist
**sym2
)
5546 return(strcmp(global_strings
+ (*sym1
)->n_un
.n_strx
,
5547 global_strings
+ (*sym2
)->n_un
.n_strx
));
5552 cmp_qsort_global_64(
5553 const struct nlist_64
**sym1
,
5554 const struct nlist_64
**sym2
)
5556 return(strcmp(global_strings
+ (*sym1
)->n_un
.n_strx
,
5557 global_strings
+ (*sym2
)->n_un
.n_strx
));
5561 * Function for bsearch for finding a global symbol that matches a stab name.
5565 cmp_bsearch_global_stab(
5567 const struct nlist
**sym
)
5570 * The +1 is for the '_' on the global symbol that is not on the
5571 * stab string that is trying to be matched.
5573 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
+ 1));
5578 cmp_bsearch_global_stab_64(
5580 const struct nlist_64
**sym
)
5583 * The +1 is for the '_' on the global symbol that is not on the
5584 * stab string that is trying to be matched.
5586 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
+ 1));
5590 * Function for bsearch for finding a global symbol that matches a stab name
5597 const struct nlist
**sym
)
5599 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
));
5604 cmp_bsearch_global_64(
5606 const struct nlist_64
**sym
)
5608 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
));
5610 #endif /* defined(NMEDIT) */