2 * Copyright (c) 2006 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@
27 #include <mach/mach_init.h>
33 #include <mach-o/arch.h>
34 #include <mach-o/fat.h>
35 #include <mach-o/loader.h>
36 #include <mach-o/nlist.h>
37 #include <mach-o/swap.h>
39 #include <uuid/uuid.h>
42 #pragma mark Typedefs, Enums, Constants
43 /*********************************************************************
44 * Typedefs, Enums, Constants
45 *********************************************************************/
54 #pragma mark Function Protos
55 /*********************************************************************
57 *********************************************************************/
58 __private_extern__ ToolError
59 readFile(const char *path
, vm_offset_t
* objAddr
, vm_size_t
* objSize
);
61 __private_extern__ ToolError
62 writeFile(int fd
, const void * data
, size_t length
);
64 __private_extern__ ToolError
65 seekFile(int fd
, off_t offset
);
67 extern char* __cxa_demangle(const char* mangled_name
,
72 #pragma mark Functions
73 /*********************************************************************
74 *********************************************************************/
75 __private_extern__ ToolError
76 writeFile(int fd
, const void * data
, size_t length
)
80 if (length
!= (size_t)write(fd
, data
, length
)) {
86 if (kErrorNone
!= err
) {
87 perror("couldn't write output");
93 /*********************************************************************
94 *********************************************************************/
95 __private_extern__ ToolError
96 seekFile(int fd
, off_t offset
)
100 if (offset
!= lseek(fd
, offset
, SEEK_SET
)) {
101 err
= kErrorDiskFull
;
106 if (kErrorNone
!= err
) {
107 perror("couldn't write output");
113 /*********************************************************************
114 *********************************************************************/
115 __private_extern__ ToolError
116 readFile(const char *path
, vm_offset_t
* objAddr
, vm_size_t
* objSize
)
118 ToolError err
= kErrorFileAccess
;
120 struct stat stat_buf
;
126 if ((fd
= open(path
, O_RDONLY
)) == -1) {
130 if (fstat(fd
, &stat_buf
) == -1) {
134 if (0 == (stat_buf
.st_mode
& S_IFREG
)) {
138 /* Don't try to map an empty file, it fails now due to conformance
139 * stuff (PR 4611502).
141 if (0 == stat_buf
.st_size
) {
146 *objSize
= stat_buf
.st_size
;
148 *objAddr
= (vm_offset_t
)mmap(NULL
/* address */, *objSize
,
149 PROT_READ
| PROT_WRITE
, MAP_FILE
| MAP_PRIVATE
/* flags */,
152 if ((void *)*objAddr
== MAP_FAILED
) {
164 if (kErrorNone
!= err
) {
165 fprintf(stderr
, "couldn't read %s: %s\n", path
, strerror(errno
));
172 enum { kExported
= 0x00000001, kObsolete
= 0x00000002 };
176 unsigned int name_len
;
178 unsigned int indirect_len
;
180 struct symbol
* list
;
181 unsigned int list_count
;
187 return (c
> ' ') && (c
<= '~') && (c
!= ':') && (c
!= '#');
191 iswhitespace( char c
)
193 return (c
== ' ') || (c
== '\t');
197 * Function for qsort for comparing symbol list names.
200 qsort_cmp(const void * _left
, const void * _right
)
202 struct symbol
* left
= (struct symbol
*) _left
;
203 struct symbol
* right
= (struct symbol
*) _right
;
205 return strcmp(left
->name
, right
->name
);
209 * Function for bsearch for finding a symbol name.
213 bsearch_cmp( const void * _key
, const void * _cmp
)
215 char * key
= (char *)_key
;
216 struct symbol
* cmp
= (struct symbol
*) _cmp
;
218 return strcmp(key
, cmp
->name
);
223 unsigned int name_len
;
227 bsearch_cmp_prefix( const void * _key
, const void * _cmp
)
229 struct bsearch_key
* key
= (struct bsearch_key
*)_key
;
230 struct symbol
* cmp
= (struct symbol
*) _cmp
;
232 return strncmp(key
->name
, cmp
->name
, key
->name_len
);
236 count_symbols(char * file
, vm_size_t file_size
)
243 for (scan
= file
; true; scan
= next
) {
244 eol
= memchr(scan
, '\n', file_size
- (scan
- file
));
256 /* Skip comment lines.
258 if (scan
[0] == '#') {
262 /* Scan past any non-symbol characters at the beginning of the line. */
263 while ((scan
< eol
) && !issymchar(*scan
)) {
267 /* No symbol on line? Move along.
273 /* Skip symbols starting with '.'.
275 if (scan
[0] == '.') {
285 store_symbols(char * file
, vm_size_t file_size
, struct symbol
* symbols
, uint32_t idx
, uint32_t max_symbols
)
296 for (scan
= file
, line
= file
; true; scan
= next
, line
= next
) {
298 char * name_term
= NULL
;
299 unsigned int name_len
= 0;
300 char * indirect
= NULL
;
301 char * indirect_term
= NULL
;
302 unsigned int indirect_len
= 0;
303 char * option
= NULL
;
304 char * option_term
= NULL
;
305 unsigned int option_len
= 0;
307 boolean_t obsolete
= 0;
309 eol
= memchr(scan
, '\n', file_size
- (scan
- file
));
323 /* Skip comment lines.
325 if (scan
[0] == '#') {
329 /* Scan past any non-symbol characters at the beginning of the line. */
330 while ((scan
< eol
) && !issymchar(*scan
)) {
334 /* No symbol on line? Move along.
340 /* Skip symbols starting with '.'.
342 if (scan
[0] == '.') {
348 /* Find the end of the symbol.
350 while ((*scan
!= '\0') && issymchar(*scan
)) {
354 /* Note char past end of symbol.
358 /* Stored length must include the terminating nul char.
360 name_len
= name_term
- name
+ 1;
362 /* Now look for an indirect.
365 while ((*scan
!= '\0') && iswhitespace(*scan
)) {
370 while ((*scan
!= '\0') && iswhitespace(*scan
)) {
373 if (issymchar(*scan
)) {
376 /* Find the end of the symbol.
378 while ((*scan
!= '\0') && issymchar(*scan
)) {
382 /* Note char past end of symbol.
384 indirect_term
= scan
;
386 /* Stored length must include the terminating nul char.
388 indirect_len
= indirect_term
- indirect
+ 1;
389 } else if (*scan
== '\0') {
390 fprintf(stderr
, "bad format in symbol line: %s\n", line
);
393 } else if (*scan
!= '\0' && *scan
!= '-') {
394 fprintf(stderr
, "bad format in symbol line: %s\n", line
);
402 while ((*scan
!= '\0') && iswhitespace(*scan
)) {
409 if (isalpha(*scan
)) {
412 /* Find the end of the option.
414 while ((*scan
!= '\0') && isalpha(*scan
)) {
418 /* Note char past end of option.
421 option_len
= option_term
- option
;
423 if (option_len
>= sizeof(optionstr
)) {
424 fprintf(stderr
, "option too long in symbol line: %s\n", line
);
427 memcpy(optionstr
, option
, option_len
);
428 optionstr
[option_len
] = '\0';
432 if (!strncmp(optionstr
, "obsolete", option_len
)) {
435 } else if (*scan
== '\0') {
436 fprintf(stderr
, "bad format in symbol line: %s\n", line
);
442 if (idx
>= max_symbols
) {
443 fprintf(stderr
, "symbol[%d/%d] overflow: %s\n", idx
, max_symbols
, line
);
449 *indirect_term
= '\0';
452 symbols
[idx
].name
= name
;
453 symbols
[idx
].name_len
= name_len
;
454 symbols
[idx
].indirect
= indirect
;
455 symbols
[idx
].indirect_len
= indirect_len
;
456 symbols
[idx
].flags
= (obsolete
) ? kObsolete
: 0;
458 strtabsize
+= symbols
[idx
].name_len
+ symbols
[idx
].indirect_len
;
465 static const NXArchInfo
*
466 lookup_arch(const char *archstring
)
469 * As new architectures are supported by xnu, add a mapping function
470 * without relying on host libraries.
472 static const NXArchInfo archlist
[] = {
473 { "x86_64", 0x01000007 /* CPU_TYPE_X86_64 */, 3 /* CPU_SUBTYPE_X86_64_ALL */, NX_LittleEndian
, NULL
},
474 { "x86_64h", 0x01000007 /* CPU_TYPE_X86_64 */, 8 /* CPU_SUBTYPE_X86_64_H */, NX_LittleEndian
, NULL
},
475 { "armv7", 12 /* CPU_TYPE_ARM */, 9 /* CPU_SUBTYPE_ARM_V7 */, NX_LittleEndian
, NULL
},
476 { "armv7s", 12 /* CPU_TYPE_ARM */, 11 /* CPU_SUBTYPE_ARM_V7S */, NX_LittleEndian
, NULL
},
477 { "armv7k", 12 /* CPU_TYPE_ARM */, 12 /* CPU_SUBTYPE_ARM_V7K */, NX_LittleEndian
, NULL
},
478 { "arm64", 0x0100000c /* CPU_TYPE_ARM64 */, 0 /* CPU_SUBTYPE_ARM64_ALL */, NX_LittleEndian
, NULL
},
479 { "arm64e", 0x0100000c /* CPU_TYPE_ARM64 */, 2 /* CPU_SUBTYPE_ARM64_E */, NX_LittleEndian
, NULL
},
483 for (i
= 0; i
< sizeof(archlist
) / sizeof(archlist
[0]); i
++) {
484 if (0 == strcmp(archstring
, archlist
[i
].name
)) {
492 /*********************************************************************
493 *********************************************************************/
495 main(int argc
, char * argv
[])
499 const char * output_name
= NULL
;
500 uint32_t zero
= 0, num_files
= 0;
502 uint32_t strx
, strtabsize
, strtabpad
;
503 struct symbol
* import_symbols
;
504 struct symbol
* export_symbols
;
505 uint32_t num_import_syms
, num_export_syms
;
506 uint32_t result_count
, num_removed_syms
;
507 uint32_t import_idx
, export_idx
;
508 const NXArchInfo
* host_arch
;
509 const NXArchInfo
* target_arch
;
510 boolean_t require_imports
= true;
511 boolean_t diff
= false;
516 vm_size_t mapped_size
;
521 struct file files
[64];
523 host_arch
= NXGetLocalArchInfo();
524 target_arch
= host_arch
;
526 for (i
= 1; i
< argc
; i
+= 2) {
529 if (!strcmp("-sect", argv
[i
])) {
530 require_imports
= false;
534 if (!strcmp("-diff", argv
[i
])) {
535 require_imports
= false;
541 if (i
== (argc
- 1)) {
542 fprintf(stderr
, "bad arguments: %s\n", argv
[i
]);
546 if (!strcmp("-arch", argv
[i
])) {
547 target_arch
= lookup_arch(argv
[i
+ 1]);
549 fprintf(stderr
, "unknown architecture name: %s\n", argv
[i
+ 1]);
554 if (!strcmp("-output", argv
[i
])) {
555 output_name
= argv
[i
+ 1];
559 if (!strcmp("-import", argv
[i
])) {
561 } else if (!strcmp("-export", argv
[i
])) {
564 fprintf(stderr
, "unknown option: %s\n", argv
[i
]);
568 err
= readFile(argv
[i
+ 1], &files
[num_files
].mapped
, &files
[num_files
].mapped_size
);
569 if (kErrorNone
!= err
) {
573 if (files
[num_files
].mapped
&& files
[num_files
].mapped_size
) {
574 files
[num_files
].import = import;
575 files
[num_files
].path
= argv
[i
+ 1];
581 fprintf(stderr
, "no output file\n");
587 for (filenum
= 0; filenum
< num_files
; filenum
++) {
588 files
[filenum
].nsyms
= count_symbols((char *) files
[filenum
].mapped
, files
[filenum
].mapped_size
);
589 if (files
[filenum
].import) {
590 num_import_syms
+= files
[filenum
].nsyms
;
592 num_export_syms
+= files
[filenum
].nsyms
;
596 import_symbols
= calloc(num_import_syms
, sizeof(struct symbol
));
597 export_symbols
= calloc(num_export_syms
, sizeof(struct symbol
));
602 for (filenum
= 0; filenum
< num_files
; filenum
++) {
603 if (files
[filenum
].import) {
604 store_symbols((char *) files
[filenum
].mapped
, files
[filenum
].mapped_size
,
605 import_symbols
, import_idx
, num_import_syms
);
606 import_idx
+= files
[filenum
].nsyms
;
608 store_symbols((char *) files
[filenum
].mapped
, files
[filenum
].mapped_size
,
609 export_symbols
, export_idx
, num_export_syms
);
610 export_idx
+= files
[filenum
].nsyms
;
612 if (false && !files
[filenum
].nsyms
) {
613 fprintf(stderr
, "warning: file %s contains no names\n", files
[filenum
].path
);
618 qsort(import_symbols
, num_import_syms
, sizeof(struct symbol
), &qsort_cmp
);
619 qsort(export_symbols
, num_export_syms
, sizeof(struct symbol
), &qsort_cmp
);
622 num_removed_syms
= 0;
624 if (num_import_syms
) {
625 for (export_idx
= 0; export_idx
< num_export_syms
; export_idx
++) {
626 struct symbol
* result
;
631 name
= export_symbols
[export_idx
].indirect
;
632 len
= export_symbols
[export_idx
].indirect_len
;
634 name
= export_symbols
[export_idx
].name
;
635 len
= export_symbols
[export_idx
].name_len
;
637 wild
= ((len
> 2) && ('*' == name
[len
-= 2]));
639 struct bsearch_key key
;
642 result
= bsearch(&key
, import_symbols
,
643 num_import_syms
, sizeof(struct symbol
), &bsearch_cmp_prefix
);
646 struct symbol
* first
;
647 struct symbol
* last
;
649 strtabsize
+= (result
->name_len
+ result
->indirect_len
);
652 while (--first
>= &import_symbols
[0]) {
653 if (bsearch_cmp_prefix(&key
, first
)) {
656 strtabsize
+= (first
->name_len
+ first
->indirect_len
);
661 while (++last
< (&import_symbols
[0] + num_import_syms
)) {
662 if (bsearch_cmp_prefix(&key
, last
)) {
665 strtabsize
+= (last
->name_len
+ last
->indirect_len
);
667 result_count
+= last
- first
;
669 export_symbols
[export_idx
].list
= first
;
670 export_symbols
[export_idx
].list_count
= last
- first
;
671 export_symbols
[export_idx
].flags
|= kExported
;
674 result
= bsearch(name
, import_symbols
,
675 num_import_syms
, sizeof(struct symbol
), &bsearch_cmp
);
678 if (!result
&& require_imports
) {
680 char * demangled_result
=
681 __cxa_demangle(export_symbols
[export_idx
].name
+ 1, NULL
, NULL
, &status
);
682 fprintf(stderr
, "exported name not in import list: %s\n",
683 demangled_result
? demangled_result
: export_symbols
[export_idx
].name
);
684 // fprintf(stderr, " : %s\n", export_symbols[export_idx].name);
685 if (demangled_result
) {
686 free(demangled_result
);
692 result
= &export_symbols
[export_idx
];
697 if (result
&& !wild
) {
698 export_symbols
[export_idx
].flags
|= kExported
;
699 strtabsize
+= (export_symbols
[export_idx
].name_len
+ export_symbols
[export_idx
].indirect_len
);
701 export_symbols
[export_idx
].list
= &export_symbols
[export_idx
];
702 export_symbols
[export_idx
].list_count
= 1;
706 strtabpad
= (strtabsize
+ 3) & ~3;
708 if (require_imports
&& num_removed_syms
) {
713 fd
= open(output_name
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0755);
715 perror("couldn't write output");
716 err
= kErrorFileAccess
;
720 struct symtab_command symcmd
;
721 struct uuid_command uuidcmd
;
724 symcmd
.cmd
= LC_SYMTAB
;
725 symcmd
.cmdsize
= sizeof(symcmd
);
726 symcmd
.nsyms
= result_count
;
727 symcmd
.strsize
= strtabpad
;
729 uuidcmd
.cmd
= LC_UUID
;
730 uuidcmd
.cmdsize
= sizeof(uuidcmd
);
731 uuid_generate(uuidcmd
.uuid
);
733 if (CPU_ARCH_ABI64
& target_arch
->cputype
) {
734 struct mach_header_64 hdr
;
735 struct segment_command_64 segcmd
;
737 hdr
.magic
= MH_MAGIC_64
;
738 hdr
.cputype
= target_arch
->cputype
;
739 hdr
.cpusubtype
= target_arch
->cpusubtype
;
740 hdr
.filetype
= MH_KEXT_BUNDLE
;
742 hdr
.sizeofcmds
= sizeof(segcmd
) + sizeof(symcmd
) + sizeof(uuidcmd
);
743 hdr
.flags
= MH_INCRLINK
;
744 symsoffset
= mach_vm_round_page(hdr
.sizeofcmds
);
746 segcmd
.cmd
= LC_SEGMENT_64
;
747 segcmd
.cmdsize
= sizeof(segcmd
);
748 strncpy(segcmd
.segname
, SEG_LINKEDIT
, sizeof(segcmd
.segname
));
750 segcmd
.vmsize
= result_count
* sizeof(struct nlist_64
) + strtabpad
;
751 segcmd
.fileoff
= symsoffset
;
752 segcmd
.filesize
= segcmd
.vmsize
;
753 segcmd
.maxprot
= PROT_READ
;
754 segcmd
.initprot
= PROT_READ
;
756 segcmd
.flags
= SG_NORELOC
;
758 symcmd
.symoff
= symsoffset
;
759 symcmd
.stroff
= result_count
* sizeof(struct nlist_64
)
762 if (target_arch
->byteorder
!= host_arch
->byteorder
) {
763 swap_mach_header_64(&hdr
, target_arch
->byteorder
);
764 swap_segment_command_64(&segcmd
, target_arch
->byteorder
);
766 err
= writeFile(fd
, &hdr
, sizeof(hdr
));
767 if (kErrorNone
!= err
) {
770 err
= writeFile(fd
, &segcmd
, sizeof(segcmd
));
772 struct mach_header hdr
;
773 struct segment_command segcmd
;
775 hdr
.magic
= MH_MAGIC
;
776 hdr
.cputype
= target_arch
->cputype
;
777 hdr
.cpusubtype
= target_arch
->cpusubtype
;
778 hdr
.filetype
= MH_KEXT_BUNDLE
;
780 hdr
.sizeofcmds
= sizeof(segcmd
) + sizeof(symcmd
) + sizeof(uuidcmd
);
781 hdr
.flags
= MH_INCRLINK
;
782 symsoffset
= mach_vm_round_page(hdr
.sizeofcmds
);
784 segcmd
.cmd
= LC_SEGMENT
;
785 segcmd
.cmdsize
= sizeof(segcmd
);
786 strncpy(segcmd
.segname
, SEG_LINKEDIT
, sizeof(segcmd
.segname
));
788 segcmd
.vmsize
= result_count
* sizeof(struct nlist
) + strtabpad
;
789 segcmd
.fileoff
= symsoffset
;
790 segcmd
.filesize
= segcmd
.vmsize
;
791 segcmd
.maxprot
= PROT_READ
;
792 segcmd
.initprot
= PROT_READ
;
794 segcmd
.flags
= SG_NORELOC
;
796 symcmd
.symoff
= symsoffset
;
797 symcmd
.stroff
= result_count
* sizeof(struct nlist
)
800 if (target_arch
->byteorder
!= host_arch
->byteorder
) {
801 swap_mach_header(&hdr
, target_arch
->byteorder
);
802 swap_segment_command(&segcmd
, target_arch
->byteorder
);
804 err
= writeFile(fd
, &hdr
, sizeof(hdr
));
805 if (kErrorNone
!= err
) {
808 err
= writeFile(fd
, &segcmd
, sizeof(segcmd
));
811 if (kErrorNone
!= err
) {
815 if (target_arch
->byteorder
!= host_arch
->byteorder
) {
816 swap_symtab_command(&symcmd
, target_arch
->byteorder
);
817 swap_uuid_command(&uuidcmd
, target_arch
->byteorder
);
819 err
= writeFile(fd
, &symcmd
, sizeof(symcmd
));
820 if (kErrorNone
!= err
) {
823 err
= writeFile(fd
, &uuidcmd
, sizeof(uuidcmd
));
824 if (kErrorNone
!= err
) {
828 err
= seekFile(fd
, symsoffset
);
829 if (kErrorNone
!= err
) {
834 for (export_idx
= 0; export_idx
< num_export_syms
; export_idx
++) {
835 if (!export_symbols
[export_idx
].name
) {
838 if (!(kExported
& export_symbols
[export_idx
].flags
)) {
843 && export_symbols
[export_idx
- 1].name
844 && !strcmp(export_symbols
[export_idx
- 1].name
, export_symbols
[export_idx
].name
)) {
845 fprintf(stderr
, "duplicate export: %s\n", export_symbols
[export_idx
- 1].name
);
846 err
= kErrorDuplicate
;
850 for (import_idx
= 0; import_idx
< export_symbols
[export_idx
].list_count
; import_idx
++) {
851 if (export_symbols
[export_idx
].list
!= &export_symbols
[export_idx
]) {
852 printf("wild: %s, %s\n", export_symbols
[export_idx
].name
,
853 export_symbols
[export_idx
].list
[import_idx
].name
);
855 if (CPU_ARCH_ABI64
& target_arch
->cputype
) {
860 nl
.n_un
.n_strx
= strx
;
861 strx
+= export_symbols
[export_idx
].list
[import_idx
].name_len
;
863 if (export_symbols
[export_idx
].flags
& kObsolete
) {
864 nl
.n_desc
|= N_DESC_DISCARDED
;
867 if (export_symbols
[export_idx
].list
[import_idx
].indirect
) {
868 nl
.n_type
= N_INDR
| N_EXT
;
870 strx
+= export_symbols
[export_idx
].list
[import_idx
].indirect_len
;
872 nl
.n_type
= N_UNDF
| N_EXT
;
876 if (target_arch
->byteorder
!= host_arch
->byteorder
) {
877 swap_nlist_64(&nl
, 1, target_arch
->byteorder
);
880 err
= writeFile(fd
, &nl
, sizeof(nl
));
886 nl
.n_un
.n_strx
= strx
;
887 strx
+= export_symbols
[export_idx
].list
[import_idx
].name_len
;
889 if (export_symbols
[export_idx
].flags
& kObsolete
) {
890 nl
.n_desc
|= N_DESC_DISCARDED
;
893 if (export_symbols
[export_idx
].list
[import_idx
].indirect
) {
894 nl
.n_type
= N_INDR
| N_EXT
;
896 strx
+= export_symbols
[export_idx
].list
[import_idx
].indirect_len
;
898 nl
.n_type
= N_UNDF
| N_EXT
;
902 if (target_arch
->byteorder
!= host_arch
->byteorder
) {
903 swap_nlist(&nl
, 1, target_arch
->byteorder
);
906 err
= writeFile(fd
, &nl
, sizeof(nl
));
910 if (kErrorNone
!= err
) {
915 strx
= sizeof(uint32_t);
916 err
= writeFile(fd
, &zero
, strx
);
917 if (kErrorNone
!= err
) {
921 for (export_idx
= 0; export_idx
< num_export_syms
; export_idx
++) {
922 if (!export_symbols
[export_idx
].name
) {
926 for (import_idx
= 0; import_idx
< export_symbols
[export_idx
].list_count
; import_idx
++) {
927 err
= writeFile(fd
, export_symbols
[export_idx
].list
[import_idx
].name
,
928 export_symbols
[export_idx
].list
[import_idx
].name_len
);
929 if (kErrorNone
!= err
) {
932 if (export_symbols
[export_idx
].list
[import_idx
].indirect
) {
933 err
= writeFile(fd
, export_symbols
[export_idx
].list
[import_idx
].indirect
,
934 export_symbols
[export_idx
].list
[import_idx
].indirect_len
);
935 if (kErrorNone
!= err
) {
942 err
= writeFile(fd
, &zero
, strtabpad
- strtabsize
);
943 if (kErrorNone
!= err
) {
951 for (filenum
= 0; filenum
< num_files
; filenum
++) {
953 if (files
[filenum
].mapped_size
) {
954 munmap((caddr_t
)files
[filenum
].mapped
, files
[filenum
].mapped_size
);
955 files
[filenum
].mapped
= 0;
956 files
[filenum
].mapped_size
= 0;
960 if (kErrorNone
!= err
) {
961 if (output_name
&& strncmp(output_name
, "/dev/", 5)) {