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"
49 /* These are set from the command line arguments */
51 char *progname
= NULL
; /* name of the program for error messages (argv[0]) */
52 static char *output_file
;/* name of the output file */
53 static char *sfile
; /* filename of global symbol names to keep */
54 static char *Rfile
; /* filename of global symbol names to remove */
55 static long Aflag
; /* save only absolute symbols with non-zero value and
56 .objc_class_name_* symbols */
57 static long iflag
; /* -i ignore symbols in -s file not in object */
59 static long pflag
; /* make all defined global symbols private extern */
60 #else /* !defined(NMEDIT) */
61 static char *dfile
; /* filename of filenames of debugger symbols to keep */
62 static long uflag
; /* save undefined symbols */
63 static long rflag
; /* save symbols referenced dynamically */
64 static long nflag
; /* save N_SECT global symbols */
65 static long Sflag
; /* -S strip only debugger symbols N_STAB */
66 static long xflag
; /* -x strip non-globals */
67 static long Xflag
; /* -X strip local symbols with 'L' names */
68 static long cflag
; /* -c strip section contents from dynamic libraries
69 files to create stub libraries */
70 static long no_uuid
; /* -no_uuid strip LC_UUID load commands */
71 static long strip_all
= 1;
73 * This is set on an object by object basis if the strip_all flag is still set
74 * and the object is an executable that is for use with the dynamic linker.
75 * This has the same effect as -r and -u.
77 static enum bool default_dyld_executable
= FALSE
;
81 * Data structures to perform selective stripping of symbol table entries.
82 * save_symbols is the names of the symbols from the -s <file> argument.
83 * remove_symbols is the names of the symbols from the -R <file> argument.
85 static struct symbol_list
*save_symbols
= NULL
;
86 static unsigned long nsave_symbols
= 0;
87 static struct symbol_list
*remove_symbols
= NULL
;
88 static unsigned long nremove_symbols
= 0;
91 * saves points to an array of longs that is allocated. This array is a map of
92 * old symbol indexes to new symbol indexes. The new symbol indexes are
93 * plus 1 and zero value means that old symbol is not in the new symbol table.
94 * ref_saves is used in the same way but for the reference table.
95 * nmedits is an array and indexed by the symbol index the value indicates if
96 * the symbol was edited and turned into a non-global.
98 static long *saves
= NULL
;
100 static long *ref_saves
= NULL
;
102 static enum bool *nmedits
= NULL
;
106 * These hold the new symbol and string table created by strip_symtab()
107 * and the new counts of local, defined external and undefined symbols.
109 static struct nlist
*new_symbols
= NULL
;
110 static struct nlist_64
*new_symbols64
= NULL
;
111 static unsigned long new_nsyms
= 0;
112 static char *new_strings
= NULL
;
113 static unsigned long new_strsize
= 0;
114 static unsigned long new_nlocalsym
= 0;
115 static unsigned long new_nextdefsym
= 0;
116 static unsigned long new_nundefsym
= 0;
119 * These hold the new table of contents, reference table and module table for
122 static struct dylib_table_of_contents
*new_tocs
= NULL
;
123 static unsigned long new_ntoc
= 0;
124 static struct dylib_reference
*new_refs
= NULL
;
125 static unsigned long new_nextrefsyms
= 0;
127 static struct dylib_module
*new_mods
= NULL
;
128 static struct dylib_module_64
*new_mods64
= NULL
;
129 static unsigned long new_nmodtab
= 0;
134 * The list of file names to save debugging symbols from.
136 static char **debug_filenames
= NULL
;
137 static long ndebug_filenames
= 0;
144 struct nlist_64 symbol64
;
146 static char *qsort_strings
= NULL
;
147 #endif /* !defined(NMEDIT) */
150 /* Internal routines */
154 static void strip_file(
156 struct arch_flag
*arch_flags
,
157 unsigned long narch_flags
,
158 enum bool all_archs
);
160 static void strip_arch(
162 unsigned long narchs
,
163 struct arch_flag
*arch_flags
,
164 unsigned long narch_flags
,
165 enum bool all_archs
);
167 static void strip_object(
169 struct member
*member
,
170 struct object
*object
);
172 static void check_object_relocs(
174 struct member
*member
,
175 struct object
*object
,
178 unsigned long long sectsize
,
180 struct relocation_info
*relocs
,
182 struct nlist
*symbols
,
183 struct nlist_64
*symbols64
,
186 long *missing_reloc_symbols
,
187 enum byte_sex host_byte_sex
);
189 static void check_indirect_symtab(
191 struct member
*member
,
192 struct object
*object
,
193 unsigned long nitems
,
194 unsigned long reserved1
,
195 unsigned long section_type
,
197 struct nlist
*symbols
,
198 struct nlist_64
*symbols64
,
201 long *missing_reloc_symbols
,
202 enum byte_sex host_byte_sex
);
205 static enum bool strip_symtab(
207 struct member
*member
,
208 struct object
*object
,
209 struct nlist
*symbols
,
210 struct nlist_64
*symbols64
,
213 unsigned long strsize
,
214 struct dylib_table_of_contents
*tocs
,
216 struct dylib_module
*mods
,
217 struct dylib_module_64
*mods64
,
218 unsigned long nmodtab
,
219 struct dylib_reference
*refs
,
220 unsigned long nextrefsyms
,
221 uint32_t *indirectsyms
,
222 unsigned long nindirectsyms
);
224 static void strip_LC_UUID_commands(
226 struct member
*member
,
227 struct object
*object
);
230 static void strip_LC_CODE_SIGNATURE_commands(
232 struct member
*member
,
233 struct object
*object
);
234 #endif /* !(NMEDIT) */
236 static enum bool private_extern_reference_by_module(
237 unsigned long symbol_index
,
238 struct dylib_reference
*refs
,
239 unsigned long nextrefsyms
);
241 static enum bool symbol_pointer_used(
242 unsigned long symbol_index
,
243 uint32_t *indirectsyms
,
244 unsigned long nindirectsyms
);
246 static int cmp_qsort_undef_map(
247 const struct undef_map
*sym1
,
248 const struct undef_map
*sym2
);
250 static int cmp_qsort_undef_map_64(
251 const struct undef_map64
*sym1
,
252 const struct undef_map64
*sym2
);
253 #endif /* !defined(NMEDIT) */
256 static enum bool edit_symtab(
258 struct member
*member
,
259 struct object
*object
,
260 struct nlist
*symbols
,
261 struct nlist_64
*symbols64
,
264 unsigned long strsize
,
265 struct dylib_table_of_contents
*tocs
,
267 struct dylib_module
*mods
,
268 struct dylib_module_64
*mods64
,
269 unsigned long nmodtab
,
270 struct dylib_reference
*refs
,
271 unsigned long nextrefsyms
);
275 static void setup_debug_filenames(
278 static int cmp_qsort_filename(
282 static int cmp_bsearch_filename(
289 * This variable and routines are used for nmedit(1) only.
291 static char *global_strings
= NULL
;
293 static int cmp_qsort_global(
294 const struct nlist
**sym1
,
295 const struct nlist
**sym2
);
297 static int cmp_qsort_global_64(
298 const struct nlist_64
**sym1
,
299 const struct nlist_64
**sym2
);
301 static int cmp_bsearch_global_stab(
303 const struct nlist
**sym
);
305 static int cmp_bsearch_global_stab_64(
307 const struct nlist_64
**sym
);
309 static int cmp_bsearch_global(
311 const struct nlist
**sym
);
313 static int cmp_bsearch_global_64(
315 const struct nlist_64
**sym
);
325 unsigned long j
, args_left
, files_specified
;
326 struct arch_flag
*arch_flags
;
327 unsigned long narch_flags
;
329 struct symbol_list
*sp
;
339 for (i
= 1; i
< argc
; i
++){
340 if(argv
[i
][0] == '-'){
341 if(argv
[i
][1] == '\0'){
345 if(strcmp(argv
[i
], "-o") == 0){
347 fatal("-o requires an argument");
348 if(output_file
!= NULL
)
349 fatal("only one -o option allowed");
350 output_file
= argv
[i
+ 1];
353 else if(strcmp(argv
[i
], "-s") == 0){
355 fatal("-s requires an argument");
357 fatal("only one -s option allowed");
361 else if(strcmp(argv
[i
], "-R") == 0){
363 fatal("-R requires an argument");
365 fatal("only one -R option allowed");
370 else if(strcmp(argv
[i
], "-d") == 0){
372 fatal("-d requires an argument");
374 fatal("only one -d option allowed");
378 else if(strcmp(argv
[i
], "-no_uuid") == 0){
381 #endif /* !defined(NMEDIT) */
382 else if(strcmp(argv
[i
], "-arch") == 0){
384 error("missing argument(s) to %s option", argv
[i
]);
387 if(strcmp("all", argv
[i
+1]) == 0){
391 arch_flags
= reallocate(arch_flags
,
392 (narch_flags
+ 1) * sizeof(struct arch_flag
));
393 if(get_arch_from_flag(argv
[i
+1],
394 arch_flags
+ narch_flags
) == 0){
395 error("unknown architecture specification flag: "
396 "%s %s", argv
[i
], argv
[i
+1]);
400 for(j
= 0; j
< narch_flags
; j
++){
401 if(arch_flags
[j
].cputype
==
402 arch_flags
[narch_flags
].cputype
&&
403 (arch_flags
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
404 (arch_flags
[narch_flags
].cpusubtype
&
405 ~CPU_SUBTYPE_MASK
) &&
406 strcmp(arch_flags
[j
].name
,
407 arch_flags
[narch_flags
].name
) == 0)
416 for(j
= 1; argv
[i
][j
] != '\0'; j
++){
422 #else /* !defined(NMEDIT) */
450 #endif /* !defined(NMEDIT) */
455 #endif /* !defined(NMEDIT) */
464 error("unrecognized option: %s", argv
[i
]);
474 files_specified
+= argc
- (i
+ 1);
476 if(files_specified
> 1 && output_file
!= NULL
){
477 error("-o <filename> can only be used when one file is specified");
482 setup_symbol_list(sfile
, &save_symbols
, &nsave_symbols
);
486 if(Rfile
== NULL
&& pflag
== 0){
487 error("-s <filename>, -R <filename> or -p argument required");
494 setup_symbol_list(Rfile
, &remove_symbols
, &nremove_symbols
);
496 for(j
= 0; j
< nremove_symbols
; j
++){
497 sp
= bsearch(remove_symbols
[j
].name
,
498 save_symbols
, nsave_symbols
,
499 sizeof(struct symbol_list
),
500 (int (*)(const void *, const void *))
501 symbol_list_bsearch
);
503 error("symbol name: %s is listed in both -s %s and -R "
504 "%s files (can't be both saved and removed)",
505 remove_symbols
[j
].name
, sfile
, Rfile
);
513 /* the default when no -arch flags is present is to strip all archs */
519 setup_debug_filenames(dfile
);
521 #endif /* !defined(NMEDIT) */
525 for (i
= 1; i
< argc
; i
++) {
526 if(args_left
&& argv
[i
][0] == '-'){
527 if(argv
[i
][1] == '\0')
529 else if(strcmp(argv
[i
], "-o") == 0 ||
530 strcmp(argv
[i
], "-s") == 0 ||
531 strcmp(argv
[i
], "-R") == 0 ||
533 strcmp(argv
[i
], "-d") == 0 ||
534 #endif /* !defined(NMEDIT) */
535 strcmp(argv
[i
], "-arch") == 0)
539 char resolved_path
[PATH_MAX
+ 1];
541 if(realpath(argv
[i
], resolved_path
) == NULL
)
542 strip_file(argv
[i
], arch_flags
, narch_flags
, all_archs
);
544 strip_file(resolved_path
, arch_flags
,narch_flags
,all_archs
);
548 if(files_specified
== 0)
549 fatal("no files specified");
552 return(EXIT_FAILURE
);
554 return(EXIT_SUCCESS
);
563 fprintf(stderr
, "Usage: %s [-AnuSXx] [-] [-d filename] [-s filename] "
564 "[-R filename] [-o output] file [...] \n", progname
);
565 #else /* defined(NMEDIT) */
566 fprintf(stderr
, "Usage: %s -s filename [-R filename] [-p] [-A] [-] "
567 "[-o output] file [...] \n",
577 struct arch_flag
*arch_flags
,
578 unsigned long narch_flags
,
582 unsigned long narchs
;
583 struct stat stat_buf
;
584 unsigned long previous_errors
;
585 enum bool unix_standard_mode
;
594 previous_errors
= errors
;
597 /* breakout the file for processing */
598 breakout(input_file
, &archs
, &narchs
, FALSE
);
602 /* checkout the file for symbol table replacement processing */
603 checkout(archs
, narchs
);
605 /* process the symbols in the input file */
606 strip_arch(archs
, narchs
, arch_flags
, narch_flags
, all_archs
);
610 /* create the output file */
611 if(stat(input_file
, &stat_buf
) == -1)
612 system_error("can't stat input file: %s", input_file
);
613 if(output_file
!= NULL
){
614 writeout(archs
, narchs
, output_file
, stat_buf
.st_mode
& 0777,
615 TRUE
, FALSE
, FALSE
, NULL
);
618 unix_standard_mode
= get_unix_standard_mode();
622 output_file
= makestr(input_file
, ".nmedit", NULL
);
623 #else /* !defined(NMEDIT) */
625 * In UNIX standard conformance mode we are not allowed to replace
626 * a file that is not writeable.
628 if(unix_standard_mode
== TRUE
&&
629 access(input_file
, W_OK
) == -1){
630 system_error("file: %s is not writable", input_file
);
631 goto strip_file_return
;
633 output_file
= makestr(input_file
, ".strip", NULL
);
636 * The UNIX standard conformance test suite expects files of
637 * MAXPATHLEN to work.
639 if(strlen(output_file
) >= MAXPATHLEN
){
641 * If there is a directory path in the name try to change
642 * the current working directory to that path.
644 if((p
= rindex(output_file
, '/')) != NULL
){
645 if((cwd_fd
= open(".", O_RDONLY
, 0)) == -1){
646 system_error("can't open current working directory");
647 goto strip_file_return
;
650 if(chdir(output_file
) == -1){
651 system_error("can't change current working directory "
652 "to: %s", output_file
);
653 goto strip_file_return
;
655 p
= rindex(input_file
, '/');
656 rename_file
= makestr(p
+ 1, NULL
);
659 * Create what might be a short enough name.
662 output_file
= makestr("strip.XXXXXX", NULL
);
663 output_file
= mktemp(output_file
);
666 writeout(archs
, narchs
, output_file
, stat_buf
.st_mode
& 0777,
667 TRUE
, FALSE
, FALSE
, NULL
);
668 if(rename_file
!= NULL
){
669 if(rename(output_file
, rename_file
) == -1)
670 system_error("can't move temporary file: %s to file: %s",
671 output_file
, rename_file
);
675 if(rename(output_file
, input_file
) == -1)
676 system_error("can't move temporary file: %s to input "
677 "file: %s", output_file
, input_file
);
683 * If we changed the current working directory change back to
684 * the previous working directory.
687 if(fchdir(cwd_fd
) == -1)
688 system_error("can't change back to previous working "
690 if(close(cwd_fd
) == -1)
691 system_error("can't close previous working directory");
697 #endif /* !defined(NMEDIT) */
698 /* clean-up data structures */
699 free_archs(archs
, narchs
);
701 errors
+= previous_errors
;
708 unsigned long narchs
,
709 struct arch_flag
*arch_flags
,
710 unsigned long narch_flags
,
713 unsigned long i
, j
, k
, offset
, size
, missing_syms
;
715 cpu_subtype_t cpusubtype
;
716 struct arch_flag host_arch_flag
;
717 enum bool arch_process
, any_processing
, *arch_flag_processed
, family
;
718 const struct arch_flag
*family_arch_flag
;
721 * Using the specified arch_flags process specified objects for those
724 any_processing
= FALSE
;
725 arch_flag_processed
= NULL
;
727 arch_flag_processed
= allocate(narch_flags
* sizeof(enum bool));
728 memset(arch_flag_processed
, '\0', narch_flags
* sizeof(enum bool));
729 for(i
= 0; i
< narchs
; i
++){
731 * Determine the architecture (cputype and cpusubtype) of arch[i]
735 if(archs
[i
].type
== OFILE_ARCHIVE
){
736 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
737 if(archs
[i
].members
[j
].type
== OFILE_Mach_O
){
738 cputype
= archs
[i
].members
[j
].object
->mh_cputype
;
739 cpusubtype
= archs
[i
].members
[j
].object
->mh_cpusubtype
;
744 else if(archs
[i
].type
== OFILE_Mach_O
){
745 cputype
= archs
[i
].object
->mh_cputype
;
746 cpusubtype
= archs
[i
].object
->mh_cpusubtype
;
748 else if(archs
[i
].fat_arch
!= NULL
){
749 cputype
= archs
[i
].fat_arch
->cputype
;
750 cpusubtype
= archs
[i
].fat_arch
->cpusubtype
;
752 arch_process
= FALSE
;
753 if(all_archs
== TRUE
){
756 else if(narch_flags
!= 0){
758 if(narch_flags
== 1){
760 get_arch_family_from_cputype(arch_flags
[0].cputype
);
761 if(family_arch_flag
!= NULL
)
763 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
764 (arch_flags
[0].cpusubtype
& ~CPU_SUBTYPE_MASK
));
766 for(j
= 0; j
< narch_flags
; j
++){
767 if(arch_flags
[j
].cputype
== cputype
&&
768 ((arch_flags
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
769 (cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
772 arch_flag_processed
[j
] = TRUE
;
778 (void)get_arch_from_host(&host_arch_flag
, NULL
);
779 if(host_arch_flag
.cputype
== cputype
&&
780 (host_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
781 (cpusubtype
& ~CPU_SUBTYPE_MASK
))
784 if(narchs
!= 1 && arch_process
== FALSE
)
786 any_processing
= TRUE
;
789 * Now this arch[i] has been selected to be processed so process it
790 * according to its type.
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 strip_object(archs
+ i
, archs
[i
].members
+ j
,
796 archs
[i
].members
[j
].object
);
801 for(k
= 0; k
< nsave_symbols
; k
++){
802 if(save_symbols
[k
].seen
== FALSE
){
803 if(missing_syms
== 0){
804 error_arch(archs
+ i
, NULL
, "symbols names "
805 "listed in: %s not in: ", sfile
);
808 fprintf(stderr
, "%s\n", save_symbols
[k
].name
);
812 for(k
= 0; k
< nsave_symbols
; k
++){
813 save_symbols
[k
].seen
= FALSE
;
817 for(k
= 0; k
< nremove_symbols
; k
++){
818 if(remove_symbols
[k
].seen
== FALSE
){
819 if(missing_syms
== 0){
820 error_arch(archs
+ i
, NULL
, "symbols names "
821 "listed in: %s not defined in: ",
825 fprintf(stderr
, "%s\n", remove_symbols
[k
].name
);
829 for(k
= 0; k
< nremove_symbols
; k
++){
830 remove_symbols
[k
].seen
= FALSE
;
833 * Reset the library offsets and size.
836 for(j
= 0; j
< archs
[i
].nmembers
; j
++){
837 archs
[i
].members
[j
].offset
= offset
;
839 if(archs
[i
].members
[j
].member_long_name
== TRUE
){
840 size
= round(archs
[i
].members
[j
].member_name_size
, 8) +
841 (round(sizeof(struct ar_hdr
), 8) -
842 sizeof(struct ar_hdr
));
843 archs
[i
].toc_long_name
= TRUE
;
845 if(archs
[i
].members
[j
].object
!= NULL
){
847 round(archs
[i
].members
[j
].object
->object_size
-
848 archs
[i
].members
[j
].object
->input_sym_info_size
+
849 archs
[i
].members
[j
].object
->output_sym_info_size
,
851 sprintf(archs
[i
].members
[j
].ar_hdr
->ar_size
, "%-*ld",
852 (int)sizeof(archs
[i
].members
[j
].ar_hdr
->ar_size
),
855 * This has to be done by hand because sprintf puts a
856 * null at the end of the buffer.
858 memcpy(archs
[i
].members
[j
].ar_hdr
->ar_fmag
, ARFMAG
,
859 (int)sizeof(archs
[i
].members
[j
].ar_hdr
->ar_fmag
));
862 size
+= archs
[i
].members
[j
].unknown_size
;
864 offset
+= sizeof(struct ar_hdr
) + size
;
866 archs
[i
].library_size
= offset
;
868 else if(archs
[i
].type
== OFILE_Mach_O
){
869 strip_object(archs
+ i
, NULL
, archs
[i
].object
);
872 warning_arch(archs
+ i
, NULL
, "can't process non-object and "
873 "non-archive file: ");
877 if(all_archs
== FALSE
&& narch_flags
!= 0){
878 for(i
= 0; i
< narch_flags
; i
++){
879 if(arch_flag_processed
[i
] == FALSE
)
880 error("file: %s does not contain architecture: %s",
881 archs
[0].file_name
, arch_flags
[i
].name
);
883 free(arch_flag_processed
);
885 if(any_processing
== FALSE
)
886 fatal("no processing done on input file: %s (specify a -arch flag)",
894 struct member
*member
,
895 struct object
*object
)
897 enum byte_sex host_byte_sex
;
898 struct nlist
*symbols
;
899 struct nlist_64
*symbols64
;
902 unsigned long strsize
;
903 unsigned long offset
;
904 struct dylib_table_of_contents
*tocs
;
906 struct dylib_module
*mods
;
907 struct dylib_module_64
*mods64
;
908 unsigned long nmodtab
;
909 struct dylib_reference
*refs
;
910 unsigned long nextrefsyms
;
911 uint32_t *indirectsyms
;
912 unsigned long nindirectsyms
;
914 struct load_command
*lc
;
915 struct segment_command
*sg
;
916 struct segment_command_64
*sg64
;
918 struct section_64
*s64
;
919 struct relocation_info
*relocs
;
920 struct scattered_relocation_info
*sreloc
;
921 long missing_reloc_symbols
;
922 unsigned long stride
, section_type
, nitems
;
930 host_byte_sex
= get_host_byte_sex();
932 /* Don't do anything to stub dylibs which have no load commands. */
933 if(object
->mh_filetype
== MH_DYLIB_STUB
){
934 if((object
->mh
!= NULL
&& object
->mh
->ncmds
== 0) ||
935 (object
->mh64
!= NULL
&& object
->mh64
->ncmds
== 0)){
939 if(object
->st
== NULL
|| object
->st
->nsyms
== 0){
940 warning_arch(arch
, member
, "input object file stripped: ");
944 nsyms
= object
->st
->nsyms
;
945 if(object
->mh
!= NULL
){
946 symbols
= (struct nlist
*)
947 (object
->object_addr
+ object
->st
->symoff
);
948 if(object
->object_byte_sex
!= host_byte_sex
)
949 swap_nlist(symbols
, nsyms
, host_byte_sex
);
954 symbols64
= (struct nlist_64
*)
955 (object
->object_addr
+ object
->st
->symoff
);
956 if(object
->object_byte_sex
!= host_byte_sex
)
957 swap_nlist_64(symbols64
, nsyms
, host_byte_sex
);
959 strings
= object
->object_addr
+ object
->st
->stroff
;
960 strsize
= object
->st
->strsize
;
963 if(object
->mh
!= NULL
)
964 flags
= object
->mh
->flags
;
966 flags
= object
->mh64
->flags
;
967 if(object
->mh_filetype
== MH_DYLIB
&&
968 (flags
& MH_PREBOUND
) != MH_PREBOUND
){
969 arch
->dont_update_LC_ID_DYLIB_timestamp
= TRUE
;
971 if(object
->mh_filetype
!= MH_DYLIB
&& cflag
)
972 fatal_arch(arch
, member
, "-c can't be used on non-dynamic "
974 #endif /* !(NMEDIT) */
975 if(object
->mh_filetype
== MH_DYLIB_STUB
)
976 fatal_arch(arch
, member
, "dynamic stub library can't be changed "
979 if(object
->mh_filetype
== MH_DYLIB
){
980 tocs
= (struct dylib_table_of_contents
*)
981 (object
->object_addr
+ object
->dyst
->tocoff
);
982 ntoc
= object
->dyst
->ntoc
;
983 nmodtab
= object
->dyst
->nmodtab
;
984 if(object
->mh
!= NULL
){
985 mods
= (struct dylib_module
*)
986 (object
->object_addr
+ object
->dyst
->modtaboff
);
987 if(object
->object_byte_sex
!= host_byte_sex
)
988 swap_dylib_module(mods
, nmodtab
, host_byte_sex
);
993 mods64
= (struct dylib_module_64
*)
994 (object
->object_addr
+ object
->dyst
->modtaboff
);
995 if(object
->object_byte_sex
!= host_byte_sex
)
996 swap_dylib_module_64(mods64
, nmodtab
, host_byte_sex
);
998 refs
= (struct dylib_reference
*)
999 (object
->object_addr
+ object
->dyst
->extrefsymoff
);
1000 nextrefsyms
= object
->dyst
->nextrefsyms
;
1001 if(object
->object_byte_sex
!= host_byte_sex
){
1002 swap_dylib_table_of_contents(tocs
, ntoc
, host_byte_sex
);
1003 swap_dylib_reference(refs
, nextrefsyms
, host_byte_sex
);
1007 * In the -c flag is specified then strip the section contents of
1008 * this dynamic library and change it into a stub library. When
1009 * creating a stub library the timestamp is not changed.
1012 arch
->dont_update_LC_ID_DYLIB_timestamp
= TRUE
;
1014 lc
= object
->load_commands
;
1015 if(object
->mh
!= NULL
){
1016 ncmds
= object
->mh
->ncmds
;
1017 object
->mh_filetype
= MH_DYLIB_STUB
;
1018 object
->mh
->filetype
= MH_DYLIB_STUB
;
1021 ncmds
= object
->mh64
->ncmds
;
1022 object
->mh_filetype
= MH_DYLIB_STUB
;
1023 object
->mh64
->filetype
= MH_DYLIB_STUB
;
1025 for(i
= 0; i
< ncmds
; i
++){
1026 if(lc
->cmd
== LC_SEGMENT
){
1027 sg
= (struct segment_command
*)lc
;
1028 if(strcmp(sg
->segname
, SEG_LINKEDIT
) != 0){
1030 * Zero out the section offset, reloff, and size
1031 * fields as the section contents are being removed.
1033 s
= (struct section
*)
1034 ((char *)sg
+ sizeof(struct segment_command
));
1035 for(j
= 0; j
< sg
->nsects
; j
++){
1037 * For section types with indirect tables we
1038 * do not zero out the section size in a stub
1039 * library. As the section size is needed to
1040 * know now many indirect table entries the
1041 * section has. This is a bit odd but programs
1042 * dealing with MH_DYLIB_STUB filetypes special
1045 section_type
= s
[j
].flags
& SECTION_TYPE
;
1046 if(section_type
!= S_SYMBOL_STUBS
&&
1047 section_type
!= S_LAZY_SYMBOL_POINTERS
&&
1048 section_type
!= S_NON_LAZY_SYMBOL_POINTERS
){
1055 /* zero out file offset and size in the segment */
1060 else if(lc
->cmd
== LC_SEGMENT_64
){
1061 sg64
= (struct segment_command_64
*)lc
;
1062 if(strcmp(sg64
->segname
, SEG_LINKEDIT
) != 0){
1064 * Zero out the section offset, reloff, and size
1065 * fields as the section contents are being removed.
1067 s64
= (struct section_64
*)
1069 sizeof(struct segment_command_64
));
1070 for(j
= 0; j
< sg64
->nsects
; j
++){
1072 * For section types with indirect tables we
1073 * do not zero out the section size in a stub
1074 * library. As the section size is needed to
1075 * know now many indirect table entries the
1076 * section has. This is a bit odd but programs
1077 * dealing with MH_DYLIB_STUB filetypes special
1080 section_type
= s64
[j
].flags
& SECTION_TYPE
;
1081 if(section_type
!= S_SYMBOL_STUBS
&&
1082 section_type
!= S_LAZY_SYMBOL_POINTERS
&&
1083 section_type
!= S_NON_LAZY_SYMBOL_POINTERS
){
1090 /* zero out file offset and size in the segment */
1095 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1098 * To get the right amount of the file copied out by writeout()
1099 * for the case when we are stripping out the section contents
1100 * we reduce the object size by the size of the section contents
1101 * including the padding after the load commands. Then this
1102 * size minus the size of the input symbolic information is
1105 if(object
->mh
!= NULL
){
1106 object
->object_size
-= (object
->seg_linkedit
->fileoff
-
1107 (sizeof(struct mach_header
) +
1108 object
->mh
->sizeofcmds
));
1110 * Set the file offset to the link edit information to be
1111 * right after the load commands.
1113 object
->seg_linkedit
->fileoff
=
1114 sizeof(struct mach_header
) +
1115 object
->mh
->sizeofcmds
;
1118 object
->object_size
-= (object
->seg_linkedit64
->fileoff
-
1119 (sizeof(struct mach_header_64
) +
1120 object
->mh64
->sizeofcmds
));
1122 * Set the file offset to the link edit information to be
1123 * right after the load commands.
1125 object
->seg_linkedit64
->fileoff
=
1126 sizeof(struct mach_header_64
) +
1127 object
->mh64
->sizeofcmds
;
1130 #endif /* !(NMEDIT) */
1143 * coalesced symbols can be stripped only if they are not used via an
1144 * symbol pointer. So to know that strip_symtab() needs to be passed
1145 * the indirect symbol table.
1147 if(object
->dyst
!= NULL
&& object
->dyst
->nindirectsyms
!= 0){
1148 nindirectsyms
= object
->dyst
->nindirectsyms
;
1149 indirectsyms
= (uint32_t *)
1150 (object
->object_addr
+ object
->dyst
->indirectsymoff
);
1151 if(object
->object_byte_sex
!= host_byte_sex
)
1152 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
1156 indirectsyms
= NULL
;
1160 if(object
->mh
!= NULL
)
1161 object
->input_sym_info_size
=
1162 nsyms
* sizeof(struct nlist
) +
1165 object
->input_sym_info_size
=
1166 nsyms
* sizeof(struct nlist_64
) +
1169 if(object
->mh
!= NULL
)
1170 flags
= object
->mh
->flags
;
1172 flags
= object
->mh64
->flags
;
1174 (flags
& MH_DYLDLINK
) == MH_DYLDLINK
&&
1175 object
->mh_filetype
== MH_EXECUTE
)
1176 default_dyld_executable
= TRUE
;
1178 default_dyld_executable
= FALSE
;
1179 #endif /* !defined(NMEDIT) */
1182 if(sfile
!= NULL
|| Rfile
!= NULL
|| dfile
!= NULL
|| Aflag
|| uflag
||
1183 Sflag
|| xflag
|| Xflag
|| nflag
|| rflag
||
1184 default_dyld_executable
|| object
->mh_filetype
== MH_DYLIB
||
1185 object
->mh_filetype
== MH_DYLINKER
)
1186 #endif /* !defined(NMEDIT) */
1189 if(edit_symtab(arch
, member
, object
, symbols
, symbols64
, nsyms
,
1190 strings
, strsize
, tocs
, ntoc
, mods
, mods64
, nmodtab
, refs
,
1191 nextrefsyms
) == FALSE
)
1193 #else /* !defined(NMEDIT) */
1194 if(strip_symtab(arch
, member
, object
, symbols
, symbols64
, nsyms
,
1195 strings
, strsize
, tocs
, ntoc
, mods
, mods64
, nmodtab
, refs
,
1196 nextrefsyms
, indirectsyms
, nindirectsyms
) == FALSE
)
1199 strip_LC_UUID_commands(arch
, member
, object
);
1200 #endif /* !defined(NMEDIT) */
1201 if(object
->mh
!= NULL
)
1202 object
->output_sym_info_size
=
1203 new_nsyms
* sizeof(struct nlist
) +
1206 object
->output_sym_info_size
=
1207 new_nsyms
* sizeof(struct nlist_64
) +
1210 object
->st
->nsyms
= new_nsyms
;
1211 object
->st
->strsize
= new_strsize
;
1213 if(object
->mh
!= NULL
)
1214 object
->output_symbols
= new_symbols
;
1216 object
->output_symbols64
= new_symbols64
;
1217 object
->output_nsymbols
= new_nsyms
;
1218 object
->output_strings
= new_strings
;
1219 object
->output_strings_size
= new_strsize
;
1221 if(object
->split_info_cmd
!= NULL
){
1222 object
->output_split_info_data
= object
->object_addr
+
1223 object
->split_info_cmd
->dataoff
;
1224 object
->output_split_info_data_size
=
1225 object
->split_info_cmd
->datasize
;
1227 if(object
->code_sig_cmd
!= NULL
){
1230 #endif /* !(NMEDIT) */
1232 object
->output_code_sig_data
= object
->object_addr
+
1233 object
->code_sig_cmd
->dataoff
;
1234 object
->output_code_sig_data_size
=
1235 object
->code_sig_cmd
->datasize
;
1239 if(object
->dyst
!= NULL
){
1240 object
->dyst
->ilocalsym
= 0;
1241 object
->dyst
->nlocalsym
= new_nlocalsym
;
1242 object
->dyst
->iextdefsym
= new_nlocalsym
;
1243 object
->dyst
->nextdefsym
= new_nextdefsym
;
1244 object
->dyst
->iundefsym
= new_nlocalsym
+ new_nextdefsym
;
1245 object
->dyst
->nundefsym
= new_nundefsym
;
1246 if(object
->dyst
->nindirectsyms
!= 0){
1247 object
->output_indirect_symtab
= indirectsyms
;
1248 if(object
->object_byte_sex
!= host_byte_sex
)
1249 swap_indirect_symbols(indirectsyms
, nindirectsyms
,
1250 object
->object_byte_sex
);
1254 * If the -c option is specified the object's filetype will
1255 * have been changed from MH_DYLIB to MH_DYLIB_STUB above.
1257 if(object
->mh_filetype
== MH_DYLIB
||
1258 object
->mh_filetype
== MH_DYLIB_STUB
){
1259 object
->output_tocs
= new_tocs
;
1260 object
->output_ntoc
= new_ntoc
;
1262 if(object
->mh
!= NULL
)
1263 object
->output_mods
= new_mods
;
1265 object
->output_mods64
= new_mods64
;
1266 object
->output_nmodtab
= new_nmodtab
;
1268 object
->output_mods
= mods
;
1269 object
->output_nmodtab
= nmodtab
;
1271 object
->output_refs
= new_refs
;
1272 object
->output_nextrefsyms
= new_nextrefsyms
;
1273 if(object
->object_byte_sex
!= host_byte_sex
){
1274 swap_dylib_table_of_contents(new_tocs
, new_ntoc
,
1275 object
->object_byte_sex
);
1277 if(object
->mh
!= NULL
)
1278 swap_dylib_module(new_mods
, new_nmodtab
,
1279 object
->object_byte_sex
);
1281 swap_dylib_module_64(new_mods64
, new_nmodtab
,
1282 object
->object_byte_sex
);
1284 if(object
->mh
!= NULL
)
1285 swap_dylib_module(mods
, nmodtab
,
1286 object
->object_byte_sex
);
1288 swap_dylib_module_64(mods64
, nmodtab
,
1289 object
->object_byte_sex
);
1291 swap_dylib_reference(new_refs
, new_nextrefsyms
,
1292 object
->object_byte_sex
);
1295 object
->input_sym_info_size
+=
1296 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1297 object
->dyst
->nextrel
* sizeof(struct relocation_info
) +
1298 object
->dyst
->ntoc
* sizeof(struct dylib_table_of_contents
)+
1299 object
->dyst
->nextrefsyms
* sizeof(struct dylib_reference
);
1300 if(object
->mh
!= NULL
){
1301 object
->input_sym_info_size
+=
1302 object
->dyst
->nmodtab
* sizeof(struct dylib_module
) +
1303 object
->dyst
->nindirectsyms
* sizeof(uint32_t);
1306 object
->input_sym_info_size
+=
1307 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
) +
1308 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1309 object
->input_indirectsym_pad
;
1313 * When stripping out the section contents to create a
1314 * dynamic library stub the relocation info also gets
1318 #endif /* !(NMEDIT) */
1320 object
->output_sym_info_size
+=
1321 object
->dyst
->nlocrel
* sizeof(struct relocation_info
) +
1322 object
->dyst
->nextrel
* sizeof(struct relocation_info
);
1324 object
->output_sym_info_size
+=
1325 new_ntoc
* sizeof(struct dylib_table_of_contents
)+
1326 new_nextrefsyms
* sizeof(struct dylib_reference
) +
1327 object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1328 object
->input_indirectsym_pad
;
1329 if(object
->mh
!= NULL
){
1330 object
->output_sym_info_size
+=
1331 object
->dyst
->nmodtab
* sizeof(struct dylib_module
);
1334 object
->output_sym_info_size
+=
1335 object
->dyst
->nmodtab
* sizeof(struct dylib_module_64
);
1337 if(object
->hints_cmd
!= NULL
){
1338 object
->input_sym_info_size
+=
1339 object
->hints_cmd
->nhints
*
1340 sizeof(struct twolevel_hint
);
1341 object
->output_sym_info_size
+=
1342 object
->hints_cmd
->nhints
*
1343 sizeof(struct twolevel_hint
);
1345 if(object
->split_info_cmd
!= NULL
){
1346 object
->input_sym_info_size
+=
1347 object
->split_info_cmd
->datasize
;
1348 object
->output_sym_info_size
+=
1349 object
->split_info_cmd
->datasize
;
1351 if(object
->code_sig_cmd
!= NULL
){
1352 object
->input_sym_info_size
=
1353 round(object
->input_sym_info_size
, 16);
1354 object
->input_sym_info_size
+=
1355 object
->code_sig_cmd
->datasize
;
1358 strip_LC_CODE_SIGNATURE_commands(arch
, member
, object
);
1361 #endif /* !(NMEDIT) */
1363 object
->output_sym_info_size
=
1364 round(object
->output_sym_info_size
, 16);
1365 object
->output_sym_info_size
+=
1366 object
->code_sig_cmd
->datasize
;
1370 object
->dyst
->ntoc
= new_ntoc
;
1371 object
->dyst
->nextrefsyms
= new_nextrefsyms
;
1373 if(object
->seg_linkedit
!= NULL
||
1374 object
->seg_linkedit64
!= NULL
){
1375 if(object
->mh
!= NULL
)
1376 offset
= object
->seg_linkedit
->fileoff
;
1378 offset
= object
->seg_linkedit64
->fileoff
;
1382 if(object
->dyst
->nlocrel
!= 0 &&
1383 object
->dyst
->locreloff
< offset
)
1384 offset
= object
->dyst
->locreloff
;
1385 if(object
->st
->nsyms
!= 0 &&
1386 object
->st
->symoff
< offset
)
1387 offset
= object
->st
->symoff
;
1388 if(object
->dyst
->nextrel
!= 0 &&
1389 object
->dyst
->extreloff
< offset
)
1390 offset
= object
->dyst
->extreloff
;
1391 if(object
->dyst
->nindirectsyms
!= 0 &&
1392 object
->dyst
->indirectsymoff
< offset
)
1393 offset
= object
->dyst
->indirectsymoff
;
1394 if(object
->dyst
->ntoc
!= 0 &&
1395 object
->dyst
->tocoff
< offset
)
1396 offset
= object
->dyst
->tocoff
;
1397 if(object
->dyst
->nmodtab
!= 0 &&
1398 object
->dyst
->modtaboff
< offset
)
1399 offset
= object
->dyst
->modtaboff
;
1400 if(object
->dyst
->nextrefsyms
!= 0 &&
1401 object
->dyst
->extrefsymoff
< offset
)
1402 offset
= object
->dyst
->extrefsymoff
;
1403 if(object
->st
->strsize
!= 0 &&
1404 object
->st
->stroff
< offset
)
1405 offset
= object
->st
->stroff
;
1408 if(object
->dyst
->nlocrel
!= 0){
1409 object
->output_loc_relocs
= (struct relocation_info
*)
1410 (object
->object_addr
+ object
->dyst
->locreloff
);
1413 * When stripping out the section contents to create a
1414 * dynamic library stub the relocation info also gets
1418 object
->dyst
->nlocrel
= 0;
1419 object
->dyst
->locreloff
= 0;
1422 #endif /* defined(NMEDIT) */
1424 object
->dyst
->locreloff
= offset
;
1425 offset
+= object
->dyst
->nlocrel
*
1426 sizeof(struct relocation_info
);
1430 object
->dyst
->locreloff
= 0;
1432 if(object
->split_info_cmd
!= NULL
){
1433 object
->split_info_cmd
->dataoff
= offset
;
1434 offset
+= object
->split_info_cmd
->datasize
;
1437 if(object
->st
->nsyms
!= 0){
1438 object
->st
->symoff
= offset
;
1439 if(object
->mh
!= NULL
)
1440 offset
+= object
->st
->nsyms
* sizeof(struct nlist
);
1442 offset
+= object
->st
->nsyms
* sizeof(struct nlist_64
);
1445 object
->st
->symoff
= 0;
1447 if(object
->hints_cmd
!= NULL
){
1448 if(object
->hints_cmd
->nhints
!= 0){
1449 object
->output_hints
= (struct twolevel_hint
*)
1450 (object
->object_addr
+ object
->hints_cmd
->offset
);
1451 object
->hints_cmd
->offset
= offset
;
1452 offset
+= object
->hints_cmd
->nhints
*
1453 sizeof(struct twolevel_hint
);
1456 object
->hints_cmd
->offset
= 0;
1459 if(object
->dyst
->nextrel
!= 0){
1460 object
->output_ext_relocs
= (struct relocation_info
*)
1461 (object
->object_addr
+ object
->dyst
->extreloff
);
1464 * When stripping out the section contents to create a
1465 * dynamic library stub the relocation info also gets
1469 object
->dyst
->nextrel
= 0;
1470 object
->dyst
->extreloff
= 0;
1473 #endif /* defined(NMEDIT) */
1475 object
->dyst
->extreloff
= offset
;
1476 offset
+= object
->dyst
->nextrel
*
1477 sizeof(struct relocation_info
);
1481 object
->dyst
->extreloff
= 0;
1483 if(object
->dyst
->nindirectsyms
!= 0){
1484 object
->dyst
->indirectsymoff
= offset
;
1485 offset
+= object
->dyst
->nindirectsyms
* sizeof(uint32_t) +
1486 object
->input_indirectsym_pad
;
1489 object
->dyst
->indirectsymoff
= 0;;
1491 if(object
->dyst
->ntoc
!= 0){
1492 object
->dyst
->tocoff
= offset
;
1493 offset
+= object
->dyst
->ntoc
*
1494 sizeof(struct dylib_table_of_contents
);
1497 object
->dyst
->tocoff
= 0;
1499 if(object
->dyst
->nmodtab
!= 0){
1502 * When stripping out the section contents to create a
1503 * dynamic library stub zero out the fields in the module
1504 * table for the sections and relocation information and
1505 * clear Objective-C address and size from modules.
1508 if(object
->mh
!= NULL
){
1509 for(k
= 0; k
< object
->dyst
->nmodtab
; k
++){
1510 mods
[k
].iinit_iterm
= 0;
1511 mods
[k
].ninit_nterm
= 0;
1512 mods
[k
].iextrel
= 0;
1513 mods
[k
].nextrel
= 0;
1514 mods
[k
].objc_module_info_addr
= 0;
1515 mods
[k
].objc_module_info_size
= 0;
1519 for(k
= 0; k
< object
->dyst
->nmodtab
; k
++){
1520 mods64
[k
].iinit_iterm
= 0;
1521 mods64
[k
].ninit_nterm
= 0;
1522 mods64
[k
].iextrel
= 0;
1523 mods64
[k
].nextrel
= 0;
1524 mods64
[k
].objc_module_info_addr
= 0;
1525 mods64
[k
].objc_module_info_size
= 0;
1529 #endif /* !(NMEDIT) */
1530 object
->dyst
->modtaboff
= offset
;
1531 if(object
->mh
!= NULL
)
1532 offset
+= object
->dyst
->nmodtab
*
1533 sizeof(struct dylib_module
);
1535 offset
+= object
->dyst
->nmodtab
*
1536 sizeof(struct dylib_module_64
);
1539 object
->dyst
->modtaboff
= 0;
1541 if(object
->dyst
->nextrefsyms
!= 0){
1542 object
->dyst
->extrefsymoff
= offset
;
1543 offset
+= object
->dyst
->nextrefsyms
*
1544 sizeof(struct dylib_reference
);
1547 object
->dyst
->extrefsymoff
= 0;
1549 if(object
->st
->strsize
!= 0){
1550 object
->st
->stroff
= offset
;
1551 offset
+= object
->st
->strsize
;
1554 object
->st
->stroff
= 0;
1556 if(object
->code_sig_cmd
!= NULL
){
1557 offset
= round(offset
, 16);
1558 object
->code_sig_cmd
->dataoff
= offset
;
1559 offset
+= object
->code_sig_cmd
->datasize
;
1563 if(new_strsize
!= 0){
1564 if(object
->mh
!= NULL
)
1565 object
->st
->stroff
= object
->st
->symoff
+
1566 new_nsyms
* sizeof(struct nlist
);
1568 object
->st
->stroff
= object
->st
->symoff
+
1569 new_nsyms
* sizeof(struct nlist_64
);
1572 object
->st
->stroff
= 0;
1574 object
->st
->symoff
= 0;
1581 saves
= (long *)allocate(object
->st
->nsyms
* sizeof(long));
1582 bzero(saves
, object
->st
->nsyms
* sizeof(long));
1584 object
->output_sym_info_size
= 0;
1585 object
->st
->symoff
= 0;
1586 object
->st
->nsyms
= 0;
1587 object
->st
->stroff
= 0;
1588 object
->st
->strsize
= 0;
1589 if(object
->dyst
!= NULL
){
1590 object
->dyst
->ilocalsym
= 0;
1591 object
->dyst
->nlocalsym
= 0;
1592 object
->dyst
->iextdefsym
= 0;
1593 object
->dyst
->nextdefsym
= 0;
1594 object
->dyst
->iundefsym
= 0;
1595 object
->dyst
->nundefsym
= 0;
1598 * We set these so that checking can be done below to report the
1599 * symbols that can't be stripped because of relocation entries
1600 * or indirect symbol table entries. If these table are non-zero
1601 * number of entries it will be an error as we are trying to
1604 if(object
->dyst
!= NULL
){
1605 if(object
->dyst
->nextrel
!= 0){
1606 object
->output_ext_relocs
= (struct relocation_info
*)
1607 (object
->object_addr
+ object
->dyst
->extreloff
);
1609 if(object
->dyst
->nindirectsyms
!= 0){
1610 object
->output_indirect_symtab
= (uint32_t *)
1611 (object
->object_addr
+
1612 object
->dyst
->indirectsymoff
);
1613 if(object
->object_byte_sex
!= host_byte_sex
)
1614 swap_indirect_symbols(
1615 object
->output_indirect_symtab
,
1616 object
->dyst
->nindirectsyms
,
1617 object
->object_byte_sex
);
1620 * Since this file has a dynamic symbol table and if this file
1621 * has local relocation entries on input make sure they are
1622 * there on output. This is a rare case that it will not have
1623 * external relocs or indirect symbols but can happen as is the
1624 * case with the dynamic linker itself.
1626 if(object
->dyst
->nlocrel
!= 0){
1627 object
->output_loc_relocs
= (struct relocation_info
*)
1628 (object
->object_addr
+ object
->dyst
->locreloff
);
1629 object
->output_sym_info_size
+=
1630 object
->dyst
->nlocrel
* sizeof(struct relocation_info
);
1634 #endif /* !defined(NMEDIT) */
1637 * Always clear the prebind checksum if any when creating a new file.
1639 if(object
->cs
!= NULL
)
1640 object
->cs
->cksum
= 0;
1642 if(object
->seg_linkedit
!= NULL
){
1643 object
->seg_linkedit
->filesize
+= object
->output_sym_info_size
-
1644 object
->input_sym_info_size
;
1645 object
->seg_linkedit
->vmsize
= object
->seg_linkedit
->filesize
;
1647 else if(object
->seg_linkedit64
!= NULL
){
1648 /* Do this in two steps to avoid 32/64-bit casting problems. */
1649 object
->seg_linkedit64
->filesize
-= object
->input_sym_info_size
;
1650 object
->seg_linkedit64
->filesize
+= object
->output_sym_info_size
;
1651 object
->seg_linkedit64
->vmsize
= object
->seg_linkedit64
->filesize
;
1655 * Check and update the external relocation entries to make sure
1656 * referenced symbols are not stripped and refer to the new symbol
1659 * The external relocation entries can be located in one of two places,
1660 * first off of the sections or second off of the dynamic symtab.
1662 missing_reloc_symbols
= 0;
1663 lc
= object
->load_commands
;
1664 if(object
->mh
!= NULL
)
1665 ncmds
= object
->mh
->ncmds
;
1667 ncmds
= object
->mh64
->ncmds
;
1668 for(i
= 0; i
< ncmds
; i
++){
1669 if(lc
->cmd
== LC_SEGMENT
&&
1670 object
->seg_linkedit
!= (struct segment_command
*)lc
){
1671 sg
= (struct segment_command
*)lc
;
1672 s
= (struct section
*)((char *)sg
+
1673 sizeof(struct segment_command
));
1674 for(j
= 0; j
< sg
->nsects
; j
++){
1676 if(s
->reloff
+ s
->nreloc
*
1677 sizeof(struct relocation_info
) >
1678 object
->object_size
){
1679 fatal_arch(arch
, member
, "truncated or malformed "
1680 "object (relocation entries for section (%.16s,"
1681 "%.16s) extends past the end of the file)",
1682 s
->segname
, s
->sectname
);
1684 relocs
= (struct relocation_info
*)
1685 (object
->object_addr
+ s
->reloff
);
1686 if(object
->object_byte_sex
!= host_byte_sex
)
1687 swap_relocation_info(relocs
, s
->nreloc
,
1689 if(s
->offset
+ s
->size
> object
->object_size
){
1690 fatal_arch(arch
, member
, "truncated or malformed "
1691 "object (contents of section (%.16s,"
1692 "%.16s) extends past the end of the file)",
1693 s
->segname
, s
->sectname
);
1695 contents
= object
->object_addr
+ s
->offset
;
1696 check_object_relocs(arch
, member
, object
, s
->segname
,
1697 s
->sectname
, s
->size
, contents
, relocs
, s
->nreloc
,
1698 symbols
, symbols64
, nsyms
, strings
,
1699 &missing_reloc_symbols
, host_byte_sex
);
1700 if(object
->object_byte_sex
!= host_byte_sex
)
1701 swap_relocation_info(relocs
, s
->nreloc
,
1702 object
->object_byte_sex
);
1707 else if(lc
->cmd
== LC_SEGMENT_64
&&
1708 object
->seg_linkedit64
!= (struct segment_command_64
*)lc
){
1709 sg64
= (struct segment_command_64
*)lc
;
1710 s64
= (struct section_64
*)((char *)sg64
+
1711 sizeof(struct segment_command_64
));
1712 for(j
= 0; j
< sg64
->nsects
; j
++){
1713 if(s64
->nreloc
!= 0){
1714 if(s64
->reloff
+ s64
->nreloc
*
1715 sizeof(struct relocation_info
) >
1716 object
->object_size
){
1717 fatal_arch(arch
, member
, "truncated or malformed "
1718 "object (relocation entries for section (%.16s,"
1719 "%.16s) extends past the end of the file)",
1720 s64
->segname
, s64
->sectname
);
1722 relocs
= (struct relocation_info
*)
1723 (object
->object_addr
+ s64
->reloff
);
1724 if(object
->object_byte_sex
!= host_byte_sex
)
1725 swap_relocation_info(relocs
, s64
->nreloc
,
1727 if(s64
->offset
+ s64
->size
> object
->object_size
){
1728 fatal_arch(arch
, member
, "truncated or malformed "
1729 "object (contents of section (%.16s,"
1730 "%.16s) extends past the end of the file)",
1731 s64
->segname
, s64
->sectname
);
1733 contents
= object
->object_addr
+ s64
->offset
;
1734 check_object_relocs(arch
, member
, object
, s64
->segname
,
1735 s64
->sectname
, s64
->size
, contents
, relocs
,
1736 s64
->nreloc
, symbols
, symbols64
, nsyms
, strings
,
1737 &missing_reloc_symbols
, host_byte_sex
);
1738 if(object
->object_byte_sex
!= host_byte_sex
)
1739 swap_relocation_info(relocs
, s64
->nreloc
,
1740 object
->object_byte_sex
);
1745 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1747 if(object
->dyst
!= NULL
&& object
->dyst
->nextrel
!= 0){
1748 relocs
= object
->output_ext_relocs
;
1749 if(object
->object_byte_sex
!= host_byte_sex
)
1750 swap_relocation_info(relocs
, object
->dyst
->nextrel
,
1753 for(i
= 0; i
< object
->dyst
->nextrel
; i
++){
1754 if((relocs
[i
].r_address
& R_SCATTERED
) == 0 &&
1755 relocs
[i
].r_extern
== 1){
1756 if(relocs
[i
].r_symbolnum
> nsyms
){
1757 fatal_arch(arch
, member
, "bad r_symbolnum for external "
1758 "relocation entry %ld in: ", i
);
1760 if(saves
[relocs
[i
].r_symbolnum
] == 0){
1761 if(missing_reloc_symbols
== 0){
1762 error_arch(arch
, member
, "symbols referenced by "
1763 "relocation entries that can't be stripped in: ");
1764 missing_reloc_symbols
= 1;
1766 if(object
->mh
!= NULL
){
1767 fprintf(stderr
, "%s\n", strings
+ symbols
1768 [relocs
[i
].r_symbolnum
].n_un
.n_strx
);
1771 fprintf(stderr
, "%s\n", strings
+ symbols64
1772 [relocs
[i
].r_symbolnum
].n_un
.n_strx
);
1774 saves
[relocs
[i
].r_symbolnum
] = -1;
1776 if(saves
[relocs
[i
].r_symbolnum
] != -1){
1777 relocs
[i
].r_symbolnum
=
1778 saves
[relocs
[i
].r_symbolnum
] - 1;
1782 fatal_arch(arch
, member
, "bad external relocation entry "
1783 "%ld (not external) in: ", i
);
1785 if((relocs
[i
].r_address
& R_SCATTERED
) == 0){
1786 if(reloc_has_pair(object
->mh_cputype
, relocs
[i
].r_type
))
1790 sreloc
= (struct scattered_relocation_info
*)relocs
+ i
;
1791 if(reloc_has_pair(object
->mh_cputype
, sreloc
->r_type
))
1795 if(object
->object_byte_sex
!= host_byte_sex
)
1796 swap_relocation_info(relocs
, object
->dyst
->nextrel
,
1797 object
->object_byte_sex
);
1801 * Check and update the indirect symbol table entries to make sure
1802 * referenced symbols are not stripped and refer to the new symbol
1805 if(object
->dyst
!= NULL
&& object
->dyst
->nindirectsyms
!= 0){
1806 if(object
->object_byte_sex
!= host_byte_sex
)
1807 swap_indirect_symbols(object
->output_indirect_symtab
,
1808 object
->dyst
->nindirectsyms
, host_byte_sex
);
1810 lc
= object
->load_commands
;
1811 if(object
->mh
!= NULL
)
1812 ncmds
= object
->mh
->ncmds
;
1814 ncmds
= object
->mh64
->ncmds
;
1815 for(i
= 0; i
< ncmds
; i
++){
1816 if(lc
->cmd
== LC_SEGMENT
&&
1817 object
->seg_linkedit
!= (struct segment_command
*)lc
){
1818 sg
= (struct segment_command
*)lc
;
1819 s
= (struct section
*)((char *)sg
+
1820 sizeof(struct segment_command
));
1821 for(j
= 0; j
< sg
->nsects
; j
++){
1822 section_type
= s
->flags
& SECTION_TYPE
;
1823 if(section_type
== S_LAZY_SYMBOL_POINTERS
||
1824 section_type
== S_NON_LAZY_SYMBOL_POINTERS
)
1826 else if(section_type
== S_SYMBOL_STUBS
)
1827 stride
= s
->reserved2
;
1832 nitems
= s
->size
/ stride
;
1833 contents
= object
->object_addr
+ s
->offset
;
1834 check_indirect_symtab(arch
, member
, object
, nitems
,
1835 s
->reserved1
, section_type
, contents
, symbols
,
1836 symbols64
, nsyms
, strings
, &missing_reloc_symbols
,
1841 else if(lc
->cmd
== LC_SEGMENT_64
&&
1842 object
->seg_linkedit64
!= (struct segment_command_64
*)lc
){
1843 sg64
= (struct segment_command_64
*)lc
;
1844 s64
= (struct section_64
*)((char *)sg64
+
1845 sizeof(struct segment_command_64
));
1846 for(j
= 0; j
< sg64
->nsects
; j
++){
1847 section_type
= s64
->flags
& SECTION_TYPE
;
1848 if(section_type
== S_LAZY_SYMBOL_POINTERS
||
1849 section_type
== S_NON_LAZY_SYMBOL_POINTERS
)
1851 else if(section_type
== S_SYMBOL_STUBS
)
1852 stride
= s64
->reserved2
;
1857 nitems
= s64
->size
/ stride
;
1858 contents
= object
->object_addr
+ s64
->offset
;
1859 check_indirect_symtab(arch
, member
, object
, nitems
,
1860 s64
->reserved1
, section_type
, contents
, symbols
,
1861 symbols64
, nsyms
, strings
, &missing_reloc_symbols
,
1866 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1869 if(object
->object_byte_sex
!= host_byte_sex
)
1870 swap_indirect_symbols(object
->output_indirect_symtab
,
1871 object
->dyst
->nindirectsyms
, object
->object_byte_sex
);
1875 * Issue a warning if object file has a code signature that the
1876 * operation will invalidate it.
1878 if(object
->code_sig_cmd
!= NULL
)
1879 warning_arch(arch
, member
, "changes being made to the file will "
1880 "invalidate the code signature in: ");
1884 * check_object_relocs() is used to check and update the external relocation
1885 * entries from a section in an object file, to make sure referenced symbols
1886 * are not stripped and are changed to refer to the new symbol table indexes.
1890 check_object_relocs(
1892 struct member
*member
,
1893 struct object
*object
,
1896 unsigned long long sectsize
,
1898 struct relocation_info
*relocs
,
1900 struct nlist
*symbols
,
1901 struct nlist_64
*symbols64
,
1902 unsigned long nsyms
,
1904 long *missing_reloc_symbols
,
1905 enum byte_sex host_byte_sex
)
1907 unsigned long k
, n_strx
;
1910 unsigned long value
, n_ext
;
1913 struct scattered_relocation_info
*sreloc
;
1915 for(k
= 0; k
< nreloc
; k
++){
1916 if((relocs
[k
].r_address
& R_SCATTERED
) == 0 &&
1917 relocs
[k
].r_extern
== 1){
1918 if(relocs
[k
].r_symbolnum
> nsyms
){
1919 fatal_arch(arch
, member
, "bad r_symbolnum for relocation "
1920 "entry %ld in section (%.16s,%.16s) in: ", k
, segname
,
1923 if(object
->mh
!= NULL
){
1924 n_strx
= symbols
[relocs
[k
].r_symbolnum
].n_un
.n_strx
;
1925 n_value
= symbols
[relocs
[k
].r_symbolnum
].n_value
;
1928 n_strx
= symbols64
[relocs
[k
].r_symbolnum
].n_un
.n_strx
;
1929 n_value
= symbols64
[relocs
[k
].r_symbolnum
].n_value
;
1932 if(saves
[relocs
[k
].r_symbolnum
] == 0){
1933 if(*missing_reloc_symbols
== 0){
1934 error_arch(arch
, member
, "symbols referenced by "
1935 "relocation entries that can't be stripped in: ");
1936 *missing_reloc_symbols
= 1;
1938 fprintf(stderr
, "%s\n", strings
+ n_strx
);
1939 saves
[relocs
[k
].r_symbolnum
] = -1;
1941 #else /* defined(NMEDIT) */
1943 * We are letting nmedit change global coalesed symbols into
1944 * statics in MH_OBJECT file types only. Relocation entries to
1945 * global coalesced symbols are external relocs.
1947 if(object
->mh
!= NULL
)
1948 n_ext
= new_symbols
[saves
[relocs
[k
].r_symbolnum
] - 1].
1951 n_ext
= new_symbols64
[saves
[relocs
[k
].r_symbolnum
] - 1].
1953 if(n_ext
!= N_EXT
&&
1954 object
->mh_cputype
!= CPU_TYPE_X86_64
){
1956 * We need to do the relocation for this external relocation
1957 * entry so the item to be relocated is correct for a local
1958 * relocation entry. We don't need to do this for x86-64.
1960 if(relocs
[k
].r_address
+ sizeof(long) > sectsize
){
1961 fatal_arch(arch
, member
, "truncated or malformed "
1962 "object (r_address of relocation entry %lu of "
1963 "section (%.16s,%.16s) extends past the end "
1964 "of the section)", k
, segname
, sectname
);
1966 if(object
->mh
!= NULL
){
1967 value
= *(unsigned long *)
1968 (contents
+ relocs
[k
].r_address
);
1969 if(object
->object_byte_sex
!= host_byte_sex
)
1970 value
= SWAP_LONG(value
);
1972 * We handle a very limited form here. Only VANILLA
1973 * (r_type == 0) long (r_length==2) absolute or pcrel
1974 * that won't need a scattered relocation entry.
1976 if(relocs
[k
].r_type
!= 0 ||
1977 relocs
[k
].r_length
!= 2){
1978 fatal_arch(arch
, member
, "don't have "
1979 "code to convert external relocation "
1980 "entry %ld in section (%.16s,%.16s) "
1981 "for global coalesced symbol: %s "
1982 "in: ", k
, segname
, sectname
,
1986 if(object
->object_byte_sex
!= host_byte_sex
)
1987 value
= SWAP_LONG(value
);
1988 *(unsigned long *)(contents
+ relocs
[k
].r_address
) =
1992 value64
= *(uint64_t *)(contents
+ relocs
[k
].r_address
);
1993 if(object
->object_byte_sex
!= host_byte_sex
)
1994 value64
= SWAP_LONG_LONG(value64
);
1996 * We handle a very limited form here. Only VANILLA
1997 * (r_type == 0) quad (r_length==3) absolute or pcrel
1998 * that won't need a scattered relocation entry.
2000 if(relocs
[k
].r_type
!= 0 ||
2001 relocs
[k
].r_length
!= 3){
2002 fatal_arch(arch
, member
, "don't have "
2003 "code to convert external relocation "
2004 "entry %ld in section (%.16s,%.16s) "
2005 "for global coalesced symbol: %s "
2006 "in: ", k
, segname
, sectname
,
2010 if(object
->object_byte_sex
!= host_byte_sex
)
2011 value64
= SWAP_LONG_LONG(value
);
2012 *(uint64_t *)(contents
+ relocs
[k
].r_address
) = value64
;
2015 * Turn the extern reloc into a local.
2017 if(object
->mh
!= NULL
)
2018 relocs
[k
].r_symbolnum
=
2019 new_symbols
[saves
[relocs
[k
].r_symbolnum
] - 1].n_sect
;
2021 relocs
[k
].r_symbolnum
=
2022 new_symbols64
[saves
[relocs
[k
].r_symbolnum
] - 1].n_sect
;
2023 relocs
[k
].r_extern
= 0;
2026 if(relocs
[k
].r_extern
== 1 &&
2027 saves
[relocs
[k
].r_symbolnum
] != -1){
2028 relocs
[k
].r_symbolnum
= saves
[relocs
[k
].r_symbolnum
] - 1;
2031 if((relocs
[k
].r_address
& R_SCATTERED
) == 0){
2032 if(reloc_has_pair(object
->mh_cputype
, relocs
[k
].r_type
) == TRUE
)
2036 sreloc
= (struct scattered_relocation_info
*)relocs
+ k
;
2037 if(reloc_has_pair(object
->mh_cputype
, sreloc
->r_type
) == TRUE
)
2044 * check_indirect_symtab() checks and updates the indirect symbol table entries
2045 * to make sure referenced symbols are not stripped and refer to the new symbol
2050 check_indirect_symtab(
2052 struct member
*member
,
2053 struct object
*object
,
2054 unsigned long nitems
,
2055 unsigned long reserved1
,
2056 unsigned long section_type
,
2058 struct nlist
*symbols
,
2059 struct nlist_64
*symbols64
,
2060 unsigned long nsyms
,
2062 long *missing_reloc_symbols
,
2063 enum byte_sex host_byte_sex
)
2065 unsigned long k
, index
;
2067 uint32_t n_strx
, value
;
2069 enum bool made_local
;
2071 for(k
= 0; k
< nitems
; k
++){
2073 index
= object
->output_indirect_symtab
[reserved1
+ k
];
2074 if(index
== INDIRECT_SYMBOL_LOCAL
||
2075 index
== INDIRECT_SYMBOL_ABS
||
2076 index
== (INDIRECT_SYMBOL_LOCAL
| INDIRECT_SYMBOL_ABS
))
2079 fatal_arch(arch
, member
,"indirect symbol table entry %ld (past " "the end of the symbol table) in: ", reserved1
+ k
);
2081 if(pflag
== 0 && nmedits
[index
] == TRUE
&& saves
[index
] != -1)
2083 if(saves
[index
] == 0)
2087 * Indirect symbol table entries for defined symbols in a
2088 * non-lazy pointer section that are not saved are changed to
2089 * INDIRECT_SYMBOL_LOCAL which their values just have to be
2090 * slid if the are not absolute symbols.
2092 if(object
->mh
!= NULL
){
2093 n_type
= symbols
[index
].n_type
;
2094 n_strx
= symbols
[index
].n_un
.n_strx
;
2097 n_type
= symbols64
[index
].n_type
;
2098 n_strx
= symbols64
[index
].n_un
.n_strx
;
2100 if((n_type
&& N_TYPE
) != N_UNDF
&&
2101 (n_type
&& N_TYPE
) != N_PBUD
&&
2102 section_type
== S_NON_LAZY_SYMBOL_POINTERS
){
2103 object
->output_indirect_symtab
[reserved1
+ k
] =
2104 INDIRECT_SYMBOL_LOCAL
;
2105 if((n_type
& N_TYPE
) == N_ABS
)
2106 object
->output_indirect_symtab
[reserved1
+ k
] |=
2107 INDIRECT_SYMBOL_ABS
;
2110 * When creating a stub shared library the section contents
2111 * are not updated since they will be stripped.
2113 if(object
->mh_filetype
!= MH_DYLIB_STUB
){
2114 if(object
->mh
!= NULL
){
2115 value
= symbols
[index
].n_value
;
2116 if (symbols
[index
].n_desc
& N_ARM_THUMB_DEF
)
2118 if(object
->object_byte_sex
!= host_byte_sex
)
2119 value
= SWAP_LONG(value
);
2120 *(uint32_t *)(contents
+ k
* 4) = value
;
2123 value64
= symbols64
[index
].n_value
;
2124 if(object
->object_byte_sex
!= host_byte_sex
)
2125 value64
= SWAP_LONG_LONG(value64
);
2126 *(uint64_t *)(contents
+ k
* 8) = value64
;
2132 object
->output_indirect_symtab
[reserved1
+ k
] =
2135 #else /* !defined(NMEDIT) */
2137 if(*missing_reloc_symbols
== 0){
2138 error_arch(arch
, member
, "symbols referenced by "
2139 "indirect symbol table entries that can't be "
2141 *missing_reloc_symbols
= 1;
2143 fprintf(stderr
, "%s\n", strings
+ n_strx
);
2146 #endif /* !defined(NMEDIT) */
2150 #else /* !defined(NMEDIT) */
2151 if(made_local
== FALSE
&& saves
[index
] != -1)
2152 #endif /* !defined(NMEDIT) */
2154 object
->output_indirect_symtab
[reserved1
+k
] = saves
[index
] - 1;
2161 * This is called if there is a -d option specified. It reads the file with
2162 * the strings in it and places them in the array debug_filenames and sorts
2163 * them by name. The file that contains the file names must have names one
2164 * per line with no white space (except the newlines).
2168 setup_debug_filenames(
2171 int fd
, i
, strings_size
;
2172 struct stat stat_buf
;
2175 if((fd
= open(dfile
, O_RDONLY
)) < 0){
2176 system_error("can't open: %s", dfile
);
2179 if(fstat(fd
, &stat_buf
) == -1){
2180 system_error("can't stat: %s", dfile
);
2184 strings_size
= stat_buf
.st_size
;
2185 strings
= (char *)allocate(strings_size
+ 1);
2186 strings
[strings_size
] = '\0';
2187 if(read(fd
, strings
, strings_size
) != strings_size
){
2188 system_error("can't read: %s", dfile
);
2193 for(i
= 0; i
< strings_size
; i
++){
2200 debug_filenames
= (char **)allocate(ndebug_filenames
* sizeof(char *));
2202 for(i
= 0; i
< ndebug_filenames
; i
++){
2203 debug_filenames
[i
] = p
;
2206 qsort(debug_filenames
, ndebug_filenames
, sizeof(char *),
2207 (int (*)(const void *, const void *))cmp_qsort_filename
);
2210 printf("Debug filenames:\n");
2211 for(i
= 0; i
< ndebug_filenames
; i
++){
2212 printf("filename = %s\n", debug_filenames
[i
]);
2218 * Strip the symbol table to the level specified by the command line arguments.
2219 * The new symbol table is built and new_symbols is left pointing to it. The
2220 * number of new symbols is left in new_nsyms, the new string table is built
2221 * and new_stings is left pointing to it and new_strsize is left containing it.
2222 * This routine returns zero if successfull and non-zero otherwise.
2228 struct member
*member
,
2229 struct object
*object
,
2230 struct nlist
*symbols
,
2231 struct nlist_64
*symbols64
,
2232 unsigned long nsyms
,
2234 unsigned long strsize
,
2235 struct dylib_table_of_contents
*tocs
,
2237 struct dylib_module
*mods
,
2238 struct dylib_module_64
*mods64
,
2239 unsigned long nmodtab
,
2240 struct dylib_reference
*refs
,
2241 unsigned long nextrefsyms
,
2242 uint32_t *indirectsyms
,
2243 unsigned long nindirectsyms
)
2245 unsigned long i
, j
, k
, n
, inew_syms
, save_debug
, missing_syms
;
2246 unsigned long missing_symbols
;
2247 char *p
, *q
, **pp
, *basename
;
2248 struct symbol_list
*sp
;
2249 unsigned long new_ext_strsize
, len
, *changes
, inew_undefsyms
;
2250 unsigned char nsects
;
2251 struct load_command
*lc
;
2252 struct segment_command
*sg
;
2253 struct segment_command_64
*sg64
;
2254 struct section
*s
, **sections
;
2255 struct section_64
*s64
, **sections64
;
2256 uint32_t ncmds
, mh_flags
, s_flags
, n_strx
;
2258 struct undef_map
*undef_map
;
2259 struct undef_map64
*undef_map64
;
2260 uint8_t n_type
, n_sect
;
2263 uint32_t module_name
, iextdefsym
, nextdefsym
, ilocalsym
, nlocalsym
;
2264 uint32_t irefsym
, nrefsym
;
2269 saves
= (long *)allocate(nsyms
* sizeof(long));
2270 bzero(saves
, nsyms
* sizeof(long));
2272 for(i
= 0; i
< nsave_symbols
; i
++)
2273 save_symbols
[i
].sym
= NULL
;
2274 for(i
= 0; i
< nremove_symbols
; i
++)
2275 remove_symbols
[i
].sym
= NULL
;
2277 for(i
= 0; i
< nsave_symbols
; i
++)
2278 save_symbols
[i
].seen
= FALSE
;
2279 for(i
= 0; i
< nremove_symbols
; i
++)
2280 remove_symbols
[i
].seen
= FALSE
;
2284 new_strsize
= sizeof(long);
2288 new_ext_strsize
= 0;
2291 * Gather an array of section struct pointers so we can later determine
2292 * if we run into a global symbol in a coalesced section and not strip
2297 lc
= object
->load_commands
;
2298 if(object
->mh
!= NULL
)
2299 ncmds
= object
->mh
->ncmds
;
2301 ncmds
= object
->mh64
->ncmds
;
2302 for(i
= 0; i
< ncmds
; i
++){
2303 if(lc
->cmd
== LC_SEGMENT
){
2304 sg
= (struct segment_command
*)lc
;
2305 nsects
+= sg
->nsects
;
2307 else if(lc
->cmd
== LC_SEGMENT_64
){
2308 sg64
= (struct segment_command_64
*)lc
;
2309 nsects
+= sg64
->nsects
;
2311 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2313 if(object
->mh
!= NULL
){
2314 sections
= allocate(nsects
* sizeof(struct section
*));
2319 sections64
= allocate(nsects
* sizeof(struct section_64
*));
2322 lc
= object
->load_commands
;
2323 for(i
= 0; i
< ncmds
; i
++){
2324 if(lc
->cmd
== LC_SEGMENT
){
2325 sg
= (struct segment_command
*)lc
;
2326 s
= (struct section
*)((char *)sg
+
2327 sizeof(struct segment_command
));
2328 for(j
= 0; j
< sg
->nsects
; j
++)
2329 sections
[nsects
++] = s
++;
2331 else if(lc
->cmd
== LC_SEGMENT_64
){
2332 sg64
= (struct segment_command_64
*)lc
;
2333 s64
= (struct section_64
*)((char *)sg64
+
2334 sizeof(struct segment_command_64
));
2335 for(j
= 0; j
< sg64
->nsects
; j
++)
2336 sections64
[nsects
++] = s64
++;
2338 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2341 for(i
= 0; i
< nsyms
; i
++){
2343 if(object
->mh
!= NULL
){
2344 mh_flags
= object
->mh
->flags
;
2345 n_strx
= symbols
[i
].n_un
.n_strx
;
2346 n_type
= symbols
[i
].n_type
;
2347 n_sect
= symbols
[i
].n_sect
;
2348 if((n_type
& N_TYPE
) == N_SECT
){
2349 if(n_sect
== 0 || n_sect
> nsects
){
2350 error_arch(arch
, member
, "bad n_sect for symbol "
2351 "table entry %ld in: ", i
);
2354 s_flags
= sections
[n_sect
- 1]->flags
;
2356 n_desc
= symbols
[i
].n_desc
;
2357 n_value
= symbols
[i
].n_value
;
2360 mh_flags
= object
->mh64
->flags
;
2361 n_strx
= symbols64
[i
].n_un
.n_strx
;
2362 n_type
= symbols64
[i
].n_type
;
2363 n_sect
= symbols64
[i
].n_sect
;
2364 if((n_type
& N_TYPE
) == N_SECT
){
2365 if(n_sect
== 0 || n_sect
> nsects
){
2366 error_arch(arch
, member
, "bad n_sect for symbol "
2367 "table entry %ld in: ", i
);
2370 s_flags
= sections64
[n_sect
- 1]->flags
;
2372 n_desc
= symbols64
[i
].n_desc
;
2373 n_value
= symbols64
[i
].n_value
;
2376 if(n_strx
> strsize
){
2377 error_arch(arch
, member
, "bad string index for symbol "
2378 "table entry %ld in: ", i
);
2382 if((n_type
& N_TYPE
) == N_INDR
){
2384 if(n_value
> strsize
){
2385 error_arch(arch
, member
, "bad string index for "
2386 "indirect symbol table entry %ld in: ", i
);
2391 if((n_type
& N_EXT
) == 0){ /* local symbol */
2393 * strip -x or -X on an x86_64 .o file should do nothing.
2395 if(object
->mh
== NULL
&&
2396 object
->mh64
->cputype
== CPU_TYPE_X86_64
&&
2397 object
->mh64
->filetype
== MH_OBJECT
&&
2398 (xflag
== 1 || Xflag
== 1)){
2400 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2403 saves
[i
] = new_nsyms
;
2406 * The cases a local symbol might be saved is with -X -S or
2409 else if((!strip_all
&& (Xflag
|| Sflag
)) || dfile
){
2410 if(n_type
& N_STAB
){ /* debug symbol */
2411 if(dfile
&& n_type
== N_SO
){
2413 basename
= strrchr(strings
+ n_strx
, '/');
2414 if(basename
!= NULL
)
2417 basename
= strings
+ n_strx
;
2418 pp
= bsearch(basename
, debug_filenames
,
2419 ndebug_filenames
, sizeof(char *),
2420 (int (*)(const void *, const void *)
2421 )cmp_bsearch_filename
);
2423 * Save the bracketing N_SO. For each N_SO that
2424 * has a filename there is an N_SO that has a
2425 * name of "" which ends the stabs for that file
2427 if(*basename
!= '\0'){
2435 * This is a bracketing SO so if we are
2436 * currently saving debug symbols save this
2437 * last one and turn off saving debug syms.
2441 new_strsize
+= strlen(strings
+
2445 saves
[i
] = new_nsyms
;
2454 if(saves
[i
] == 0 && (!Sflag
|| save_debug
)){
2456 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2459 saves
[i
] = new_nsyms
;
2462 else{ /* non-debug local symbol */
2463 if(xflag
== 0 && (Sflag
|| Xflag
)){
2466 strings
[n_strx
] != 'L')){
2468 * If this file is a for the dynamic linker and
2469 * this symbol is in a section marked so that
2470 * static symbols are stripped then don't
2473 if((mh_flags
& MH_DYLDLINK
) != MH_DYLDLINK
||
2474 (n_type
& N_TYPE
) != N_SECT
||
2475 (s_flags
& S_ATTR_STRIP_STATIC_SYMS
) !=
2476 S_ATTR_STRIP_STATIC_SYMS
){
2477 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2480 saves
[i
] = new_nsyms
;
2485 * Treat a local symbol that was a private extern as if
2486 * were global if it is referenced by a module and save
2489 if((n_type
& N_PEXT
) == N_PEXT
){
2491 private_extern_reference_by_module(
2492 i
, refs
,nextrefsyms
) == TRUE
){
2494 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2497 saves
[i
] = new_nsyms
;
2500 * We need to save symbols that were private externs
2501 * that are used with indirect symbols.
2504 symbol_pointer_used(i
, indirectsyms
,
2505 nindirectsyms
) == TRUE
){
2507 len
= strlen(strings
+ n_strx
) + 1;
2512 saves
[i
] = new_nsyms
;
2518 * Treat a local symbol that was a private extern as if were
2519 * global if it is not referenced by a module.
2521 else if((n_type
& N_PEXT
) == N_PEXT
){
2522 if(saves
[i
] == 0 && sfile
){
2523 sp
= bsearch(strings
+ n_strx
,
2524 save_symbols
, nsave_symbols
,
2525 sizeof(struct symbol_list
),
2526 (int (*)(const void *, const void *))
2527 symbol_list_bsearch
);
2529 if(sp
->sym
== NULL
){
2530 if(object
->mh
!= NULL
)
2531 sp
->sym
= &(symbols
[i
]);
2533 sp
->sym
= &(symbols64
[i
]);
2537 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2540 saves
[i
] = new_nsyms
;
2544 private_extern_reference_by_module(
2545 i
, refs
,nextrefsyms
) == TRUE
){
2547 new_strsize
+= strlen(strings
+ n_strx
) + 1;
2550 saves
[i
] = new_nsyms
;
2553 * We need to save symbols that were private externs that
2554 * are used with indirect symbols.
2557 symbol_pointer_used(i
, indirectsyms
, nindirectsyms
) ==
2560 len
= strlen(strings
+ n_strx
) + 1;
2565 saves
[i
] = new_nsyms
;
2569 else{ /* global symbol */
2571 * strip -R on an x86_64 .o file should do nothing.
2574 (object
->mh
!= NULL
||
2575 object
->mh64
->cputype
!= CPU_TYPE_X86_64
||
2576 object
->mh64
->filetype
!= MH_OBJECT
)){
2577 sp
= bsearch(strings
+ n_strx
,
2578 remove_symbols
, nremove_symbols
,
2579 sizeof(struct symbol_list
),
2580 (int (*)(const void *, const void *))
2581 symbol_list_bsearch
);
2583 if((n_type
& N_TYPE
) == N_UNDF
||
2584 (n_type
& N_TYPE
) == N_PBUD
){
2585 error_arch(arch
, member
, "symbol: %s undefined"
2586 " and can't be stripped from: ",
2589 else if(sp
->sym
!= NULL
){
2590 sym
= (struct nlist
*)sp
->sym
;
2591 if((sym
->n_type
& N_PEXT
) != N_PEXT
)
2592 error_arch(arch
, member
, "more than one symbol "
2593 "for: %s found in: ", sp
->name
);
2596 if(object
->mh
!= NULL
)
2597 sp
->sym
= &(symbols
[i
]);
2599 sp
->sym
= &(symbols64
[i
]);
2602 if(n_desc
& REFERENCED_DYNAMICALLY
){
2603 error_arch(arch
, member
, "symbol: %s is dynamically"
2604 " referenced and can't be stripped "
2605 "from: ", sp
->name
);
2607 if((n_type
& N_TYPE
) == N_SECT
&&
2608 (s_flags
& SECTION_TYPE
) == S_COALESCED
){
2609 error_arch(arch
, member
, "symbol: %s is a global "
2610 "coalesced symbol and can't be "
2611 "stripped from: ", sp
->name
);
2613 /* don't save this symbol */
2617 if(Aflag
&& (n_type
& N_TYPE
) == N_ABS
&&
2620 strncmp(strings
+ n_strx
,
2621 ".objc_class_name_",
2622 sizeof(".objc_class_name_") - 1) == 0))){
2623 len
= strlen(strings
+ n_strx
) + 1;
2625 new_ext_strsize
+= len
;
2628 saves
[i
] = new_nsyms
;
2630 if(saves
[i
] == 0 && (uflag
|| default_dyld_executable
) &&
2631 ((((n_type
& N_TYPE
) == N_UNDF
) &&
2633 (n_type
& N_TYPE
) == N_PBUD
)){
2635 len
= strlen(strings
+ n_strx
) + 1;
2637 new_ext_strsize
+= len
;
2641 saves
[i
] = new_nsyms
;
2643 if(saves
[i
] == 0 && nflag
&&
2644 (n_type
& N_TYPE
) == N_SECT
){
2646 len
= strlen(strings
+ n_strx
) + 1;
2648 new_ext_strsize
+= len
;
2652 saves
[i
] = new_nsyms
;
2654 if(saves
[i
] == 0 && sfile
){
2655 sp
= bsearch(strings
+ n_strx
,
2656 save_symbols
, nsave_symbols
,
2657 sizeof(struct symbol_list
),
2658 (int (*)(const void *, const void *))
2659 symbol_list_bsearch
);
2661 if(sp
->sym
!= NULL
){
2662 sym
= (struct nlist
*)sp
->sym
;
2663 if((sym
->n_type
& N_PEXT
) != N_PEXT
)
2664 error_arch(arch
, member
, "more than one symbol "
2665 "for: %s found in: ", sp
->name
);
2668 if(object
->mh
!= NULL
)
2669 sp
->sym
= &(symbols
[i
]);
2671 sp
->sym
= &(symbols64
[i
]);
2673 len
= strlen(strings
+ n_strx
) + 1;
2675 new_ext_strsize
+= len
;
2676 if((n_type
& N_TYPE
) == N_UNDF
||
2677 (n_type
& N_TYPE
) == N_PBUD
)
2682 saves
[i
] = new_nsyms
;
2687 * We only need to save coalesced symbols that are used as
2688 * indirect symbols in 32-bit applications.
2690 * In 64-bit applications, we only need to save coalesced
2691 * symbols that are used as weak definitions.
2693 if(object
->mh
!= NULL
&&
2695 (n_type
& N_TYPE
) == N_SECT
&&
2696 (s_flags
& SECTION_TYPE
) == S_COALESCED
&&
2697 symbol_pointer_used(i
, indirectsyms
, nindirectsyms
) == TRUE
){
2699 len
= strlen(strings
+ n_strx
) + 1;
2701 new_ext_strsize
+= len
;
2705 saves
[i
] = new_nsyms
;
2708 (n_type
& N_TYPE
) == N_SECT
&&
2709 (n_desc
& N_WEAK_DEF
) != 0){
2711 len
= strlen(strings
+ n_strx
) + 1;
2713 new_ext_strsize
+= len
;
2717 saves
[i
] = new_nsyms
;
2719 if(saves
[i
] == 0 && ((Xflag
|| Sflag
|| xflag
) ||
2720 ((rflag
|| default_dyld_executable
) &&
2721 n_desc
& REFERENCED_DYNAMICALLY
))){
2722 len
= strlen(strings
+ n_strx
) + 1;
2724 new_ext_strsize
+= len
;
2725 if((n_type
& N_TYPE
) == N_INDR
){
2726 len
= strlen(strings
+ n_value
) + 1;
2728 new_ext_strsize
+= len
;
2730 if((n_type
& N_TYPE
) == N_UNDF
||
2731 (n_type
& N_TYPE
) == N_PBUD
)
2736 saves
[i
] = new_nsyms
;
2741 * The module table's module names are placed with the external strings.
2742 * So size them and add this to the external string size.
2744 for(i
= 0; i
< nmodtab
; i
++){
2745 if(object
->mh
!= NULL
)
2746 module_name
= mods
[i
].module_name
;
2748 module_name
= mods64
[i
].module_name
;
2749 if(module_name
== 0 || module_name
> strsize
){
2750 error_arch(arch
, member
, "bad string index for module_name "
2751 "of module table entry %ld in: ", i
);
2754 len
= strlen(strings
+ module_name
) + 1;
2756 new_ext_strsize
+= len
;
2760 * Updating the reference table may require a symbol not yet listed as
2761 * as saved to be present in the output file. If a defined external
2762 * symbol is removed and there is a undefined reference to it in the
2763 * reference table an undefined symbol needs to be created for it in
2764 * the output file. If this happens the number of new symbols and size
2765 * of the new strings are adjusted. And the array changes[] is set to
2766 * map the old symbol index to the new symbol index for the symbol that
2767 * is changed to an undefined symbol.
2769 missing_symbols
= 0;
2770 if(ref_saves
!= NULL
)
2772 ref_saves
= (long *)allocate(nextrefsyms
* sizeof(long));
2773 bzero(ref_saves
, nextrefsyms
* sizeof(long));
2774 changes
= (unsigned long *)allocate(nsyms
* sizeof(long));
2775 bzero(changes
, nsyms
* sizeof(long));
2776 new_nextrefsyms
= 0;
2777 for(i
= 0; i
< nextrefsyms
; i
++){
2778 if(refs
[i
].isym
> nsyms
){
2779 error_arch(arch
, member
, "bad symbol table index for "
2780 "reference table entry %ld in: ", i
);
2783 if(saves
[refs
[i
].isym
]){
2785 ref_saves
[i
] = new_nextrefsyms
;
2788 if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
||
2789 refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
){
2790 if(changes
[refs
[i
].isym
] == 0){
2791 if(object
->mh
!= NULL
)
2792 n_strx
= symbols
[refs
[i
].isym
].n_un
.n_strx
;
2794 n_strx
= symbols64
[refs
[i
].isym
].n_un
.n_strx
;
2795 len
= strlen(strings
+ n_strx
) + 1;
2797 new_ext_strsize
+= len
;
2800 changes
[refs
[i
].isym
] = new_nsyms
;
2802 ref_saves
[i
] = new_nextrefsyms
;
2807 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
||
2808 refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
){
2809 if(missing_symbols
== 0){
2810 error_arch(arch
, member
, "private extern symbols "
2811 "referenced by modules can't be stripped in: ");
2812 missing_symbols
= 1;
2814 if(object
->mh
!= NULL
)
2815 n_strx
= symbols
[refs
[i
].isym
].n_un
.n_strx
;
2817 n_strx
= symbols64
[refs
[i
].isym
].n_un
.n_strx
;
2818 fprintf(stderr
, "%s\n", strings
+ n_strx
);
2819 saves
[refs
[i
].isym
] = -1;
2824 if(missing_symbols
== 1)
2830 for(i
= 0; i
< nsave_symbols
; i
++){
2831 if(save_symbols
[i
].sym
== NULL
){
2832 if(missing_syms
== 0){
2833 error_arch(arch
, member
, "symbols names listed "
2834 "in: %s not in: ", sfile
);
2837 fprintf(stderr
, "%s\n", save_symbols
[i
].name
);
2843 * strip -R on an x86_64 .o file should do nothing.
2846 (object
->mh
!= NULL
||
2847 object
->mh64
->cputype
!= CPU_TYPE_X86_64
||
2848 object
->mh64
->filetype
!= MH_OBJECT
)){
2849 for(i
= 0; i
< nremove_symbols
; i
++){
2850 if(remove_symbols
[i
].sym
== NULL
){
2851 if(missing_syms
== 0){
2852 error_arch(arch
, member
, "symbols names listed "
2853 "in: %s not in: ", Rfile
);
2856 fprintf(stderr
, "%s\n", remove_symbols
[i
].name
);
2862 if(object
->mh
!= NULL
){
2863 new_symbols
= (struct nlist
*)
2864 allocate(new_nsyms
* sizeof(struct nlist
));
2865 new_symbols64
= NULL
;
2869 new_symbols64
= (struct nlist_64
*)
2870 allocate(new_nsyms
* sizeof(struct nlist_64
));
2872 new_strsize
= round(new_strsize
, sizeof(long));
2873 new_strings
= (char *)allocate(new_strsize
);
2874 new_strings
[new_strsize
- 3] = '\0';
2875 new_strings
[new_strsize
- 2] = '\0';
2876 new_strings
[new_strsize
- 1] = '\0';
2878 memset(new_strings
, '\0', sizeof(long));
2879 p
= new_strings
+ sizeof(long);
2880 q
= p
+ new_ext_strsize
;
2882 /* if all strings were stripped set the size to zero */
2883 if(new_strsize
== sizeof(long))
2887 * Now create a symbol table and string table in this order
2890 * external defined symbols
2897 for(i
= 0; i
< nsyms
; i
++){
2899 if(object
->mh
!= NULL
){
2900 n_strx
= symbols
[i
].n_un
.n_strx
;
2901 n_type
= symbols
[i
].n_type
;
2904 n_strx
= symbols64
[i
].n_un
.n_strx
;
2905 n_type
= symbols64
[i
].n_type
;
2907 if((n_type
& N_EXT
) == 0){
2908 if(object
->mh
!= NULL
)
2909 new_symbols
[inew_syms
] = symbols
[i
];
2911 new_symbols64
[inew_syms
] = symbols64
[i
];
2913 strcpy(q
, strings
+ n_strx
);
2914 if(object
->mh
!= NULL
)
2915 new_symbols
[inew_syms
].n_un
.n_strx
=
2918 new_symbols64
[inew_syms
].n_un
.n_strx
=
2923 saves
[i
] = inew_syms
;
2927 for(i
= 0; i
< nsyms
; i
++){
2929 if(object
->mh
!= NULL
){
2930 n_strx
= symbols
[i
].n_un
.n_strx
;
2931 n_type
= symbols
[i
].n_type
;
2932 n_value
= symbols
[i
].n_value
;
2935 n_strx
= symbols64
[i
].n_un
.n_strx
;
2936 n_type
= symbols64
[i
].n_type
;
2937 n_value
= symbols64
[i
].n_value
;
2939 if((n_type
& N_EXT
) == N_EXT
&&
2940 ((n_type
& N_TYPE
) != N_UNDF
&&
2941 (n_type
& N_TYPE
) != N_PBUD
)){
2942 if(object
->mh
!= NULL
)
2943 new_symbols
[inew_syms
] = symbols
[i
];
2945 new_symbols64
[inew_syms
] = symbols64
[i
];
2947 strcpy(p
, strings
+ n_strx
);
2948 if(object
->mh
!= NULL
)
2949 new_symbols
[inew_syms
].n_un
.n_strx
=
2952 new_symbols64
[inew_syms
].n_un
.n_strx
=
2956 if((n_type
& N_TYPE
) == N_INDR
){
2958 strcpy(p
, strings
+ n_value
);
2959 if(object
->mh
!= NULL
)
2960 new_symbols
[inew_syms
].n_value
=
2963 new_symbols64
[inew_syms
].n_value
=
2969 saves
[i
] = inew_syms
;
2974 * Build the new undefined symbols into a map and sort it.
2977 if(object
->mh
!= NULL
){
2978 undef_map
= (struct undef_map
*)allocate(new_nundefsym
*
2979 sizeof(struct undef_map
));
2984 undef_map64
= (struct undef_map64
*)allocate(new_nundefsym
*
2985 sizeof(struct undef_map64
));
2987 for(i
= 0; i
< nsyms
; i
++){
2989 if(object
->mh
!= NULL
){
2990 n_strx
= symbols
[i
].n_un
.n_strx
;
2991 n_type
= symbols
[i
].n_type
;
2994 n_strx
= symbols64
[i
].n_un
.n_strx
;
2995 n_type
= symbols64
[i
].n_type
;
2997 if((n_type
& N_EXT
) == N_EXT
&&
2998 ((n_type
& N_TYPE
) == N_UNDF
||
2999 (n_type
& N_TYPE
) == N_PBUD
)){
3000 if(object
->mh
!= NULL
)
3001 undef_map
[inew_undefsyms
].symbol
= symbols
[i
];
3003 undef_map64
[inew_undefsyms
].symbol64
= symbols64
[i
];
3005 strcpy(p
, strings
+ n_strx
);
3006 if(object
->mh
!= NULL
)
3007 undef_map
[inew_undefsyms
].symbol
.n_un
.n_strx
=
3010 undef_map64
[inew_undefsyms
].symbol64
.n_un
.n_strx
=
3014 if(object
->mh
!= NULL
)
3015 undef_map
[inew_undefsyms
].index
= i
;
3017 undef_map64
[inew_undefsyms
].index
= i
;
3022 for(i
= 0; i
< nsyms
; i
++){
3024 if(object
->mh
!= NULL
)
3025 n_strx
= symbols
[i
].n_un
.n_strx
;
3027 n_strx
= symbols64
[i
].n_un
.n_strx
;
3029 strcpy(p
, strings
+ n_strx
);
3030 if(object
->mh
!= NULL
)
3031 undef_map
[inew_undefsyms
].symbol
.n_un
.n_strx
=
3034 undef_map64
[inew_undefsyms
].symbol64
.n_un
.n_strx
=
3038 if(object
->mh
!= NULL
){
3039 undef_map
[inew_undefsyms
].symbol
.n_type
= N_UNDF
| N_EXT
;
3040 undef_map
[inew_undefsyms
].symbol
.n_sect
= NO_SECT
;
3041 undef_map
[inew_undefsyms
].symbol
.n_desc
= 0;
3042 undef_map
[inew_undefsyms
].symbol
.n_value
= 0;
3043 undef_map
[inew_undefsyms
].index
= i
;
3046 undef_map64
[inew_undefsyms
].symbol64
.n_type
= N_UNDF
|N_EXT
;
3047 undef_map64
[inew_undefsyms
].symbol64
.n_sect
= NO_SECT
;
3048 undef_map64
[inew_undefsyms
].symbol64
.n_desc
= 0;
3049 undef_map64
[inew_undefsyms
].symbol64
.n_value
= 0;
3050 undef_map64
[inew_undefsyms
].index
= i
;
3055 /* Sort the undefined symbols by name */
3056 qsort_strings
= new_strings
;
3057 if(object
->mh
!= NULL
)
3058 qsort(undef_map
, new_nundefsym
, sizeof(struct undef_map
),
3059 (int (*)(const void *, const void *))cmp_qsort_undef_map
);
3061 qsort(undef_map64
, new_nundefsym
, sizeof(struct undef_map64
),
3062 (int (*)(const void *, const void *))cmp_qsort_undef_map_64
);
3063 /* Copy the symbols now in sorted order into new_symbols */
3064 for(i
= 0; i
< new_nundefsym
; i
++){
3065 if(object
->mh
!= NULL
){
3066 new_symbols
[inew_syms
] = undef_map
[i
].symbol
;
3068 saves
[undef_map
[i
].index
] = inew_syms
;
3071 new_symbols64
[inew_syms
] = undef_map64
[i
].symbol64
;
3073 saves
[undef_map64
[i
].index
] = inew_syms
;
3078 * Fixup the module table's module name strings adding them to the
3079 * string table. Also fix the indexes into the symbol table for
3080 * external and local symbols. And fix up the indexes into the
3083 for(i
= 0; i
< nmodtab
; i
++){
3084 if(object
->mh
!= NULL
){
3085 strcpy(p
, strings
+ mods
[i
].module_name
);
3086 mods
[i
].module_name
= p
- new_strings
;
3087 iextdefsym
= mods
[i
].iextdefsym
;
3088 nextdefsym
= mods
[i
].nextdefsym
;
3089 ilocalsym
= mods
[i
].ilocalsym
;
3090 nlocalsym
= mods
[i
].nlocalsym
;
3091 irefsym
= mods
[i
].irefsym
;
3092 nrefsym
= mods
[i
].nrefsym
;
3095 strcpy(p
, strings
+ mods64
[i
].module_name
);
3096 mods64
[i
].module_name
= p
- new_strings
;
3097 iextdefsym
= mods64
[i
].iextdefsym
;
3098 nextdefsym
= mods64
[i
].nextdefsym
;
3099 ilocalsym
= mods64
[i
].ilocalsym
;
3100 nlocalsym
= mods64
[i
].nlocalsym
;
3101 irefsym
= mods64
[i
].irefsym
;
3102 nrefsym
= mods64
[i
].nrefsym
;
3106 if(iextdefsym
> nsyms
){
3107 error_arch(arch
, member
, "bad index into externally defined "
3108 "symbols of module table entry %ld in: ", i
);
3111 if(iextdefsym
+ nextdefsym
> nsyms
){
3112 error_arch(arch
, member
, "bad number of externally defined "
3113 "symbols of module table entry %ld in: ", i
);
3116 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
3117 if(saves
[j
] != 0 && changes
[j
] == 0)
3121 for(k
= j
; k
< iextdefsym
+ nextdefsym
; k
++){
3122 if(saves
[k
] != 0 && changes
[k
] == 0)
3126 if(object
->mh
!= NULL
){
3127 mods
[i
].iextdefsym
= 0;
3128 mods
[i
].nextdefsym
= 0;
3131 mods64
[i
].iextdefsym
= 0;
3132 mods64
[i
].nextdefsym
= 0;
3136 if(object
->mh
!= NULL
){
3137 mods
[i
].iextdefsym
= saves
[j
] - 1;
3138 mods
[i
].nextdefsym
= n
;
3141 mods64
[i
].iextdefsym
= saves
[j
] - 1;
3142 mods64
[i
].nextdefsym
= n
;
3146 if(ilocalsym
> nsyms
){
3147 error_arch(arch
, member
, "bad index into symbols for local "
3148 "symbols of module table entry %ld in: ", i
);
3151 if(ilocalsym
+ nlocalsym
> nsyms
){
3152 error_arch(arch
, member
, "bad number of local "
3153 "symbols of module table entry %ld in: ", i
);
3156 for(j
= ilocalsym
; j
< ilocalsym
+ nlocalsym
; j
++){
3161 for(k
= j
; k
< ilocalsym
+ nlocalsym
; k
++){
3166 if(object
->mh
!= NULL
){
3167 mods
[i
].ilocalsym
= 0;
3168 mods
[i
].nlocalsym
= 0;
3171 mods64
[i
].ilocalsym
= 0;
3172 mods64
[i
].nlocalsym
= 0;
3176 if(object
->mh
!= NULL
){
3177 mods
[i
].ilocalsym
= saves
[j
] - 1;
3178 mods
[i
].nlocalsym
= n
;
3181 mods64
[i
].ilocalsym
= saves
[j
] - 1;
3182 mods64
[i
].nlocalsym
= n
;
3186 if(irefsym
> nextrefsyms
){
3187 error_arch(arch
, member
, "bad index into reference table "
3188 "of module table entry %ld in: ", i
);
3191 if(irefsym
+ nrefsym
> nextrefsyms
){
3192 error_arch(arch
, member
, "bad number of reference table "
3193 "entries of module table entry %ld in: ", i
);
3196 for(j
= irefsym
; j
< irefsym
+ nrefsym
; j
++){
3197 if(ref_saves
[j
] != 0)
3201 for(k
= j
; k
< irefsym
+ nrefsym
; k
++){
3202 if(ref_saves
[k
] != 0)
3206 if(object
->mh
!= NULL
){
3207 mods
[i
].irefsym
= 0;
3208 mods
[i
].nrefsym
= 0;
3211 mods64
[i
].irefsym
= 0;
3212 mods64
[i
].nrefsym
= 0;
3216 if(object
->mh
!= NULL
){
3217 mods
[i
].irefsym
= ref_saves
[j
] - 1;
3218 mods
[i
].nrefsym
= n
;
3221 mods64
[i
].irefsym
= ref_saves
[j
] - 1;
3222 mods64
[i
].nrefsym
= n
;
3228 * Create a new reference table.
3230 new_refs
= allocate(new_nextrefsyms
* sizeof(struct dylib_reference
));
3232 for(i
= 0; i
< nextrefsyms
; i
++){
3234 if(saves
[refs
[i
].isym
]){
3235 new_refs
[j
].isym
= saves
[refs
[i
].isym
] - 1;
3236 new_refs
[j
].flags
= refs
[i
].flags
;
3239 if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
||
3240 refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
){
3241 new_refs
[j
].isym
= changes
[refs
[i
].isym
] - 1;
3242 new_refs
[j
].flags
= refs
[i
].flags
;
3250 * Create a new dylib table of contents.
3253 for(i
= 0; i
< ntoc
; i
++){
3254 if(tocs
[i
].symbol_index
>= nsyms
){
3255 error_arch(arch
, member
, "bad symbol index for table of "
3256 "contents table entry %ld in: ", i
);
3259 if(saves
[tocs
[i
].symbol_index
] != 0 &&
3260 changes
[tocs
[i
].symbol_index
] == 0)
3263 new_tocs
= allocate(new_ntoc
* sizeof(struct dylib_table_of_contents
));
3265 for(i
= 0; i
< ntoc
; i
++){
3266 if(saves
[tocs
[i
].symbol_index
] != 0 &&
3267 changes
[tocs
[i
].symbol_index
] == 0){
3268 new_tocs
[j
].symbol_index
= saves
[tocs
[i
].symbol_index
] - 1;
3269 new_tocs
[j
].module_index
= tocs
[i
].module_index
;
3274 if(undef_map
!= NULL
)
3276 if(undef_map64
!= NULL
)
3280 if(sections
!= NULL
)
3282 if(sections64
!= NULL
)
3292 * strip_LC_UUID_commands() is called when -no_uuid is specified to remove any
3293 * LC_UUID load commands from the object's load commands.
3297 strip_LC_UUID_commands(
3299 struct member
*member
,
3300 struct object
*object
)
3302 uint32_t i
, ncmds
, nuuids
, mh_sizeofcmds
, sizeofcmds
;
3303 struct load_command
*lc1
, *lc2
, *new_load_commands
;
3304 struct segment_command
*sg
;
3307 * See if there are any LC_UUID load commands.
3310 lc1
= arch
->object
->load_commands
;
3311 if(arch
->object
->mh
!= NULL
){
3312 ncmds
= arch
->object
->mh
->ncmds
;
3313 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
3316 ncmds
= arch
->object
->mh64
->ncmds
;
3317 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
3319 for(i
= 0; i
< ncmds
; i
++){
3320 if(lc1
->cmd
== LC_UUID
){
3323 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
3325 /* if no LC_UUID load commands just return */
3330 * Allocate space for the new load commands as zero it out so any holes
3331 * will be zero bytes.
3333 new_load_commands
= allocate(mh_sizeofcmds
);
3334 memset(new_load_commands
, '\0', mh_sizeofcmds
);
3337 * Copy all the load commands except the LC_UUID load commands into the
3338 * allocated space for the new load commands.
3340 lc1
= arch
->object
->load_commands
;
3341 lc2
= new_load_commands
;
3343 for(i
= 0; i
< ncmds
; i
++){
3344 if(lc1
->cmd
!= LC_UUID
){
3345 memcpy(lc2
, lc1
, lc1
->cmdsize
);
3346 sizeofcmds
+= lc2
->cmdsize
;
3347 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
3349 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
3353 * Finally copy the updated load commands over the existing load
3356 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
3357 if(mh_sizeofcmds
> sizeofcmds
){
3358 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
3359 (mh_sizeofcmds
- sizeofcmds
));
3362 if(arch
->object
->mh
!= NULL
) {
3363 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
3364 arch
->object
->mh
->ncmds
= ncmds
;
3366 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
3367 arch
->object
->mh64
->ncmds
= ncmds
;
3369 free(new_load_commands
);
3371 /* reset the pointers into the load commands */
3372 lc1
= arch
->object
->load_commands
;
3373 for(i
= 0; i
< ncmds
; i
++){
3376 arch
->object
->st
= (struct symtab_command
*)lc1
;
3379 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
3381 case LC_TWOLEVEL_HINTS
:
3382 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
3384 case LC_PREBIND_CKSUM
:
3385 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
3388 sg
= (struct segment_command
*)lc1
;
3389 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
3390 arch
->object
->seg_linkedit
= sg
;
3392 case LC_SEGMENT_SPLIT_INFO
:
3393 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
3395 case LC_CODE_SIGNATURE
:
3396 object
->code_sig_cmd
= (struct linkedit_data_command
*)lc1
;
3399 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
3405 * strip_LC_CODE_SIGNATURE_commands() is called when -c is specified to remove
3406 * any LC_CODE_SIGNATURE load commands from the object's load commands.
3410 strip_LC_CODE_SIGNATURE_commands(
3412 struct member
*member
,
3413 struct object
*object
)
3415 uint32_t i
, ncmds
, mh_sizeofcmds
, sizeofcmds
;
3416 struct load_command
*lc1
, *lc2
, *new_load_commands
;
3417 struct segment_command
*sg
;
3420 * See if there is an LC_CODE_SIGNATURE load command and if no command
3423 if(object
->code_sig_cmd
== NULL
)
3427 * Allocate space for the new load commands and zero it out so any holes
3428 * will be zero bytes.
3430 if(arch
->object
->mh
!= NULL
){
3431 ncmds
= arch
->object
->mh
->ncmds
;
3432 mh_sizeofcmds
= arch
->object
->mh
->sizeofcmds
;
3435 ncmds
= arch
->object
->mh64
->ncmds
;
3436 mh_sizeofcmds
= arch
->object
->mh64
->sizeofcmds
;
3438 new_load_commands
= allocate(mh_sizeofcmds
);
3439 memset(new_load_commands
, '\0', mh_sizeofcmds
);
3442 * Copy all the load commands except the LC_CODE_SIGNATURE load commands
3443 * into the allocated space for the new load commands.
3445 lc1
= arch
->object
->load_commands
;
3446 lc2
= new_load_commands
;
3448 for(i
= 0; i
< ncmds
; i
++){
3449 if(lc1
->cmd
!= LC_CODE_SIGNATURE
){
3450 memcpy(lc2
, lc1
, lc1
->cmdsize
);
3451 sizeofcmds
+= lc2
->cmdsize
;
3452 lc2
= (struct load_command
*)((char *)lc2
+ lc2
->cmdsize
);
3454 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
3458 * Finally copy the updated load commands over the existing load
3461 memcpy(arch
->object
->load_commands
, new_load_commands
, sizeofcmds
);
3462 if(mh_sizeofcmds
> sizeofcmds
){
3463 memset((char *)arch
->object
->load_commands
+ sizeofcmds
, '\0',
3464 (mh_sizeofcmds
- sizeofcmds
));
3467 if(arch
->object
->mh
!= NULL
) {
3468 arch
->object
->mh
->sizeofcmds
= sizeofcmds
;
3469 arch
->object
->mh
->ncmds
= ncmds
;
3471 arch
->object
->mh64
->sizeofcmds
= sizeofcmds
;
3472 arch
->object
->mh64
->ncmds
= ncmds
;
3474 free(new_load_commands
);
3476 /* reset the pointers into the load commands */
3477 object
->code_sig_cmd
= NULL
;
3478 lc1
= arch
->object
->load_commands
;
3479 for(i
= 0; i
< ncmds
; i
++){
3482 arch
->object
->st
= (struct symtab_command
*)lc1
;
3485 arch
->object
->dyst
= (struct dysymtab_command
*)lc1
;
3487 case LC_TWOLEVEL_HINTS
:
3488 arch
->object
->hints_cmd
= (struct twolevel_hints_command
*)lc1
;
3490 case LC_PREBIND_CKSUM
:
3491 arch
->object
->cs
= (struct prebind_cksum_command
*)lc1
;
3494 sg
= (struct segment_command
*)lc1
;
3495 if(strcmp(sg
->segname
, SEG_LINKEDIT
) == 0)
3496 arch
->object
->seg_linkedit
= sg
;
3498 case LC_SEGMENT_SPLIT_INFO
:
3499 object
->split_info_cmd
= (struct linkedit_data_command
*)lc1
;
3502 lc1
= (struct load_command
*)((char *)lc1
+ lc1
->cmdsize
);
3506 * To get the right amount of the file copied out by writeout() for the
3507 * case when we are stripping out the section contents we already reduce
3508 * the object size by the size of the section contents including the
3509 * padding after the load commands. So here we need to further reduce
3510 * it by the load command for the LC_CODE_SIGNATURE (a struct
3511 * linkedit_data_command) we are removing.
3513 object
->object_size
-= sizeof(struct linkedit_data_command
);
3515 * Then this size minus the size of the input symbolic information is
3516 * what is copied out from the file by writeout(). Which in this case
3517 * is just the new headers.
3521 * Finally for -c the file offset to the link edit information is to be
3522 * right after the load commands. So reset this for the updated size
3523 * of the load commands without the LC_CODE_SIGNATURE.
3525 if(object
->mh
!= NULL
)
3526 object
->seg_linkedit
->fileoff
= sizeof(struct mach_header
) +
3529 object
->seg_linkedit64
->fileoff
= sizeof(struct mach_header_64
) +
3532 #endif /* !(NMEDIT) */
3535 * private_extern_reference_by_module() is passed a symbol_index of a private
3536 * extern symbol and the module table. If the symbol_index appears in the
3537 * module symbol table this returns TRUE else it returns FALSE.
3541 private_extern_reference_by_module(
3542 unsigned long symbol_index
,
3543 struct dylib_reference
*refs
,
3544 unsigned long nextrefsyms
)
3548 for(i
= 0; i
< nextrefsyms
; i
++){
3549 if(refs
[i
].isym
== symbol_index
){
3550 if(refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
||
3551 refs
[i
].flags
== REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
){
3560 * symbol_pointer_used() is passed a symbol_index and the indirect table. If
3561 * the symbol_index appears in the indirect symbol table this returns TRUE else
3566 symbol_pointer_used(
3567 unsigned long symbol_index
,
3568 uint32_t *indirectsyms
,
3569 unsigned long nindirectsyms
)
3573 for(i
= 0; i
< nindirectsyms
; i
++){
3574 if(indirectsyms
[i
] == symbol_index
)
3581 * Function for qsort for comparing undefined map entries.
3585 cmp_qsort_undef_map(
3586 const struct undef_map
*sym1
,
3587 const struct undef_map
*sym2
)
3589 return(strcmp(qsort_strings
+ sym1
->symbol
.n_un
.n_strx
,
3590 qsort_strings
+ sym2
->symbol
.n_un
.n_strx
));
3595 cmp_qsort_undef_map_64(
3596 const struct undef_map64
*sym1
,
3597 const struct undef_map64
*sym2
)
3599 return(strcmp(qsort_strings
+ sym1
->symbol64
.n_un
.n_strx
,
3600 qsort_strings
+ sym2
->symbol64
.n_un
.n_strx
));
3602 #endif /* !defined(NMEDIT) */
3606 * Function for qsort for comparing object names.
3614 return(strcmp(*name1
, *name2
));
3618 * Function for bsearch for finding a object name.
3622 cmp_bsearch_filename(
3626 return(strcmp(name1
, *name2
));
3628 #endif /* !defined(NMEDIT) */
3635 struct member
*member
,
3636 struct object
*object
,
3637 struct nlist
*symbols
,
3638 struct nlist_64
*symbols64
,
3639 unsigned long nsyms
,
3641 unsigned long strsize
,
3642 struct dylib_table_of_contents
*tocs
,
3644 struct dylib_module
*mods
,
3645 struct dylib_module_64
*mods64
,
3646 unsigned long nmodtab
,
3647 struct dylib_reference
*refs
,
3648 unsigned long nextrefsyms
)
3650 unsigned long i
, j
, k
;
3651 unsigned char data_n_sect
, nsects
;
3652 struct load_command
*lc
;
3653 struct segment_command
*sg
;
3654 struct segment_command_64
*sg64
;
3655 struct section
*s
, **sections
;
3656 struct section_64
*s64
, **sections64
;
3658 unsigned long missing_syms
;
3659 struct symbol_list
*sp
;
3660 struct nlist
**global_symbol
;
3661 struct nlist_64
**global_symbol64
;
3662 enum bool global_symbol_found
;
3663 char *global_name
, save_char
;
3664 enum bool dwarf_debug_map
;
3665 enum byte_sex host_byte_sex
;
3666 long missing_reloc_symbols
;
3667 enum bool edit_symtab_return
;
3670 unsigned long new_ext_strsize
, len
, inew_syms
;
3672 struct nlist
**changed_globals
;
3673 struct nlist_64
**changed_globals64
;
3674 unsigned long nchanged_globals
;
3675 uint32_t ncmds
, s_flags
, n_strx
, module_name
, ilocalsym
, nlocalsym
;
3676 uint32_t iextdefsym
, nextdefsym
;
3677 uint8_t n_type
, n_sect
, global_symbol_n_sect
;
3679 enum bool warned_about_global_coalesced_symbols
;
3681 edit_symtab_return
= TRUE
;
3682 host_byte_sex
= get_host_byte_sex();
3683 missing_reloc_symbols
= 0;
3684 warned_about_global_coalesced_symbols
= FALSE
;
3688 nmedits
= allocate(nsyms
* sizeof(enum bool));
3689 for(i
= 0; i
< nsyms
; i
++)
3693 * If nmedit is operating on a dynamic library then symbols are turned
3694 * into private externs with the extern bit off not into static symbols.
3696 if(object
->mh_filetype
== MH_DYLIB
&& pflag
== TRUE
){
3697 error_arch(arch
, member
, "can't use -p with dynamic libraries");
3702 * As part of the MAJOR guess for the second pass to fix stabs for the
3703 * globals symbols that get turned into non-global symbols. We need to
3704 * change the stabs. To do this we to know if a N_GSYM is for a data
3705 * symbol or not to know to turn it into an N_STSYM or a N_FUN.
3706 * This logic as determined by compiling test cases with and without
3707 * the key word 'static' and looking at the difference between the STABS
3708 * the compiler generates and trying to match that here.
3710 * We also use this loop and the next to gather an array of section
3711 * struct pointers so we can later determine if we run into a global
3712 * symbol in a coalesced section and not turn those symbols into
3718 data_n_sect
= NO_SECT
;
3719 lc
= object
->load_commands
;
3720 if(object
->mh
!= NULL
)
3721 ncmds
= object
->mh
->ncmds
;
3723 ncmds
= object
->mh64
->ncmds
;
3724 for(i
= 0; i
< ncmds
; i
++){
3725 if(lc
->cmd
== LC_SEGMENT
){
3726 sg
= (struct segment_command
*)lc
;
3727 s
= (struct section
*)((char *)sg
+
3728 sizeof(struct segment_command
));
3729 nsects
+= sg
->nsects
;
3730 for(j
= 0; j
< sg
->nsects
; j
++){
3731 if(strcmp(s
->segname
, SEG_DATA
) == 0 &&
3732 strcmp(s
->sectname
, SECT_DATA
) == 0 &&
3733 data_n_sect
== NO_SECT
){
3734 data_n_sect
= n_sect
;
3741 else if(lc
->cmd
== LC_SEGMENT_64
){
3742 sg64
= (struct segment_command_64
*)lc
;
3743 s64
= (struct section_64
*)((char *)sg64
+
3744 sizeof(struct segment_command_64
));
3745 nsects
+= sg64
->nsects
;
3746 for(j
= 0; j
< sg64
->nsects
; j
++){
3747 if(strcmp(s64
->segname
, SEG_DATA
) == 0 &&
3748 strcmp(s64
->sectname
, SECT_DATA
) == 0 &&
3749 data_n_sect
== NO_SECT
){
3750 data_n_sect
= n_sect
;
3757 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
3759 if(object
->mh
!= NULL
){
3760 sections
= allocate(nsects
* sizeof(struct section
*));
3765 sections64
= allocate(nsects
* sizeof(struct section_64
*));
3768 lc
= object
->load_commands
;
3769 for(i
= 0; i
< ncmds
; i
++){
3770 if(lc
->cmd
== LC_SEGMENT
){
3771 sg
= (struct segment_command
*)lc
;
3772 s
= (struct section
*)((char *)sg
+
3773 sizeof(struct segment_command
));
3774 for(j
= 0; j
< sg
->nsects
; j
++){
3775 sections
[nsects
++] = s
++;
3778 else if(lc
->cmd
== LC_SEGMENT_64
){
3779 sg64
= (struct segment_command_64
*)lc
;
3780 s64
= (struct section_64
*)((char *)sg64
+
3781 sizeof(struct segment_command_64
));
3782 for(j
= 0; j
< sg64
->nsects
; j
++){
3783 sections64
[nsects
++] = s64
++;
3786 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
3790 * Zero out the saved symbols so they can be recorded for this file.
3792 for(i
= 0; i
< nsave_symbols
; i
++)
3793 save_symbols
[i
].sym
= NULL
;
3794 for(i
= 0; i
< nremove_symbols
; i
++)
3795 remove_symbols
[i
].sym
= NULL
;
3797 for(i
= 0; i
< nsave_symbols
; i
++)
3798 save_symbols
[i
].seen
= FALSE
;
3799 for(i
= 0; i
< nremove_symbols
; i
++)
3800 remove_symbols
[i
].seen
= FALSE
;
3803 nchanged_globals
= 0;
3804 if(object
->mh
!= NULL
){
3805 changed_globals
= allocate(nsyms
* sizeof(struct nlist
*));
3806 changed_globals64
= NULL
;
3807 for(i
= 0; i
< nsyms
; i
++)
3808 changed_globals
[i
] = NULL
;
3811 changed_globals
= NULL
;
3812 changed_globals64
= allocate(nsyms
* sizeof(struct nlist_64
*));
3813 for(i
= 0; i
< nsyms
; i
++)
3814 changed_globals64
[i
] = NULL
;
3818 * These are the variables for the new symbol table and new string
3819 * table. Since this routine only turns globals into non-globals the
3820 * number of symbols does not change. But the count of local, defined
3821 * external symbols does change.
3828 new_strsize
= sizeof(long);
3829 new_ext_strsize
= 0;
3832 * First pass: turn the globals symbols into non-global symbols.
3834 for(i
= 0; i
< nsyms
; i
++){
3837 if(object
->mh
!= NULL
){
3838 n_strx
= symbols
[i
].n_un
.n_strx
;
3839 n_type
= symbols
[i
].n_type
;
3840 n_sect
= symbols
[i
].n_sect
;
3841 if((n_type
& N_TYPE
) == N_SECT
)
3842 s_flags
= sections
[n_sect
- 1]->flags
;
3843 n_value
= symbols
[i
].n_value
;
3846 n_strx
= symbols64
[i
].n_un
.n_strx
;
3847 n_type
= symbols64
[i
].n_type
;
3848 n_sect
= symbols64
[i
].n_sect
;
3849 if((n_type
& N_TYPE
) == N_SECT
)
3850 s_flags
= sections64
[n_sect
- 1]->flags
;
3851 n_value
= symbols64
[i
].n_value
;
3854 if(n_strx
> strsize
){
3855 error_arch(arch
, member
, "bad string index for symbol "
3856 "table entry %lu in: ", i
);
3859 len
= strlen(strings
+ n_strx
) + 1;
3862 if((n_type
& N_TYPE
) != N_UNDF
&&
3863 (n_type
& N_TYPE
) != N_PBUD
){
3864 if((n_type
& N_TYPE
) == N_SECT
){
3865 if(n_sect
> nsects
){
3866 error_arch(arch
, member
, "bad n_sect for symbol "
3867 "table entry %lu in: ", i
);
3870 if(((s_flags
& SECTION_TYPE
) == S_COALESCED
) &&
3872 object
->mh_filetype
!= MH_OBJECT
){
3873 /* this remains a global defined symbol */
3874 if(warned_about_global_coalesced_symbols
== FALSE
){
3875 warning_arch(arch
, member
, "can't make global "
3876 "coalesced symbols (like %s) into static "
3877 "symbols (use ld(1)'s "
3878 "-exported_symbols_list option) in a final "
3879 "linked image: ", strings
+ n_strx
);
3880 warned_about_global_coalesced_symbols
= TRUE
;
3883 new_ext_strsize
+= len
;
3885 sp
= bsearch(strings
+ n_strx
,
3886 remove_symbols
, nremove_symbols
,
3887 sizeof(struct symbol_list
),
3888 (int (*)(const void *, const void *))
3889 symbol_list_bsearch
);
3891 if(sp
->sym
!= NULL
){
3892 error_arch(arch
, member
, "more than one "
3893 "symbol for: %s found in: ", sp
->name
);
3897 if(object
->mh
!= NULL
)
3898 sp
->sym
= &(symbols
[i
]);
3900 sp
->sym
= &(symbols64
[i
]);
3902 warning_arch(arch
, member
, "can't make "
3903 "global coalesced symbol: %s into a "
3904 "static symbol in: ", sp
->name
);
3908 * In case the user has listed this coalesced
3909 * symbol in the save list look for it and mark it
3910 * as seen so we don't complain about not seeing it.
3912 sp
= bsearch(strings
+ n_strx
,
3913 save_symbols
, nsave_symbols
,
3914 sizeof(struct symbol_list
),
3915 (int (*)(const void *, const void *))
3916 symbol_list_bsearch
);
3918 if(sp
->sym
!= NULL
){
3919 error_arch(arch
, member
, "more than one "
3920 "symbol for: %s found in: ", sp
->name
);
3924 if(object
->mh
!= NULL
)
3925 sp
->sym
= &(symbols
[i
]);
3927 sp
->sym
= &(symbols64
[i
]);
3931 continue; /* leave this symbol unchanged */
3934 sp
= bsearch(strings
+ n_strx
,
3935 remove_symbols
, nremove_symbols
,
3936 sizeof(struct symbol_list
),
3937 (int (*)(const void *, const void *))
3938 symbol_list_bsearch
);
3940 if(sp
->sym
!= NULL
){
3941 error_arch(arch
, member
, "more than one symbol "
3942 "for: %s found in: ", sp
->name
);
3946 if(object
->mh
!= NULL
)
3947 sp
->sym
= &(symbols
[i
]);
3949 sp
->sym
= &(symbols64
[i
]);
3956 * If there is no list of saved symbols, then all
3957 * symbols will be saved unless listed in the remove
3962 * There is no save list, so if there is also no
3963 * remove list but the -p flag is specified or it is
3964 * a dynamic library then change all symbols.
3966 if((pflag
|| object
->mh_filetype
== MH_DYLIB
)
3967 && nremove_symbols
== 0)
3969 /* this remains a global defined symbol */
3971 new_ext_strsize
+= len
;
3973 continue; /* leave this symbol unchanged */
3976 sp
= bsearch(strings
+ n_strx
,
3977 save_symbols
, nsave_symbols
,
3978 sizeof(struct symbol_list
),
3979 (int (*)(const void *, const void *))
3980 symbol_list_bsearch
);
3982 if(sp
->sym
!= NULL
){
3983 error_arch(arch
, member
, "more than one symbol "
3984 "for: %s found in: ", sp
->name
);
3988 if(object
->mh
!= NULL
)
3989 sp
->sym
= &(symbols
[i
]);
3991 sp
->sym
= &(symbols64
[i
]);
3993 /* this remains a global defined symbol */
3995 new_ext_strsize
+= len
;
4000 if(Aflag
&& n_type
== (N_EXT
| N_ABS
) &&
4003 strncmp(strings
+ n_strx
,
4004 ".objc_class_name_",
4005 sizeof(".objc_class_name_") - 1) == 0))){
4006 /* this remains a global defined symbol */
4008 new_ext_strsize
+= len
;
4013 if((n_type
& N_TYPE
) != N_INDR
){
4015 if(object
->mh
!= NULL
)
4016 changed_globals
[nchanged_globals
++] =
4019 changed_globals64
[nchanged_globals
++] =
4022 /* this remains a global defined symbol */
4024 new_ext_strsize
+= len
;
4028 /* this will become a non-global symbol */
4034 /* this remains a global defined symbol */
4036 new_ext_strsize
+= len
;
4043 /* this is an undefined symbol */
4045 new_ext_strsize
+= len
;
4050 /* this is a local symbol */
4057 * The module table's module names are placed with the external
4058 * strings. So size them and add this to the external string size.
4060 for(i
= 0; i
< nmodtab
; i
++){
4061 if(object
->mh
!= NULL
)
4062 module_name
= mods
[i
].module_name
;
4064 module_name
= mods64
[i
].module_name
;
4065 if(module_name
== 0 || module_name
> strsize
){
4066 error_arch(arch
, member
, "bad string index for module_name "
4067 "of module table entry %ld in: ", i
);
4070 len
= strlen(strings
+ module_name
) + 1;
4072 new_ext_strsize
+= len
;
4076 * Warn about symbols to be saved that were missing.
4081 for(i
= 0; i
< nsave_symbols
; i
++){
4082 if(save_symbols
[i
].sym
== NULL
){
4083 if(missing_syms
== 0){
4084 error_arch(arch
, member
, "symbols names listed "
4085 "in: %s not in: ", sfile
);
4088 fprintf(stderr
, "%s\n", save_symbols
[i
].name
);
4091 for(i
= 0; i
< nremove_symbols
; i
++){
4092 if(remove_symbols
[i
].sym
== NULL
){
4093 if(missing_syms
== 0){
4094 error_arch(arch
, member
, "symbols names listed "
4095 "in: %s not in: ", Rfile
);
4098 fprintf(stderr
, "%s\n", remove_symbols
[i
].name
);
4105 * Second pass: fix stabs for the globals symbols that got turned into
4106 * non-global symbols. This is a MAJOR guess. The specific changes
4107 * to do here were determined by compiling test cases with and without
4108 * the key word 'static' and looking at the difference between the STABS
4109 * the compiler generates and trying to match that here.
4111 global_strings
= strings
;
4112 if(object
->mh
!= NULL
)
4113 qsort(changed_globals
, nchanged_globals
, sizeof(struct nlist
*),
4114 (int (*)(const void *, const void *))cmp_qsort_global
);
4116 qsort(changed_globals64
, nchanged_globals
,sizeof(struct nlist_64
*),
4117 (int (*)(const void *, const void *))cmp_qsort_global_64
);
4118 dwarf_debug_map
= FALSE
;
4119 for(i
= 0; i
< nsyms
; i
++){
4121 if(object
->mh
!= NULL
){
4122 n_strx
= symbols
[i
].n_un
.n_strx
;
4123 n_type
= symbols
[i
].n_type
;
4124 n_desc
= symbols
[i
].n_desc
;
4127 n_strx
= symbols64
[i
].n_un
.n_strx
;
4128 n_type
= symbols64
[i
].n_type
;
4129 n_desc
= symbols64
[i
].n_desc
;
4132 dwarf_debug_map
= FALSE
;
4133 else if (n_type
== N_OSO
)
4134 dwarf_debug_map
= n_desc
!= 0;
4135 else if (dwarf_debug_map
&& n_type
== N_GSYM
){
4136 global_name
= strings
+ n_strx
;
4137 if(object
->mh
!= NULL
){
4138 global_symbol
= bsearch(global_name
, changed_globals
,
4139 nchanged_globals
,sizeof(struct nlist
*),
4140 (int (*)(const void *, const void *))
4141 cmp_bsearch_global
);
4142 if(global_symbol
!= NULL
){
4143 symbols
[i
].n_type
= N_STSYM
;
4144 symbols
[i
].n_sect
= (*global_symbol
)->n_sect
;
4145 symbols
[i
].n_value
= (*global_symbol
)->n_value
;
4149 global_symbol64
= bsearch(global_name
, changed_globals64
,
4151 sizeof(struct nlist_64
*),
4152 (int (*)(const void *, const void *))
4153 cmp_bsearch_global_64
);
4154 if(global_symbol64
!= NULL
){
4155 symbols64
[i
].n_type
= N_STSYM
;
4156 symbols64
[i
].n_sect
= (*global_symbol64
)->n_sect
;
4157 symbols64
[i
].n_value
= (*global_symbol64
)->n_value
;
4161 else if(! dwarf_debug_map
&&
4162 (n_type
== N_GSYM
|| n_type
== N_FUN
) &&
4163 (n_strx
!= 0 && strings
[n_strx
] != '\0')){
4164 global_name
= strings
+ n_strx
;
4165 if((global_name
[0] == '+' || global_name
[0] == '-') &&
4166 global_name
[1] == '['){
4168 while(j
+ n_strx
< strsize
&& global_name
[j
] != ']')
4170 if(j
+ n_strx
< strsize
&& global_name
[j
] == ']')
4175 while(j
+ n_strx
< strsize
&& global_name
[j
] != ':')
4177 if(j
+ n_strx
>= strsize
){
4178 error_arch(arch
, member
, "bad N_STAB symbol name for entry "
4179 "%lu (does not contain ':' separating name from type) "
4183 save_char
= global_name
[j
];
4184 global_name
[j
] = '\0';
4186 global_symbol_found
= FALSE
;
4187 global_symbol_n_sect
= 0;
4188 if(object
->mh
!= NULL
){
4189 global_symbol
= bsearch(global_name
, changed_globals
,
4190 nchanged_globals
,sizeof(struct nlist
*),
4191 (int (*)(const void *, const void *))
4192 cmp_bsearch_global_stab
);
4193 global_symbol64
= NULL
;
4194 if(global_symbol
!= NULL
){
4195 global_symbol_found
= TRUE
;
4196 global_symbol_n_sect
= (*global_symbol
)->n_sect
;
4200 global_symbol64
= bsearch(global_name
, changed_globals64
,
4202 sizeof(struct nlist_64
*),
4203 (int (*)(const void *, const void *))
4204 cmp_bsearch_global_stab_64
);
4205 global_symbol
= NULL
;
4206 if(global_symbol64
!= NULL
){
4207 global_symbol_found
= TRUE
;
4208 global_symbol_n_sect
= (*global_symbol64
)->n_sect
;
4211 global_name
[j
] = save_char
;
4212 if(global_symbol_found
== TRUE
){
4213 if(n_type
== N_GSYM
){
4214 if(global_symbol_n_sect
== data_n_sect
){
4215 if(object
->mh
!= NULL
)
4216 symbols
[i
].n_type
= N_STSYM
;
4218 symbols64
[i
].n_type
= N_STSYM
;
4221 if(object
->mh
!= NULL
)
4222 symbols
[i
].n_type
= N_FUN
;
4224 symbols64
[i
].n_type
= N_FUN
;
4226 if(object
->mh
!= NULL
){
4227 symbols
[i
].n_sect
= (*global_symbol
)->n_sect
;
4228 symbols
[i
].n_value
= (*global_symbol
)->n_value
;
4229 symbols
[i
].n_desc
= (*global_symbol
)->n_desc
;
4232 symbols64
[i
].n_sect
= (*global_symbol64
)->n_sect
;
4233 symbols64
[i
].n_value
= (*global_symbol64
)->n_value
;
4234 symbols64
[i
].n_desc
= (*global_symbol64
)->n_desc
;
4236 if(j
+ 1 + n_strx
>= strsize
||
4237 global_name
[j
+1] != 'G'){
4238 error_arch(arch
, member
, "bad N_GSYM symbol name "
4239 "for entry %lu (does not have type 'G' after "
4240 "':' in name) in: ", i
);
4243 global_name
[j
+1] = 'S';
4245 else{ /* n_type == N_FUN */
4246 if(j
+ 1 + n_strx
>= strsize
||
4247 global_name
[j
+1] == 'F'){
4248 global_name
[j
+1] = 'f';
4254 global_strings
= NULL
;
4257 * Now what needs to be done is to create the new symbol table moving
4258 * those global symbols being changed into non-globals into the areas
4259 * in the symbol table for local symbols. The symbol table and string
4260 * table must be in this order:
4264 * external defined symbols
4272 saves
= (long *)allocate(nsyms
* sizeof(long));
4273 bzero(saves
, nsyms
* sizeof(long));
4275 if(object
->mh
!= NULL
){
4276 new_symbols
= (struct nlist
*)
4277 allocate(new_nsyms
* sizeof(struct nlist
));
4278 new_symbols64
= NULL
;
4282 new_symbols64
= (struct nlist_64
*)
4283 allocate(new_nsyms
* sizeof(struct nlist_64
));
4285 new_strsize
= round(new_strsize
, sizeof(long));
4286 new_strings
= (char *)allocate(new_strsize
);
4287 new_strings
[new_strsize
- 3] = '\0';
4288 new_strings
[new_strsize
- 2] = '\0';
4289 new_strings
[new_strsize
- 1] = '\0';
4291 memset(new_strings
, '\0', sizeof(long));
4292 p
= new_strings
+ sizeof(long);
4293 q
= p
+ new_ext_strsize
;
4296 * If this is a dynamic library the movement of the symbols has to be
4297 * done with respect to the modules. As the local symbols, and external
4298 * defined symbols are grouped together for each module. Then a new
4299 * module table needs to be created with the new indexes into the symbol
4300 * table for each module.
4302 new_nmodtab
= nmodtab
;
4304 new_nextrefsyms
= nextrefsyms
;
4305 if(object
->mh_filetype
== MH_DYLIB
&& nmodtab
!= 0){
4306 if(object
->mh
!= NULL
){
4307 new_mods
= allocate(nmodtab
* sizeof(struct dylib_module
));
4312 new_mods64
= allocate(nmodtab
* sizeof(struct dylib_module_64
));
4317 * This first loop through the module table sets the index and
4318 * counts of the local symbols for each module.
4320 for(i
= 0; i
< nmodtab
; i
++){
4322 * First put the existing local symbols into the new symbol
4325 if(object
->mh
!= NULL
){
4326 new_mods
[i
].ilocalsym
= inew_syms
;
4327 new_mods
[i
].nlocalsym
= 0;
4328 ilocalsym
= mods
[i
].ilocalsym
;
4329 nlocalsym
= mods
[i
].nlocalsym
;
4332 new_mods64
[i
].ilocalsym
= inew_syms
;
4333 new_mods64
[i
].nlocalsym
= 0;
4334 ilocalsym
= mods64
[i
].ilocalsym
;
4335 nlocalsym
= mods64
[i
].nlocalsym
;
4337 for(j
= ilocalsym
; j
< ilocalsym
+ nlocalsym
; j
++){
4338 if(object
->mh
!= NULL
){
4339 n_strx
= symbols
[j
].n_un
.n_strx
;
4340 n_type
= symbols
[j
].n_type
;
4343 n_strx
= symbols64
[j
].n_un
.n_strx
;
4344 n_type
= symbols64
[j
].n_type
;
4346 if((n_type
& N_EXT
) == 0){
4347 if(object
->mh
!= NULL
)
4348 new_symbols
[inew_syms
] = symbols
[j
];
4350 new_symbols64
[inew_syms
] = symbols64
[j
];
4352 strcpy(q
, strings
+ n_strx
);
4353 if(object
->mh
!= NULL
)
4354 new_symbols
[inew_syms
].n_un
.n_strx
=
4357 new_symbols64
[inew_syms
].n_un
.n_strx
=
4362 saves
[j
] = inew_syms
;
4363 if(object
->mh
!= NULL
)
4364 new_mods
[i
].nlocalsym
++;
4366 new_mods64
[i
].nlocalsym
++;
4370 * Next put the global symbols that were changed into
4371 * non-global symbols into the new symbol table and moved their
4372 * counts to the local symbol counts.
4374 if(object
->mh
!= NULL
){
4375 iextdefsym
= mods
[i
].iextdefsym
;
4376 nextdefsym
= mods
[i
].nextdefsym
;
4379 iextdefsym
= mods64
[i
].iextdefsym
;
4380 nextdefsym
= mods64
[i
].nextdefsym
;
4382 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
4383 if(object
->mh
!= NULL
){
4384 n_strx
= symbols
[j
].n_un
.n_strx
;
4385 n_type
= symbols
[j
].n_type
;
4388 n_strx
= symbols64
[j
].n_un
.n_strx
;
4389 n_type
= symbols64
[j
].n_type
;
4391 if((n_type
& N_EXT
) != 0){
4392 if(nmedits
[j
] == TRUE
){
4394 * Change the new symbol to a private extern symbol
4395 * with the extern bit off.
4397 if(object
->mh
!= NULL
){
4398 new_symbols
[inew_syms
] = symbols
[j
];
4399 new_symbols
[inew_syms
].n_type
|= N_PEXT
;
4400 new_symbols
[inew_syms
].n_type
&= ~N_EXT
;
4403 new_symbols64
[inew_syms
] = symbols64
[j
];
4404 new_symbols64
[inew_syms
].n_type
|= N_PEXT
;
4405 new_symbols64
[inew_syms
].n_type
&= ~N_EXT
;
4408 strcpy(q
, strings
+ n_strx
);
4409 if(object
->mh
!= NULL
)
4410 new_symbols
[inew_syms
].n_un
.n_strx
=
4413 new_symbols64
[inew_syms
].n_un
.n_strx
=
4418 saves
[j
] = inew_syms
;
4419 if(object
->mh
!= NULL
)
4420 new_mods
[i
].nlocalsym
++;
4422 new_mods64
[i
].nlocalsym
++;
4428 * Next put the unchanged defined global symbols into the new
4431 for(i
= 0; i
< nmodtab
; i
++){
4432 if(object
->mh
!= NULL
){
4433 new_mods
[i
].iextdefsym
= inew_syms
;
4434 new_mods
[i
].nextdefsym
= 0;
4435 iextdefsym
= mods
[i
].iextdefsym
;
4436 nextdefsym
= mods
[i
].nextdefsym
;
4439 new_mods64
[i
].iextdefsym
= inew_syms
;
4440 new_mods64
[i
].nextdefsym
= 0;
4441 iextdefsym
= mods64
[i
].iextdefsym
;
4442 nextdefsym
= mods64
[i
].nextdefsym
;
4444 for(j
= iextdefsym
; j
< iextdefsym
+ nextdefsym
; j
++){
4445 if(object
->mh
!= NULL
){
4446 n_strx
= symbols
[j
].n_un
.n_strx
;
4447 n_type
= symbols
[j
].n_type
;
4450 n_strx
= symbols64
[j
].n_un
.n_strx
;
4451 n_type
= symbols64
[j
].n_type
;
4453 if((n_type
& N_EXT
) != 0){
4454 if(nmedits
[j
] == FALSE
){
4455 if(object
->mh
!= NULL
)
4456 new_symbols
[inew_syms
] = symbols
[j
];
4458 new_symbols64
[inew_syms
] = symbols64
[j
];
4460 strcpy(p
, strings
+ n_strx
);
4461 if(object
->mh
!= NULL
)
4462 new_symbols
[inew_syms
].n_un
.n_strx
=
4465 new_symbols64
[inew_syms
].n_un
.n_strx
=
4470 saves
[j
] = inew_syms
;
4471 if(object
->mh
!= NULL
)
4472 new_mods
[i
].nextdefsym
++;
4474 new_mods64
[i
].nextdefsym
++;
4480 * Last put the undefined symbols into the new symbol table.
4482 for(i
= 0; i
< nsyms
; i
++){
4483 if(object
->mh
!= NULL
){
4484 n_strx
= symbols
[i
].n_un
.n_strx
;
4485 n_type
= symbols
[i
].n_type
;
4488 n_strx
= symbols64
[i
].n_un
.n_strx
;
4489 n_type
= symbols64
[i
].n_type
;
4491 if((n_type
& N_EXT
) != 0 &&
4492 ((n_type
& N_TYPE
) == N_UNDF
||
4493 (n_type
& N_TYPE
) == N_PBUD
)){
4494 if(object
->mh
!= NULL
)
4495 new_symbols
[inew_syms
] = symbols
[i
];
4497 new_symbols64
[inew_syms
] = symbols64
[i
];
4499 strcpy(p
, strings
+ n_strx
);
4500 if(object
->mh
!= NULL
)
4501 new_symbols
[inew_syms
].n_un
.n_strx
=
4504 new_symbols64
[inew_syms
].n_un
.n_strx
=
4509 saves
[i
] = inew_syms
;
4514 * Place the module table's module names with the external strings
4515 * and set the names in the new module table. And then copy the
4516 * other unchanged fields.
4518 for(i
= 0; i
< nmodtab
; i
++){
4519 if(object
->mh
!= NULL
){
4520 strcpy(p
, strings
+ mods
[i
].module_name
);
4521 new_mods
[i
].module_name
= p
- new_strings
;
4524 new_mods
[i
].irefsym
= mods
[i
].irefsym
;
4525 new_mods
[i
].nrefsym
= mods
[i
].nrefsym
;
4526 new_mods
[i
].iextrel
= mods
[i
].iextrel
;
4527 new_mods
[i
].nextrel
= mods
[i
].nextrel
;
4528 new_mods
[i
].iinit_iterm
= mods
[i
].iinit_iterm
;
4529 new_mods
[i
].ninit_nterm
= mods
[i
].ninit_nterm
;
4530 new_mods
[i
].objc_module_info_addr
=
4531 mods
[i
].objc_module_info_addr
;
4532 new_mods
[i
].objc_module_info_size
=
4533 mods
[i
].objc_module_info_size
;
4536 strcpy(p
, strings
+ mods64
[i
].module_name
);
4537 new_mods64
[i
].module_name
= p
- new_strings
;
4540 new_mods64
[i
].irefsym
= mods64
[i
].irefsym
;
4541 new_mods64
[i
].nrefsym
= mods64
[i
].nrefsym
;
4542 new_mods64
[i
].iextrel
= mods64
[i
].iextrel
;
4543 new_mods64
[i
].nextrel
= mods64
[i
].nextrel
;
4544 new_mods64
[i
].iinit_iterm
= mods64
[i
].iinit_iterm
;
4545 new_mods64
[i
].ninit_nterm
= mods64
[i
].ninit_nterm
;
4546 new_mods64
[i
].objc_module_info_addr
=
4547 mods64
[i
].objc_module_info_addr
;
4548 new_mods64
[i
].objc_module_info_size
=
4549 mods64
[i
].objc_module_info_size
;
4554 * Update the reference table with the new symbol indexes for all
4555 * entries and change type of reference (the flags field) for those
4556 * symbols that got changed from globals to non-globals.
4558 new_nextrefsyms
= nextrefsyms
;
4559 new_refs
= allocate(new_nextrefsyms
*
4560 sizeof(struct dylib_reference
));
4562 for(i
= 0; i
< nextrefsyms
; i
++){
4563 if(nmedits
[refs
[i
].isym
] == TRUE
){
4564 if(refs
[i
].flags
== REFERENCE_FLAG_DEFINED
)
4566 REFERENCE_FLAG_PRIVATE_DEFINED
;
4567 else if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_NON_LAZY
)
4569 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY
;
4570 else if(refs
[i
].flags
== REFERENCE_FLAG_UNDEFINED_LAZY
)
4572 REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY
;
4574 new_refs
[i
].flags
= refs
[i
].flags
;
4577 new_refs
[i
].flags
= refs
[i
].flags
;
4579 new_refs
[i
].isym
= saves
[refs
[i
].isym
] - 1;
4583 * Create a new dylib table of contents without the global symbols
4584 * that got turned into non-globals.
4586 new_ntoc
= ntoc
- nchanged_globals
;
4587 new_tocs
= allocate(new_ntoc
*
4588 sizeof(struct dylib_table_of_contents
));
4590 for(i
= 0; i
< ntoc
; i
++){
4591 if(tocs
[i
].symbol_index
>= nsyms
){
4592 error_arch(arch
, member
, "bad symbol index for table of "
4593 "contents table entry %ld in: ", i
);
4596 if(nmedits
[tocs
[i
].symbol_index
] == FALSE
){
4597 new_tocs
[k
].symbol_index
= saves
[tocs
[i
].symbol_index
] - 1;
4598 new_tocs
[k
].module_index
= tocs
[i
].module_index
;
4604 * If is not a dynamic library so all global symbols changed into
4605 * statics can be moved to the end of the local symbols. If the pflag
4606 * is set then the changed symbols remain global and just get the
4607 * private extern bit set.
4611 * First put the existing local symbols into the new symbol table.
4614 for(i
= 0; i
< nsyms
; i
++){
4615 if(object
->mh
!= NULL
){
4616 n_strx
= symbols
[i
].n_un
.n_strx
;
4617 n_type
= symbols
[i
].n_type
;
4620 n_strx
= symbols64
[i
].n_un
.n_strx
;
4621 n_type
= symbols64
[i
].n_type
;
4623 if((n_type
& N_EXT
) == 0){
4624 if(object
->mh
!= NULL
)
4625 new_symbols
[inew_syms
] = symbols
[i
];
4627 new_symbols64
[inew_syms
] = symbols64
[i
];
4629 strcpy(q
, strings
+ n_strx
);
4630 if(object
->mh
!= NULL
)
4631 new_symbols
[inew_syms
].n_un
.n_strx
=
4634 new_symbols64
[inew_syms
].n_un
.n_strx
=
4639 saves
[i
] = inew_syms
;
4643 * Next put the global symbols that were changed into statics
4644 * symbols into the new symbol table.
4647 for(i
= 0; i
< nsyms
; i
++){
4648 if(object
->mh
!= NULL
){
4649 n_strx
= symbols
[i
].n_un
.n_strx
;
4650 n_type
= symbols
[i
].n_type
;
4653 n_strx
= symbols64
[i
].n_un
.n_strx
;
4654 n_type
= symbols64
[i
].n_type
;
4656 if((n_type
& N_EXT
) != 0){
4657 if(nmedits
[i
] == TRUE
){
4659 * Change the new symbol to not be an extern symbol
4660 * by turning off the extern bit.
4662 if(object
->mh
!= NULL
){
4663 new_symbols
[inew_syms
] = symbols
[i
];
4664 new_symbols
[inew_syms
].n_type
&= ~N_EXT
;
4665 new_symbols
[inew_syms
].n_desc
&= ~N_WEAK_DEF
;
4668 new_symbols64
[inew_syms
] = symbols64
[i
];
4669 new_symbols64
[inew_syms
].n_type
&= ~N_EXT
;
4670 new_symbols64
[inew_syms
].n_desc
&= ~N_WEAK_DEF
;
4673 strcpy(q
, strings
+ n_strx
);
4674 if(object
->mh
!= NULL
)
4675 new_symbols
[inew_syms
].n_un
.n_strx
=
4678 new_symbols64
[inew_syms
].n_un
.n_strx
=
4683 saves
[i
] = inew_syms
;
4689 * Last put the unchanged global symbols into the new symbol table
4690 * and symbols changed into private externs.
4692 for(i
= 0; i
< nsyms
; i
++){
4693 if(object
->mh
!= NULL
){
4694 n_strx
= symbols
[i
].n_un
.n_strx
;
4695 n_type
= symbols
[i
].n_type
;
4698 n_strx
= symbols64
[i
].n_un
.n_strx
;
4699 n_type
= symbols64
[i
].n_type
;
4701 if((n_type
& N_EXT
) != 0){
4702 if(nmedits
[i
] == FALSE
|| pflag
== TRUE
){
4703 if(object
->mh
!= NULL
)
4704 new_symbols
[inew_syms
] = symbols
[i
];
4706 new_symbols64
[inew_syms
] = symbols64
[i
];
4707 if(nmedits
[i
] == TRUE
&& pflag
== TRUE
){
4709 * Change the new symbol to be a private extern
4710 * symbol by turning on the private extern bit.
4712 if(object
->mh
!= NULL
)
4713 new_symbols
[inew_syms
].n_type
|= N_PEXT
;
4715 new_symbols64
[inew_syms
].n_type
|= N_PEXT
;
4718 strcpy(p
, strings
+ n_strx
);
4719 if(object
->mh
!= NULL
)
4720 new_symbols
[inew_syms
].n_un
.n_strx
=
4723 new_symbols64
[inew_syms
].n_un
.n_strx
=
4728 saves
[i
] = inew_syms
;
4734 if(sections
!= NULL
);
4736 if(sections64
!= NULL
);
4746 * Function for qsort for comparing global symbol names.
4751 const struct nlist
**sym1
,
4752 const struct nlist
**sym2
)
4754 return(strcmp(global_strings
+ (*sym1
)->n_un
.n_strx
,
4755 global_strings
+ (*sym2
)->n_un
.n_strx
));
4760 cmp_qsort_global_64(
4761 const struct nlist_64
**sym1
,
4762 const struct nlist_64
**sym2
)
4764 return(strcmp(global_strings
+ (*sym1
)->n_un
.n_strx
,
4765 global_strings
+ (*sym2
)->n_un
.n_strx
));
4769 * Function for bsearch for finding a global symbol that matches a stab name.
4773 cmp_bsearch_global_stab(
4775 const struct nlist
**sym
)
4778 * The +1 is for the '_' on the global symbol that is not on the
4779 * stab string that is trying to be matched.
4781 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
+ 1));
4786 cmp_bsearch_global_stab_64(
4788 const struct nlist_64
**sym
)
4791 * The +1 is for the '_' on the global symbol that is not on the
4792 * stab string that is trying to be matched.
4794 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
+ 1));
4798 * Function for bsearch for finding a global symbol that matches a stab name
4805 const struct nlist
**sym
)
4807 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
));
4812 cmp_bsearch_global_64(
4814 const struct nlist_64
**sym
)
4816 return(strcmp(name
, global_strings
+ (*sym
)->n_un
.n_strx
));
4818 #endif /* defined(NMEDIT) */