2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * The strip(1) and nmedit(l) program. This understands only Mach-O format
25 * files (with the restriction the symbol table is at the end of the file) and
26 * fat files with Mach-O files in them.
34 #include <sys/types.h>
36 #include <mach-o/loader.h>
37 #include <mach-o/reloc.h>
38 #include <mach-o/nlist.h>
39 #include <mach-o/stab.h>
40 #include "stuff/breakout.h"
41 #include "stuff/allocate.h"
42 #include "stuff/errors.h"
43 #include "stuff/round.h"
44 #include "stuff/reloc.h"
45 #include "stuff/reloc.h"
46 #include "stuff/symbol_list.h"
47 #include "stuff/unix_standard_mode.h"
48 #include "stuff/execute.h"
50 #include <mach-o/prune_trie.h>
51 #endif /* TRIE_SUPPORT */
53 /* These are set from the command line arguments */
55 char *progname
= NULL
; /* name of the program for error messages (argv[0]) */
56 static char *output_file
;/* name of the output file */
57 static char *sfile
; /* filename of global symbol names to keep */
58 static char *Rfile
; /* filename of global symbol names to remove */
59 static uint32_t Aflag
; /* save only absolute symbols with non-zero value and
60 .objc_class_name_* symbols */
61 static uint32_t 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;
142 * The index into the new symbols where the defined external start.
144 static uint32_t inew_nextdefsym
= 0;
147 * These hold the new table of contents, reference table and module table for
150 static struct dylib_table_of_contents
*new_tocs
= NULL
;
151 static uint32_t new_ntoc
= 0;
152 static struct dylib_reference
*new_refs
= NULL
;
153 static uint32_t new_nextrefsyms
= 0;
155 static struct dylib_module
*new_mods
= NULL
;
156 static struct dylib_module_64
*new_mods64
= NULL
;
157 static uint32_t new_nmodtab
= 0;
162 * The list of file names to save debugging symbols from.
164 static char **debug_filenames
= NULL
;
165 static uint32_t ndebug_filenames
= 0;
172 struct nlist_64 symbol64
;
174 static char *qsort_strings
= NULL
;
175 #endif /* !defined(NMEDIT) */
178 /* Internal routines */
182 static void strip_file(
184 struct arch_flag
*arch_flags
,
185 uint32_t narch_flags
,
186 enum bool all_archs
);
188 static void strip_arch(
191 struct arch_flag
*arch_flags
,
192 uint32_t narch_flags
,
193 enum bool all_archs
);
195 static void strip_object(
197 struct member
*member
,
198 struct object
*object
);
200 static uint32_t get_starting_syminfo_offset(
201 struct object
*object
);
203 static void check_object_relocs(
205 struct member
*member
,
206 struct object
*object
,
211 struct relocation_info
*relocs
,
213 struct nlist
*symbols
,
214 struct nlist_64
*symbols64
,
217 int32_t *missing_reloc_symbols
,
218 enum byte_sex host_byte_sex
);
220 static void check_indirect_symtab(
222 struct member
*member
,
223 struct object
*object
,
226 uint32_t section_type
,
228 struct nlist
*symbols
,
229 struct nlist_64
*symbols64
,
232 int32_t *missing_reloc_symbols
,
233 enum byte_sex host_byte_sex
);
236 static enum bool strip_symtab(
238 struct member
*member
,
239 struct object
*object
,
240 struct dylib_table_of_contents
*tocs
,
242 struct dylib_module
*mods
,
243 struct dylib_module_64
*mods64
,
245 struct dylib_reference
*refs
,
246 uint32_t nextrefsyms
);
251 #endif /* TRIE_SUPPORT */
253 static void make_ld_r_object(
255 struct member
*member
,
256 struct object
*object
);
258 static void strip_LC_UUID_commands(
260 struct member
*member
,
261 struct object
*object
);
264 static void strip_LC_CODE_SIGNATURE_commands(
266 struct member
*member
,
267 struct object
*object
);
268 #endif /* !(NMEDIT) */
270 static enum bool private_extern_reference_by_module(
271 uint32_t symbol_index
,
272 struct dylib_reference
*refs
,
273 uint32_t nextrefsyms
);
275 static enum bool symbol_pointer_used(
276 uint32_t symbol_index
,
277 uint32_t *indirectsyms
,
278 uint32_t nindirectsyms
);
280 static int cmp_qsort_undef_map(
281 const struct undef_map
*sym1
,
282 const struct undef_map
*sym2
);
284 static int cmp_qsort_undef_map_64(
285 const struct undef_map64
*sym1
,
286 const struct undef_map64
*sym2
);
287 #endif /* !defined(NMEDIT) */
290 static enum bool edit_symtab(
292 struct member
*member
,
293 struct object
*object
,
294 struct nlist
*symbols
,
295 struct nlist_64
*symbols64
,
299 struct dylib_table_of_contents
*tocs
,
301 struct dylib_module
*mods
,
302 struct dylib_module_64
*mods64
,
304 struct dylib_reference
*refs
,
305 uint32_t nextrefsyms
);
309 static void setup_debug_filenames(
312 static int cmp_qsort_filename(
316 static int cmp_bsearch_filename(
323 * This variable and routines are used for nmedit(1) only.
325 static char *global_strings
= NULL
;
327 static int cmp_qsort_global(
328 const struct nlist
**sym1
,
329 const struct nlist
**sym2
);
331 static int cmp_qsort_global_64(
332 const struct nlist_64
**sym1
,
333 const struct nlist_64
**sym2
);
335 static int cmp_bsearch_global_stab(
337 const struct nlist
**sym
);
339 static int cmp_bsearch_global_stab_64(
341 const struct nlist_64
**sym
);
343 static int cmp_bsearch_global(
345 const struct nlist
**sym
);
347 static int cmp_bsearch_global_64(
349 const struct nlist_64
**sym
);
359 uint32_t j
, args_left
, files_specified
;
360 struct arch_flag
*arch_flags
;
361 uint32_t narch_flags
;
363 struct symbol_list
*sp
;
373 for (i
= 1; i
< argc
; i
++){
374 if(argv
[i
][0] == '-'){
375 if(argv
[i
][1] == '\0'){
379 if(strcmp(argv
[i
], "-o") == 0){
381 fatal("-o requires an argument");
382 if(output_file
!= NULL
)
383 fatal("only one -o option allowed");
384 output_file
= argv
[i
+ 1];
387 else if(strcmp(argv
[i
], "-s") == 0){
389 fatal("-s requires an argument");
391 fatal("only one -s option allowed");
395 else if(strcmp(argv
[i
], "-R") == 0){
397 fatal("-R requires an argument");
399 fatal("only one -R option allowed");
404 else if(strcmp(argv
[i
], "-d") == 0){
406 fatal("-d requires an argument");
408 fatal("only one -d option allowed");
412 else if(strcmp(argv
[i
], "-no_uuid") == 0){
415 else if(strcmp(argv
[i
], "-no_code_signature") == 0){
416 no_code_signature
= 1;
418 #endif /* !defined(NMEDIT) */
419 else if(strcmp(argv
[i
], "-arch") == 0){
421 error("missing argument(s) to %s option", argv
[i
]);
424 if(strcmp("all", argv
[i
+1]) == 0){
428 arch_flags
= reallocate(arch_flags
,
429 (narch_flags
+ 1) * sizeof(struct arch_flag
));
430 if(get_arch_from_flag(argv
[i
+1],
431 arch_flags
+ narch_flags
) == 0){
432 error("unknown architecture specification flag: "
433 "%s %s", argv
[i
], argv
[i
+1]);
437 for(j
= 0; j
< narch_flags
; j
++){
438 if(arch_flags
[j
].cputype
==
439 arch_flags
[narch_flags
].cputype
&&
440 (arch_flags
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
441 (arch_flags
[narch_flags
].cpusubtype
&
442 ~CPU_SUBTYPE_MASK
) &&
443 strcmp(arch_flags
[j
].name
,
444 arch_flags
[narch_flags
].name
) == 0)
453 for(j
= 1; argv
[i
][j
] != '\0'; j
++){
459 #else /* !defined(NMEDIT) */
491 #endif /* !defined(NMEDIT) */
496 #endif /* !defined(NMEDIT) */
515 error("unrecognized option: %s", argv
[i
]);
525 files_specified
+= argc
- (i
+ 1);
527 if(files_specified
> 1 && output_file
!= NULL
){
528 error("-o <filename> can only be used when one file is specified");
533 setup_symbol_list(sfile
, &save_symbols
, &nsave_symbols
);
537 if(Rfile
== NULL
&& pflag
== 0){
538 error("-s <filename>, -R <filename> or -p argument required");
545 setup_symbol_list(Rfile
, &remove_symbols
, &nremove_symbols
);
547 for(j
= 0; j
< nremove_symbols
; j
++){
548 sp
= bsearch(remove_symbols
[j
].name
,
549 save_symbols
, nsave_symbols
,
550 sizeof(struct symbol_list
),
551 (int (*)(const void *, const void *))
552 symbol_list_bsearch
);
554 error("symbol name: %s is listed in both -s %s and -R "
555 "%s files (can't be both saved and removed)",
556 remove_symbols
[j
].name
, sfile
, Rfile
);
564 /* the default when no -arch flags is present is to strip all archs */
570 setup_debug_filenames(dfile
);
572 #endif /* !defined(NMEDIT) */
576 for (i
= 1; i
< argc
; i
++) {
577 if(args_left
&& argv
[i
][0] == '-'){
578 if(argv
[i
][1] == '\0')
580 else if(strcmp(argv
[i
], "-o") == 0 ||
581 strcmp(argv
[i
], "-s") == 0 ||
582 strcmp(argv
[i
], "-R") == 0 ||
584 strcmp(argv
[i
], "-d") == 0 ||
585 #endif /* !defined(NMEDIT) */
586 strcmp(argv
[i
], "-arch") == 0)
590 char resolved_path
[PATH_MAX
+ 1];
592 if(realpath(argv
[i
], resolved_path
) == NULL
)
593 strip_file(argv
[i
], arch_flags
, narch_flags
, all_archs
);
595 strip_file(resolved_path
, arch_flags
,narch_flags
,all_archs
);
599 if(files_specified
== 0)
600 fatal("no files specified");
603 return(EXIT_FAILURE
);
605 return(EXIT_SUCCESS
);
614 fprintf(stderr
, "Usage: %s [-AanuStXx] [-no_uuid] [-no_code_signature] "
615 "[-] [-d filename] [-s filename] [-R filename] [-o output] "
616 "file [...]\n", progname
);
617 #else /* defined(NMEDIT) */
618 fprintf(stderr
, "Usage: %s -s filename [-R filename] [-p] [-A] [-] "
619 "[-o output] file [...] \n",
629 struct arch_flag
*arch_flags
,
630 uint32_t narch_flags
,
636 struct stat stat_buf
;
637 uint32_t previous_errors
;
638 enum bool unix_standard_mode
;
647 previous_errors
= errors
;
650 /* breakout the file for processing */
651 ofile
= breakout(input_file
, &archs
, &narchs
, FALSE
);
655 /* checkout the file for symbol table replacement processing */
656 checkout(archs
, narchs
);
658 /* process the symbols in the input file */
659 strip_arch(archs
, narchs
, arch_flags
, narch_flags
, all_archs
);
661 free_archs(archs
, narchs
);
666 /* create the output file */
667 if(stat(input_file
, &stat_buf
) == -1)
668 system_error("can't stat input file: %s", input_file
);
669 if(output_file
!= NULL
){
670 writeout(archs
, narchs
, output_file
, stat_buf
.st_mode
& 0777,
671 TRUE
, FALSE
, FALSE
, NULL
);
674 unix_standard_mode
= get_unix_standard_mode();
678 output_file
= makestr(input_file
, ".nmedit", NULL
);
679 #else /* !defined(NMEDIT) */
681 * In UNIX standard conformance mode we are not allowed to replace
682 * a file that is not writeable.
684 if(unix_standard_mode
== TRUE
&&
685 access(input_file
, W_OK
) == -1){
686 system_error("file: %s is not writable", input_file
);
687 goto strip_file_return
;
689 output_file
= makestr(input_file
, ".strip", NULL
);
692 * The UNIX standard conformance test suite expects files of
693 * MAXPATHLEN to work.
695 if(strlen(output_file
) >= MAXPATHLEN
){
697 * If there is a directory path in the name try to change
698 * the current working directory to that path.
700 if((p
= rindex(output_file
, '/')) != NULL
){
701 if((cwd_fd
= open(".", O_RDONLY
, 0)) == -1){
702 system_error("can't open current working directory");
703 goto strip_file_return
;
706 if(chdir(output_file
) == -1){
707 system_error("can't change current working directory "
708 "to: %s", output_file
);
709 goto strip_file_return
;
711 p
= rindex(input_file
, '/');
712 rename_file
= makestr(p
+ 1, NULL
);
715 * Create what might be a short enough name.
718 output_file
= makestr("strip.XXXXXX", NULL
);
719 output_file
= mktemp(output_file
);
722 writeout(archs
, narchs
, output_file
, stat_buf
.st_mode
& 0777,
723 TRUE
, FALSE
, FALSE
, NULL
);
724 if(rename_file
!= NULL
){
725 if(rename(output_file
, rename_file
) == -1)
726 system_error("can't move temporary file: %s to file: %s",
727 output_file
, rename_file
);
731 if(rename(output_file
, input_file
) == -1)
732 system_error("can't move temporary file: %s to input "
733 "file: %s", output_file
, input_file
);
739 * If we changed the current working directory change back to
740 * the previous working directory.
743 if(fchdir(cwd_fd
) == -1)
744 system_error("can't change back to previous working "
746 if(close(cwd_fd
) == -1)
747 system_error("can't close previous working directory");
753 #endif /* !defined(NMEDIT) */
754 /* clean-up data structures */
755 free_archs(archs
, narchs
);
758 errors
+= previous_errors
;
766 struct arch_flag
*arch_flags
,
767 uint32_t narch_flags
,
770 uint32_t i
, j
, k
, offset
, size
, missing_syms
;
772 cpu_subtype_t cpusubtype
;
773 struct arch_flag host_arch_flag
;
774 enum bool arch_process
, any_processing
, *arch_flag_processed
, family
;
775 const struct arch_flag
*family_arch_flag
;
778 * Using the specified arch_flags process specified objects for those
781 any_processing
= FALSE
;
782 arch_flag_processed
= NULL
;
784 arch_flag_processed
= allocate(narch_flags
* sizeof(enum bool));
785 memset(arch_flag_processed
, '\0', narch_flags
* sizeof(enum bool));
786 for(i
= 0; i
< narchs
; i
++){
788 * Determine the architecture (cputype and cpusubtype) of arch[i]
792 if(archs
[i
].type
== OFILE_ARCHIVE
){
793 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
794 if(archs
[i
].members
[j
].type
== OFILE_Mach_O
){
795 cputype
= archs
[i
].members
[j
].object
->mh_cputype
;
796 cpusubtype
= archs
[i
].members
[j
].object
->mh_cpusubtype
;
801 else if(archs
[i
].type
== OFILE_Mach_O
){
802 cputype
= archs
[i
].object
->mh_cputype
;
803 cpusubtype
= archs
[i
].object
->mh_cpusubtype
;
805 else if(archs
[i
].fat_arch
!= NULL
){
806 cputype
= archs
[i
].fat_arch
->cputype
;
807 cpusubtype
= archs
[i
].fat_arch
->cpusubtype
;
809 arch_process
= FALSE
;
810 if(all_archs
== TRUE
){
813 else if(narch_flags
!= 0){
815 if(narch_flags
== 1){
817 get_arch_family_from_cputype(arch_flags
[0].cputype
);
818 if(family_arch_flag
!= NULL
)
820 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
821 (arch_flags
[0].cpusubtype
& ~CPU_SUBTYPE_MASK
));
823 for(j
= 0; j
< narch_flags
; j
++){
824 if(arch_flags
[j
].cputype
== cputype
&&
825 ((arch_flags
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
826 (cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
829 arch_flag_processed
[j
] = TRUE
;
835 (void)get_arch_from_host(&host_arch_flag
, NULL
);
836 if(host_arch_flag
.cputype
== cputype
&&
837 (host_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
838 (cpusubtype
& ~CPU_SUBTYPE_MASK
))
841 if(narchs
!= 1 && arch_process
== FALSE
)
843 any_processing
= TRUE
;
846 * Now this arch[i] has been selected to be processed so process it
847 * according to its type.
849 if(archs
[i
].type
== OFILE_ARCHIVE
){
850 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
851 if(archs
[i
].members
[j
].type
== OFILE_Mach_O
){
852 strip_object(archs
+ i
, archs
[i
].members
+ j
,
853 archs
[i
].members
[j
].object
);
858 for(k
= 0; k
< nsave_symbols
; k
++){
859 if(save_symbols
[k
].seen
== FALSE
){
860 if(missing_syms
== 0){
861 error_arch(archs
+ i
, NULL
, "symbols names "
862 "listed in: %s not in: ", sfile
);
865 fprintf(stderr
, "%s\n", save_symbols
[k
].name
);
869 for(k
= 0; k
< nsave_symbols
; k
++){
870 save_symbols
[k
].seen
= FALSE
;
874 for(k
= 0; k
< nremove_symbols
; k
++){
875 if(remove_symbols
[k
].seen
== FALSE
){
876 if(missing_syms
== 0){
877 error_arch(archs
+ i
, NULL
, "symbols names "
878 "listed in: %s not defined in: ",
882 fprintf(stderr
, "%s\n", remove_symbols
[k
].name
);
886 for(k
= 0; k
< nremove_symbols
; k
++){
887 remove_symbols
[k
].seen
= FALSE
;
890 * Reset the library offsets and size.
893 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
894 archs
[i
].members
[j
].offset
= offset
;
896 if(archs
[i
].members
[j
].member_long_name
== TRUE
){
897 size
= round(archs
[i
].members
[j
].member_name_size
, 8) +
898 (round(sizeof(struct ar_hdr
), 8) -
899 sizeof(struct ar_hdr
));
900 archs
[i
].toc_long_name
= TRUE
;
902 if(archs
[i
].members
[j
].object
!= NULL
){
904 round(archs
[i
].members
[j
].object
->object_size
-
905 archs
[i
].members
[j
].object
->input_sym_info_size
+
906 archs
[i
].members
[j
].object
->output_sym_info_size
,
908 sprintf(archs
[i
].members
[j
].ar_hdr
->ar_size
, "%-*ld",
909 (int)sizeof(archs
[i
].members
[j
].ar_hdr
->ar_size
),
912 * This has to be done by hand because sprintf puts a
913 * null at the end of the buffer.
915 memcpy(archs
[i
].members
[j
].ar_hdr
->ar_fmag
, ARFMAG
,
916 (int)sizeof(archs
[i
].members
[j
].ar_hdr
->ar_fmag
));
919 size
+= archs
[i
].members
[j
].unknown_size
;
921 offset
+= sizeof(struct ar_hdr
) + size
;
923 archs
[i
].library_size
= offset
;
925 else if(archs
[i
].type
== OFILE_Mach_O
){
926 strip_object(archs
+ i
, NULL
, archs
[i
].object
);
929 warning_arch(archs
+ i
, NULL
, "can't process non-object and "
930 "non-archive file: ");
934 if(all_archs
== FALSE
&& narch_flags
!= 0){
935 for(i
= 0; i
< narch_flags
; i
++){
936 if(arch_flag_processed
[i
] == FALSE
)
937 error("file: %s does not contain architecture: %s",
938 archs
[0].file_name
, arch_flags
[i
].name
);
940 free(arch_flag_processed
);
942 if(any_processing
== FALSE
)
943 fatal("no processing done on input file: %s (specify a -arch flag)",
951 struct member
*member
,
952 struct object
*object
)
954 enum byte_sex host_byte_sex
;
956 struct dylib_table_of_contents
*tocs
;
958 struct dylib_module
*mods
;
959 struct dylib_module_64
*mods64
;
961 struct dylib_reference
*refs
;
962 uint32_t nextrefsyms
;
964 struct load_command
*lc
;
965 struct segment_command
*sg
;
966 struct segment_command_64
*sg64
;
968 struct section_64
*s64
;
969 struct relocation_info
*relocs
;
970 struct scattered_relocation_info
*sreloc
;
971 int32_t missing_reloc_symbols
;
972 uint32_t stride
, section_type
, nitems
;
974 uint32_t dyld_info_start
;
975 uint32_t dyld_info_end
;
982 host_byte_sex
= get_host_byte_sex();
984 /* Don't do anything to stub dylibs which have no load commands. */
985 if(object
->mh_filetype
== MH_DYLIB_STUB
){
986 if((object
->mh
!= NULL
&& object
->mh
->ncmds
== 0) ||
987 (object
->mh64
!= NULL
&& object
->mh64
->ncmds
== 0)){
991 if(object
->mh_filetype
== MH_DSYM
)
992 fatal_arch(arch
, member
, "can't process dSYM companion file: ");
993 if(object
->st
== NULL
|| object
->st
->nsyms
== 0){
994 warning_arch(arch
, member
, "input object file stripped: ");
998 nsyms
= object
->st
->nsyms
;
999 if(object
->mh
!= NULL
){
1000 symbols
= (struct nlist
*)
1001 (object
->object_addr
+ object
->st
->symoff
);
1002 if(object
->object_byte_sex
!= host_byte_sex
)
1003 swap_nlist(symbols
, nsyms
, host_byte_sex
);
1008 symbols64
= (struct nlist_64
*)
1009 (object
->object_addr
+ object
->st
->symoff
);
1010 if(object
->object_byte_sex
!= host_byte_sex
)
1011 swap_nlist_64(symbols64
, nsyms
, host_byte_sex
);
1013 strings
= object
->object_addr
+ object
->st
->stroff
;
1014 strsize
= object
->st
->strsize
;
1017 if(object
->mh
!= NULL
)
1018 flags
= object
->mh
->flags
;
1020 flags
= object
->mh64
->flags
;
1021 if(object
->mh_filetype
== MH_DYLIB
&&
1022 (flags
& MH_PREBOUND
) != MH_PREBOUND
){
1023 arch
->dont_update_LC_ID_DYLIB_timestamp
= TRUE
;
1025 if(object
->mh_filetype
!= MH_DYLIB
&& cflag
)
1026 fatal_arch(arch
, member
, "-c can't be used on non-dynamic "
1028 #endif /* !(NMEDIT) */
1029 if(object
->mh_filetype
== MH_DYLIB_STUB
)
1030 fatal_arch(arch
, member
, "dynamic stub library can't be changed "
1033 if(object
->mh_filetype
== MH_DYLIB
){
1034 tocs
= (struct dylib_table_of_contents
*)
1035 (object
->object_addr
+ object
->dyst
->tocoff
);
1036 ntoc
= object
->dyst
->ntoc
;
1037 nmodtab
= object
->dyst
->nmodtab
;
1038 if(object
->mh
!= NULL
){
1039 mods
= (struct dylib_module
*)
1040 (object
->object_addr
+ object
->dyst
->modtaboff
);
1041 if(object
->object_byte_sex
!= host_byte_sex
)
1042 swap_dylib_module(mods
, nmodtab
, host_byte_sex
);
1047 mods64
= (struct dylib_module_64
*)
1048 (object
->object_addr
+ object
->dyst
->modtaboff
);
1049 if(object
->object_byte_sex
!= host_byte_sex
)
1050 swap_dylib_module_64(mods64
, nmodtab
, host_byte_sex
);
1052 refs
= (struct dylib_reference
*)
1053 (object
->object_addr
+ object
->dyst
->extrefsymoff
);
1054 nextrefsyms
= object
->dyst
->nextrefsyms
;
1055 if(object
->object_byte_sex
!= host_byte_sex
){
1056 swap_dylib_table_of_contents(tocs
, ntoc
, host_byte_sex
);
1057 swap_dylib_reference(refs
, nextrefsyms
, host_byte_sex
);
1061 * In the -c flag is specified then strip the section contents of
1062 * this dynamic library and change it into a stub library. When
1063 * creating a stub library the timestamp is not changed.
1066 arch
->dont_update_LC_ID_DYLIB_timestamp
= TRUE
;
1068 lc
= object
->load_commands
;
1069 if(object
->mh
!= NULL
){
1070 ncmds
= object
->mh
->ncmds
;
1071 object
->mh_filetype
= MH_DYLIB_STUB
;
1072 object
->mh
->filetype
= MH_DYLIB_STUB
;
1075 ncmds
= object
->mh64
->ncmds
;
1076 object
->mh_filetype
= MH_DYLIB_STUB
;
1077 object
->mh64
->filetype
= MH_DYLIB_STUB
;
1079 for(i
= 0; i
< ncmds
; i
++){
1080 if(lc
->cmd
== LC_SEGMENT
){
1081 sg
= (struct segment_command
*)lc
;
1082 if(strcmp(sg
->segname
, SEG_LINKEDIT
) != 0){
1084 * Zero out the section offset, reloff, and size
1085 * fields as the section contents are being removed.
1087 s
= (struct section
*)
1088 ((char *)sg
+ sizeof(struct segment_command
));
1089 for(j
= 0; j
< sg
->nsects
; j
++){
1091 * For section types with indirect tables we
1092 * do not zero out the section size in a stub
1093 * library. As the section size is needed to
1094 * know now many indirect table entries the
1095 * section has. This is a bit odd but programs
1096 * dealing with MH_DYLIB_STUB filetypes special
1099 section_type
= s
[j
].flags
& SECTION_TYPE
;
1100 if(section_type
!= S_SYMBOL_STUBS
&&
1101 section_type
!= S_LAZY_SYMBOL_POINTERS
&&
1102 section_type
!= S_LAZY_DYLIB_SYMBOL_POINTERS
&&
1103 section_type
!= S_NON_LAZY_SYMBOL_POINTERS
){
1110 /* zero out file offset and size in the segment */
1115 else if(lc
->cmd
== LC_SEGMENT_64
){
1116 sg64
= (struct segment_command_64
*)lc
;
1117 if(strcmp(sg64
->segname
, SEG_LINKEDIT
) != 0){
1119 * Zero out the section offset, reloff, and size
1120 * fields as the section contents are being removed.
1122 s64
= (struct section_64
*)
1124 sizeof(struct segment_command_64
));
1125 for(j
= 0; j
< sg64
->nsects
; j
++){
1127 * For section types with indirect tables we
1128 * do not zero out the section size in a stub
1129 * library. As the section size is needed to
1130 * know now many indirect table entries the
1131 * section has. This is a bit odd but programs
1132 * dealing with MH_DYLIB_STUB filetypes special
1135 section_type
= s64
[j
].flags
& SECTION_TYPE
;
1136 if(section_type
!= S_SYMBOL_STUBS
&&
1137 section_type
!= S_LAZY_SYMBOL_POINTERS
&&
1138 section_type
!= S_LAZY_DYLIB_SYMBOL_POINTERS
&&
1139 section_type
!= S_NON_LAZY_SYMBOL_POINTERS
){
1146 /* zero out file offset and size in the segment */
1151 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1154 * To get the right amount of the file copied out by writeout()
1155 * for the case when we are stripping out the section contents
1156 * we reduce the object size by the size of the section contents
1157 * including the padding after the load commands. Then this
1158 * size minus the size of the input symbolic information is
1161 if(object
->mh
!= NULL
){
1162 object
->object_size
-= (object
->seg_linkedit
->fileoff
-
1163 (sizeof(struct mach_header
) +
1164 object
->mh
->sizeofcmds
));
1166 * Set the file offset to the link edit information to be
1167 * right after the load commands.
1169 object
->seg_linkedit
->fileoff
=
1170 sizeof(struct mach_header
) +
1171 object
->mh
->sizeofcmds
;
1174 object
->object_size
-= (object
->seg_linkedit64
->fileoff
-
1175 (sizeof(struct mach_header_64
) +
1176 object
->mh64
->sizeofcmds
));
1178 * Set the file offset to the link edit information to be
1179 * right after the load commands.
1181 object
->seg_linkedit64
->fileoff
=
1182 sizeof(struct mach_header_64
) +
1183 object
->mh64
->sizeofcmds
;
1186 #endif /* !(NMEDIT) */
1199 * coalesced symbols can be stripped only if they are not used via an
1200 * symbol pointer. So to know that strip_symtab() needs to be passed
1201 * the indirect symbol table.
1203 if(object
->dyst
!= NULL
&& object
->dyst
->nindirectsyms
!= 0){
1204 nindirectsyms
= object
->dyst
->nindirectsyms
;
1205 indirectsyms
= (uint32_t *)
1206 (object
->object_addr
+ object
->dyst
->indirectsymoff
);
1207 if(object
->object_byte_sex
!= host_byte_sex
)
1208 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
1212 indirectsyms
= NULL
;
1216 if(object
->mh
!= NULL
)
1217 object
->input_sym_info_size
=
1218 nsyms
* sizeof(struct nlist
) +
1221 object
->input_sym_info_size
=
1222 nsyms
* sizeof(struct nlist_64
) +
1225 if(object
->mh
!= NULL
)
1226 flags
= object
->mh
->flags
;
1228 flags
= object
->mh64
->flags
;
1230 (flags
& MH_DYLDLINK
) == MH_DYLDLINK
&&
1231 object
->mh_filetype
== MH_EXECUTE
)
1232 default_dyld_executable
= TRUE
;
1234 default_dyld_executable
= FALSE
;
1235 #endif /* !defined(NMEDIT) */
1238 if(sfile
!= NULL
|| Rfile
!= NULL
|| dfile
!= NULL
|| Aflag
|| aflag
||
1239 uflag
|| Sflag
|| xflag
|| Xflag
|| tflag
|| nflag
|| rflag
||
1240 default_dyld_executable
|| object
->mh_filetype
== MH_DYLIB
||
1241 object
->mh_filetype
== MH_DYLINKER
)
1242 #endif /* !defined(NMEDIT) */
1245 if(edit_symtab(arch
, member
, object
, symbols
, symbols64
, nsyms
,
1246 strings
, strsize
, tocs
, ntoc
, mods
, mods64
, nmodtab
, refs
,
1247 nextrefsyms
) == FALSE
)
1249 #else /* !defined(NMEDIT) */
1250 if(strip_symtab(arch
, member
, object
, tocs
, ntoc
, mods
, mods64
,
1251 nmodtab
, refs
, nextrefsyms
) == FALSE
)
1254 strip_LC_UUID_commands(arch
, member
, object
);
1255 #endif /* !defined(NMEDIT) */
1256 if(object
->mh
!= NULL
)
1257 object
->output_sym_info_size
=
1258 new_nsyms
* sizeof(struct nlist
) +
1261 object
->output_sym_info_size
=
1262 new_nsyms
* sizeof(struct nlist_64
) +
1265 object
->st
->nsyms
= new_nsyms
;
1266 object
->st
->strsize
= new_strsize
;
1268 if(object
->mh
!= NULL
)
1269 object
->output_symbols
= new_symbols
;
1271 object
->output_symbols64
= new_symbols64
;
1272 object
->output_nsymbols
= new_nsyms
;
1273 object
->output_strings
= new_strings
;
1274 object
->output_strings_size
= new_strsize
;
1276 if(object
->dyld_info
!= NULL
){
1277 /* there are five parts to the dyld info, but
1278 strip does not alter them, so copy as a block */
1279 dyld_info_start
= 0;
1280 if (object
->dyld_info
->rebase_off
!= 0)
1281 dyld_info_start
= object
->dyld_info
->rebase_off
;
1282 else if (object
->dyld_info
->bind_off
!= 0)
1283 dyld_info_start
= object
->dyld_info
->bind_off
;
1284 else if (object
->dyld_info
->weak_bind_off
!= 0)
1285 dyld_info_start
= object
->dyld_info
->weak_bind_off
;
1286 else if (object
->dyld_info
->lazy_bind_off
!= 0)
1287 dyld_info_start
= object
->dyld_info
->lazy_bind_off
;
1288 else if (object
->dyld_info
->export_off
!= 0)
1289 dyld_info_start
= object
->dyld_info
->export_off
;
1291 if (object
->dyld_info
->export_size
!= 0)
1292 dyld_info_end
= object
->dyld_info
->export_off
1293 + object
->dyld_info
->export_size
;
1294 else if (object
->dyld_info
->lazy_bind_size
!= 0)
1295 dyld_info_end
= object
->dyld_info
->lazy_bind_off
1296 + object
->dyld_info
->lazy_bind_size
;
1297 else if (object
->dyld_info
->weak_bind_size
!= 0)
1298 dyld_info_end
= object
->dyld_info
->weak_bind_off
1299 + object
->dyld_info
->weak_bind_size
;
1300 else if (object
->dyld_info
->bind_size
!= 0)
1301 dyld_info_end
= object
->dyld_info
->bind_off
1302 + object
->dyld_info
->bind_size
;
1303 else if (object
->dyld_info
->rebase_size
!= 0)
1304 dyld_info_end
= object
->dyld_info
->rebase_off
1305 + object
->dyld_info
->rebase_size
;
1306 object
->output_dyld_info
= object
->object_addr
+ dyld_info_start
;
1307 object
->output_dyld_info_size
= dyld_info_end
- dyld_info_start
;
1308 object
->output_sym_info_size
+= object
->output_dyld_info_size
;
1309 /* warn about strip -s or -R on a final linked image with dyld_info */
1310 if(nsave_symbols
!= 0){
1311 warning_arch(arch
, NULL
, "removing global symbols from a final linked"
1312 " no longer supported. Use -exported_symbols_list at link time when building: ");
1315 if(object
->split_info_cmd
!= NULL
){
1316 object
->output_split_info_data
= object
->object_addr
+
1317 object
->split_info_cmd
->dataoff
;
1318 object
->output_split_info_data_size
=
1319 object
->split_info_cmd
->datasize
;
1321 if(object
->code_sig_cmd
!= NULL
){
1323 if(!cflag
&& !no_code_signature
)
1324 #endif /* !(NMEDIT) */
1326 object
->output_code_sig_data
= object
->object_addr
+
1327 object
->code_sig_cmd
->dataoff
;
1328 object
->output_code_sig_data_size
=
1329 object
->code_sig_cmd
->datasize
;
1333 if(object
->dyst
!= NULL
){
1334 object
->dyst
->ilocalsym
= 0;
1335 object
->dyst
->nlocalsym
= new_nlocalsym
;
1336 object
->dyst
->iextdefsym
= new_nlocalsym
;
1337 object
->dyst
->nextdefsym
= new_nextdefsym
;
1338 object
->dyst
->iundefsym
= new_nlocalsym
+ new_nextdefsym
;
1339 object
->dyst
->nundefsym
= new_nundefsym
;
1340 if(object
->dyst
->nindirectsyms
!= 0){
1341 object
->output_indirect_symtab
= indirectsyms
;
1342 if(object
->object_byte_sex
!= host_byte_sex
)
1343 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
1344 object
->object_byte_sex
);
1348 * If the -c option is specified the object's filetype will
1349 * have been changed from MH_DYLIB to MH_DYLIB_STUB above.
1351 if(object
->mh_filetype
== MH_DYLIB
||
1352 object
->mh_filetype
== MH_DYLIB_STUB
){
1353 object
->output_tocs
= new_tocs
;
1354 object
->output_ntoc
= new_ntoc
;
1356 if(object
->mh
!= NULL
)
1357 object
->output_mods
= new_mods
;
1359 object
->output_mods64
= new_mods64
;
1360 object
->output_nmodtab
= new_nmodtab
;
1362 object
->output_mods
= mods
;
1363 object
->output_nmodtab
= nmodtab
;
1365 object
->output_refs
= new_refs
;
1366 object
->output_nextrefsyms
= new_nextrefsyms
;
1367 if(object
->object_byte_sex
!= host_byte_sex
){
1368 swap_dylib_table_of_contents(new_tocs
, new_ntoc
,
1369 object
->object_byte_sex
);
1371 if(object
->mh
!= NULL
)
1372 swap_dylib_module(new_mods
, new_nmodtab
,
1373 object
->object_byte_sex
);
1375 swap_dylib_module_64(new_mods64
, new_nmodtab
,
1376 object
->object_byte_sex
);
1378 if(object
->mh
!= NULL
)
1379 swap_dylib_module(mods
, nmodtab
,
1380 object
->object_byte_sex
);
1382 swap_dylib_module_64(mods64
, nmodtab
,
1383 object
->object_byte_sex
);
1385 swap_dylib_reference(new_refs
, new_nextrefsyms
,
1386 object
->object_byte_sex
);
1389 if(object
->dyld_info
!= NULL
){
1390 object
->input_sym_info_size
+= object
->dyld_info
->rebase_size
1391 + object
->dyld_info
->bind_size
1392 + object
->dyld_info
->weak_bind_size
1393 + object
->dyld_info
->lazy_bind_size
1394 + object
->dyld_info
->export_size
;
1396 object
->input_sym_info_size
+=
1397 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1398 object
->dyst
->nextrel
* sizeof(struct relocation_info
) +
1399 object
->dyst
->ntoc
* sizeof(struct dylib_table_of_contents
)+
1400 object
->dyst
->nextrefsyms
* sizeof(struct dylib_reference
);
1401 if(object
->mh
!= NULL
){
1402 object
->input_sym_info_size
+=
1403 object
->dyst
->nmodtab
* sizeof(struct dylib_module
) +
1404 object
->dyst
->nindirectsyms
* sizeof(uint32_t);
1407 object
->input_sym_info_size
+=
1408 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
) +
1409 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1410 object
->input_indirectsym_pad
;
1414 * When stripping out the section contents to create a
1415 * dynamic library stub the relocation info also gets
1419 #endif /* !(NMEDIT) */
1421 object
->output_sym_info_size
+=
1422 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1423 object
->dyst
->nextrel
* sizeof(struct relocation_info
);
1425 object
->output_sym_info_size
+=
1426 new_ntoc
* sizeof(struct dylib_table_of_contents
)+
1427 new_nextrefsyms
* sizeof(struct dylib_reference
) +
1428 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1429 object
->input_indirectsym_pad
;
1430 if(object
->mh
!= NULL
){
1431 object
->output_sym_info_size
+=
1432 object
->dyst
->nmodtab
* sizeof(struct dylib_module
);
1435 object
->output_sym_info_size
+=
1436 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
);
1438 if(object
->hints_cmd
!= NULL
){
1439 object
->input_sym_info_size
+=
1440 object
->hints_cmd
->nhints
*
1441 sizeof(struct twolevel_hint
);
1442 object
->output_sym_info_size
+=
1443 object
->hints_cmd
->nhints
*
1444 sizeof(struct twolevel_hint
);
1446 if(object
->split_info_cmd
!= NULL
){
1447 object
->input_sym_info_size
+=
1448 object
->split_info_cmd
->datasize
;
1449 object
->output_sym_info_size
+=
1450 object
->split_info_cmd
->datasize
;
1452 if(object
->code_sig_cmd
!= NULL
){
1453 object
->input_sym_info_size
=
1454 round(object
->input_sym_info_size
, 16);
1455 object
->input_sym_info_size
+=
1456 object
->code_sig_cmd
->datasize
;
1458 if(cflag
|| no_code_signature
){
1459 strip_LC_CODE_SIGNATURE_commands(arch
, member
, object
);
1462 #endif /* !(NMEDIT) */
1464 object
->output_sym_info_size
=
1465 round(object
->output_sym_info_size
, 16);
1466 object
->output_sym_info_size
+=
1467 object
->code_sig_cmd
->datasize
;
1471 object
->dyst
->ntoc
= new_ntoc
;
1472 object
->dyst
->nextrefsyms
= new_nextrefsyms
;
1474 offset
= get_starting_syminfo_offset(object
);
1476 if(object
->dyld_info
!= 0){
1477 if (object
->dyld_info
->rebase_off
!= 0){
1478 object
->dyld_info
->rebase_off
= offset
;
1479 offset
+= object
->dyld_info
->rebase_size
;
1481 if (object
->dyld_info
->bind_off
!= 0){
1482 object
->dyld_info
->bind_off
= offset
;
1483 offset
+= object
->dyld_info
->bind_size
;
1485 if (object
->dyld_info
->weak_bind_off
!= 0){
1486 object
->dyld_info
->weak_bind_off
= offset
;
1487 offset
+= object
->dyld_info
->weak_bind_size
;
1489 if (object
->dyld_info
->lazy_bind_off
!= 0){
1490 object
->dyld_info
->lazy_bind_off
= offset
;
1491 offset
+= object
->dyld_info
->lazy_bind_size
;
1493 if (object
->dyld_info
->export_off
!= 0){
1494 object
->dyld_info
->export_off
= offset
;
1495 offset
+= object
->dyld_info
->export_size
;
1499 if(object
->dyst
->nlocrel
!= 0){
1500 object
->output_loc_relocs
= (struct relocation_info
*)
1501 (object
->object_addr
+ object
->dyst
->locreloff
);
1504 * When stripping out the section contents to create a
1505 * dynamic library stub the relocation info also gets
1509 object
->dyst
->nlocrel
= 0;
1510 object
->dyst
->locreloff
= 0;
1513 #endif /* defined(NMEDIT) */
1515 object
->dyst
->locreloff
= offset
;
1516 offset
+= object
->dyst
->nlocrel
*
1517 sizeof(struct relocation_info
);
1521 object
->dyst
->locreloff
= 0;
1523 if(object
->split_info_cmd
!= NULL
){
1524 object
->split_info_cmd
->dataoff
= offset
;
1525 offset
+= object
->split_info_cmd
->datasize
;
1528 if(object
->st
->nsyms
!= 0){
1529 object
->st
->symoff
= offset
;
1530 if(object
->mh
!= NULL
)
1531 offset
+= object
->st
->nsyms
* sizeof(struct nlist
);
1533 offset
+= object
->st
->nsyms
* sizeof(struct nlist_64
);
1536 object
->st
->symoff
= 0;
1538 if(object
->hints_cmd
!= NULL
){
1539 if(object
->hints_cmd
->nhints
!= 0){
1540 object
->output_hints
= (struct twolevel_hint
*)
1541 (object
->object_addr
+ object
->hints_cmd
->offset
);
1542 object
->hints_cmd
->offset
= offset
;
1543 offset
+= object
->hints_cmd
->nhints
*
1544 sizeof(struct twolevel_hint
);
1547 object
->hints_cmd
->offset
= 0;
1550 if(object
->dyst
->nextrel
!= 0){
1551 object
->output_ext_relocs
= (struct relocation_info
*)
1552 (object
->object_addr
+ object
->dyst
->extreloff
);
1555 * When stripping out the section contents to create a
1556 * dynamic library stub the relocation info also gets
1560 object
->dyst
->nextrel
= 0;
1561 object
->dyst
->extreloff
= 0;
1564 #endif /* defined(NMEDIT) */
1566 object
->dyst
->extreloff
= offset
;
1567 offset
+= object
->dyst
->nextrel
*
1568 sizeof(struct relocation_info
);
1572 object
->dyst
->extreloff
= 0;
1574 if(object
->dyst
->nindirectsyms
!= 0){
1575 object
->dyst
->indirectsymoff
= offset
;
1576 offset
+= object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1577 object
->input_indirectsym_pad
;
1580 object
->dyst
->indirectsymoff
= 0;;
1582 if(object
->dyst
->ntoc
!= 0){
1583 object
->dyst
->tocoff
= offset
;
1584 offset
+= object
->dyst
->ntoc
*
1585 sizeof(struct dylib_table_of_contents
);
1588 object
->dyst
->tocoff
= 0;
1590 if(object
->dyst
->nmodtab
!= 0){
1593 * When stripping out the section contents to create a
1594 * dynamic library stub zero out the fields in the module
1595 * table for the sections and relocation information and
1596 * clear Objective-C address and size from modules.
1599 if(object
->mh
!= NULL
){
1600 for(k
= 0; k
< object
->dyst
->nmodtab
; k
++){
1601 mods
[k
].iinit_iterm
= 0;
1602 mods
[k
].ninit_nterm
= 0;
1603 mods
[k
].iextrel
= 0;
1604 mods
[k
].nextrel
= 0;
1605 mods
[k
].objc_module_info_addr
= 0;
1606 mods
[k
].objc_module_info_size
= 0;
1610 for(k
= 0; k
< object
->dyst
->nmodtab
; k
++){
1611 mods64
[k
].iinit_iterm
= 0;
1612 mods64
[k
].ninit_nterm
= 0;
1613 mods64
[k
].iextrel
= 0;
1614 mods64
[k
].nextrel
= 0;
1615 mods64
[k
].objc_module_info_addr
= 0;
1616 mods64
[k
].objc_module_info_size
= 0;
1620 #endif /* !(NMEDIT) */
1621 object
->dyst
->modtaboff
= offset
;
1622 if(object
->mh
!= NULL
)
1623 offset
+= object
->dyst
->nmodtab
*
1624 sizeof(struct dylib_module
);
1626 offset
+= object
->dyst
->nmodtab
*
1627 sizeof(struct dylib_module_64
);
1630 object
->dyst
->modtaboff
= 0;
1632 if(object
->dyst
->nextrefsyms
!= 0){
1633 object
->dyst
->extrefsymoff
= offset
;
1634 offset
+= object
->dyst
->nextrefsyms
*
1635 sizeof(struct dylib_reference
);
1638 object
->dyst
->extrefsymoff
= 0;
1640 if(object
->st
->strsize
!= 0){
1641 object
->st
->stroff
= offset
;
1642 offset
+= object
->st
->strsize
;
1645 object
->st
->stroff
= 0;
1647 if(object
->code_sig_cmd
!= NULL
){
1648 offset
= round(offset
, 16);
1649 object
->code_sig_cmd
->dataoff
= offset
;
1650 offset
+= object
->code_sig_cmd
->datasize
;
1654 if(new_strsize
!= 0){
1655 if(object
->mh
!= NULL
)
1656 object
->st
->stroff
= object
->st
->symoff
+
1657 new_nsyms
* sizeof(struct nlist
);
1659 object
->st
->stroff
= object
->st
->symoff
+
1660 new_nsyms
* sizeof(struct nlist_64
);
1663 object
->st
->stroff
= 0;
1665 object
->st
->symoff
= 0;
1671 * Here we are doing a full symbol strip. In some cases it may
1672 * leave the local relocation entries as well as LOCAL indirect
1673 * symbol table entries.
1677 saves
= (int32_t *)allocate(object
->st
->nsyms
* sizeof(int32_t));
1678 bzero(saves
, object
->st
->nsyms
* sizeof(int32_t));
1681 * Account for the symbolic info in the input file.
1683 if(object
->dyst
!= NULL
){
1684 object
->input_sym_info_size
+=
1685 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1686 object
->dyst
->nextrel
* sizeof(struct relocation_info
) +
1687 object
->dyst
->ntoc
* sizeof(struct dylib_table_of_contents
)+
1688 object
->dyst
->nextrefsyms
* sizeof(struct dylib_reference
);
1689 if(object
->mh
!= NULL
){
1690 object
->input_sym_info_size
+=
1691 object
->dyst
->nmodtab
* sizeof(struct dylib_module
) +
1692 object
->dyst
->nindirectsyms
* sizeof(uint32_t);
1695 object
->input_sym_info_size
+=
1696 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
) +
1697 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1698 object
->input_indirectsym_pad
;
1703 * Determine the offset where the remaining symbolic info will start
1704 * in the output file (if any).
1706 offset
= get_starting_syminfo_offset(object
);
1709 * For a full symbol strip all these values in the output file are
1712 object
->st
->symoff
= 0;
1713 object
->st
->nsyms
= 0;
1714 object
->st
->stroff
= 0;
1715 object
->st
->strsize
= 0;
1716 if(object
->dyst
!= NULL
){
1717 object
->dyst
->ilocalsym
= 0;
1718 object
->dyst
->nlocalsym
= 0;
1719 object
->dyst
->iextdefsym
= 0;
1720 object
->dyst
->nextdefsym
= 0;
1721 object
->dyst
->iundefsym
= 0;
1722 object
->dyst
->nundefsym
= 0;
1726 * This will accumulate any remaining symbolic info size in the
1729 object
->output_sym_info_size
= 0;
1732 * We set these so that checking can be done below to report the
1733 * symbols that can't be stripped because of relocation entries
1734 * or indirect symbol table entries. Normally if these table have a
1735 * non-zero number of entries it will be an error as we are trying
1736 * to strip everything. But it maybe that there are only LOCAL
1737 * indirect entries which is odd but will be OK.
1739 if(object
->dyst
!= NULL
){
1740 if(object
->dyst
->nextrel
!= 0){
1741 object
->output_ext_relocs
= (struct relocation_info
*)
1742 (object
->object_addr
+ object
->dyst
->extreloff
);
1745 * Since this file has a dynamic symbol table and if this file
1746 * has local relocation entries on input make sure they are
1747 * there on output. This is a rare case that it will not have
1748 * external relocs or indirect symbols but can happen as is the
1749 * case with the dynamic linker itself.
1751 if(object
->dyst
->nlocrel
!= 0){
1752 object
->output_loc_relocs
= (struct relocation_info
*)
1753 (object
->object_addr
+ object
->dyst
->locreloff
);
1754 object
->output_sym_info_size
+=
1755 object
->dyst
->nlocrel
* sizeof(struct relocation_info
);
1757 object
->dyst
->locreloff
= offset
;
1758 offset
+= object
->dyst
->nlocrel
*
1759 sizeof(struct relocation_info
);
1762 if(object
->dyst
->nindirectsyms
!= 0){
1763 object
->output_indirect_symtab
= (uint32_t *)
1764 (object
->object_addr
+
1765 object
->dyst
->indirectsymoff
);
1766 if(object
->object_byte_sex
!= host_byte_sex
)
1767 swap_indirect_symbols(
1768 object
->output_indirect_symtab
,
1769 object
->dyst
->nindirectsyms
,
1770 object
->object_byte_sex
);
1772 object
->output_sym_info_size
+=
1773 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1774 object
->input_indirectsym_pad
;
1776 object
->dyst
->indirectsymoff
= offset
;
1777 offset
+= object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1778 object
->input_indirectsym_pad
;
1782 #endif /* !defined(NMEDIT) */
1785 * Always clear the prebind checksum if any when creating a new file.
1787 if(object
->cs
!= NULL
)
1788 object
->cs
->cksum
= 0;
1790 if(object
->seg_linkedit
!= NULL
){
1791 object
->seg_linkedit
->filesize
+= object
->output_sym_info_size
-
1792 object
->input_sym_info_size
;
1793 object
->seg_linkedit
->vmsize
= object
->seg_linkedit
->filesize
;
1795 else if(object
->seg_linkedit64
!= NULL
){
1796 /* Do this in two steps to avoid 32/64-bit casting problems. */
1797 object
->seg_linkedit64
->filesize
-= object
->input_sym_info_size
;
1798 object
->seg_linkedit64
->filesize
+= object
->output_sym_info_size
;
1799 object
->seg_linkedit64
->vmsize
= object
->seg_linkedit64
->filesize
;
1803 * Check and update the external relocation entries to make sure
1804 * referenced symbols are not stripped and refer to the new symbol
1807 * The external relocation entries can be located in one of two places,
1808 * first off of the sections or second off of the dynamic symtab.
1810 missing_reloc_symbols
= 0;
1811 lc
= object
->load_commands
;
1812 if(object
->mh
!= NULL
)
1813 ncmds
= object
->mh
->ncmds
;
1815 ncmds
= object
->mh64
->ncmds
;
1816 for(i
= 0; i
< ncmds
; i
++){
1817 if(lc
->cmd
== LC_SEGMENT
&&
1818 object
->seg_linkedit
!= (struct segment_command
*)lc
){
1819 sg
= (struct segment_command
*)lc
;
1820 s
= (struct section
*)((char *)sg
+
1821 sizeof(struct segment_command
));
1822 for(j
= 0; j
< sg
->nsects
; j
++){
1824 if(s
->reloff
+ s
->nreloc
*
1825 sizeof(struct relocation_info
) >
1826 object
->object_size
){
1827 fatal_arch(arch
, member
, "truncated or malformed "
1828 "object (relocation entries for section (%.16s,"
1829 "%.16s) extends past the end of the file)",
1830 s
->segname
, s
->sectname
);
1832 relocs
= (struct relocation_info
*)
1833 (object
->object_addr
+ s
->reloff
);
1834 if(object
->object_byte_sex
!= host_byte_sex
)
1835 swap_relocation_info(relocs
, s
->nreloc
,
1837 if(s
->offset
+ s
->size
> object
->object_size
){
1838 fatal_arch(arch
, member
, "truncated or malformed "
1839 "object (contents of section (%.16s,"
1840 "%.16s) extends past the end of the file)",
1841 s
->segname
, s
->sectname
);
1843 contents
= object
->object_addr
+ s
->offset
;
1844 check_object_relocs(arch
, member
, object
, s
->segname
,
1845 s
->sectname
, s
->size
, contents
, relocs
, s
->nreloc
,
1846 symbols
, symbols64
, nsyms
, strings
,
1847 &missing_reloc_symbols
, host_byte_sex
);
1848 if(object
->object_byte_sex
!= host_byte_sex
)
1849 swap_relocation_info(relocs
, s
->nreloc
,
1850 object
->object_byte_sex
);
1855 else if(lc
->cmd
== LC_SEGMENT_64
&&
1856 object
->seg_linkedit64
!= (struct segment_command_64
*)lc
){
1857 sg64
= (struct segment_command_64
*)lc
;
1858 s64
= (struct section_64
*)((char *)sg64
+
1859 sizeof(struct segment_command_64
));
1860 for(j
= 0; j
< sg64
->nsects
; j
++){
1861 if(s64
->nreloc
!= 0){
1862 if(s64
->reloff
+ s64
->nreloc
*
1863 sizeof(struct relocation_info
) >
1864 object
->object_size
){
1865 fatal_arch(arch
, member
, "truncated or malformed "
1866 "object (relocation entries for section (%.16s,"
1867 "%.16s) extends past the end of the file)",
1868 s64
->segname
, s64
->sectname
);
1870 relocs
= (struct relocation_info
*)
1871 (object
->object_addr
+ s64
->reloff
);
1872 if(object
->object_byte_sex
!= host_byte_sex
)
1873 swap_relocation_info(relocs
, s64
->nreloc
,
1875 if(s64
->offset
+ s64
->size
> object
->object_size
){
1876 fatal_arch(arch
, member
, "truncated or malformed "
1877 "object (contents of section (%.16s,"
1878 "%.16s) extends past the end of the file)",
1879 s64
->segname
, s64
->sectname
);
1881 contents
= object
->object_addr
+ s64
->offset
;
1882 check_object_relocs(arch
, member
, object
, s64
->segname
,
1883 s64
->sectname
, s64
->size
, contents
, relocs
,
1884 s64
->nreloc
, symbols
, symbols64
, nsyms
, strings
,
1885 &missing_reloc_symbols
, host_byte_sex
);
1886 if(object
->object_byte_sex
!= host_byte_sex
)
1887 swap_relocation_info(relocs
, s64
->nreloc
,
1888 object
->object_byte_sex
);
1893 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1895 if(object
->dyst
!= NULL
&& object
->dyst
->nextrel
!= 0){
1896 relocs
= object
->output_ext_relocs
;
1897 if(object
->object_byte_sex
!= host_byte_sex
)
1898 swap_relocation_info(relocs
, object
->dyst
->nextrel
,
1901 for(i
= 0; i
< object
->dyst
->nextrel
; i
++){
1902 if((relocs
[i
].r_address
& R_SCATTERED
) == 0 &&
1903 relocs
[i
].r_extern
== 1){
1904 if(relocs
[i
].r_symbolnum
> nsyms
){
1905 fatal_arch(arch
, member
, "bad r_symbolnum for external "
1906 "relocation entry %d in: ", i
);
1908 if(saves
[relocs
[i
].r_symbolnum
] == 0){
1909 if(missing_reloc_symbols
== 0){
1910 error_arch(arch
, member
, "symbols referenced by "
1911 "relocation entries that can't be stripped in: ");
1912 missing_reloc_symbols
= 1;
1914 if(object
->mh
!= NULL
){
1915 fprintf(stderr
, "%s\n", strings
+ symbols
1916 [relocs
[i
].r_symbolnum
].n_un
.n_strx
);
1919 fprintf(stderr
, "%s\n", strings
+ symbols64
1920 [relocs
[i
].r_symbolnum
].n_un
.n_strx
);
1922 saves
[relocs
[i
].r_symbolnum
] = -1;
1924 if(saves
[relocs
[i
].r_symbolnum
] != -1){
1925 relocs
[i
].r_symbolnum
=
1926 saves
[relocs
[i
].r_symbolnum
] - 1;
1930 fatal_arch(arch
, member
, "bad external relocation entry "
1931 "%d (not external) in: ", i
);
1933 if((relocs
[i
].r_address
& R_SCATTERED
) == 0){
1934 if(reloc_has_pair(object
->mh_cputype
, relocs
[i
].r_type
))
1938 sreloc
= (struct scattered_relocation_info
*)relocs
+ i
;
1939 if(reloc_has_pair(object
->mh_cputype
, sreloc
->r_type
))
1943 if(object
->object_byte_sex
!= host_byte_sex
)
1944 swap_relocation_info(relocs
, object
->dyst
->nextrel
,
1945 object
->object_byte_sex
);
1949 * Check and update the indirect symbol table entries to make sure
1950 * referenced symbols are not stripped and refer to the new symbol
1953 if(object
->dyst
!= NULL
&& object
->dyst
->nindirectsyms
!= 0){
1954 if(object
->object_byte_sex
!= host_byte_sex
)
1955 swap_indirect_symbols(object
->output_indirect_symtab
,
1956 object
->dyst
->nindirectsyms
, host_byte_sex
);
1958 lc
= object
->load_commands
;
1959 if(object
->mh
!= NULL
)
1960 ncmds
= object
->mh
->ncmds
;
1962 ncmds
= object
->mh64
->ncmds
;
1963 for(i
= 0; i
< ncmds
; i
++){
1964 if(lc
->cmd
== LC_SEGMENT
&&
1965 object
->seg_linkedit
!= (struct segment_command
*)lc
){
1966 sg
= (struct segment_command
*)lc
;
1967 s
= (struct section
*)((char *)sg
+
1968 sizeof(struct segment_command
));
1969 for(j
= 0; j
< sg
->nsects
; j
++){
1970 section_type
= s
->flags
& SECTION_TYPE
;
1971 if(section_type
== S_LAZY_SYMBOL_POINTERS
||
1972 section_type
== S_LAZY_DYLIB_SYMBOL_POINTERS
||
1973 section_type
== S_NON_LAZY_SYMBOL_POINTERS
)
1975 else if(section_type
== S_SYMBOL_STUBS
)
1976 stride
= s
->reserved2
;
1981 nitems
= s
->size
/ stride
;
1982 contents
= object
->object_addr
+ s
->offset
;
1983 check_indirect_symtab(arch
, member
, object
, nitems
,
1984 s
->reserved1
, section_type
, contents
, symbols
,
1985 symbols64
, nsyms
, strings
, &missing_reloc_symbols
,
1990 else if(lc
->cmd
== LC_SEGMENT_64
&&
1991 object
->seg_linkedit64
!= (struct segment_command_64
*)lc
){
1992 sg64
= (struct segment_command_64
*)lc
;
1993 s64
= (struct section_64
*)((char *)sg64
+
1994 sizeof(struct segment_command_64
));
1995 for(j
= 0; j
< sg64
->nsects
; j
++){
1996 section_type
= s64
->flags
& SECTION_TYPE
;
1997 if(section_type
== S_LAZY_SYMBOL_POINTERS
||
1998 section_type
== S_LAZY_DYLIB_SYMBOL_POINTERS
||
1999 section_type
== S_NON_LAZY_SYMBOL_POINTERS
)
2001 else if(section_type
== S_SYMBOL_STUBS
)
2002 stride
= s64
->reserved2
;
2007 nitems
= s64
->size
/ stride
;
2008 contents
= object
->object_addr
+ s64
->offset
;
2009 check_indirect_symtab(arch
, member
, object
, nitems
,
2010 s64
->reserved1
, section_type
, contents
, symbols
,
2011 symbols64
, nsyms
, strings
, &missing_reloc_symbols
,
2016 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2019 if(object
->object_byte_sex
!= host_byte_sex
)
2020 swap_indirect_symbols(object
->output_indirect_symtab
,
2021 object
->dyst
->nindirectsyms
, object
->object_byte_sex
);
2025 * Issue a warning if object file has a code signature that the
2026 * operation will invalidate it.
2028 if(object
->code_sig_cmd
!= NULL
)
2029 warning_arch(arch
, member
, "changes being made to the file will "
2030 "invalidate the code signature in: ");
2034 * get_starting_syminfo_offset() returns the starting offset of the symbolic
2035 * info in the object file.
2039 get_starting_syminfo_offset(
2040 struct object
*object
)
2044 if(object
->seg_linkedit
!= NULL
||
2045 object
->seg_linkedit64
!= NULL
){
2046 if(object
->mh
!= NULL
)
2047 offset
= object
->seg_linkedit
->fileoff
;
2049 offset
= object
->seg_linkedit64
->fileoff
;
2053 if(object
->dyst
!= NULL
&&
2054 object
->dyst
->nlocrel
!= 0 &&
2055 object
->dyst
->locreloff
< offset
)
2056 offset
= object
->dyst
->locreloff
;
2057 if(object
->st
->nsyms
!= 0 &&
2058 object
->st
->symoff
< offset
)
2059 offset
= object
->st
->symoff
;
2060 if(object
->dyst
!= NULL
&&
2061 object
->dyst
->nextrel
!= 0 &&
2062 object
->dyst
->extreloff
< offset
)
2063 offset
= object
->dyst
->extreloff
;
2064 if(object
->dyst
!= NULL
&&
2065 object
->dyst
->nindirectsyms
!= 0 &&
2066 object
->dyst
->indirectsymoff
< offset
)
2067 offset
= object
->dyst
->indirectsymoff
;
2068 if(object
->dyst
!= NULL
&&
2069 object
->dyst
->ntoc
!= 0 &&
2070 object
->dyst
->tocoff
< offset
)
2071 offset
= object
->dyst
->tocoff
;
2072 if(object
->dyst
!= NULL
&&
2073 object
->dyst
->nmodtab
!= 0 &&
2074 object
->dyst
->modtaboff
< offset
)
2075 offset
= object
->dyst
->modtaboff
;
2076 if(object
->dyst
!= NULL
&&
2077 object
->dyst
->nextrefsyms
!= 0 &&
2078 object
->dyst
->extrefsymoff
< offset
)
2079 offset
= object
->dyst
->extrefsymoff
;
2080 if(object
->st
->strsize
!= 0 &&
2081 object
->st
->stroff
< offset
)
2082 offset
= object
->st
->stroff
;
2088 * check_object_relocs() is used to check and update the external relocation
2089 * entries from a section in an object file, to make sure referenced symbols
2090 * are not stripped and are changed to refer to the new symbol table indexes.
2094 check_object_relocs(
2096 struct member
*member
,
2097 struct object
*object
,
2102 struct relocation_info
*relocs
,
2104 struct nlist
*symbols
,
2105 struct nlist_64
*symbols64
,
2108 int32_t *missing_reloc_symbols
,
2109 enum byte_sex host_byte_sex
)
2114 uint32_t value
, n_ext
;
2117 struct scattered_relocation_info
*sreloc
;
2119 for(k
= 0; k
< nreloc
; k
++){
2120 if((relocs
[k
].r_address
& R_SCATTERED
) == 0 &&
2121 relocs
[k
].r_extern
== 1){
2122 if(relocs
[k
].r_symbolnum
> nsyms
){
2123 fatal_arch(arch
, member
, "bad r_symbolnum for relocation "
2124 "entry %d in section (%.16s,%.16s) in: ", k
, segname
,
2127 if(object
->mh
!= NULL
){
2128 n_strx
= symbols
[relocs
[k
].r_symbolnum
].n_un
.n_strx
;
2129 n_value
= symbols
[relocs
[k
].r_symbolnum
].n_value
;
2132 n_strx
= symbols64
[relocs
[k
].r_symbolnum
].n_un
.n_strx
;
2133 n_value
= symbols64
[relocs
[k
].r_symbolnum
].n_value
;
2136 if(saves
[relocs
[k
].r_symbolnum
] == 0){
2137 if(*missing_reloc_symbols
== 0){
2138 error_arch(arch
, member
, "symbols referenced by "
2139 "relocation entries that can't be stripped in: ");
2140 *missing_reloc_symbols
= 1;
2142 fprintf(stderr
, "%s\n", strings
+ n_strx
);
2143 saves
[relocs
[k
].r_symbolnum
] = -1;
2145 #else /* defined(NMEDIT) */
2147 * We are letting nmedit change global coalesed symbols into
2148 * statics in MH_OBJECT file types only. Relocation entries to
2149 * global coalesced symbols are external relocs.
2151 if(object
->mh
!= NULL
)
2152 n_ext
= new_symbols
[saves
[relocs
[k
].r_symbolnum
] - 1].
2155 n_ext
= new_symbols64
[saves
[relocs
[k
].r_symbolnum
] - 1].
2157 if(n_ext
!= N_EXT
&&
2158 object
->mh_cputype
!= CPU_TYPE_X86_64
){
2160 * We need to do the relocation for this external relocation
2161 * entry so the item to be relocated is correct for a local
2162 * relocation entry. We don't need to do this for x86-64.
2164 if(relocs
[k
].r_address
+ sizeof(int32_t) > sectsize
){
2165 fatal_arch(arch
, member
, "truncated or malformed "
2166 "object (r_address of relocation entry %u of "
2167 "section (%.16s,%.16s) extends past the end "
2168 "of the section)", k
, segname
, sectname
);
2170 if(object
->mh
!= NULL
){
2171 value
= *(uint32_t *)
2172 (contents
+ relocs
[k
].r_address
);
2173 if(object
->object_byte_sex
!= host_byte_sex
)
2174 value
= SWAP_INT(value
);
2176 * We handle a very limited form here. Only VANILLA
2177 * (r_type == 0) long (r_length==2) absolute or pcrel
2178 * that won't need a scattered relocation entry.
2180 if(relocs
[k
].r_type
!= 0 ||
2181 relocs
[k
].r_length
!= 2){
2182 fatal_arch(arch
, member
, "don't have "
2183 "code to convert external relocation "
2184 "entry %d in section (%.16s,%.16s) "
2185 "for global coalesced symbol: %s "
2186 "in: ", k
, segname
, sectname
,
2190 if(object
->object_byte_sex
!= host_byte_sex
)
2191 value
= SWAP_INT(value
);
2192 *(uint32_t *)(contents
+ relocs
[k
].r_address
) =
2196 value64
= *(uint64_t *)(contents
+ relocs
[k
].r_address
);
2197 if(object
->object_byte_sex
!= host_byte_sex
)
2198 value64
= SWAP_LONG_LONG(value64
);
2200 * We handle a very limited form here. Only VANILLA
2201 * (r_type == 0) quad (r_length==3) absolute or pcrel
2202 * that won't need a scattered relocation entry.
2204 if(relocs
[k
].r_type
!= 0 ||
2205 relocs
[k
].r_length
!= 3){
2206 fatal_arch(arch
, member
, "don't have "
2207 "code to convert external relocation "
2208 "entry %d in section (%.16s,%.16s) "
2209 "for global coalesced symbol: %s "
2210 "in: ", k
, segname
, sectname
,
2214 if(object
->object_byte_sex
!= host_byte_sex
)
2215 value64
= SWAP_LONG_LONG(value64
);
2216 *(uint64_t *)(contents
+ relocs
[k
].r_address
) = value64
;
2219 * Turn the extern reloc into a local.
2221 if(object
->mh
!= NULL
)
2222 relocs
[k
].r_symbolnum
=
2223 new_symbols
[saves
[relocs
[k
].r_symbolnum
] - 1].n_sect
;
2225 relocs
[k
].r_symbolnum
=
2226 new_symbols64
[saves
[relocs
[k
].r_symbolnum
] - 1].n_sect
;
2227 relocs
[k
].r_extern
= 0;
2230 if(relocs
[k
].r_extern
== 1 &&
2231 saves
[relocs
[k
].r_symbolnum
] != -1){
2232 relocs
[k
].r_symbolnum
= saves
[relocs
[k
].r_symbolnum
] - 1;
2235 if((relocs
[k
].r_address
& R_SCATTERED
) == 0){
2236 if(reloc_has_pair(object
->mh_cputype
, relocs
[k
].r_type
) == TRUE
)
2240 sreloc
= (struct scattered_relocation_info
*)relocs
+ k
;
2241 if(reloc_has_pair(object
->mh_cputype
, sreloc
->r_type
) == TRUE
)
2248 * check_indirect_symtab() checks and updates the indirect symbol table entries
2249 * to make sure referenced symbols are not stripped and refer to the new symbol
2254 check_indirect_symtab(
2256 struct member
*member
,
2257 struct object
*object
,
2260 uint32_t section_type
,
2262 struct nlist
*symbols
,
2263 struct nlist_64
*symbols64
,
2266 int32_t *missing_reloc_symbols
,
2267 enum byte_sex host_byte_sex
)
2271 uint32_t n_strx
, value
;
2273 enum bool made_local
;
2275 for(k
= 0; k
< nitems
; k
++){
2277 index
= object
->output_indirect_symtab
[reserved1
+ k
];
2278 if(index
== INDIRECT_SYMBOL_LOCAL
||
2279 index
== INDIRECT_SYMBOL_ABS
||
2280 index
== (INDIRECT_SYMBOL_LOCAL
| INDIRECT_SYMBOL_ABS
))
2283 fatal_arch(arch
, member
,"indirect symbol table entry %d (past " "the end of the symbol table) in: ", reserved1
+ k
);
2285 if(pflag
== 0 && nmedits
[index
] == TRUE
&& saves
[index
] != -1)
2287 if(saves
[index
] == 0)
2291 * Indirect symbol table entries for defined symbols in a
2292 * non-lazy pointer section that are not saved are changed to
2293 * INDIRECT_SYMBOL_LOCAL which their values just have to be
2294 * slid if the are not absolute symbols.
2296 if(object
->mh
!= NULL
){
2297 n_type
= symbols
[index
].n_type
;
2298 n_strx
= symbols
[index
].n_un
.n_strx
;
2301 n_type
= symbols64
[index
].n_type
;
2302 n_strx
= symbols64
[index
].n_un
.n_strx
;
2304 if((n_type
&& N_TYPE
) != N_UNDF
&&
2305 (n_type
&& N_TYPE
) != N_PBUD
&&
2306 section_type
== S_NON_LAZY_SYMBOL_POINTERS
){
2307 object
->output_indirect_symtab
[reserved1
+ k
] =
2308 INDIRECT_SYMBOL_LOCAL
;
2309 if((n_type
& N_TYPE
) == N_ABS
)
2310 object
->output_indirect_symtab
[reserved1
+ k
] |=
2311 INDIRECT_SYMBOL_ABS
;
2314 * When creating a stub shared library the section contents
2315 * are not updated since they will be stripped.
2317 if(object
->mh_filetype
!= MH_DYLIB_STUB
){
2318 if(object
->mh
!= NULL
){
2319 value
= symbols
[index
].n_value
;
2320 if (symbols
[index
].n_desc
& N_ARM_THUMB_DEF
)
2322 if(object
->object_byte_sex
!= host_byte_sex
)
2323 value
= SWAP_INT(value
);
2324 *(uint32_t *)(contents
+ k
* 4) = value
;
2327 value64
= symbols64
[index
].n_value
;
2328 if(object
->object_byte_sex
!= host_byte_sex
)
2329 value64
= SWAP_LONG_LONG(value64
);
2330 *(uint64_t *)(contents
+ k
* 8) = value64
;
2336 object
->output_indirect_symtab
[reserved1
+ k
] =
2339 #else /* !defined(NMEDIT) */
2341 if(*missing_reloc_symbols
== 0){
2342 error_arch(arch
, member
, "symbols referenced by "
2343 "indirect symbol table entries that can't be "
2345 *missing_reloc_symbols
= 1;
2347 fprintf(stderr
, "%s\n", strings
+ n_strx
);
2350 #endif /* !defined(NMEDIT) */
2354 #else /* !defined(NMEDIT) */
2355 if(made_local
== FALSE
&& saves
[index
] != -1)
2356 #endif /* !defined(NMEDIT) */
2358 object
->output_indirect_symtab
[reserved1
+k
] = saves
[index
] - 1;
2365 * This is called if there is a -d option specified. It reads the file with
2366 * the strings in it and places them in the array debug_filenames and sorts
2367 * them by name. The file that contains the file names must have names one
2368 * per line with no white space (except the newlines).
2372 setup_debug_filenames(
2375 int fd
, i
, strings_size
;
2376 struct stat stat_buf
;
2379 if((fd
= open(dfile
, O_RDONLY
)) < 0){
2380 system_error("can't open: %s", dfile
);
2383 if(fstat(fd
, &stat_buf
) == -1){
2384 system_error("can't stat: %s", dfile
);
2388 strings_size
= stat_buf
.st_size
;
2389 strings
= (char *)allocate(strings_size
+ 1);
2390 strings
[strings_size
] = '\0';
2391 if(read(fd
, strings
, strings_size
) != strings_size
){
2392 system_error("can't read: %s", dfile
);
2397 for(i
= 0; i
< strings_size
; i
++){
2404 debug_filenames
= (char **)allocate(ndebug_filenames
* sizeof(char *));
2406 for(i
= 0; i
< ndebug_filenames
; i
++){
2407 debug_filenames
[i
] = p
;
2410 qsort(debug_filenames
, ndebug_filenames
, sizeof(char *),
2411 (int (*)(const void *, const void *))cmp_qsort_filename
);
2414 printf("Debug filenames:\n");
2415 for(i
= 0; i
< ndebug_filenames
; i
++){
2416 printf("filename = %s\n", debug_filenames
[i
]);
2422 * Strip the symbol table to the level specified by the command line arguments.
2423 * The new symbol table is built and new_symbols is left pointing to it. The
2424 * number of new symbols is left in new_nsyms, the new string table is built
2425 * and new_stings is left pointing to it and new_strsize is left containing it.
2426 * This routine returns zero if successfull and non-zero otherwise.
2432 struct member
*member
,
2433 struct object
*object
,
2434 struct dylib_table_of_contents
*tocs
,
2436 struct dylib_module
*mods
,
2437 struct dylib_module_64
*mods64
,
2439 struct dylib_reference
*refs
,
2440 uint32_t nextrefsyms
)
2442 uint32_t i
, j
, k
, n
, inew_syms
, save_debug
, missing_syms
;
2443 uint32_t missing_symbols
;
2444 char *p
, *q
, **pp
, *basename
;
2445 struct symbol_list
*sp
;
2446 uint32_t new_ext_strsize
, len
, *changes
, inew_undefsyms
;
2447 unsigned char nsects
;
2448 struct load_command
*lc
;
2449 struct segment_command
*sg
;
2450 struct segment_command_64
*sg64
;
2451 struct section
*s
, **sections
;
2452 struct section_64
*s64
, **sections64
;
2453 uint32_t ncmds
, mh_flags
, s_flags
, n_strx
;
2455 struct undef_map
*undef_map
;
2456 struct undef_map64
*undef_map64
;
2457 uint8_t n_type
, n_sect
;
2460 uint32_t module_name
, iextdefsym
, nextdefsym
, ilocalsym
, nlocalsym
;
2461 uint32_t irefsym
, nrefsym
;
2462 unsigned char text_nsect
;
2463 enum bool has_dwarf
, hack_5614542
;
2469 for(i
= 0; i
< nsave_symbols
; i
++)
2470 save_symbols
[i
].sym
= NULL
;
2471 for(i
= 0; i
< nremove_symbols
; i
++)
2472 remove_symbols
[i
].sym
= NULL
;
2474 for(i
= 0; i
< nsave_symbols
; i
++)
2475 save_symbols
[i
].seen
= FALSE
;
2476 for(i
= 0; i
< nremove_symbols
; i
++)
2477 remove_symbols
[i
].seen
= FALSE
;
2481 if(object
->mh
!= NULL
)
2482 new_strsize
= sizeof(int32_t);
2484 new_strsize
= sizeof(int64_t);
2488 new_ext_strsize
= 0;
2491 * If this an object file that has DWARF debugging sections to strip
2492 * then we have to run ld -r on it.
2494 if(object
->mh_filetype
== MH_OBJECT
&& (Sflag
|| xflag
)){
2496 lc
= object
->load_commands
;
2497 if(object
->mh
!= NULL
)
2498 ncmds
= object
->mh
->ncmds
;
2500 ncmds
= object
->mh64
->ncmds
;
2501 for(i
= 0; i
< ncmds
&& has_dwarf
== FALSE
; i
++){
2502 if(lc
->cmd
== LC_SEGMENT
){
2503 sg
= (struct segment_command
*)lc
;
2504 s
= (struct section
*)((char *)sg
+
2505 sizeof(struct segment_command
));
2506 for(j
= 0; j
< sg
->nsects
; j
++){
2507 if(s
->flags
& S_ATTR_DEBUG
){
2514 else if(lc
->cmd
== LC_SEGMENT_64
){
2515 sg64
= (struct segment_command_64
*)lc
;
2516 s64
= (struct section_64
*)((char *)sg64
+
2517 sizeof(struct segment_command_64
));
2518 for(j
= 0; j
< sg64
->nsects
; j
++){
2519 if(s64
->flags
& S_ATTR_DEBUG
){
2526 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2529 * Because of the bugs in ld(1) for:
2530 * radr://5675774 ld64 should preserve JBSR relocations without
2532 * radr://5658046 cctools-679 creates scattered relocations in
2533 * __TEXT,__const section in kexts, which breaks
2534 * kexts built for older systems
2535 * we can't use ld -r to strip dwarf info in 32-bit objects until
2536 * these are fixed. But if the user as specified the -l flag then
2537 * go ahead and do it and the user will have to be aware of these
2540 if((lflag
== TRUE
&& has_dwarf
== TRUE
) || object
->mh64
!= NULL
)
2541 make_ld_r_object(arch
, member
, object
);
2544 * Because of the "design" of 64-bit object files and the lack of
2545 * local relocation entries it is not possible for strip(1) to do its
2546 * job without becoming a static link editor. The "design" does not
2547 * actually strip the symbols it simply renames them to things like
2548 * "l1000". And they become static symbols but still have external
2549 * relocation entries. Thus can never actually be stripped. Also some
2550 * symbols, *.eh, symbols are not even changed to these names if there
2551 * corresponding global symbol is not stripped. So strip(1) only
2552 * recourse is to use the unified linker to create an ld -r object then
2553 * save all resulting symbols (both static and global) and hope the user
2554 * does not notice the stripping is not what they asked for.
2556 if(object
->mh_filetype
== MH_OBJECT
&&
2557 (object
->mh64
!= NULL
&& object
->ld_r_ofile
== NULL
))
2558 make_ld_r_object(arch
, member
, object
);
2561 * Since make_ld_r_object() may create an object with more symbols
2562 * this has to be done after make_ld_r_object() and nsyms is updated.
2564 saves
= (int32_t *)allocate(nsyms
* sizeof(int32_t));
2565 bzero(saves
, nsyms
* sizeof(int32_t));
2568 * Gather an array of section struct pointers so we can later determine
2569 * if we run into a global symbol in a coalesced section and not strip
2574 text_nsect
= NO_SECT
;
2575 lc
= object
->load_commands
;
2576 if(object
->mh
!= NULL
)
2577 ncmds
= object
->mh
->ncmds
;
2579 ncmds
= object
->mh64
->ncmds
;
2580 for(i
= 0; i
< ncmds
; i
++){
2581 if(lc
->cmd
== LC_SEGMENT
){
2582 sg
= (struct segment_command
*)lc
;
2583 nsects
+= sg
->nsects
;
2585 else if(lc
->cmd
== LC_SEGMENT_64
){
2586 sg64
= (struct segment_command_64
*)lc
;
2587 nsects
+= sg64
->nsects
;
2589 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2591 if(object
->mh
!= NULL
){
2592 sections
= allocate(nsects
* sizeof(struct section
*));
2597 sections64
= allocate(nsects
* sizeof(struct section_64
*));
2600 lc
= object
->load_commands
;
2601 for(i
= 0; i
< ncmds
; i
++){
2602 if(lc
->cmd
== LC_SEGMENT
){
2603 sg
= (struct segment_command
*)lc
;
2604 s
= (struct section
*)((char *)sg
+
2605 sizeof(struct segment_command
));
2606 for(j
= 0; j
< sg
->nsects
; j
++){
2607 if(strcmp((s
+ j
)->sectname
, SECT_TEXT
) == 0 &&
2608 strcmp((s
+ j
)->segname
, SEG_TEXT
) == 0)
2609 text_nsect
= nsects
+ 1;
2610 sections
[nsects
++] = s
++;
2613 else if(lc
->cmd
== LC_SEGMENT_64
){
2614 sg64
= (struct segment_command_64
*)lc
;
2615 s64
= (struct section_64
*)((char *)sg64
+
2616 sizeof(struct segment_command_64
));
2617 for(j
= 0; j
< sg64
->nsects
; j
++){
2618 if(strcmp((s64
+ j
)->sectname
, SECT_TEXT
) == 0 &&
2619 strcmp((s64
+ j
)->segname
, SEG_TEXT
) == 0)
2620 text_nsect
= nsects
+ 1;
2621 sections64
[nsects
++] = s64
++;
2624 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2627 for(i
= 0; i
< nsyms
; i
++){
2629 if(object
->mh
!= NULL
){
2630 mh_flags
= object
->mh
->flags
;
2631 n_strx
= symbols
[i
].n_un
.n_strx
;
2632 n_type
= symbols
[i
].n_type
;
2633 n_sect
= symbols
[i
].n_sect
;
2634 if((n_type
& N_TYPE
) == N_SECT
){
2635 if(n_sect
== 0 || n_sect
> nsects
){
2636 error_arch(arch
, member
, "bad n_sect for symbol "
2637 "table entry %d in: ", i
);
2640 s_flags
= sections
[n_sect
- 1]->flags
;
2642 n_desc
= symbols
[i
].n_desc
;
2643 n_value
= symbols
[i
].n_value
;
2646 mh_flags
= object
->mh64
->flags
;
2647 n_strx
= symbols64
[i
].n_un
.n_strx
;
2648 n_type
= symbols64
[i
].n_type
;
2649 n_sect
= symbols64
[i
].n_sect
;
2650 if((n_type
& N_TYPE
) == N_SECT
){
2651 if(n_sect
== 0 || n_sect
> nsects
){
2652 error_arch(arch
, member
, "bad n_sect for symbol "
2653 "table entry %d in: ", i
);
2656 s_flags
= sections64
[n_sect
- 1]->flags
;
2658 n_desc
= symbols64
[i
].n_desc
;
2659 n_value
= symbols64
[i
].n_value
;
2662 if(n_strx
> strsize
){
2663 error_arch(arch
, member
, "bad string index for symbol "
2664 "table entry %d in: ", i
);
2668 if((n_type
& N_TYPE
) == N_INDR
){
2670 if(n_value
> strsize
){
2671 error_arch(arch
, member
, "bad string index for "
2672 "indirect symbol table entry %d in: ", i
);
2677 if((n_type
& N_EXT
) == 0){ /* local symbol */
2680 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2683 saves
[i
] = new_nsyms
;
2686 * For x86_64 .o files we have run ld -r on them and are stuck
2687 * keeping all resulting symbols.
2689 else if(object
->mh
== NULL
&&
2690 object
->mh64
->cputype
== CPU_TYPE_X86_64
&&
2691 object
->mh64
->filetype
== MH_OBJECT
){
2693 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2696 saves
[i
] = new_nsyms
;
2699 * The cases a local symbol might be saved are with -X, -S, -t,
2700 * or with -d filename.
2702 else if((!strip_all
&& (Xflag
|| tflag
|| Sflag
)) || dfile
){
2703 if(n_type
& N_STAB
){ /* debug symbol */
2704 if(dfile
&& n_type
== N_SO
){
2706 basename
= strrchr(strings
+ n_strx
, '/');
2707 if(basename
!= NULL
)
2710 basename
= strings
+ n_strx
;
2711 pp
= bsearch(basename
, debug_filenames
,
2712 ndebug_filenames
, sizeof(char *),
2713 (int (*)(const void *, const void *)
2714 )cmp_bsearch_filename
);
2716 * Save the bracketing N_SO. For each N_SO that
2717 * has a filename there is an N_SO that has a
2718 * name of "" which ends the stabs for that file
2720 if(*basename
!= '\0'){
2728 * This is a bracketing SO so if we are
2729 * currently saving debug symbols save this
2730 * last one and turn off saving debug syms.
2734 new_strsize
+= strlen(strings
+
2738 saves
[i
] = new_nsyms
;
2747 if(saves
[i
] == 0 && (!Sflag
|| save_debug
)){
2749 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2752 saves
[i
] = new_nsyms
;
2755 else{ /* non-debug local symbol */
2756 if(xflag
== 0 && (Sflag
|| Xflag
|| tflag
)){
2758 * No -x (strip all local), and one of -S (strip
2759 * debug), -X (strip 'L' local), or -t (strip
2760 * local except non-'L' text) was given.
2762 if((Xflag
&& n_strx
!= 0 &&
2763 strings
[n_strx
] != 'L') ||
2764 (tflag
&& (n_type
& N_TYPE
) == N_SECT
&&
2765 n_sect
== text_nsect
&& n_strx
!= 0 &&
2766 strings
[n_strx
] != 'L') ||
2767 (Sflag
&& !Xflag
&& !tflag
)) {
2769 * If this file is a for the dynamic linker and
2770 * this symbol is in a section marked so that
2771 * static symbols are stripped then don't
2774 if((mh_flags
& MH_DYLDLINK
) != MH_DYLDLINK
||
2775 (n_type
& N_TYPE
) != N_SECT
||
2776 (s_flags
& S_ATTR_STRIP_STATIC_SYMS
) !=
2777 S_ATTR_STRIP_STATIC_SYMS
){
2778 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2781 saves
[i
] = new_nsyms
;
2786 * Treat a local symbol that was a private extern as if
2787 * were global if it is referenced by a module and save
2790 if((n_type
& N_PEXT
) == N_PEXT
){
2792 private_extern_reference_by_module(
2793 i
, refs
,nextrefsyms
) == TRUE
){
2795 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2798 saves
[i
] = new_nsyms
;
2801 * We need to save symbols that were private externs
2802 * that are used with indirect symbols.
2805 symbol_pointer_used(i
, indirectsyms
,
2806 nindirectsyms
) == TRUE
){
2808 len
= strlen(strings
+ n_strx
) + 1;
2813 saves
[i
] = new_nsyms
;
2819 * Treat a local symbol that was a private extern as if were
2820 * global if it is not referenced by a module.
2822 else if((n_type
& N_PEXT
) == N_PEXT
){
2823 if(saves
[i
] == 0 && sfile
){
2824 sp
= bsearch(strings
+ n_strx
,
2825 save_symbols
, nsave_symbols
,
2826 sizeof(struct symbol_list
),
2827 (int (*)(const void *, const void *))
2828 symbol_list_bsearch
);
2830 if(sp
->sym
== NULL
){
2831 if(object
->mh
!= NULL
)
2832 sp
->sym
= &(symbols
[i
]);
2834 sp
->sym
= &(symbols64
[i
]);
2838 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2841 saves
[i
] = new_nsyms
;
2845 private_extern_reference_by_module(
2846 i
, refs
,nextrefsyms
) == TRUE
){
2848 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2851 saves
[i
] = new_nsyms
;
2854 * We need to save symbols that were private externs that
2855 * are used with indirect symbols.
2858 symbol_pointer_used(i
, indirectsyms
, nindirectsyms
) ==
2861 len
= strlen(strings
+ n_strx
) + 1;
2866 saves
[i
] = new_nsyms
;
2870 else{ /* global symbol */
2872 * strip -R on an x86_64 .o file should do nothing.
2875 (object
->mh
!= NULL
||
2876 object
->mh64
->cputype
!= CPU_TYPE_X86_64
||
2877 object
->mh64
->filetype
!= MH_OBJECT
)){
2878 sp
= bsearch(strings
+ n_strx
,
2879 remove_symbols
, nremove_symbols
,
2880 sizeof(struct symbol_list
),
2881 (int (*)(const void *, const void *))
2882 symbol_list_bsearch
);
2884 if((n_type
& N_TYPE
) == N_UNDF
||
2885 (n_type
& N_TYPE
) == N_PBUD
){
2886 error_arch(arch
, member
, "symbol: %s undefined"
2887 " and can't be stripped from: ",
2890 else if(sp
->sym
!= NULL
){
2891 sym
= (struct nlist
*)sp
->sym
;
2892 if((sym
->n_type
& N_PEXT
) != N_PEXT
)
2893 error_arch(arch
, member
, "more than one symbol "
2894 "for: %s found in: ", sp
->name
);
2897 if(object
->mh
!= NULL
)
2898 sp
->sym
= &(symbols
[i
]);
2900 sp
->sym
= &(symbols64
[i
]);
2903 if(n_desc
& REFERENCED_DYNAMICALLY
){
2904 error_arch(arch
, member
, "symbol: %s is dynamically"
2905 " referenced and can't be stripped "
2906 "from: ", sp
->name
);
2908 if((n_type
& N_TYPE
) == N_SECT
&&
2909 (s_flags
& SECTION_TYPE
) == S_COALESCED
){
2910 error_arch(arch
, member
, "symbol: %s is a global "
2911 "coalesced symbol and can't be "
2912 "stripped from: ", sp
->name
);
2914 /* don't save this symbol */
2918 if(Aflag
&& (n_type
& N_TYPE
) == N_ABS
&&
2921 strncmp(strings
+ n_strx
,
2922 ".objc_class_name_",
2923 sizeof(".objc_class_name_") - 1) == 0))){
2924 len
= strlen(strings
+ n_strx
) + 1;
2926 new_ext_strsize
+= len
;
2929 saves
[i
] = new_nsyms
;
2931 if(saves
[i
] == 0 && (uflag
|| default_dyld_executable
) &&
2932 ((((n_type
& N_TYPE
) == N_UNDF
) &&
2934 (n_type
& N_TYPE
) == N_PBUD
)){
2936 len
= strlen(strings
+ n_strx
) + 1;
2938 new_ext_strsize
+= len
;
2942 saves
[i
] = new_nsyms
;
2944 if(saves
[i
] == 0 && nflag
&&
2945 (n_type
& N_TYPE
) == N_SECT
){
2947 len
= strlen(strings
+ n_strx
) + 1;
2949 new_ext_strsize
+= len
;
2953 saves
[i
] = new_nsyms
;
2955 if(saves
[i
] == 0 && sfile
){
2956 sp
= bsearch(strings
+ n_strx
,
2957 save_symbols
, nsave_symbols
,
2958 sizeof(struct symbol_list
),
2959 (int (*)(const void *, const void *))
2960 symbol_list_bsearch
);
2962 if(sp
->sym
!= NULL
){
2963 sym
= (struct nlist
*)sp
->sym
;
2964 if((sym
->n_type
& N_PEXT
) != N_PEXT
)
2965 error_arch(arch
, member
, "more than one symbol "
2966 "for: %s found in: ", sp
->name
);
2969 if(object
->mh
!= NULL
)
2970 sp
->sym
= &(symbols
[i
]);
2972 sp
->sym
= &(symbols64
[i
]);
2974 len
= strlen(strings
+ n_strx
) + 1;
2976 new_ext_strsize
+= len
;
2977 if((n_type
& N_TYPE
) == N_UNDF
||
2978 (n_type
& N_TYPE
) == N_PBUD
)
2983 saves
[i
] = new_nsyms
;
2988 * We only need to save coalesced symbols that are used as
2989 * indirect symbols in 32-bit applications.
2991 * In 64-bit applications, we only need to save coalesced
2992 * symbols that are used as weak definitions.
2994 if(object
->mh
!= NULL
&&
2996 (n_type
& N_TYPE
) == N_SECT
&&
2997 (s_flags
& SECTION_TYPE
) == S_COALESCED
&&
2998 symbol_pointer_used(i
, indirectsyms
, nindirectsyms
) == TRUE
){
3000 len
= strlen(strings
+ n_strx
) + 1;
3002 new_ext_strsize
+= len
;
3006 saves
[i
] = new_nsyms
;
3009 (n_type
& N_TYPE
) == N_SECT
&&
3010 (n_desc
& N_WEAK_DEF
) != 0){
3012 len
= strlen(strings
+ n_strx
) + 1;
3014 new_ext_strsize
+= len
;
3018 saves
[i
] = new_nsyms
;
3021 ((Xflag
|| Sflag
|| xflag
|| tflag
|| aflag
) ||
3022 ((rflag
|| default_dyld_executable
) &&
3023 n_desc
& REFERENCED_DYNAMICALLY
))){
3024 len
= strlen(strings
+ n_strx
) + 1;
3026 new_ext_strsize
+= len
;
3027 if((n_type
& N_TYPE
) == N_INDR
){
3028 len
= strlen(strings
+ n_value
) + 1;
3030 new_ext_strsize
+= len
;
3032 if((n_type
& N_TYPE
) == N_UNDF
||
3033 (n_type
& N_TYPE
) == N_PBUD
)
3038 saves
[i
] = new_nsyms
;
3041 * For x86_64 .o files we have run ld -r on them and are stuck
3042 * keeping all resulting symbols.
3045 object
->mh
== NULL
&&
3046 object
->mh64
->cputype
== CPU_TYPE_X86_64
&&
3047 object
->mh64
->filetype
== MH_OBJECT
){
3048 len
= strlen(strings
+ n_strx
) + 1;
3050 new_ext_strsize
+= len
;
3051 if((n_type
& N_TYPE
) == N_INDR
){
3052 len
= strlen(strings
+ n_value
) + 1;
3054 new_ext_strsize
+= len
;
3056 if((n_type
& N_TYPE
) == N_UNDF
||
3057 (n_type
& N_TYPE
) == N_PBUD
)
3062 saves
[i
] = new_nsyms
;
3067 * The module table's module names are placed with the external strings.
3068 * So size them and add this to the external string size.
3070 for(i
= 0; i
< nmodtab
; i
++){
3071 if(object
->mh
!= NULL
)
3072 module_name
= mods
[i
].module_name
;
3074 module_name
= mods64
[i
].module_name
;
3075 if(module_name
== 0 || module_name
> strsize
){
3076 error_arch(arch
, member
, "bad string index for module_name "
3077 "of module table entry %d in: ", i
);
3080 len
= strlen(strings
+ module_name
) + 1;
3082 new_ext_strsize
+= len
;
3086 * Updating the reference table may require a symbol not yet listed as
3087 * as saved to be present in the output file. If a defined external
3088 * symbol is removed and there is a undefined reference to it in the
3089 * reference table an undefined symbol needs to be created for it in
3090 * the output file. If this happens the number of new symbols and size
3091 * of the new strings are adjusted. And the array changes[] is set to
3092 * map the old symbol index to the new symbol index for the symbol that
3093 * is changed to an undefined symbol.
3095 missing_symbols
= 0;
3096 if(ref_saves
!= NULL
)
3098 ref_saves
= (int32_t *)allocate(nextrefsyms
* sizeof(int32_t));
3099 bzero(ref_saves
, nextrefsyms
* sizeof(int32_t));
3100 changes
= (uint32_t *)allocate(nsyms
* sizeof(int32_t));
3101 bzero(changes
, nsyms
* sizeof(int32_t));
3102 new_nextrefsyms
= 0;
3103 for(i
= 0; i
< nextrefsyms
; i
++){
3104 if(refs
[i
].isym
> nsyms
){
3105 error_arch(arch
, member
, "bad symbol table index for "
3106 "reference table entry %d in: ", i
);
3109 if(saves
[refs
[i
].isym
]){
3111 ref_saves
[i
] = new_nextrefsyms
;
3114 if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
||
3115 refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
){
3116 if(changes
[refs
[i
].isym
] == 0){
3117 if(object
->mh
!= NULL
)
3118 n_strx
= symbols
[refs
[i
].isym
].n_un
.n_strx
;
3120 n_strx
= symbols64
[refs
[i
].isym
].n_un
.n_strx
;
3121 len
= strlen(strings
+ n_strx
) + 1;
3123 new_ext_strsize
+= len
;
3126 changes
[refs
[i
].isym
] = new_nsyms
;
3128 ref_saves
[i
] = new_nextrefsyms
;
3133 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
||
3134 refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
){
3135 if(missing_symbols
== 0){
3136 error_arch(arch
, member
, "private extern symbols "
3137 "referenced by modules can't be stripped in: ");
3138 missing_symbols
= 1;
3140 if(object
->mh
!= NULL
)
3141 n_strx
= symbols
[refs
[i
].isym
].n_un
.n_strx
;
3143 n_strx
= symbols64
[refs
[i
].isym
].n_un
.n_strx
;
3144 fprintf(stderr
, "%s\n", strings
+ n_strx
);
3145 saves
[refs
[i
].isym
] = -1;
3150 if(missing_symbols
== 1)
3156 for(i
= 0; i
< nsave_symbols
; i
++){
3157 if(save_symbols
[i
].sym
== NULL
){
3158 if(missing_syms
== 0){
3159 error_arch(arch
, member
, "symbols names listed "
3160 "in: %s not in: ", sfile
);
3163 fprintf(stderr
, "%s\n", save_symbols
[i
].name
);
3169 * strip -R on an x86_64 .o file should do nothing.
3172 (object
->mh
!= NULL
||
3173 object
->mh64
->cputype
!= CPU_TYPE_X86_64
||
3174 object
->mh64
->filetype
!= MH_OBJECT
)){
3175 for(i
= 0; i
< nremove_symbols
; i
++){
3176 if(remove_symbols
[i
].sym
== NULL
){
3177 if(missing_syms
== 0){
3178 error_arch(arch
, member
, "symbols names listed "
3179 "in: %s not in: ", Rfile
);
3182 fprintf(stderr
, "%s\n", remove_symbols
[i
].name
);
3189 * If there is a chance that we could end up with an indirect symbol
3190 * with an index of zero we need to avoid that due to a work around
3191 * in the dynamic linker for a bug it is working around that was in
3192 * the old classic static linker. See radar bug 5614542 and the
3193 * related bugs 3685312 and 3534709.
3195 * A reasonable way to do this to know that local symbols are first in
3196 * the symbol table. So if we have any local symbols this won't happen
3197 * and if there are no indirect symbols it will also not happen. Past
3198 * that we'll just add a local symbol so it will end up at symbol index
3199 * zero and avoid any indirect symbol having that index.
3201 * If one really wanted they could build up the new symbol table then
3202 * look at all the indirect symbol table entries to see if any of them
3203 * have an index of zero then in that case throw that new symbol table
3204 * away and rebuild the symbol and string table once again after adding
3205 * a local symbol. This seems not all that resonable to save one symbol
3206 * table entry and a few bytes in the string table for the complexity it
3207 * would add and what it would save.
3209 if(new_nlocalsym
== 0 && nindirectsyms
!= 0){
3210 len
= strlen("radr://5614542") + 1;
3214 hack_5614542
= TRUE
;
3217 hack_5614542
= FALSE
;
3220 if(object
->mh
!= NULL
){
3221 new_symbols
= (struct nlist
*)
3222 allocate(new_nsyms
* sizeof(struct nlist
));
3223 new_symbols64
= NULL
;
3227 new_symbols64
= (struct nlist_64
*)
3228 allocate(new_nsyms
* sizeof(struct nlist_64
));
3230 if(object
->mh
!= NULL
)
3231 new_strsize
= round(new_strsize
, sizeof(int32_t));
3233 new_strsize
= round(new_strsize
, sizeof(int64_t));
3234 new_strings
= (char *)allocate(new_strsize
);
3235 if(object
->mh
!= NULL
){
3236 new_strings
[new_strsize
- 3] = '\0';
3237 new_strings
[new_strsize
- 2] = '\0';
3238 new_strings
[new_strsize
- 1] = '\0';
3241 new_strings
[new_strsize
- 7] = '\0';
3242 new_strings
[new_strsize
- 6] = '\0';
3243 new_strings
[new_strsize
- 5] = '\0';
3244 new_strings
[new_strsize
- 4] = '\0';
3245 new_strings
[new_strsize
- 3] = '\0';
3246 new_strings
[new_strsize
- 2] = '\0';
3247 new_strings
[new_strsize
- 1] = '\0';
3250 memset(new_strings
, '\0', sizeof(int32_t));
3251 p
= new_strings
+ sizeof(int32_t);
3252 q
= p
+ new_ext_strsize
;
3255 * If all strings were stripped set the size to zero but only for 32-bit
3256 * because the unified linker seems to set the filesize of empty .o
3257 * files to include the string table.
3259 if(object
->mh
!= NULL
&& new_strsize
== sizeof(int32_t))
3263 * Now create a symbol table and string table in this order
3266 * external defined symbols
3275 * If we are doing the hack for radar bug 5614542 (see above) add the
3276 * one local symbol and string.
3278 * We use an N_OPT stab which should be safe to use and not mess any
3279 * thing up. In Mac OS X, gcc(1) writes one N_OPT stab saying the file
3280 * is compiled with gcc(1). Then gdb(1) looks for that stab, but it
3281 * also looks at the name. If the name string is "gcc_compiled" or
3282 * "gcc2_compiled" gdb(1) sets its "compiled by gcc flag. If the N_OPT
3283 * is emitted INSIDE an N_SO section, then gdb(1) thinks that object
3284 * module was compiled by Sun's compiler, which apparently sticks one
3285 * outermost N_LBRAC/N_RBRAC pair, which gdb(1) strips off. But if the
3286 * N_OPT comes before any N_SO stabs, then gdb(1) will just ignore it.
3287 * Since this N_OPT is the first local symbol, it will always come
3288 * before any N_SO stabs that might be around and should be fine.
3290 if(hack_5614542
== TRUE
){
3291 if(object
->mh
!= NULL
){
3292 new_symbols
[inew_syms
].n_type
= N_OPT
;
3293 new_symbols
[inew_syms
].n_sect
= NO_SECT
;
3294 new_symbols
[inew_syms
].n_desc
= 0;
3295 new_symbols
[inew_syms
].n_value
= 0x05614542;
3298 new_symbols64
[inew_syms
].n_type
= N_OPT
;
3299 new_symbols64
[inew_syms
].n_sect
= NO_SECT
;
3300 new_symbols64
[inew_syms
].n_desc
= 0;
3301 new_symbols64
[inew_syms
].n_value
= 0x05614542;
3303 strcpy(q
, "radr://5614542");
3304 if(object
->mh
!= NULL
)
3305 new_symbols
[inew_syms
].n_un
.n_strx
=
3308 new_symbols64
[inew_syms
].n_un
.n_strx
=
3314 for(i
= 0; i
< nsyms
; i
++){
3316 if(object
->mh
!= NULL
){
3317 n_strx
= symbols
[i
].n_un
.n_strx
;
3318 n_type
= symbols
[i
].n_type
;
3321 n_strx
= symbols64
[i
].n_un
.n_strx
;
3322 n_type
= symbols64
[i
].n_type
;
3324 if((n_type
& N_EXT
) == 0){
3325 if(object
->mh
!= NULL
)
3326 new_symbols
[inew_syms
] = symbols
[i
];
3328 new_symbols64
[inew_syms
] = symbols64
[i
];
3330 strcpy(q
, strings
+ n_strx
);
3331 if(object
->mh
!= NULL
)
3332 new_symbols
[inew_syms
].n_un
.n_strx
=
3335 new_symbols64
[inew_syms
].n_un
.n_strx
=
3340 saves
[i
] = inew_syms
;
3344 inew_nextdefsym
= inew_syms
;
3345 for(i
= 0; i
< nsyms
; i
++){
3347 if(object
->mh
!= NULL
){
3348 n_strx
= symbols
[i
].n_un
.n_strx
;
3349 n_type
= symbols
[i
].n_type
;
3350 n_value
= symbols
[i
].n_value
;
3353 n_strx
= symbols64
[i
].n_un
.n_strx
;
3354 n_type
= symbols64
[i
].n_type
;
3355 n_value
= symbols64
[i
].n_value
;
3357 if((n_type
& N_EXT
) == N_EXT
&&
3358 ((n_type
& N_TYPE
) != N_UNDF
&&
3359 (n_type
& N_TYPE
) != N_PBUD
)){
3360 if(object
->mh
!= NULL
)
3361 new_symbols
[inew_syms
] = symbols
[i
];
3363 new_symbols64
[inew_syms
] = symbols64
[i
];
3365 strcpy(p
, strings
+ n_strx
);
3366 if(object
->mh
!= NULL
)
3367 new_symbols
[inew_syms
].n_un
.n_strx
=
3370 new_symbols64
[inew_syms
].n_un
.n_strx
=
3374 if((n_type
& N_TYPE
) == N_INDR
){
3376 strcpy(p
, strings
+ n_value
);
3377 if(object
->mh
!= NULL
)
3378 new_symbols
[inew_syms
].n_value
=
3381 new_symbols64
[inew_syms
].n_value
=
3387 saves
[i
] = inew_syms
;
3392 * Build the new undefined symbols into a map and sort it.
3395 if(object
->mh
!= NULL
){
3396 undef_map
= (struct undef_map
*)allocate(new_nundefsym
*
3397 sizeof(struct undef_map
));
3402 undef_map64
= (struct undef_map64
*)allocate(new_nundefsym
*
3403 sizeof(struct undef_map64
));
3405 for(i
= 0; i
< nsyms
; i
++){
3407 if(object
->mh
!= NULL
){
3408 n_strx
= symbols
[i
].n_un
.n_strx
;
3409 n_type
= symbols
[i
].n_type
;
3412 n_strx
= symbols64
[i
].n_un
.n_strx
;
3413 n_type
= symbols64
[i
].n_type
;
3415 if((n_type
& N_EXT
) == N_EXT
&&
3416 ((n_type
& N_TYPE
) == N_UNDF
||
3417 (n_type
& N_TYPE
) == N_PBUD
)){
3418 if(object
->mh
!= NULL
)
3419 undef_map
[inew_undefsyms
].symbol
= symbols
[i
];
3421 undef_map64
[inew_undefsyms
].symbol64
= symbols64
[i
];
3423 strcpy(p
, strings
+ n_strx
);
3424 if(object
->mh
!= NULL
)
3425 undef_map
[inew_undefsyms
].symbol
.n_un
.n_strx
=
3428 undef_map64
[inew_undefsyms
].symbol64
.n_un
.n_strx
=
3432 if(object
->mh
!= NULL
)
3433 undef_map
[inew_undefsyms
].index
= i
;
3435 undef_map64
[inew_undefsyms
].index
= i
;
3440 for(i
= 0; i
< nsyms
; i
++){
3442 if(object
->mh
!= NULL
)
3443 n_strx
= symbols
[i
].n_un
.n_strx
;
3445 n_strx
= symbols64
[i
].n_un
.n_strx
;
3447 strcpy(p
, strings
+ n_strx
);
3448 if(object
->mh
!= NULL
)
3449 undef_map
[inew_undefsyms
].symbol
.n_un
.n_strx
=
3452 undef_map64
[inew_undefsyms
].symbol64
.n_un
.n_strx
=
3456 if(object
->mh
!= NULL
){
3457 undef_map
[inew_undefsyms
].symbol
.n_type
= N_UNDF
| N_EXT
;
3458 undef_map
[inew_undefsyms
].symbol
.n_sect
= NO_SECT
;
3459 undef_map
[inew_undefsyms
].symbol
.n_desc
= 0;
3460 undef_map
[inew_undefsyms
].symbol
.n_value
= 0;
3461 undef_map
[inew_undefsyms
].index
= i
;
3464 undef_map64
[inew_undefsyms
].symbol64
.n_type
= N_UNDF
|N_EXT
;
3465 undef_map64
[inew_undefsyms
].symbol64
.n_sect
= NO_SECT
;
3466 undef_map64
[inew_undefsyms
].symbol64
.n_desc
= 0;
3467 undef_map64
[inew_undefsyms
].symbol64
.n_value
= 0;
3468 undef_map64
[inew_undefsyms
].index
= i
;
3473 /* Sort the undefined symbols by name */
3474 qsort_strings
= new_strings
;
3475 if(object
->mh
!= NULL
)
3476 qsort(undef_map
, new_nundefsym
, sizeof(struct undef_map
),
3477 (int (*)(const void *, const void *))cmp_qsort_undef_map
);
3479 qsort(undef_map64
, new_nundefsym
, sizeof(struct undef_map64
),
3480 (int (*)(const void *, const void *))cmp_qsort_undef_map_64
);
3481 /* Copy the symbols now in sorted order into new_symbols */
3482 for(i
= 0; i
< new_nundefsym
; i
++){
3483 if(object
->mh
!= NULL
){
3484 new_symbols
[inew_syms
] = undef_map
[i
].symbol
;
3486 saves
[undef_map
[i
].index
] = inew_syms
;
3489 new_symbols64
[inew_syms
] = undef_map64
[i
].symbol64
;
3491 saves
[undef_map64
[i
].index
] = inew_syms
;
3496 * Fixup the module table's module name strings adding them to the
3497 * string table. Also fix the indexes into the symbol table for
3498 * external and local symbols. And fix up the indexes into the
3501 for(i
= 0; i
< nmodtab
; i
++){
3502 if(object
->mh
!= NULL
){
3503 strcpy(p
, strings
+ mods
[i
].module_name
);
3504 mods
[i
].module_name
= p
- new_strings
;
3505 iextdefsym
= mods
[i
].iextdefsym
;
3506 nextdefsym
= mods
[i
].nextdefsym
;
3507 ilocalsym
= mods
[i
].ilocalsym
;
3508 nlocalsym
= mods
[i
].nlocalsym
;
3509 irefsym
= mods
[i
].irefsym
;
3510 nrefsym
= mods
[i
].nrefsym
;
3513 strcpy(p
, strings
+ mods64
[i
].module_name
);
3514 mods64
[i
].module_name
= p
- new_strings
;
3515 iextdefsym
= mods64
[i
].iextdefsym
;
3516 nextdefsym
= mods64
[i
].nextdefsym
;
3517 ilocalsym
= mods64
[i
].ilocalsym
;
3518 nlocalsym
= mods64
[i
].nlocalsym
;
3519 irefsym
= mods64
[i
].irefsym
;
3520 nrefsym
= mods64
[i
].nrefsym
;
3524 if(iextdefsym
> nsyms
){
3525 error_arch(arch
, member
, "bad index into externally defined "
3526 "symbols of module table entry %d in: ", i
);
3529 if(iextdefsym
+ nextdefsym
> nsyms
){
3530 error_arch(arch
, member
, "bad number of externally defined "
3531 "symbols of module table entry %d in: ", i
);
3534 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
3535 if(saves
[j
] != 0 && changes
[j
] == 0)
3539 for(k
= j
; k
< iextdefsym
+ nextdefsym
; k
++){
3540 if(saves
[k
] != 0 && changes
[k
] == 0)
3544 if(object
->mh
!= NULL
){
3545 mods
[i
].iextdefsym
= 0;
3546 mods
[i
].nextdefsym
= 0;
3549 mods64
[i
].iextdefsym
= 0;
3550 mods64
[i
].nextdefsym
= 0;
3554 if(object
->mh
!= NULL
){
3555 mods
[i
].iextdefsym
= saves
[j
] - 1;
3556 mods
[i
].nextdefsym
= n
;
3559 mods64
[i
].iextdefsym
= saves
[j
] - 1;
3560 mods64
[i
].nextdefsym
= n
;
3564 if(ilocalsym
> nsyms
){
3565 error_arch(arch
, member
, "bad index into symbols for local "
3566 "symbols of module table entry %d in: ", i
);
3569 if(ilocalsym
+ nlocalsym
> nsyms
){
3570 error_arch(arch
, member
, "bad number of local "
3571 "symbols of module table entry %d in: ", i
);
3574 for(j
= ilocalsym
; j
< ilocalsym
+ nlocalsym
; j
++){
3579 for(k
= j
; k
< ilocalsym
+ nlocalsym
; k
++){
3584 if(object
->mh
!= NULL
){
3585 mods
[i
].ilocalsym
= 0;
3586 mods
[i
].nlocalsym
= 0;
3589 mods64
[i
].ilocalsym
= 0;
3590 mods64
[i
].nlocalsym
= 0;
3594 if(object
->mh
!= NULL
){
3595 mods
[i
].ilocalsym
= saves
[j
] - 1;
3596 mods
[i
].nlocalsym
= n
;
3599 mods64
[i
].ilocalsym
= saves
[j
] - 1;
3600 mods64
[i
].nlocalsym
= n
;
3604 if(irefsym
> nextrefsyms
){
3605 error_arch(arch
, member
, "bad index into reference table "
3606 "of module table entry %d in: ", i
);
3609 if(irefsym
+ nrefsym
> nextrefsyms
){
3610 error_arch(arch
, member
, "bad number of reference table "
3611 "entries of module table entry %d in: ", i
);
3614 for(j
= irefsym
; j
< irefsym
+ nrefsym
; j
++){
3615 if(ref_saves
[j
] != 0)
3619 for(k
= j
; k
< irefsym
+ nrefsym
; k
++){
3620 if(ref_saves
[k
] != 0)
3624 if(object
->mh
!= NULL
){
3625 mods
[i
].irefsym
= 0;
3626 mods
[i
].nrefsym
= 0;
3629 mods64
[i
].irefsym
= 0;
3630 mods64
[i
].nrefsym
= 0;
3634 if(object
->mh
!= NULL
){
3635 mods
[i
].irefsym
= ref_saves
[j
] - 1;
3636 mods
[i
].nrefsym
= n
;
3639 mods64
[i
].irefsym
= ref_saves
[j
] - 1;
3640 mods64
[i
].nrefsym
= n
;
3646 * Create a new reference table.
3648 new_refs
= allocate(new_nextrefsyms
* sizeof(struct dylib_reference
));
3650 for(i
= 0; i
< nextrefsyms
; i
++){
3652 if(saves
[refs
[i
].isym
]){
3653 new_refs
[j
].isym
= saves
[refs
[i
].isym
] - 1;
3654 new_refs
[j
].flags
= refs
[i
].flags
;
3657 if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
||
3658 refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
){
3659 new_refs
[j
].isym
= changes
[refs
[i
].isym
] - 1;
3660 new_refs
[j
].flags
= refs
[i
].flags
;
3668 * Create a new dylib table of contents.
3671 for(i
= 0; i
< ntoc
; i
++){
3672 if(tocs
[i
].symbol_index
>= nsyms
){
3673 error_arch(arch
, member
, "bad symbol index for table of "
3674 "contents table entry %d in: ", i
);
3677 if(saves
[tocs
[i
].symbol_index
] != 0 &&
3678 changes
[tocs
[i
].symbol_index
] == 0)
3681 new_tocs
= allocate(new_ntoc
* sizeof(struct dylib_table_of_contents
));
3683 for(i
= 0; i
< ntoc
; i
++){
3684 if(saves
[tocs
[i
].symbol_index
] != 0 &&
3685 changes
[tocs
[i
].symbol_index
] == 0){
3686 new_tocs
[j
].symbol_index
= saves
[tocs
[i
].symbol_index
] - 1;
3687 new_tocs
[j
].module_index
= tocs
[i
].module_index
;
3693 * Update the export trie if it has one but only call the the
3694 * prune_trie() routine when we are removing global symbols as is
3695 * done with default stripping of a dyld executable or with the -s
3698 if(object
->dyld_info
!= NULL
&&
3699 object
->dyld_info
->export_size
!= 0 &&
3700 (default_dyld_executable
|| sfile
!= NULL
|| Rfile
!= NULL
)){
3701 const char *error_string
;
3702 uint32_t trie_new_size
;
3704 error_string
= prune_trie((uint8_t *)(object
->object_addr
+
3705 object
->dyld_info
->export_off
),
3706 object
->dyld_info
->export_size
,
3709 if(error_string
!= NULL
){
3710 error_arch(arch
, member
, "%s", error_string
);
3714 #endif /* TRIE_SUPPORT */
3716 if(undef_map
!= NULL
)
3718 if(undef_map64
!= NULL
)
3722 if(sections
!= NULL
)
3724 if(sections64
!= NULL
)
3735 * prune() is called by prune_trie() and passed a name of an external symbol
3736 * in the trie. It returns 1 if the symbols is to be pruned out and 0 if the
3737 * symbol is to be kept.
3739 * Note that it may seem like a linear search of the new symbols would not be
3740 * the best approach but in 10.6 the only defined global symbol left in a
3741 * stripped executable is __mh_execute_header and new_nextdefsym is usually 1
3742 * so this never actually loops in practice.
3751 for(i
= 0; i
< new_nextdefsym
; i
++){
3752 if(new_symbols
!= NULL
){
3753 if(strcmp(name
, new_strings
+ new_symbols
[inew_nextdefsym
+ i
]
3758 if(strcmp(name
, new_strings
+ new_symbols64
[inew_nextdefsym
+ i
]
3765 #endif /* TRIE_SUPPORT */
3768 * make_ld_r_object() takes the object file contents referenced by the passed
3769 * data structures, writes that to a temporary file, runs "ld -r" plus the
3770 * specified stripping option creating a second temporary file, reads that file
3771 * in and replaces the object file contents with that and resets the variables
3772 * pointing to the symbol, string and indirect tables.
3778 struct member
*member
,
3779 struct object
*object
)
3781 enum byte_sex host_byte_sex
;
3782 char *input_file
, *output_file
;
3784 struct ofile
*ld_r_ofile
;
3785 struct arch
*ld_r_archs
;
3786 uint32_t ld_r_narchs
, save_errors
;
3788 host_byte_sex
= get_host_byte_sex();
3791 * Swap the object file back into its bytesex before writing it to the
3792 * temporary file if needed.
3794 if(object
->object_byte_sex
!= host_byte_sex
){
3795 if(object
->mh
!= NULL
){
3796 if(swap_object_headers(object
->mh
, object
->load_commands
) ==
3798 fatal("internal error: swap_object_headers() failed");
3799 swap_nlist(symbols
, nsyms
, object
->object_byte_sex
);
3802 if(swap_object_headers(object
->mh64
, object
->load_commands
) ==
3804 fatal("internal error: swap_object_headers() failed");
3805 swap_nlist_64(symbols64
, nsyms
, object
->object_byte_sex
);
3807 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
3808 object
->object_byte_sex
);
3812 * Create an input object file for the ld -r command from the bytes
3813 * of this arch's object file.
3815 input_file
= makestr("/tmp/strip.XXXXXX", NULL
);
3816 input_file
= mktemp(input_file
);
3818 if((fd
= open(input_file
, O_WRONLY
|O_CREAT
, 0600)) < 0)
3819 system_fatal("can't open temporary file: %s", input_file
);
3821 if(write(fd
, object
->object_addr
, object
->object_size
) !=
3822 object
->object_size
)
3823 system_fatal("can't write temporary file: %s", input_file
);
3826 system_fatal("can't close temporary file: %s", input_file
);
3829 * Create a temporary name for the output file of the ld -r
3831 output_file
= makestr("/tmp/strip.XXXXXX", NULL
);
3832 output_file
= mktemp(output_file
);
3835 * Create the ld -r command line and execute it.
3837 reset_execute_list();
3838 add_execute_list("ld");
3839 add_execute_list("-keep_private_externs");
3840 add_execute_list("-r");
3842 add_execute_list("-S");
3844 add_execute_list("-x");
3845 add_execute_list(input_file
);
3846 add_execute_list("-o");
3847 add_execute_list(output_file
);
3849 add_execute_list("-x");
3850 add_execute_list("-exported_symbols_list");
3851 add_execute_list(sfile
);
3854 add_execute_list("-unexported_symbols_list");
3855 add_execute_list(Rfile
);
3857 if(execute_list(vflag
) == 0)
3858 fatal("internal link edit command failed");
3860 save_errors
= errors
;
3862 /* breakout the output file of the ld -f for processing */
3863 ld_r_ofile
= breakout(output_file
, &ld_r_archs
, &ld_r_narchs
, FALSE
);
3865 goto make_ld_r_object_cleanup
;
3867 /* checkout the file for symbol table replacement processing */
3868 checkout(ld_r_archs
, ld_r_narchs
);
3871 * Make sure the output of the ld -r is an object file with one arch.
3873 if(ld_r_narchs
!= 1 ||
3874 ld_r_archs
->type
!= OFILE_Mach_O
||
3875 ld_r_archs
->object
== NULL
||
3876 ld_r_archs
->object
->mh_filetype
!= MH_OBJECT
)
3877 fatal("internal link edit command failed to produce a thin Mach-O "
3881 * Now reset all the data of the input object with the ld -r output
3884 nsyms
= ld_r_archs
->object
->st
->nsyms
;
3885 if(ld_r_archs
->object
->mh
!= NULL
){
3886 symbols
= (struct nlist
*)
3887 (ld_r_archs
->object
->object_addr
+
3888 ld_r_archs
->object
->st
->symoff
);
3889 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3890 swap_nlist(symbols
, nsyms
, host_byte_sex
);
3895 symbols64
= (struct nlist_64
*)
3896 (ld_r_archs
->object
->object_addr
+
3897 ld_r_archs
->object
->st
->symoff
);
3898 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3899 swap_nlist_64(symbols64
, nsyms
, host_byte_sex
);
3901 strings
= ld_r_archs
->object
->object_addr
+
3902 ld_r_archs
->object
->st
->stroff
;
3903 strsize
= ld_r_archs
->object
->st
->strsize
;
3905 if(ld_r_archs
->object
->dyst
!= NULL
&&
3906 ld_r_archs
->object
->dyst
->nindirectsyms
!= 0){
3907 nindirectsyms
= ld_r_archs
->object
->dyst
->nindirectsyms
;
3908 indirectsyms
= (uint32_t *)
3909 (ld_r_archs
->object
->object_addr
+
3910 ld_r_archs
->object
->dyst
->indirectsymoff
);
3911 if(ld_r_archs
->object
->object_byte_sex
!= host_byte_sex
)
3912 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
3916 indirectsyms
= NULL
;
3920 if(ld_r_archs
->object
->mh
!= NULL
)
3921 ld_r_archs
->object
->input_sym_info_size
=
3922 nsyms
* sizeof(struct nlist
) +
3925 ld_r_archs
->object
->input_sym_info_size
=
3926 nsyms
* sizeof(struct nlist_64
) +
3930 * Copy over the object struct from the ld -r object file onto the
3931 * input object file.
3933 *object
= *ld_r_archs
->object
;
3936 * Save the ofile struct for the ld -r output so it can be umapped when
3937 * we are done. And free up the ld_r_archs now that we are done with
3940 object
->ld_r_ofile
= ld_r_ofile
;
3941 free_archs(ld_r_archs
, ld_r_narchs
);
3943 make_ld_r_object_cleanup
:
3944 errors
+= save_errors
;
3946 * Remove the input and output files and clean up.
3948 if(unlink(input_file
) == -1)
3949 system_fatal("can't remove temporary file: %s", input_file
);
3950 if(unlink(output_file
) == -1)
3951 system_fatal("can't remove temporary file: %s", output_file
);
3957 * strip_LC_UUID_commands() is called when -no_uuid is specified to remove any
3958 * LC_UUID load commands from the object's load commands.
3962 strip_LC_UUID_commands(
3964 struct member
*member
,
3965 struct object
*object
)
3967 uint32_t i
, ncmds
, nuuids
, mh_sizeofcmds
, sizeofcmds
;
3968 struct load_command
*lc1
, *lc2
, *new_load_commands
;
3969 struct segment_command
*sg
;
3972 * See if there are any LC_UUID load commands.
3975 lc1
= arch
->object
->load_commands
;
3976 if(arch
->object
->mh
!= NULL
){
3977 ncmds
= arch
->object
->mh
->ncmds
;
3978 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
3981 ncmds
= arch
->object
->mh64
->ncmds
;
3982 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
3984 for(i
= 0; i
< ncmds
; i
++){
3985 if(lc1
->cmd
== LC_UUID
){
3988 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
3990 /* if no LC_UUID load commands just return */
3995 * Allocate space for the new load commands as zero it out so any holes
3996 * will be zero bytes.
3998 new_load_commands
= allocate(mh_sizeofcmds
);
3999 memset(new_load_commands
, '\0', mh_sizeofcmds
);
4002 * Copy all the load commands except the LC_UUID load commands into the
4003 * allocated space for the new load commands.
4005 lc1
= arch
->object
->load_commands
;
4006 lc2
= new_load_commands
;
4008 for(i
= 0; i
< ncmds
; i
++){
4009 if(lc1
->cmd
!= LC_UUID
){
4010 memcpy(lc2
, lc1
, lc1
->cmdsize
);
4011 sizeofcmds
+= lc2
->cmdsize
;
4012 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
4014 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4018 * Finally copy the updated load commands over the existing load
4021 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
4022 if(mh_sizeofcmds
> sizeofcmds
){
4023 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
4024 (mh_sizeofcmds
- sizeofcmds
));
4027 if(arch
->object
->mh
!= NULL
) {
4028 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
4029 arch
->object
->mh
->ncmds
= ncmds
;
4031 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
4032 arch
->object
->mh64
->ncmds
= ncmds
;
4034 free(new_load_commands
);
4036 /* reset the pointers into the load commands */
4037 lc1
= arch
->object
->load_commands
;
4038 for(i
= 0; i
< ncmds
; i
++){
4041 arch
->object
->st
= (struct symtab_command
*)lc1
;
4044 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
4046 case LC_TWOLEVEL_HINTS
:
4047 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
4049 case LC_PREBIND_CKSUM
:
4050 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
4053 sg
= (struct segment_command
*)lc1
;
4054 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
4055 arch
->object
->seg_linkedit
= sg
;
4057 case LC_SEGMENT_SPLIT_INFO
:
4058 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
4060 case LC_CODE_SIGNATURE
:
4061 object
->code_sig_cmd
= (struct linkedit_data_command
*)lc1
;
4063 case LC_DYLD_INFO_ONLY
:
4065 object
->dyld_info
= (struct dyld_info_command
*)lc1
;
4067 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4073 * strip_LC_CODE_SIGNATURE_commands() is called when -c is specified to remove
4074 * any LC_CODE_SIGNATURE load commands from the object's load commands.
4078 strip_LC_CODE_SIGNATURE_commands(
4080 struct member
*member
,
4081 struct object
*object
)
4083 uint32_t i
, ncmds
, mh_sizeofcmds
, sizeofcmds
;
4084 struct load_command
*lc1
, *lc2
, *new_load_commands
;
4085 struct segment_command
*sg
;
4088 * See if there is an LC_CODE_SIGNATURE load command and if no command
4091 if(object
->code_sig_cmd
== NULL
)
4095 * Allocate space for the new load commands and zero it out so any holes
4096 * will be zero bytes.
4098 if(arch
->object
->mh
!= NULL
){
4099 ncmds
= arch
->object
->mh
->ncmds
;
4100 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
4103 ncmds
= arch
->object
->mh64
->ncmds
;
4104 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
4106 new_load_commands
= allocate(mh_sizeofcmds
);
4107 memset(new_load_commands
, '\0', mh_sizeofcmds
);
4110 * Copy all the load commands except the LC_CODE_SIGNATURE load commands
4111 * into the allocated space for the new load commands.
4113 lc1
= arch
->object
->load_commands
;
4114 lc2
= new_load_commands
;
4116 for(i
= 0; i
< ncmds
; i
++){
4117 if(lc1
->cmd
!= LC_CODE_SIGNATURE
){
4118 memcpy(lc2
, lc1
, lc1
->cmdsize
);
4119 sizeofcmds
+= lc2
->cmdsize
;
4120 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
4122 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4126 * Finally copy the updated load commands over the existing load
4129 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
4130 if(mh_sizeofcmds
> sizeofcmds
){
4131 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
4132 (mh_sizeofcmds
- sizeofcmds
));
4135 if(arch
->object
->mh
!= NULL
) {
4136 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
4137 arch
->object
->mh
->ncmds
= ncmds
;
4139 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
4140 arch
->object
->mh64
->ncmds
= ncmds
;
4142 free(new_load_commands
);
4144 /* reset the pointers into the load commands */
4145 object
->code_sig_cmd
= NULL
;
4146 lc1
= arch
->object
->load_commands
;
4147 for(i
= 0; i
< ncmds
; i
++){
4150 arch
->object
->st
= (struct symtab_command
*)lc1
;
4153 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
4155 case LC_TWOLEVEL_HINTS
:
4156 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
4158 case LC_PREBIND_CKSUM
:
4159 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
4162 sg
= (struct segment_command
*)lc1
;
4163 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
4164 arch
->object
->seg_linkedit
= sg
;
4166 case LC_SEGMENT_SPLIT_INFO
:
4167 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
4170 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
4175 * To get the right amount of the file copied out by writeout() for
4176 * the case when we are stripping out the section contents we
4177 * already reduce the object size by the size of the section
4178 * contents including the padding after the load commands. So here
4179 * we need to further reduce it by the load command for the
4180 * LC_CODE_SIGNATURE (a struct linkedit_data_command) we are
4183 object
->object_size
-= sizeof(struct linkedit_data_command
);
4185 * Then this size minus the size of the input symbolic information
4186 * is what is copied out from the file by writeout(). Which in this
4187 * case is just the new headers.
4191 * Finally for -c the file offset to the link edit information is to
4192 * be right after the load commands. So reset this for the updated
4193 * size of the load commands without the LC_CODE_SIGNATURE.
4195 if(object
->mh
!= NULL
)
4196 object
->seg_linkedit
->fileoff
= sizeof(struct mach_header
) +
4199 object
->seg_linkedit64
->fileoff
=
4200 sizeof(struct mach_header_64
) + sizeofcmds
;
4203 #endif /* !(NMEDIT) */
4206 * private_extern_reference_by_module() is passed a symbol_index of a private
4207 * extern symbol and the module table. If the symbol_index appears in the
4208 * module symbol table this returns TRUE else it returns FALSE.
4212 private_extern_reference_by_module(
4213 uint32_t symbol_index
,
4214 struct dylib_reference
*refs
,
4215 uint32_t nextrefsyms
)
4219 for(i
= 0; i
< nextrefsyms
; i
++){
4220 if(refs
[i
].isym
== symbol_index
){
4221 if(refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
||
4222 refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
){
4231 * symbol_pointer_used() is passed a symbol_index and the indirect table. If
4232 * the symbol_index appears in the indirect symbol table this returns TRUE else
4237 symbol_pointer_used(
4238 uint32_t symbol_index
,
4239 uint32_t *indirectsyms
,
4240 uint32_t nindirectsyms
)
4244 for(i
= 0; i
< nindirectsyms
; i
++){
4245 if(indirectsyms
[i
] == symbol_index
)
4252 * Function for qsort for comparing undefined map entries.
4256 cmp_qsort_undef_map(
4257 const struct undef_map
*sym1
,
4258 const struct undef_map
*sym2
)
4260 return(strcmp(qsort_strings
+ sym1
->symbol
.n_un
.n_strx
,
4261 qsort_strings
+ sym2
->symbol
.n_un
.n_strx
));
4266 cmp_qsort_undef_map_64(
4267 const struct undef_map64
*sym1
,
4268 const struct undef_map64
*sym2
)
4270 return(strcmp(qsort_strings
+ sym1
->symbol64
.n_un
.n_strx
,
4271 qsort_strings
+ sym2
->symbol64
.n_un
.n_strx
));
4273 #endif /* !defined(NMEDIT) */
4277 * Function for qsort for comparing object names.
4285 return(strcmp(*name1
, *name2
));
4289 * Function for bsearch for finding a object name.
4293 cmp_bsearch_filename(
4297 return(strcmp(name1
, *name2
));
4299 #endif /* !defined(NMEDIT) */
4306 struct member
*member
,
4307 struct object
*object
,
4308 struct nlist
*symbols
,
4309 struct nlist_64
*symbols64
,
4313 struct dylib_table_of_contents
*tocs
,
4315 struct dylib_module
*mods
,
4316 struct dylib_module_64
*mods64
,
4318 struct dylib_reference
*refs
,
4319 uint32_t nextrefsyms
)
4322 unsigned char data_n_sect
, nsects
;
4323 struct load_command
*lc
;
4324 struct segment_command
*sg
;
4325 struct segment_command_64
*sg64
;
4326 struct section
*s
, **sections
;
4327 struct section_64
*s64
, **sections64
;
4329 uint32_t missing_syms
;
4330 struct symbol_list
*sp
;
4331 struct nlist
**global_symbol
;
4332 struct nlist_64
**global_symbol64
;
4333 enum bool global_symbol_found
;
4334 char *global_name
, save_char
;
4335 enum bool dwarf_debug_map
;
4336 enum byte_sex host_byte_sex
;
4337 int32_t missing_reloc_symbols
;
4338 enum bool edit_symtab_return
;
4341 uint32_t new_ext_strsize
, len
, inew_syms
;
4343 struct nlist
**changed_globals
;
4344 struct nlist_64
**changed_globals64
;
4345 uint32_t nchanged_globals
;
4346 uint32_t ncmds
, s_flags
, n_strx
, module_name
, ilocalsym
, nlocalsym
;
4347 uint32_t iextdefsym
, nextdefsym
;
4348 uint8_t n_type
, n_sect
, global_symbol_n_sect
;
4350 enum bool warned_about_global_coalesced_symbols
;
4352 edit_symtab_return
= TRUE
;
4353 host_byte_sex
= get_host_byte_sex();
4354 missing_reloc_symbols
= 0;
4355 warned_about_global_coalesced_symbols
= FALSE
;
4359 nmedits
= allocate(nsyms
* sizeof(enum bool));
4360 for(i
= 0; i
< nsyms
; i
++)
4364 * If nmedit is operating on a dynamic library then symbols are turned
4365 * into private externs with the extern bit off not into static symbols.
4367 if(object
->mh_filetype
== MH_DYLIB
&& pflag
== TRUE
){
4368 error_arch(arch
, member
, "can't use -p with dynamic libraries");
4373 * As part of the MAJOR guess for the second pass to fix stabs for the
4374 * globals symbols that get turned into non-global symbols. We need to
4375 * change the stabs. To do this we to know if a N_GSYM is for a data
4376 * symbol or not to know to turn it into an N_STSYM or a N_FUN.
4377 * This logic as determined by compiling test cases with and without
4378 * the key word 'static' and looking at the difference between the STABS
4379 * the compiler generates and trying to match that here.
4381 * We also use this loop and the next to gather an array of section
4382 * struct pointers so we can later determine if we run into a global
4383 * symbol in a coalesced section and not turn those symbols into
4389 data_n_sect
= NO_SECT
;
4390 lc
= object
->load_commands
;
4391 if(object
->mh
!= NULL
)
4392 ncmds
= object
->mh
->ncmds
;
4394 ncmds
= object
->mh64
->ncmds
;
4395 for(i
= 0; i
< ncmds
; i
++){
4396 if(lc
->cmd
== LC_SEGMENT
){
4397 sg
= (struct segment_command
*)lc
;
4398 s
= (struct section
*)((char *)sg
+
4399 sizeof(struct segment_command
));
4400 nsects
+= sg
->nsects
;
4401 for(j
= 0; j
< sg
->nsects
; j
++){
4402 if(strcmp(s
->segname
, SEG_DATA
) == 0 &&
4403 strcmp(s
->sectname
, SECT_DATA
) == 0 &&
4404 data_n_sect
== NO_SECT
){
4405 data_n_sect
= n_sect
;
4412 else if(lc
->cmd
== LC_SEGMENT_64
){
4413 sg64
= (struct segment_command_64
*)lc
;
4414 s64
= (struct section_64
*)((char *)sg64
+
4415 sizeof(struct segment_command_64
));
4416 nsects
+= sg64
->nsects
;
4417 for(j
= 0; j
< sg64
->nsects
; j
++){
4418 if(strcmp(s64
->segname
, SEG_DATA
) == 0 &&
4419 strcmp(s64
->sectname
, SECT_DATA
) == 0 &&
4420 data_n_sect
== NO_SECT
){
4421 data_n_sect
= n_sect
;
4428 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
4430 if(object
->mh
!= NULL
){
4431 sections
= allocate(nsects
* sizeof(struct section
*));
4436 sections64
= allocate(nsects
* sizeof(struct section_64
*));
4439 lc
= object
->load_commands
;
4440 for(i
= 0; i
< ncmds
; i
++){
4441 if(lc
->cmd
== LC_SEGMENT
){
4442 sg
= (struct segment_command
*)lc
;
4443 s
= (struct section
*)((char *)sg
+
4444 sizeof(struct segment_command
));
4445 for(j
= 0; j
< sg
->nsects
; j
++){
4446 sections
[nsects
++] = s
++;
4449 else if(lc
->cmd
== LC_SEGMENT_64
){
4450 sg64
= (struct segment_command_64
*)lc
;
4451 s64
= (struct section_64
*)((char *)sg64
+
4452 sizeof(struct segment_command_64
));
4453 for(j
= 0; j
< sg64
->nsects
; j
++){
4454 sections64
[nsects
++] = s64
++;
4457 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
4461 * Zero out the saved symbols so they can be recorded for this file.
4463 for(i
= 0; i
< nsave_symbols
; i
++)
4464 save_symbols
[i
].sym
= NULL
;
4465 for(i
= 0; i
< nremove_symbols
; i
++)
4466 remove_symbols
[i
].sym
= NULL
;
4468 for(i
= 0; i
< nsave_symbols
; i
++)
4469 save_symbols
[i
].seen
= FALSE
;
4470 for(i
= 0; i
< nremove_symbols
; i
++)
4471 remove_symbols
[i
].seen
= FALSE
;
4474 nchanged_globals
= 0;
4475 if(object
->mh
!= NULL
){
4476 changed_globals
= allocate(nsyms
* sizeof(struct nlist
*));
4477 changed_globals64
= NULL
;
4478 for(i
= 0; i
< nsyms
; i
++)
4479 changed_globals
[i
] = NULL
;
4482 changed_globals
= NULL
;
4483 changed_globals64
= allocate(nsyms
* sizeof(struct nlist_64
*));
4484 for(i
= 0; i
< nsyms
; i
++)
4485 changed_globals64
[i
] = NULL
;
4489 * These are the variables for the new symbol table and new string
4490 * table. Since this routine only turns globals into non-globals the
4491 * number of symbols does not change. But the count of local, defined
4492 * external symbols does change.
4499 new_strsize
= sizeof(int32_t);
4500 new_ext_strsize
= 0;
4503 * First pass: turn the globals symbols into non-global symbols.
4505 for(i
= 0; i
< nsyms
; i
++){
4508 if(object
->mh
!= NULL
){
4509 n_strx
= symbols
[i
].n_un
.n_strx
;
4510 n_type
= symbols
[i
].n_type
;
4511 n_sect
= symbols
[i
].n_sect
;
4512 if((n_type
& N_TYPE
) == N_SECT
)
4513 s_flags
= sections
[n_sect
- 1]->flags
;
4514 n_value
= symbols
[i
].n_value
;
4517 n_strx
= symbols64
[i
].n_un
.n_strx
;
4518 n_type
= symbols64
[i
].n_type
;
4519 n_sect
= symbols64
[i
].n_sect
;
4520 if((n_type
& N_TYPE
) == N_SECT
)
4521 s_flags
= sections64
[n_sect
- 1]->flags
;
4522 n_value
= symbols64
[i
].n_value
;
4525 if(n_strx
> strsize
){
4526 error_arch(arch
, member
, "bad string index for symbol "
4527 "table entry %u in: ", i
);
4530 len
= strlen(strings
+ n_strx
) + 1;
4533 if((n_type
& N_TYPE
) != N_UNDF
&&
4534 (n_type
& N_TYPE
) != N_PBUD
){
4535 if((n_type
& N_TYPE
) == N_SECT
){
4536 if(n_sect
> nsects
){
4537 error_arch(arch
, member
, "bad n_sect for symbol "
4538 "table entry %u in: ", i
);
4541 if(((s_flags
& SECTION_TYPE
) == S_COALESCED
) &&
4543 object
->mh_filetype
!= MH_OBJECT
){
4544 /* this remains a global defined symbol */
4545 if(warned_about_global_coalesced_symbols
== FALSE
){
4546 warning_arch(arch
, member
, "can't make global "
4547 "coalesced symbols (like %s) into static "
4548 "symbols (use ld(1)'s "
4549 "-exported_symbols_list option) in a final "
4550 "linked image: ", strings
+ n_strx
);
4551 warned_about_global_coalesced_symbols
= TRUE
;
4554 new_ext_strsize
+= len
;
4556 sp
= bsearch(strings
+ n_strx
,
4557 remove_symbols
, nremove_symbols
,
4558 sizeof(struct symbol_list
),
4559 (int (*)(const void *, const void *))
4560 symbol_list_bsearch
);
4562 if(sp
->sym
!= NULL
){
4563 error_arch(arch
, member
, "more than one "
4564 "symbol for: %s found in: ", sp
->name
);
4568 if(object
->mh
!= NULL
)
4569 sp
->sym
= &(symbols
[i
]);
4571 sp
->sym
= &(symbols64
[i
]);
4573 warning_arch(arch
, member
, "can't make "
4574 "global coalesced symbol: %s into a "
4575 "static symbol in: ", sp
->name
);
4579 * In case the user has listed this coalesced
4580 * symbol in the save list look for it and mark it
4581 * as seen so we don't complain about not seeing it.
4583 sp
= bsearch(strings
+ n_strx
,
4584 save_symbols
, nsave_symbols
,
4585 sizeof(struct symbol_list
),
4586 (int (*)(const void *, const void *))
4587 symbol_list_bsearch
);
4589 if(sp
->sym
!= NULL
){
4590 error_arch(arch
, member
, "more than one "
4591 "symbol for: %s found in: ", sp
->name
);
4595 if(object
->mh
!= NULL
)
4596 sp
->sym
= &(symbols
[i
]);
4598 sp
->sym
= &(symbols64
[i
]);
4602 continue; /* leave this symbol unchanged */
4605 sp
= bsearch(strings
+ n_strx
,
4606 remove_symbols
, nremove_symbols
,
4607 sizeof(struct symbol_list
),
4608 (int (*)(const void *, const void *))
4609 symbol_list_bsearch
);
4611 if(sp
->sym
!= NULL
){
4612 error_arch(arch
, member
, "more than one symbol "
4613 "for: %s found in: ", sp
->name
);
4617 if(object
->mh
!= NULL
)
4618 sp
->sym
= &(symbols
[i
]);
4620 sp
->sym
= &(symbols64
[i
]);
4627 * If there is no list of saved symbols, then all
4628 * symbols will be saved unless listed in the remove
4633 * There is no save list, so if there is also no
4634 * remove list but the -p flag is specified or it is
4635 * a dynamic library then change all symbols.
4637 if((pflag
|| object
->mh_filetype
== MH_DYLIB
)
4638 && nremove_symbols
== 0)
4640 /* this remains a global defined symbol */
4642 new_ext_strsize
+= len
;
4644 continue; /* leave this symbol unchanged */
4647 sp
= bsearch(strings
+ n_strx
,
4648 save_symbols
, nsave_symbols
,
4649 sizeof(struct symbol_list
),
4650 (int (*)(const void *, const void *))
4651 symbol_list_bsearch
);
4653 if(sp
->sym
!= NULL
){
4654 error_arch(arch
, member
, "more than one symbol "
4655 "for: %s found in: ", sp
->name
);
4659 if(object
->mh
!= NULL
)
4660 sp
->sym
= &(symbols
[i
]);
4662 sp
->sym
= &(symbols64
[i
]);
4664 /* this remains a global defined symbol */
4666 new_ext_strsize
+= len
;
4671 if(Aflag
&& n_type
== (N_EXT
| N_ABS
) &&
4674 strncmp(strings
+ n_strx
,
4675 ".objc_class_name_",
4676 sizeof(".objc_class_name_") - 1) == 0))){
4677 /* this remains a global defined symbol */
4679 new_ext_strsize
+= len
;
4684 if((n_type
& N_TYPE
) != N_INDR
){
4686 if(object
->mh
!= NULL
)
4687 changed_globals
[nchanged_globals
++] =
4690 changed_globals64
[nchanged_globals
++] =
4693 /* this remains a global defined symbol */
4695 new_ext_strsize
+= len
;
4699 /* this will become a non-global symbol */
4705 /* this remains a global defined symbol */
4707 new_ext_strsize
+= len
;
4714 /* this is an undefined symbol */
4716 new_ext_strsize
+= len
;
4721 /* this is a local symbol */
4728 * The module table's module names are placed with the external
4729 * strings. So size them and add this to the external string size.
4731 for(i
= 0; i
< nmodtab
; i
++){
4732 if(object
->mh
!= NULL
)
4733 module_name
= mods
[i
].module_name
;
4735 module_name
= mods64
[i
].module_name
;
4736 if(module_name
== 0 || module_name
> strsize
){
4737 error_arch(arch
, member
, "bad string index for module_name "
4738 "of module table entry %d in: ", i
);
4741 len
= strlen(strings
+ module_name
) + 1;
4743 new_ext_strsize
+= len
;
4747 * Warn about symbols to be saved that were missing.
4752 for(i
= 0; i
< nsave_symbols
; i
++){
4753 if(save_symbols
[i
].sym
== NULL
){
4754 if(missing_syms
== 0){
4755 error_arch(arch
, member
, "symbols names listed "
4756 "in: %s not in: ", sfile
);
4759 fprintf(stderr
, "%s\n", save_symbols
[i
].name
);
4762 for(i
= 0; i
< nremove_symbols
; i
++){
4763 if(remove_symbols
[i
].sym
== NULL
){
4764 if(missing_syms
== 0){
4765 error_arch(arch
, member
, "symbols names listed "
4766 "in: %s not in: ", Rfile
);
4769 fprintf(stderr
, "%s\n", remove_symbols
[i
].name
);
4776 * Second pass: fix stabs for the globals symbols that got turned into
4777 * non-global symbols. This is a MAJOR guess. The specific changes
4778 * to do here were determined by compiling test cases with and without
4779 * the key word 'static' and looking at the difference between the STABS
4780 * the compiler generates and trying to match that here.
4782 global_strings
= strings
;
4783 if(object
->mh
!= NULL
)
4784 qsort(changed_globals
, nchanged_globals
, sizeof(struct nlist
*),
4785 (int (*)(const void *, const void *))cmp_qsort_global
);
4787 qsort(changed_globals64
, nchanged_globals
,sizeof(struct nlist_64
*),
4788 (int (*)(const void *, const void *))cmp_qsort_global_64
);
4789 dwarf_debug_map
= FALSE
;
4790 for(i
= 0; i
< nsyms
; i
++){
4792 if(object
->mh
!= NULL
){
4793 n_strx
= symbols
[i
].n_un
.n_strx
;
4794 n_type
= symbols
[i
].n_type
;
4795 n_desc
= symbols
[i
].n_desc
;
4798 n_strx
= symbols64
[i
].n_un
.n_strx
;
4799 n_type
= symbols64
[i
].n_type
;
4800 n_desc
= symbols64
[i
].n_desc
;
4803 dwarf_debug_map
= FALSE
;
4804 else if (n_type
== N_OSO
)
4805 dwarf_debug_map
= n_desc
!= 0;
4806 else if (dwarf_debug_map
&& n_type
== N_GSYM
){
4807 global_name
= strings
+ n_strx
;
4808 if(object
->mh
!= NULL
){
4809 global_symbol
= bsearch(global_name
, changed_globals
,
4810 nchanged_globals
,sizeof(struct nlist
*),
4811 (int (*)(const void *, const void *))
4812 cmp_bsearch_global
);
4813 if(global_symbol
!= NULL
){
4814 symbols
[i
].n_type
= N_STSYM
;
4815 symbols
[i
].n_sect
= (*global_symbol
)->n_sect
;
4816 symbols
[i
].n_value
= (*global_symbol
)->n_value
;
4820 global_symbol64
= bsearch(global_name
, changed_globals64
,
4822 sizeof(struct nlist_64
*),
4823 (int (*)(const void *, const void *))
4824 cmp_bsearch_global_64
);
4825 if(global_symbol64
!= NULL
){
4826 symbols64
[i
].n_type
= N_STSYM
;
4827 symbols64
[i
].n_sect
= (*global_symbol64
)->n_sect
;
4828 symbols64
[i
].n_value
= (*global_symbol64
)->n_value
;
4832 else if(! dwarf_debug_map
&&
4833 (n_type
== N_GSYM
|| n_type
== N_FUN
) &&
4834 (n_strx
!= 0 && strings
[n_strx
] != '\0')){
4835 global_name
= strings
+ n_strx
;
4836 if((global_name
[0] == '+' || global_name
[0] == '-') &&
4837 global_name
[1] == '['){
4839 while(j
+ n_strx
< strsize
&& global_name
[j
] != ']')
4841 if(j
+ n_strx
< strsize
&& global_name
[j
] == ']')
4846 while(j
+ n_strx
< strsize
&& global_name
[j
] != ':')
4848 if(j
+ n_strx
>= strsize
){
4849 error_arch(arch
, member
, "bad N_STAB symbol name for entry "
4850 "%u (does not contain ':' separating name from type) "
4854 save_char
= global_name
[j
];
4855 global_name
[j
] = '\0';
4857 global_symbol_found
= FALSE
;
4858 global_symbol_n_sect
= 0;
4859 if(object
->mh
!= NULL
){
4860 global_symbol
= bsearch(global_name
, changed_globals
,
4861 nchanged_globals
,sizeof(struct nlist
*),
4862 (int (*)(const void *, const void *))
4863 cmp_bsearch_global_stab
);
4864 global_symbol64
= NULL
;
4865 if(global_symbol
!= NULL
){
4866 global_symbol_found
= TRUE
;
4867 global_symbol_n_sect
= (*global_symbol
)->n_sect
;
4871 global_symbol64
= bsearch(global_name
, changed_globals64
,
4873 sizeof(struct nlist_64
*),
4874 (int (*)(const void *, const void *))
4875 cmp_bsearch_global_stab_64
);
4876 global_symbol
= NULL
;
4877 if(global_symbol64
!= NULL
){
4878 global_symbol_found
= TRUE
;
4879 global_symbol_n_sect
= (*global_symbol64
)->n_sect
;
4882 global_name
[j
] = save_char
;
4883 if(global_symbol_found
== TRUE
){
4884 if(n_type
== N_GSYM
){
4885 if(global_symbol_n_sect
== data_n_sect
){
4886 if(object
->mh
!= NULL
)
4887 symbols
[i
].n_type
= N_STSYM
;
4889 symbols64
[i
].n_type
= N_STSYM
;
4892 if(object
->mh
!= NULL
)
4893 symbols
[i
].n_type
= N_FUN
;
4895 symbols64
[i
].n_type
= N_FUN
;
4897 if(object
->mh
!= NULL
){
4898 symbols
[i
].n_sect
= (*global_symbol
)->n_sect
;
4899 symbols
[i
].n_value
= (*global_symbol
)->n_value
;
4900 symbols
[i
].n_desc
= (*global_symbol
)->n_desc
;
4903 symbols64
[i
].n_sect
= (*global_symbol64
)->n_sect
;
4904 symbols64
[i
].n_value
= (*global_symbol64
)->n_value
;
4905 symbols64
[i
].n_desc
= (*global_symbol64
)->n_desc
;
4907 if(j
+ 1 + n_strx
>= strsize
||
4908 global_name
[j
+1] != 'G'){
4909 error_arch(arch
, member
, "bad N_GSYM symbol name "
4910 "for entry %u (does not have type 'G' after "
4911 "':' in name) in: ", i
);
4914 global_name
[j
+1] = 'S';
4916 else{ /* n_type == N_FUN */
4917 if(j
+ 1 + n_strx
>= strsize
||
4918 global_name
[j
+1] == 'F'){
4919 global_name
[j
+1] = 'f';
4925 global_strings
= NULL
;
4928 * Now what needs to be done is to create the new symbol table moving
4929 * those global symbols being changed into non-globals into the areas
4930 * in the symbol table for local symbols. The symbol table and string
4931 * table must be in this order:
4935 * external defined symbols
4943 saves
= (int32_t *)allocate(nsyms
* sizeof(int32_t));
4944 bzero(saves
, nsyms
* sizeof(int32_t));
4946 if(object
->mh
!= NULL
){
4947 new_symbols
= (struct nlist
*)
4948 allocate(new_nsyms
* sizeof(struct nlist
));
4949 new_symbols64
= NULL
;
4953 new_symbols64
= (struct nlist_64
*)
4954 allocate(new_nsyms
* sizeof(struct nlist_64
));
4956 new_strsize
= round(new_strsize
, sizeof(int32_t));
4957 new_strings
= (char *)allocate(new_strsize
);
4958 new_strings
[new_strsize
- 3] = '\0';
4959 new_strings
[new_strsize
- 2] = '\0';
4960 new_strings
[new_strsize
- 1] = '\0';
4962 memset(new_strings
, '\0', sizeof(int32_t));
4963 p
= new_strings
+ sizeof(int32_t);
4964 q
= p
+ new_ext_strsize
;
4967 * If this is a dynamic library the movement of the symbols has to be
4968 * done with respect to the modules. As the local symbols, and external
4969 * defined symbols are grouped together for each module. Then a new
4970 * module table needs to be created with the new indexes into the symbol
4971 * table for each module.
4973 new_nmodtab
= nmodtab
;
4975 new_nextrefsyms
= nextrefsyms
;
4976 if(object
->mh_filetype
== MH_DYLIB
&& nmodtab
!= 0){
4977 if(object
->mh
!= NULL
){
4978 new_mods
= allocate(nmodtab
* sizeof(struct dylib_module
));
4983 new_mods64
= allocate(nmodtab
* sizeof(struct dylib_module_64
));
4988 * This first loop through the module table sets the index and
4989 * counts of the local symbols for each module.
4991 for(i
= 0; i
< nmodtab
; i
++){
4993 * First put the existing local symbols into the new symbol
4996 if(object
->mh
!= NULL
){
4997 new_mods
[i
].ilocalsym
= inew_syms
;
4998 new_mods
[i
].nlocalsym
= 0;
4999 ilocalsym
= mods
[i
].ilocalsym
;
5000 nlocalsym
= mods
[i
].nlocalsym
;
5003 new_mods64
[i
].ilocalsym
= inew_syms
;
5004 new_mods64
[i
].nlocalsym
= 0;
5005 ilocalsym
= mods64
[i
].ilocalsym
;
5006 nlocalsym
= mods64
[i
].nlocalsym
;
5008 for(j
= ilocalsym
; j
< ilocalsym
+ nlocalsym
; j
++){
5009 if(object
->mh
!= NULL
){
5010 n_strx
= symbols
[j
].n_un
.n_strx
;
5011 n_type
= symbols
[j
].n_type
;
5014 n_strx
= symbols64
[j
].n_un
.n_strx
;
5015 n_type
= symbols64
[j
].n_type
;
5017 if((n_type
& N_EXT
) == 0){
5018 if(object
->mh
!= NULL
)
5019 new_symbols
[inew_syms
] = symbols
[j
];
5021 new_symbols64
[inew_syms
] = symbols64
[j
];
5023 strcpy(q
, strings
+ n_strx
);
5024 if(object
->mh
!= NULL
)
5025 new_symbols
[inew_syms
].n_un
.n_strx
=
5028 new_symbols64
[inew_syms
].n_un
.n_strx
=
5033 saves
[j
] = inew_syms
;
5034 if(object
->mh
!= NULL
)
5035 new_mods
[i
].nlocalsym
++;
5037 new_mods64
[i
].nlocalsym
++;
5041 * Next put the global symbols that were changed into
5042 * non-global symbols into the new symbol table and moved their
5043 * counts to the local symbol counts.
5045 if(object
->mh
!= NULL
){
5046 iextdefsym
= mods
[i
].iextdefsym
;
5047 nextdefsym
= mods
[i
].nextdefsym
;
5050 iextdefsym
= mods64
[i
].iextdefsym
;
5051 nextdefsym
= mods64
[i
].nextdefsym
;
5053 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
5054 if(object
->mh
!= NULL
){
5055 n_strx
= symbols
[j
].n_un
.n_strx
;
5056 n_type
= symbols
[j
].n_type
;
5059 n_strx
= symbols64
[j
].n_un
.n_strx
;
5060 n_type
= symbols64
[j
].n_type
;
5062 if((n_type
& N_EXT
) != 0){
5063 if(nmedits
[j
] == TRUE
){
5065 * Change the new symbol to a private extern symbol
5066 * with the extern bit off.
5068 if(object
->mh
!= NULL
){
5069 new_symbols
[inew_syms
] = symbols
[j
];
5070 new_symbols
[inew_syms
].n_type
|= N_PEXT
;
5071 new_symbols
[inew_syms
].n_type
&= ~N_EXT
;
5074 new_symbols64
[inew_syms
] = symbols64
[j
];
5075 new_symbols64
[inew_syms
].n_type
|= N_PEXT
;
5076 new_symbols64
[inew_syms
].n_type
&= ~N_EXT
;
5079 strcpy(q
, strings
+ n_strx
);
5080 if(object
->mh
!= NULL
)
5081 new_symbols
[inew_syms
].n_un
.n_strx
=
5084 new_symbols64
[inew_syms
].n_un
.n_strx
=
5089 saves
[j
] = inew_syms
;
5090 if(object
->mh
!= NULL
)
5091 new_mods
[i
].nlocalsym
++;
5093 new_mods64
[i
].nlocalsym
++;
5099 * Next put the unchanged defined global symbols into the new
5102 for(i
= 0; i
< nmodtab
; i
++){
5103 if(object
->mh
!= NULL
){
5104 new_mods
[i
].iextdefsym
= inew_syms
;
5105 new_mods
[i
].nextdefsym
= 0;
5106 iextdefsym
= mods
[i
].iextdefsym
;
5107 nextdefsym
= mods
[i
].nextdefsym
;
5110 new_mods64
[i
].iextdefsym
= inew_syms
;
5111 new_mods64
[i
].nextdefsym
= 0;
5112 iextdefsym
= mods64
[i
].iextdefsym
;
5113 nextdefsym
= mods64
[i
].nextdefsym
;
5115 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
5116 if(object
->mh
!= NULL
){
5117 n_strx
= symbols
[j
].n_un
.n_strx
;
5118 n_type
= symbols
[j
].n_type
;
5121 n_strx
= symbols64
[j
].n_un
.n_strx
;
5122 n_type
= symbols64
[j
].n_type
;
5124 if((n_type
& N_EXT
) != 0){
5125 if(nmedits
[j
] == FALSE
){
5126 if(object
->mh
!= NULL
)
5127 new_symbols
[inew_syms
] = symbols
[j
];
5129 new_symbols64
[inew_syms
] = symbols64
[j
];
5131 strcpy(p
, strings
+ n_strx
);
5132 if(object
->mh
!= NULL
)
5133 new_symbols
[inew_syms
].n_un
.n_strx
=
5136 new_symbols64
[inew_syms
].n_un
.n_strx
=
5141 saves
[j
] = inew_syms
;
5142 if(object
->mh
!= NULL
)
5143 new_mods
[i
].nextdefsym
++;
5145 new_mods64
[i
].nextdefsym
++;
5151 * Last put the undefined symbols into the new symbol table.
5153 for(i
= 0; i
< nsyms
; i
++){
5154 if(object
->mh
!= NULL
){
5155 n_strx
= symbols
[i
].n_un
.n_strx
;
5156 n_type
= symbols
[i
].n_type
;
5159 n_strx
= symbols64
[i
].n_un
.n_strx
;
5160 n_type
= symbols64
[i
].n_type
;
5162 if((n_type
& N_EXT
) != 0 &&
5163 ((n_type
& N_TYPE
) == N_UNDF
||
5164 (n_type
& N_TYPE
) == N_PBUD
)){
5165 if(object
->mh
!= NULL
)
5166 new_symbols
[inew_syms
] = symbols
[i
];
5168 new_symbols64
[inew_syms
] = symbols64
[i
];
5170 strcpy(p
, strings
+ n_strx
);
5171 if(object
->mh
!= NULL
)
5172 new_symbols
[inew_syms
].n_un
.n_strx
=
5175 new_symbols64
[inew_syms
].n_un
.n_strx
=
5180 saves
[i
] = inew_syms
;
5185 * Place the module table's module names with the external strings
5186 * and set the names in the new module table. And then copy the
5187 * other unchanged fields.
5189 for(i
= 0; i
< nmodtab
; i
++){
5190 if(object
->mh
!= NULL
){
5191 strcpy(p
, strings
+ mods
[i
].module_name
);
5192 new_mods
[i
].module_name
= p
- new_strings
;
5195 new_mods
[i
].irefsym
= mods
[i
].irefsym
;
5196 new_mods
[i
].nrefsym
= mods
[i
].nrefsym
;
5197 new_mods
[i
].iextrel
= mods
[i
].iextrel
;
5198 new_mods
[i
].nextrel
= mods
[i
].nextrel
;
5199 new_mods
[i
].iinit_iterm
= mods
[i
].iinit_iterm
;
5200 new_mods
[i
].ninit_nterm
= mods
[i
].ninit_nterm
;
5201 new_mods
[i
].objc_module_info_addr
=
5202 mods
[i
].objc_module_info_addr
;
5203 new_mods
[i
].objc_module_info_size
=
5204 mods
[i
].objc_module_info_size
;
5207 strcpy(p
, strings
+ mods64
[i
].module_name
);
5208 new_mods64
[i
].module_name
= p
- new_strings
;
5211 new_mods64
[i
].irefsym
= mods64
[i
].irefsym
;
5212 new_mods64
[i
].nrefsym
= mods64
[i
].nrefsym
;
5213 new_mods64
[i
].iextrel
= mods64
[i
].iextrel
;
5214 new_mods64
[i
].nextrel
= mods64
[i
].nextrel
;
5215 new_mods64
[i
].iinit_iterm
= mods64
[i
].iinit_iterm
;
5216 new_mods64
[i
].ninit_nterm
= mods64
[i
].ninit_nterm
;
5217 new_mods64
[i
].objc_module_info_addr
=
5218 mods64
[i
].objc_module_info_addr
;
5219 new_mods64
[i
].objc_module_info_size
=
5220 mods64
[i
].objc_module_info_size
;
5225 * Update the reference table with the new symbol indexes for all
5226 * entries and change type of reference (the flags field) for those
5227 * symbols that got changed from globals to non-globals.
5229 new_nextrefsyms
= nextrefsyms
;
5230 new_refs
= allocate(new_nextrefsyms
*
5231 sizeof(struct dylib_reference
));
5233 for(i
= 0; i
< nextrefsyms
; i
++){
5234 if(nmedits
[refs
[i
].isym
] == TRUE
){
5235 if(refs
[i
].flags
== REFERENCE_FLAG_DEFINED
)
5237 REFERENCE_FLAG_PRIVATE_DEFINED
;
5238 else if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
)
5240 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
;
5241 else if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
)
5243 REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
;
5245 new_refs
[i
].flags
= refs
[i
].flags
;
5248 new_refs
[i
].flags
= refs
[i
].flags
;
5250 new_refs
[i
].isym
= saves
[refs
[i
].isym
] - 1;
5254 * Create a new dylib table of contents without the global symbols
5255 * that got turned into non-globals.
5257 new_ntoc
= ntoc
- nchanged_globals
;
5258 new_tocs
= allocate(new_ntoc
*
5259 sizeof(struct dylib_table_of_contents
));
5261 for(i
= 0; i
< ntoc
; i
++){
5262 if(tocs
[i
].symbol_index
>= nsyms
){
5263 error_arch(arch
, member
, "bad symbol index for table of "
5264 "contents table entry %d in: ", i
);
5267 if(nmedits
[tocs
[i
].symbol_index
] == FALSE
){
5268 new_tocs
[k
].symbol_index
= saves
[tocs
[i
].symbol_index
] - 1;
5269 new_tocs
[k
].module_index
= tocs
[i
].module_index
;
5275 * If is not a dynamic library so all global symbols changed into
5276 * statics can be moved to the end of the local symbols. If the pflag
5277 * is set then the changed symbols remain global and just get the
5278 * private extern bit set.
5282 * First put the existing local symbols into the new symbol table.
5285 for(i
= 0; i
< nsyms
; i
++){
5286 if(object
->mh
!= NULL
){
5287 n_strx
= symbols
[i
].n_un
.n_strx
;
5288 n_type
= symbols
[i
].n_type
;
5291 n_strx
= symbols64
[i
].n_un
.n_strx
;
5292 n_type
= symbols64
[i
].n_type
;
5294 if((n_type
& N_EXT
) == 0){
5295 if(object
->mh
!= NULL
)
5296 new_symbols
[inew_syms
] = symbols
[i
];
5298 new_symbols64
[inew_syms
] = symbols64
[i
];
5300 strcpy(q
, strings
+ n_strx
);
5301 if(object
->mh
!= NULL
)
5302 new_symbols
[inew_syms
].n_un
.n_strx
=
5305 new_symbols64
[inew_syms
].n_un
.n_strx
=
5310 saves
[i
] = inew_syms
;
5314 * Next put the global symbols that were changed into statics
5315 * symbols into the new symbol table.
5318 for(i
= 0; i
< nsyms
; i
++){
5319 if(object
->mh
!= NULL
){
5320 n_strx
= symbols
[i
].n_un
.n_strx
;
5321 n_type
= symbols
[i
].n_type
;
5324 n_strx
= symbols64
[i
].n_un
.n_strx
;
5325 n_type
= symbols64
[i
].n_type
;
5327 if((n_type
& N_EXT
) != 0){
5328 if(nmedits
[i
] == TRUE
){
5330 * Change the new symbol to not be an extern symbol
5331 * by turning off the extern bit.
5333 if(object
->mh
!= NULL
){
5334 new_symbols
[inew_syms
] = symbols
[i
];
5335 new_symbols
[inew_syms
].n_type
&= ~N_EXT
;
5336 new_symbols
[inew_syms
].n_desc
&= ~N_WEAK_DEF
;
5339 new_symbols64
[inew_syms
] = symbols64
[i
];
5340 new_symbols64
[inew_syms
].n_type
&= ~N_EXT
;
5341 new_symbols64
[inew_syms
].n_desc
&= ~N_WEAK_DEF
;
5344 strcpy(q
, strings
+ n_strx
);
5345 if(object
->mh
!= NULL
)
5346 new_symbols
[inew_syms
].n_un
.n_strx
=
5349 new_symbols64
[inew_syms
].n_un
.n_strx
=
5354 saves
[i
] = inew_syms
;
5360 * Last put the unchanged global symbols into the new symbol table
5361 * and symbols changed into private externs.
5363 for(i
= 0; i
< nsyms
; i
++){
5364 if(object
->mh
!= NULL
){
5365 n_strx
= symbols
[i
].n_un
.n_strx
;
5366 n_type
= symbols
[i
].n_type
;
5369 n_strx
= symbols64
[i
].n_un
.n_strx
;
5370 n_type
= symbols64
[i
].n_type
;
5372 if((n_type
& N_EXT
) != 0){
5373 if(nmedits
[i
] == FALSE
|| pflag
== TRUE
){
5374 if(object
->mh
!= NULL
)
5375 new_symbols
[inew_syms
] = symbols
[i
];
5377 new_symbols64
[inew_syms
] = symbols64
[i
];
5378 if(nmedits
[i
] == TRUE
&& pflag
== TRUE
){
5380 * Change the new symbol to be a private extern
5381 * symbol by turning on the private extern bit.
5383 if(object
->mh
!= NULL
)
5384 new_symbols
[inew_syms
].n_type
|= N_PEXT
;
5386 new_symbols64
[inew_syms
].n_type
|= N_PEXT
;
5389 strcpy(p
, strings
+ n_strx
);
5390 if(object
->mh
!= NULL
)
5391 new_symbols
[inew_syms
].n_un
.n_strx
=
5394 new_symbols64
[inew_syms
].n_un
.n_strx
=
5399 saves
[i
] = inew_syms
;
5405 if(sections
!= NULL
);
5407 if(sections64
!= NULL
);
5417 * Function for qsort for comparing global symbol names.
5422 const struct nlist
**sym1
,
5423 const struct nlist
**sym2
)
5425 return(strcmp(global_strings
+ (*sym1
)->n_un
.n_strx
,
5426 global_strings
+ (*sym2
)->n_un
.n_strx
));
5431 cmp_qsort_global_64(
5432 const struct nlist_64
**sym1
,
5433 const struct nlist_64
**sym2
)
5435 return(strcmp(global_strings
+ (*sym1
)->n_un
.n_strx
,
5436 global_strings
+ (*sym2
)->n_un
.n_strx
));
5440 * Function for bsearch for finding a global symbol that matches a stab name.
5444 cmp_bsearch_global_stab(
5446 const struct nlist
**sym
)
5449 * The +1 is for the '_' on the global symbol that is not on the
5450 * stab string that is trying to be matched.
5452 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
+ 1));
5457 cmp_bsearch_global_stab_64(
5459 const struct nlist_64
**sym
)
5462 * The +1 is for the '_' on the global symbol that is not on the
5463 * stab string that is trying to be matched.
5465 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
+ 1));
5469 * Function for bsearch for finding a global symbol that matches a stab name
5476 const struct nlist
**sym
)
5478 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
));
5483 cmp_bsearch_global_64(
5485 const struct nlist_64
**sym
)
5487 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
));
5489 #endif /* defined(NMEDIT) */