diff --git a/.merge.log b/.merge.log deleted file mode 100644 index 8c275ae..0000000 --- a/.merge.log +++ /dev/null @@ -1,842 +0,0 @@ -## cctools 877.8 -> 886 ## - -patching file ./as/i386.c -patching file ./include/stuff/ofile.h -patching file ./libstuff/checkout.c -patching file ./libstuff/ofile.c -can't find file to patch at input line 290 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../cctools-877.8/Makefile ./Makefile -|--- ../cctools-877.8/Makefile 2016-01-03 10:19:07.000000000 +0100 -|+++ ./Makefile 2016-05-02 04:22:30.000000000 +0200 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -23 out of 23 hunks ignored -The next patch would create the file ./man/llvm-otool.1, -which already exists! Assume -R? [n] -Apply anyway? [n] -Skipping patch. -1 out of 1 hunk ignored -patching file ./man/Makefile -patching file ./man/nm.1 -The next patch would create the file ./man/nm-classic.1, -which already exists! Assume -R? [n] -Apply anyway? [n] -Skipping patch. -1 out of 1 hunk ignored -The next patch would create the file ./man/otool-classic.1, -which already exists! Assume -R? [n] -Apply anyway? [n] -Skipping patch. -1 out of 1 hunk ignored -The next patch would create the file ./man/size-classic.1, -which already exists! Assume -R? [n] -Apply anyway? [n] -Skipping patch. -1 out of 1 hunk ignored -patching file ./misc/bitcode_strip.c -patching file ./misc/codesign_allocate.c -Hunk #2 NOT MERGED at 288-307, merged at 312-313. -patching file ./misc/indr.c -Hunk #2 NOT MERGED at 567-586, merged at 591-592. -patching file ./misc/inout.c -Hunk #2 NOT MERGED at 159-178, merged at 183-184. -patching file ./misc/install_name_tool.c -patching file ./misc/libtool.c -Hunk #3 NOT MERGED at 271-275,279-283. -Hunk #11 already applied at 3901. -can't find file to patch at input line 1311 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../cctools-877.8/misc/Makefile ./misc/Makefile -|--- ../cctools-877.8/misc/Makefile 2015-03-10 01:33:19.000000000 +0100 -|+++ ./misc/Makefile 2016-01-20 02:39:22.000000000 +0100 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -2 out of 2 hunks ignored -patching file ./misc/nm.c -Hunk #7 merged at 524-529. -patching file ./misc/seg_hack.c -Hunk #2 NOT MERGED at 219-238, merged at 243-244. -patching file ./misc/strip.c -Hunk #2 NOT MERGED at 911-930, merged at 935-936. -patching file ./otool/arm64_disasm.c -patching file ./otool/arm64_disasm.h -patching file ./otool/arm_disasm.c -patching file ./otool/dyld_bind_info.c -patching file ./otool/i386_disasm.c -patching file ./otool/i860_disasm.c -patching file ./otool/m68k_disasm.c -patching file ./otool/m88k_disasm.c -patching file ./otool/main.c -can't find file to patch at input line 2490 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../cctools-877.8/otool/Makefile ./otool/Makefile -|--- ../cctools-877.8/otool/Makefile 2015-03-10 01:33:19.000000000 +0100 -|+++ ./otool/Makefile 2016-01-20 02:39:22.000000000 +0100 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -3 out of 3 hunks ignored -patching file ./otool/ofile_print.c -patching file ./otool/ofile_print.h -patching file ./otool/print_bitcode.c -Hunk #1 merged at 53-56,62-71,78-80. -patching file ./otool/print_objc2_64bit.c -patching file ./otool/sparc_disasm.c - -# ld64 253.9 -> ld64 264.3.102 ## - -patching file ./doc/man/man1/ld.1 -can't find file to patch at input line 49 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../ld64-253.9/ld64.xcodeproj/project.pbxproj ./ld64.xcodeproj/project.pbxproj -|--- ../ld64-253.9/ld64.xcodeproj/project.pbxproj 2015-05-20 08:11:58.000000000 +0200 -|+++ ./ld64.xcodeproj/project.pbxproj 2016-01-27 22:57:12.000000000 +0100 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -55 out of 55 hunks ignored -patching file ./src/abstraction/MachOTrie.hpp -Hunk #2 NOT MERGED at 388-392. -patching file ./src/ld/InputFiles.cpp -Hunk #2 NOT MERGED at 340-345. -patching file ./src/ld/InputFiles.h -patching file ./src/ld/ld.cpp -patching file ./src/ld/ld.hpp -patching file ./src/ld/LinkEditClassic.hpp -patching file ./src/ld/Options.cpp -Hunk #2 merged at 196-197,203-204. -Hunk #15 merged at 2970-2973,2981-2984,2989-2992,2996-2999,3005-3008,3013-3016. -patching file ./src/ld/Options.h -patching file ./src/ld/OutputFile.cpp -patching file ./src/ld/OutputFile.h -patching file ./src/ld/parsers/generic_dylib_file.hpp -patching file ./src/ld/parsers/lto_file.cpp -patching file ./src/ld/parsers/lto_file.h -patching file ./src/ld/parsers/macho_dylib_file.cpp -Hunk #1 NOT MERGED at 37-42, merged at 48, merged at 55, merged at 145, merged at 148-149, merged at 151. -patching file ./src/ld/parsers/macho_dylib_file.h -patching file ./src/ld/parsers/macho_relocatable_file.cpp -Hunk #13 merged at 4516,4518. -patching file ./src/ld/parsers/macho_relocatable_file.h -patching file ./src/ld/parsers/textstub_dylib_file.cpp -Hunk #1 merged at 37. -Hunk #2 NOT MERGED at 71-75. -Hunk #9 merged at 514,521,526, NOT MERGED at 529-533,536,542. -patching file ./src/ld/passes/bitcode_bundle.cpp -patching file ./src/ld/passes/branch_island.cpp -patching file ./src/ld/passes/branch_shim.cpp -patching file ./src/ld/passes/code_dedup.cpp -patching file ./src/ld/passes/code_dedup.h -patching file ./src/ld/passes/compact_unwind.cpp -patching file ./src/ld/passes/objc.cpp -patching file ./src/ld/passes/stubs/stubs.cpp -patching file ./src/ld/Resolver.cpp -patching file ./src/ld/SymbolTable.cpp -patching file ./src/ld/SymbolTable.h -patching file ./src/other/machochecker.cpp -Hunk #19 NOT MERGED at 602-606. -Hunk #20 NOT MERGED at 623-627. -patching file ./src/other/unwinddump.cpp -can't find file to patch at input line 6845 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../ld64-253.9/unit-tests/run-all-unit-tests ./unit-tests/run-all-unit-tests -|--- ../ld64-253.9/unit-tests/run-all-unit-tests 2013-03-08 00:10:19.000000000 +0100 -|+++ ./unit-tests/run-all-unit-tests 2015-11-11 01:07:39.000000000 +0100 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -1 out of 1 hunk ignored -patching file ./unit-tests/test-cases/linker-optimization-hints/AdrpLdrGotLdrField.s -can't find file to patch at input line 6914 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../ld64-253.9/unit-tests/test-cases/linker-optimization-hints/Makefile ./unit-tests/test-cases/linker-optimization-hints/Makefile -|--- ../ld64-253.9/unit-tests/test-cases/linker-optimization-hints/Makefile 2014-01-27 22:34:25.000000000 +0100 -|+++ ./unit-tests/test-cases/linker-optimization-hints/Makefile 2015-11-11 01:07:39.000000000 +0100 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -5 out of 5 hunks ignored -patching file ./unit-tests/test-cases/linker_options-library-chain/bar.c -patching file ./unit-tests/test-cases/linker_options-library-chain/foo.c -patching file ./unit-tests/test-cases/linker_options-library-chain/main.c -patching file ./unit-tests/test-cases/linker_options-library-chain/Makefile -patching file ./unit-tests/test-cases/linker_options-library-chain/subbar.c -can't find file to patch at input line 7433 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../ld64-253.9/unit-tests/test-cases/objc-category-optimize/Makefile ./unit-tests/test-cases/objc-category-optimize/Makefile -|--- ../ld64-253.9/unit-tests/test-cases/objc-category-optimize/Makefile 2013-10-19 03:10:28.000000000 +0200 -|+++ ./unit-tests/test-cases/objc-category-optimize/Makefile 2015-11-11 01:07:39.000000000 +0100 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -1 out of 1 hunk ignored -can't find file to patch at input line 7460 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../ld64-253.9/unit-tests/test-cases/objc-category-optimize-load/Makefile ./unit-tests/test-cases/objc-category-optimize-load/Makefile -|--- ../ld64-253.9/unit-tests/test-cases/objc-category-optimize-load/Makefile 2013-10-19 03:10:28.000000000 +0200 -|+++ ./unit-tests/test-cases/objc-category-optimize-load/Makefile 2015-11-11 01:07:39.000000000 +0100 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -1 out of 1 hunk ignored - --------------------------------------------------------------------------------------------------------------------------------------------------------------- - -## cctools 877.5 -> 877.8 ## - -patching file include/mach-o/loader.h -patching file libstuff/execute.c -patching file libstuff/ofile.c -patching file libstuff/swap_headers.c -patching file misc/bitcode_strip.c -Hunk #11 NOT MERGED at 364-373, merged at 377, merged at 382-385. -Hunk #20 merged at 547-557. -patching file otool/main.c -patching file otool/ofile_print.c - -## ld64 253.3 -> ld64 253.9 ## - -patching file src/ld/InputFiles.cpp -patching file src/ld/ld.hpp -patching file src/ld/Options.cpp -Hunk #1 NOT MERGED at 194-205. -patching file src/ld/Options.h -patching file src/ld/parsers/lto_file.cpp -Hunk #1 merged at 324-325. -patching file src/ld/parsers/macho_dylib_file.cpp -patching file src/ld/parsers/macho_relocatable_file.cpp -patching file src/ld/parsers/macho_relocatable_file.h -patching file src/ld/parsers/textstub_dylib_file.cpp -patching file src/ld/passes/bitcode_bundle.cpp -patching file src/ld/Resolver.cpp -patching file src/other/ObjectDump.cpp - --------------------------------------------------------------------------------------------------------------------------------------------------------------- - -## cctools 870 -> 877.5 ## - -can't find file to patch at input line 4 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../cctools-870/Makefile ./Makefile -|--- ../cctools-870/Makefile 2015-08-26 07:49:15.000000000 +0200 -|+++ ./Makefile 2015-09-15 03:35:14.000000000 +0200 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -3 out of 3 hunks ignored -patching file ./as/driver.c -patching file ./include/Makefile -patching file ./include/mach/arm/_structs.h -patching file ./include/mach-o/loader.h -patching file ./include/stuff/breakout.h -patching file ./include/stuff/bytesex.h -Hunk #1 succeeded at 59 (offset 5 lines). -Hunk #2 succeeded at 432 (offset 5 lines). -patching file ./include/xar/xar.h -patching file ./libstuff/bytesex.c -Hunk #1 succeeded at 209 (offset 5 lines). -Hunk #2 succeeded at 2910 (offset 5 lines). -patching file ./libstuff/checkout.c -patching file ./libstuff/lto.c -Hunk #2 succeeded at 139 (offset 11 lines). -Hunk #3 succeeded at 168 (offset 11 lines). -patching file ./libstuff/ofile.c -Hunk #1 succeeded at 4205 (offset 5 lines). -patching file ./libstuff/swap_headers.c -Hunk #1 succeeded at 1172 (offset 5 lines). -Hunk #2 succeeded at 1759 (offset 5 lines). -patching file ./man/Makefile -patching file ./man/as.1 -patching file ./man/bitcode_strip.1 -patching file ./man/otool.1 -can't find file to patch at input line 892 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../cctools-870/misc/Makefile ./misc/Makefile -|--- ../cctools-870/misc/Makefile 2013-12-10 20:28:11.000000000 +0100 -|+++ ./misc/Makefile 2015-03-10 01:33:19.000000000 +0100 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -7 out of 7 hunks ignored -patching file ./misc/bitcode_strip.c -patching file ./misc/codesign_allocate.c -Hunk #1 succeeded at 372 (offset 20 lines). -patching file ./misc/libtool.c -Hunk #1 succeeded at 211 (offset 3 lines). -Hunk #2 succeeded at 266 (offset 3 lines). -Hunk #3 succeeded at 1524 (offset 10 lines). -Hunk #4 succeeded at 2189 (offset 10 lines). -Hunk #5 succeeded at 2202 (offset 10 lines). -Hunk #6 succeeded at 2214 (offset 10 lines). -Hunk #7 succeeded at 3493 (offset 10 lines). -Hunk #8 succeeded at 3621 (offset 10 lines). -Hunk #9 succeeded at 3700 (offset 10 lines). -Hunk #10 succeeded at 3840 (offset 10 lines). -can't find file to patch at input line 2635 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../cctools-870/otool/Makefile ./otool/Makefile -|--- ../cctools-870/otool/Makefile 2014-01-14 01:21:55.000000000 +0100 -|+++ ./otool/Makefile 2015-03-10 01:33:19.000000000 +0100 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -1 out of 1 hunk ignored -patching file ./otool/main.c -Hunk #1 succeeded at 1511 (offset 4 lines). -Hunk #2 succeeded at 1553 (offset 4 lines). -patching file ./otool/ofile_print.c -Hunk #1 succeeded at 294 (offset 8 lines). -Hunk #2 succeeded at 2292 (offset 10 lines). -Hunk #3 succeeded at 3502 (offset 10 lines). -Hunk #4 succeeded at 7631 (offset 10 lines). -Hunk #5 succeeded at 7685 (offset 10 lines). -Hunk #6 succeeded at 7701 (offset 10 lines). -Hunk #7 succeeded at 7741 (offset 10 lines). -Hunk #8 succeeded at 7757 (offset 10 lines). -Hunk #9 succeeded at 7772 (offset 10 lines). -Hunk #10 succeeded at 7781 (offset 10 lines). -Hunk #11 succeeded at 7811 (offset 10 lines). -Hunk #12 succeeded at 7826 (offset 10 lines). -Hunk #13 succeeded at 8076 (offset 12 lines). -Hunk #14 succeeded at 8173 (offset 12 lines). -patching file ./otool/ofile_print.h -patching file ./otool/print_bitcode.c -patching file ./otool/print_objc2_32bit.c -patching file ./otool/print_objc2_64bit.c - -## ld64 242.2 -> ld64 253.3 ## - -patching file ./doc/man/man1/ld.1 -can't find file to patch at input line 78 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur '--exclude=unit-tests' ../ld64-242.2/ld64.xcodeproj/project.pbxproj ./ld64.xcodeproj/project.pbxproj -|--- ../ld64-242.2/ld64.xcodeproj/project.pbxproj 2014-08-20 00:19:03.000000000 +0200 -|+++ ./ld64.xcodeproj/project.pbxproj 2015-05-20 08:11:58.000000000 +0200 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -22 out of 22 hunks ignored -patching file ./src/abstraction/MachOFileAbstraction.hpp -patching file ./src/create_configure -patching file ./src/ld/Bitcode.hpp -patching file ./src/ld/HeaderAndLoadCommands.hpp -patching file ./src/ld/InputFiles.cpp -Hunk #3 merged at 334. -Hunk #10 merged at 858, NOT MERGED at 861-870. -patching file ./src/ld/LinkEdit.hpp -patching file ./src/ld/LinkEditClassic.hpp -patching file ./src/ld/Options.cpp -Hunk #1 merged at 39-40, NOT MERGED at 47-54. -Hunk #18 NOT MERGED at 1958-1962. -patching file ./src/ld/Options.h -Hunk #13 merged at 481. -patching file ./src/ld/OutputFile.cpp -patching file ./src/ld/OutputFile.h -patching file ./src/ld/Resolver.cpp -patching file ./src/ld/Resolver.h -patching file ./src/ld/SymbolTable.cpp -patching file ./src/ld/SymbolTable.h -patching file ./src/ld/code-sign-blobs/memutils.h -Hunk #1 NOT MERGED at 56-66. -patching file ./src/ld/ld.cpp -patching file ./src/ld/ld.hpp -Hunk #1 merged at 35-36,38,45-47. -The next patch would delete the file ./src/ld/lto_file.hpp, -which does not exist! Assume -R? [n] -Apply anyway? [n] -Skipping patch. -1 out of 1 hunk ignored -patching file ./src/ld/parsers/lto_file.cpp -Hunk #1 merged at 39. -Hunk #9 NOT MERGED at 551-558. -patching file ./src/ld/parsers/lto_file.h -patching file ./src/ld/parsers/macho_dylib_file.cpp -patching file ./src/ld/parsers/macho_relocatable_file.cpp -Hunk #1 merged at 45,51. -patching file ./src/ld/parsers/macho_relocatable_file.h -patching file ./src/ld/parsers/opaque_section_file.cpp -patching file ./src/ld/parsers/textstub_dylib_file.cpp -patching file ./src/ld/parsers/textstub_dylib_file.hpp -patching file ./src/ld/passes/bitcode_bundle.cpp -patching file ./src/ld/passes/bitcode_bundle.h -patching file ./src/ld/passes/branch_island.cpp -Hunk #1 NOT MERGED at 555-559. -patching file ./src/ld/passes/branch_shim.cpp -patching file ./src/ld/passes/dylibs.cpp -patching file ./src/ld/passes/got.cpp -patching file ./src/ld/passes/huge.cpp -patching file ./src/ld/passes/objc.cpp -patching file ./src/ld/passes/order.cpp -patching file ./src/ld/passes/stubs/stub_arm.hpp -patching file ./src/ld/passes/stubs/stub_arm64.hpp -patching file ./src/ld/passes/stubs/stubs.cpp -patching file ./src/ld/passes/tlvp.cpp -patching file ./src/other/ObjectDump.cpp -patching file ./src/other/dyldinfo.cpp -Hunk #10 NOT MERGED at 1892-1895. - --------------------------------------------------------------------------------------------------------------------------------------------------------------- - -## ld64 242 -> ld64 242.2 ## - -patching file ./src/ld/passes/branch_island.cpp -patching file ./src/ld/passes/compact_unwind.cpp -patching file ./src/ld/passes/got.cpp -can't find file to patch at input line 214 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../ld64-242/unit-tests/test-cases/branch-islands/space.s ./unit-tests/test-cases/branch-islands/space.s -|--- ../ld64-242/unit-tests/test-cases/branch-islands/space.s 2013-10-19 03:10:28.000000000 +0200 -|+++ ./unit-tests/test-cases/branch-islands/space.s 2015-05-05 21:42:23.000000000 +0200 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -1 out of 1 hunk ignored - --------------------------------------------------------------------------------------------------------------------------------------------------------------- - -## cctools 862 -> 870 ## - -patching file ./as/arm.c -Hunk #1 NOT MERGED at 17844-17848. # Has already been fixed in my repo. -Hunk #2 NOT MERGED at 17893-17897. # Has already been fixed in my repo. -Hunk #3 NOT MERGED at 17940-17944. # Has already been fixed in my repo. -Hunk #4 NOT MERGED at 17988-17992. # Has already been fixed in my repo. -patching file ./as/driver.c -Hunk #1 already applied at 64. # Has already been fixed in my repo. -patching file ./include/mach-o/loader.h -patching file ./include/mach-o/stab.h -can't find file to patch at input line 86 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../cctools-862/libmacho/Makefile ./libmacho/Makefile -|--- ../cctools-862/libmacho/Makefile 2014-11-02 06:48:07.000000000 +0100 -|+++ ./libmacho/Makefile 2015-01-08 03:29:57.000000000 +0100 --------------------------- -File to patch: -Skip this patch? [y] y -Skipping patch. -10 out of 10 hunks ignored -can't find file to patch at input line 247 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../cctools-862/libmacho/arch.c ./libmacho/arch.c -|--- ../cctools-862/libmacho/arch.c 2014-11-02 06:48:07.000000000 +0100 -|+++ ./libmacho/arch.c 2014-09-29 23:48:52.000000000 +0200 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -2 out of 2 hunks ignored -can't find file to patch at input line 274 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../cctools-862/libmacho/getsecbyname.c ./libmacho/getsecbyname.c -|--- ../cctools-862/libmacho/getsecbyname.c 2014-11-02 06:48:07.000000000 +0100 -|+++ ./libmacho/getsecbyname.c 2015-01-08 03:29:57.000000000 +0100 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -10 out of 10 hunks ignored -patching file ./libstuff/arch.c -patching file ./libstuff/ofile.c -patching file ./libstuff/swap_headers.c -patching file ./man/otool.1 -patching file ./misc/codesign_allocate.c -patching file ./misc/install_name_tool.c -patching file ./misc/libtool.c -Hunk #1 NOT MERGED at 1375-1385. # Resolved. Also something I already had fixed in my repo, but not 100% correctly. -patching file ./misc/lipo.c -patching file ./misc/nm.c -patching file ./otool/arm64_disasm.c -patching file ./otool/arm_disasm.c -patching file ./otool/i386_disasm.c -patching file ./otool/main.c -patching file ./otool/ofile_print.c -patching file ./otool/ofile_print.h -patching file ./otool/otool.h -patching file ./otool/print_objc2_32bit.c -patching file ./otool/print_objc2_64bit.c - -## ld64 241.9 -> ld64 242 ## - -can't find file to patch at input line 4 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: # I do not support buildig with Xcode. --------------------------- -|diff -Naur ../ld64-241.9/ld64.xcodeproj/project.pbxproj ./ld64.xcodeproj/project.pbxproj -|--- ../ld64-241.9/ld64.xcodeproj/project.pbxproj 2014-11-04 00:58:03.000000000 +0100 -|+++ ./ld64.xcodeproj/project.pbxproj 2014-08-20 00:19:03.000000000 +0200 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -7 out of 7 hunks ignored -patching file ./src/abstraction/MachOFileAbstraction.hpp -Hunk #1 NOT MERGED at 257-276. # Has already been fixed in my repo, but in a little different way. -patching file ./src/create_configure -patching file ./src/ld/InputFiles.cpp -patching file ./src/ld/Options.cpp -patching file ./src/ld/Options.h -patching file ./src/ld/Resolver.cpp -patching file ./src/ld/ld.hpp -patching file ./src/ld/parsers/libunwind/DwarfInstructions.hpp -patching file ./src/ld/parsers/lto_file.cpp -Hunk #2 NOT MERGED at 499-507. # Resolved. -patching file ./src/ld/parsers/lto_file.h -patching file ./src/ld/parsers/macho_relocatable_file.cpp -Hunk #8 merged at 4219-4234. -patching file ./src/ld/parsers/macho_relocatable_file.h -patching file ./src/ld/passes/compact_unwind.cpp -patching file ./src/other/ObjectDump.cpp -patching file ./src/other/unwinddump.cpp - --------------------------------------------------------------------------------------------------------------------------------------------------------------- - -## cctools 855 -> 862 ## - -patching file efitools/mtoc.c -Reversed (or previously applied) patch detected! Assume -R? [n] -Apply anyway? [n] -Skipping patch. -2 out of 2 hunks ignored -- saving rejects to file efitools/mtoc.c.rej -patching file include/llvm-c/Disassembler.h -Reversed (or previously applied) patch detected! Assume -R? [n] -Apply anyway? [n] -Skipping patch. -1 out of 1 hunk ignored -- saving rejects to file include/llvm-c/Disassembler.h.rej -patching file include/mach-o/loader.h -Reversed (or previously applied) patch detected! Assume -R? [n] -Apply anyway? [n] -Skipping patch. -1 out of 1 hunk ignored -- saving rejects to file include/mach-o/loader.h.rej -patching file include/mach-o/nlist.h -Reversed (or previously applied) patch detected! Assume -R? [n] -Apply anyway? [n] -Skipping patch. -1 out of 1 hunk ignored -- saving rejects to file include/mach-o/nlist.h.rej -patching file include/stuff/llvm.h -Reversed (or previously applied) patch detected! Assume -R? [n] -Apply anyway? [n] -Skipping patch. -1 out of 1 hunk ignored -- saving rejects to file include/stuff/llvm.h.rej -can't find file to patch at input line 103 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../cctools-855/libmacho/arch.c ./libmacho/arch.c -|--- ../cctools-855/libmacho/arch.c 2014-04-05 00:42:22.000000000 +0200 -|+++ ./libmacho/arch.c 2014-11-02 06:48:07.000000000 +0100 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -1 out of 1 hunk ignored -patching file libstuff/checkout.c -patching file libstuff/llvm.c -Hunk #1 succeeded at 27 (offset 1 line). -Hunk #2 succeeded at 69 with fuzz 1 (offset -2 lines). -Hunk #3 succeeded at 78 (offset -2 lines). -Hunk #4 succeeded at 93 (offset -2 lines). -Hunk #5 succeeded at 183 (offset -2 lines). -patching file libstuff/ofile.c -patching file man/as.1 - -patching file man/libtool.1 -patching file man/otool.1 -patching file misc/libtool.c -Hunk #1 succeeded at 149 (offset 2 lines). -Hunk #2 succeeded at 977 (offset -2 lines). -Hunk #3 succeeded at 1269 (offset -2 lines). -patching file misc/lipo.c -patching file misc/nm.c -patching file misc/strip.c - -patching file otool/arm_disasm.c -patching file otool/i386_disasm.c -patching file otool/main.c -Hunk #2 succeeded at 330 with fuzz 1. -Hunk #4 succeeded at 561 (offset 1 line). -Hunk #5 succeeded at 577 (offset 1 line). -Hunk #6 succeeded at 619 (offset 1 line). -Hunk #7 succeeded at 656 (offset 1 line). -Hunk #8 succeeded at 3193 (offset 1 line). -Hunk #9 succeeded at 3207 (offset 1 line). -patching file otool/ofile_print.c -patching file otool/print_objc2_32bit.c -patching file otool/print_objc2_64bit.c - -## ld64 236.3 -> 241.9 ## - -patching file doc/man/man1/ld.1 -can't find file to patch at input line 66 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../ld64-236.3/ld64.xcodeproj/project.pbxproj ./ld64.xcodeproj/project.pbxproj -|--- ../ld64-236.3/ld64.xcodeproj/project.pbxproj 2014-04-05 00:42:29.000000000 +0200 -|+++ ./ld64.xcodeproj/project.pbxproj 2014-11-04 00:58:03.000000000 +0100 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -3 out of 3 hunks ignored -patching file src/abstraction/MachOFileAbstraction.hpp -Hunk #3 succeeded at 374 (offset 4 lines). -Hunk #4 succeeded at 446 (offset 4 lines). -patching file src/ld/HeaderAndLoadCommands.hpp -Hunk #1 succeeded at 600 (offset 9 lines). -Hunk #2 succeeded at 761 (offset 9 lines). -patching file src/ld/InputFiles.cpp -Hunk #1 succeeded at 257 (offset 2 lines). -Hunk #2 succeeded at 314 with fuzz 1 (offset 4 lines). -Hunk #3 succeeded at 381 with fuzz 2 (offset 6 lines). -Hunk #4 succeeded at 576 (offset 6 lines). -Hunk #5 succeeded at 592 (offset 6 lines). -Hunk #6 succeeded at 613 (offset 6 lines). -Hunk #7 succeeded at 627 (offset 6 lines). -Hunk #8 succeeded at 943 (offset 8 lines). -Hunk #9 succeeded at 1178 (offset 8 lines). -Hunk #10 succeeded at 1327 (offset 8 lines). -Hunk #11 succeeded at 1369 (offset 8 lines). -patching file src/ld/InputFiles.h -patching file src/ld/ld.cpp -Hunk #1 succeeded at 108 (offset 2 lines). -Hunk #2 succeeded at 120 (offset 2 lines). -Hunk #3 succeeded at 184 (offset 2 lines). -Hunk #4 succeeded at 200 (offset 2 lines). -Hunk #5 succeeded at 238 (offset 2 lines). -Hunk #6 succeeded at 254 (offset 2 lines). -Hunk #7 succeeded at 305 (offset 2 lines). -Hunk #8 succeeded at 365 (offset 2 lines). -Hunk #9 succeeded at 375 (offset 2 lines). -Hunk #10 succeeded at 496 (offset 2 lines). -Hunk #11 succeeded at 594 (offset 2 lines). -Hunk #12 succeeded at 616 (offset 2 lines). -Hunk #13 succeeded at 647 (offset 2 lines). -Hunk #14 succeeded at 898 (offset 2 lines). -Hunk #15 succeeded at 927 (offset 2 lines). -patching file src/ld/ld.hpp -Hunk #1 succeeded at 147 (offset 1 line). -Hunk #2 succeeded at 168 (offset 1 line). -Hunk #3 succeeded at 272 (offset 1 line). -Hunk #4 succeeded at 316 (offset 1 line). -Hunk #5 succeeded at 532 (offset 1 line). -Hunk #6 succeeded at 545 (offset 1 line). -Hunk #7 succeeded at 575 (offset 1 line). -Hunk #8 succeeded at 586 (offset 1 line). -Hunk #9 succeeded at 757 (offset 1 line). -Hunk #10 succeeded at 775 (offset 1 line). -Hunk #11 succeeded at 859 (offset 1 line). -Hunk #12 succeeded at 879 (offset 1 line). -patching file src/ld/LinkEditClassic.hpp -patching file src/ld/Options.cpp -Hunk #1 succeeded at 134 (offset 7 lines). -Hunk #2 succeeded at 183 (offset 7 lines). -Hunk #3 succeeded at 547 (offset 7 lines). -Hunk #4 succeeded at 1031 (offset 7 lines). -Hunk #5 succeeded at 1793 (offset 7 lines). -Hunk #6 succeeded at 3001 (offset 11 lines). -Hunk #7 succeeded at 3060 (offset 11 lines). -Hunk #8 succeeded at 3440 (offset 13 lines). -Hunk #9 succeeded at 3911 (offset 13 lines). -Hunk #10 succeeded at 4039 (offset 13 lines). -Hunk #11 succeeded at 4076 (offset 13 lines). -Hunk #12 succeeded at 4130 (offset 13 lines). -Hunk #13 succeeded at 4166 (offset 13 lines). -Hunk #14 succeeded at 4281 (offset 13 lines). -Hunk #15 succeeded at 4301 (offset 13 lines). -Hunk #16 succeeded at 4769 (offset 13 lines). -patching file src/ld/Options.h -patching file src/ld/OutputFile.cpp -Hunk #11 succeeded at 2857 (offset 6 lines). -Hunk #12 succeeded at 4587 (offset 6 lines). -Hunk #13 succeeded at 4659 (offset 6 lines). -Hunk #14 succeeded at 4734 (offset 6 lines). -Hunk #15 succeeded at 4760 (offset 6 lines). -Hunk #16 succeeded at 4946 (offset 6 lines). -patching file src/ld/parsers/libunwind/DwarfInstructions.hpp -patching file src/ld/parsers/libunwind/DwarfParser.hpp -patching file src/ld/parsers/libunwind/Registers.hpp -Hunk #1 succeeded at 1325 (offset 8 lines). -patching file src/ld/parsers/lto_file.cpp -Hunk #1 succeeded at 79 (offset 5 lines). -Hunk #2 succeeded at 113 (offset 5 lines). -Hunk #3 succeeded at 234 (offset 5 lines). -Hunk #4 succeeded at 307 (offset 5 lines). -Hunk #5 succeeded at 338 (offset 5 lines). -Hunk #6 succeeded at 425 (offset 5 lines). -Hunk #7 succeeded at 455 (offset 5 lines). -Hunk #8 succeeded at 488 (offset 5 lines). -Hunk #9 succeeded at 538 (offset 5 lines). -Hunk #10 succeeded at 584 (offset 5 lines). -Hunk #11 succeeded at 644 (offset 5 lines). -Hunk #12 succeeded at 757 (offset 5 lines). -Hunk #13 succeeded at 798 (offset 5 lines). -Hunk #14 succeeded at 850 (offset 5 lines). -patching file src/ld/parsers/lto_file.h -patching file src/ld/parsers/macho_dylib_file.cpp -Hunk #10 FAILED at 1088. -1 out of 10 hunks FAILED -- saving rejects to file src/ld/parsers/macho_dylib_file.cpp.rej -patching file src/ld/parsers/macho_relocatable_file.cpp -patching file src/ld/passes/branch_island.cpp -patching file src/ld/passes/compact_unwind.cpp -patching file src/ld/passes/objc.cpp -patching file src/ld/passes/order.cpp -patching file src/ld/Resolver.cpp -Hunk #7 succeeded at 1550 (offset 1 line). -Hunk #8 succeeded at 1581 (offset 1 line). -Hunk #9 succeeded at 1684 (offset 4 lines). -patching file src/ld/Resolver.h -patching file src/ld/SymbolTable.cpp -patching file src/other/ObjectDump.cpp -Hunk #1 succeeded at 835 (offset 4 lines). -Hunk #2 FAILED at 996. -Hunk #3 succeeded at 1016 (offset 7 lines). -1 out of 3 hunks FAILED -- saving rejects to file src/other/ObjectDump.cpp.rej -patching file src/other/unwinddump.cpp -can't find file to patch at input line 3517 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../ld64-236.3/unit-tests/include/common.makefile ./unit-tests/include/common.makefile -|--- ../ld64-236.3/unit-tests/include/common.makefile 2014-04-05 00:42:29.000000000 +0200 -|+++ ./unit-tests/include/common.makefile 2014-09-11 00:24:46.000000000 +0200 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -2 out of 2 hunks ignored -patching file unit-tests/test-cases/alias-basic/aliases.s -patching file unit-tests/test-cases/alias-basic/main.c -patching file unit-tests/test-cases/alias-basic/Makefile -can't find file to patch at input line 3639 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../ld64-236.3/unit-tests/test-cases/alias-objects/aliases.s ./unit-tests/test-cases/alias-objects/aliases.s -|--- ../ld64-236.3/unit-tests/test-cases/alias-objects/aliases.s 2014-04-05 00:42:29.000000000 +0200 -|+++ ./unit-tests/test-cases/alias-objects/aliases.s 2014-09-11 00:24:46.000000000 +0200 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -1 out of 1 hunk ignored -can't find file to patch at input line 3668 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../ld64-236.3/unit-tests/test-cases/alias-objects/Makefile ./unit-tests/test-cases/alias-objects/Makefile -|--- ../ld64-236.3/unit-tests/test-cases/alias-objects/Makefile 2014-04-05 00:42:29.000000000 +0200 -|+++ ./unit-tests/test-cases/alias-objects/Makefile 2014-09-11 00:24:46.000000000 +0200 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -2 out of 2 hunks ignored -patching file unit-tests/test-cases/alt-entry/foo.c -patching file unit-tests/test-cases/alt-entry/main.c -patching file unit-tests/test-cases/alt-entry/Makefile -patching file unit-tests/test-cases/lto-r/bar.c -patching file unit-tests/test-cases/lto-r/foo.c -patching file unit-tests/test-cases/lto-r/main.c -patching file unit-tests/test-cases/lto-r/Makefile -patching file unit-tests/test-cases/lto-rename_section/a.c -patching file unit-tests/test-cases/lto-rename_section/b.c -patching file unit-tests/test-cases/lto-rename_section/main.c -patching file unit-tests/test-cases/lto-rename_section/Makefile -patching file unit-tests/test-cases/lto-rename_segment/a.c -patching file unit-tests/test-cases/lto-rename_segment/b.c -patching file unit-tests/test-cases/lto-rename_segment/main.c -patching file unit-tests/test-cases/lto-rename_segment/Makefile -patching file unit-tests/test-cases/lto-symbol-section-move/foo.c -patching file unit-tests/test-cases/lto-symbol-section-move/main.c -patching file unit-tests/test-cases/lto-symbol-section-move/Makefile -patching file unit-tests/test-cases/lto-symbol-section-move/other.c -patching file unit-tests/test-cases/lto-symbol-section-move/ram1.symbols -patching file unit-tests/test-cases/lto-symbol-section-move/rom1.symbols -patching file unit-tests/test-cases/preload-section_order/extra.s -patching file unit-tests/test-cases/preload-section_order/main1.expected -patching file unit-tests/test-cases/preload-section_order/main2.expected -patching file unit-tests/test-cases/preload-section_order/main.c -patching file unit-tests/test-cases/preload-section_order/Makefile -patching file unit-tests/test-cases/preload-section_order/more.s -patching file unit-tests/test-cases/preload-segment_order/a.c -patching file unit-tests/test-cases/preload-segment_order/b.c -patching file unit-tests/test-cases/preload-segment_order/main.c -patching file unit-tests/test-cases/preload-segment_order/main-segs.expected -patching file unit-tests/test-cases/preload-segment_order/Makefile -can't find file to patch at input line 4481 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../ld64-236.3/unit-tests/test-cases/section-labels/main.c ./unit-tests/test-cases/section-labels/main.c -|--- ../ld64-236.3/unit-tests/test-cases/section-labels/main.c 2014-04-05 00:42:29.000000000 +0200 -|+++ ./unit-tests/test-cases/section-labels/main.c 2014-09-11 00:24:46.000000000 +0200 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -1 out of 1 hunk ignored -patching file unit-tests/test-cases/symbol-section-move/main.c -patching file unit-tests/test-cases/symbol-section-move/Makefile -patching file unit-tests/test-cases/symbol-section-move/other.c -patching file unit-tests/test-cases/symbol-section-move/ram1.symbols -patching file unit-tests/test-cases/symbol-section-move/rom1.symbols -can't find file to patch at input line 4654 -Perhaps you used the wrong -p or --strip option? -The text leading up to this was: --------------------------- -|diff -Naur ../ld64-236.3/unit-tests/test-cases/weak_import-undefined/Makefile ./unit-tests/test-cases/weak_import-undefined/Makefile -|--- ../ld64-236.3/unit-tests/test-cases/weak_import-undefined/Makefile 2014-04-05 00:42:29.000000000 +0200 -|+++ ./unit-tests/test-cases/weak_import-undefined/Makefile 2014-09-11 00:24:46.000000000 +0200 --------------------------- -File to patch: -Skip this patch? [y] -Skipping patch. -1 out of 1 hunk ignored diff --git a/.travis.yml b/.travis.yml index 174dcba..b4401cd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,14 @@ language: cpp +dist: trusty os: - linux compiler: - - gcc - clang before_install: - - if [ $TRAVIS_OS_NAME == linux ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; sudo apt-get update -qq && sudo apt-get install -y gcc-4.7 g++-4.7 gobjc-4.7 llvm-dev; fi - - if [ $CXX == g++ ]; then export CC=gcc-4.7 && export CXX=g++-4.7; fi + - if [ $TRAVIS_OS_NAME == linux ]; then sudo apt-get install -y git gcc g++ gobjc llvm-dev cmake; fi script: - - cd cctools && ./autogen.sh && ./configure && make + - mkdir -p tmp && TMP=$PWD/tmp && git clone https://github.com/tpoechtrager/apple-libtapi.git && cd apple-libtapi && INSTALLPREFIX=$TMP ./build.sh && ./install.sh && cd .. && cd cctools && ./configure --with-libtapi=$TMP && make diff --git a/README.md b/README.md index ec8ccae..be5855c 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,43 @@ -# Apple cctools port for Linux, *BSD and Windows (Cygwin) # +# Apple cctools and ld64 port for Linux, *BSD and macOS # -Current Version: 886 + ld64-264.3.102. +Current Version: cctools: 949.0.1, ld64: 512.4. Originally ported by [cjacker](http://ios-toolchain-based-on-clang-for-linux.googlecode.com). ## SUPPORTED HOSTS ## **SUPPORTED OPERATING SYSTEMS:** -Linux, FreeBSD, NetBSD, OpenBSD, DragonFlyBSD, -Windows (Cygwin), Mac OS X and iOS +Linux, Android (Termux), FreeBSD, +Mac OS X, iOS, OpenBSD and NetBSD **SUPPORTED HOST ARCHITECTURES:** -x86, x86_64, arm - -Untested, but compiles: - -aarch64, ppc, ppc64 +x86, x86_64, arm, arm64/aarch64 ## SUPPORTED TARGET ARCHITECTURES ## -armv4t, armv5, armv6, armv7, armv7f, armv7k, armv7s, armv6m -armv7m, armv7em, armv8, arm64, arm64v8, i386, x86_64 and x86_64h. +armv6, armv7, armv7s, arm64, arm64e, +arm64_32 (untested), i386, x86_64, x86_64h, +armv6m, armv7k, armv7m and armv7em + +arm64e requires [Apple LLVM/Clang](https://github.com/apple/llvm-project). ## SUPPORTED TARGET OPERATING SYSTEMS ## -Mac OS X, iOS, watchOS (untested) and tvOS (untested) +macOS, iOS, tvOS, watchOS, bridgeOS, Mac Catalyst, +iOS Simluator, watchOS Simulator, DriverKit + +Not all of the targets have been tested. ## DEPENDENCIES ## -`Clang 3.2+ or gcc/g++/gcc-objc 4.7+`, `automake`, `autogen` and `libtool`. +`Clang 3.4+` + +SDKs with .tdb stubs (>= Xcode 7) require the TAPI library to be installed. +=> https://github.com/tpoechtrager/apple-libtapi + +musl-libc based systems require the musl-fts library to be installed. +=> https://github.com/pullmoll/musl-fts Optional, but recommended: @@ -42,11 +50,24 @@ Do not install libxar-dev on Ubuntu, it's a different package. ## INSTALLATION ## -* `cd cctools` -* `./autogen.sh` -* `./configure --prefix= --target= [--with-llvm-config=...]` -* `make` -* `make install` +### Install Apple's TAPI library: +This step is only required if you intend to use SDKs with .tdb stubs. + + git clone https://github.com/tpoechtrager/apple-libtapi.git + cd apple-libtapi + [INSTALLPREFIX=/home/user/cctools] ./build.sh + ./install.sh + +### Install cctools and ld64: + git clone https://github.com/tpoechtrager/cctools-port.git + cd cctools-port/cctools + ./configure \ + [--prefix=/home/user/cctools] \ + [--with-libtapi=/home/user/cctools] \ + [--target=] \ + [--with-llvm-config=...] + make + make install target = `i386-apple-darwin11`, `x86_64-apple-darwin11`, `arm-apple-darwin11`, ... @@ -55,4 +76,4 @@ If you get compile errors because of `unistd.h`, then please run ## TRAVIS CI ## -[![Build Status](https://travis-ci.org/tpoechtrager/cctools-port.svg?branch=master)](https://travis-ci.org/tpoechtrager/cctools-port) +[![Build Status](https://travis-ci.org/tpoechtrager/cctools-port.svg?branch=949.0.1-ld64-512.4)](https://travis-ci.org/tpoechtrager/cctools-port) diff --git a/cctools/Makefile.am b/cctools/Makefile.am index be83f0a..52c84b8 100644 --- a/cctools/Makefile.am +++ b/cctools/Makefile.am @@ -1,7 +1,7 @@ if ISDARWIN -SUBDIRS=libstuff ar as misc otool ld64 +SUBDIRS=libstuff libmacho ar as misc otool efitools ld64 man else -SUBDIRS=libstuff ar as misc libobjc2 otool ld64 +SUBDIRS=libobjc2 libstuff libmacho ar as misc otool efitools ld64 man endif ACLOCAL_AMFLAGS = -I m4 diff --git a/cctools/Makefile.in b/cctools/Makefile.in new file mode 100644 index 0000000..5a503c0 --- /dev/null +++ b/cctools/Makefile.in @@ -0,0 +1,845 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +depcomp = +am__maybe_remake_depfiles = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir distdir-am dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +DIST_SUBDIRS = libobjc2 libstuff libmacho ar as misc otool efitools \ + ld64 man +am__DIST_COMMON = $(srcdir)/Makefile.in AUTHORS COPYING ChangeLog \ + INSTALL NEWS README compile config.guess config.sub install-sh \ + ltmain.sh missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +GZIP_ENV = --best +DIST_ARCHIVES = $(distdir).tar.bz2 +DIST_TARGETS = dist-bzip2 +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@ISDARWIN_FALSE@SUBDIRS = libobjc2 libstuff libmacho ar as misc otool efitools ld64 man +@ISDARWIN_TRUE@SUBDIRS = libstuff libmacho ar as misc otool efitools ld64 man +ACLOCAL_AMFLAGS = -I m4 +DSTROOT = +RC_OS = macos +all: all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu --ignore-deps'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu --ignore-deps \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-zstd: distdir + tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + *.tar.zst*) \ + zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-libtool \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + clean-libtool cscope cscopelist-am ctags ctags-am dist \ + dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ + dist-xz dist-zip dist-zstd distcheck distclean \ + distclean-generic distclean-libtool distclean-tags \ + distcleancheck distdir distuninstallcheck dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am + +.PRECIOUS: Makefile + + +installhdrs: + cd include; $(MAKE) DSTROOT=$(DSTROOT) RC_OS=$(RC_OS) install + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/ar/Makefile.in b/cctools/ar/Makefile.in new file mode 100644 index 0000000..9c7540d --- /dev/null +++ b/cctools/ar/Makefile.in @@ -0,0 +1,726 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = ar$(EXEEXT) +subdir = ar +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_ar_OBJECTS = ar-append.$(OBJEXT) ar-ar.$(OBJEXT) \ + ar-archive.$(OBJEXT) ar-contents.$(OBJEXT) ar-delete.$(OBJEXT) \ + ar-extract.$(OBJEXT) ar-misc.$(OBJEXT) ar-move.$(OBJEXT) \ + ar-print.$(OBJEXT) ar-replace.$(OBJEXT) +ar_OBJECTS = $(am_ar_OBJECTS) +ar_DEPENDENCIES = $(top_builddir)/libstuff/libstuff.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +ar_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ar_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(ar_SOURCES) +DIST_SOURCES = $(ar_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ar_LDADD = \ + $(top_builddir)/libstuff/libstuff.la + +ar_CFLAGS = -D__DARWIN_UNIX03 -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -I$(top_srcdir)/libstuff $(WARNINGS) $(LTO_DEF) $(ENDIAN_FLAG) +ar_SOURCES = \ + append.c \ + ar.c \ + archive.c \ + contents.c \ + delete.c \ + extract.c \ + misc.c \ + move.c \ + print.c \ + replace.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps ar/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps ar/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +ar$(EXEEXT): $(ar_OBJECTS) $(ar_DEPENDENCIES) $(EXTRA_ar_DEPENDENCIES) + @rm -f ar$(EXEEXT) + $(AM_V_CCLD)$(ar_LINK) $(ar_OBJECTS) $(ar_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +ar-append.o: append.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-append.o `test -f 'append.c' || echo '$(srcdir)/'`append.c + +ar-append.obj: append.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-append.obj `if test -f 'append.c'; then $(CYGPATH_W) 'append.c'; else $(CYGPATH_W) '$(srcdir)/append.c'; fi` + +ar-ar.o: ar.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-ar.o `test -f 'ar.c' || echo '$(srcdir)/'`ar.c + +ar-ar.obj: ar.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-ar.obj `if test -f 'ar.c'; then $(CYGPATH_W) 'ar.c'; else $(CYGPATH_W) '$(srcdir)/ar.c'; fi` + +ar-archive.o: archive.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-archive.o `test -f 'archive.c' || echo '$(srcdir)/'`archive.c + +ar-archive.obj: archive.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-archive.obj `if test -f 'archive.c'; then $(CYGPATH_W) 'archive.c'; else $(CYGPATH_W) '$(srcdir)/archive.c'; fi` + +ar-contents.o: contents.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-contents.o `test -f 'contents.c' || echo '$(srcdir)/'`contents.c + +ar-contents.obj: contents.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-contents.obj `if test -f 'contents.c'; then $(CYGPATH_W) 'contents.c'; else $(CYGPATH_W) '$(srcdir)/contents.c'; fi` + +ar-delete.o: delete.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-delete.o `test -f 'delete.c' || echo '$(srcdir)/'`delete.c + +ar-delete.obj: delete.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-delete.obj `if test -f 'delete.c'; then $(CYGPATH_W) 'delete.c'; else $(CYGPATH_W) '$(srcdir)/delete.c'; fi` + +ar-extract.o: extract.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-extract.o `test -f 'extract.c' || echo '$(srcdir)/'`extract.c + +ar-extract.obj: extract.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-extract.obj `if test -f 'extract.c'; then $(CYGPATH_W) 'extract.c'; else $(CYGPATH_W) '$(srcdir)/extract.c'; fi` + +ar-misc.o: misc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-misc.o `test -f 'misc.c' || echo '$(srcdir)/'`misc.c + +ar-misc.obj: misc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-misc.obj `if test -f 'misc.c'; then $(CYGPATH_W) 'misc.c'; else $(CYGPATH_W) '$(srcdir)/misc.c'; fi` + +ar-move.o: move.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-move.o `test -f 'move.c' || echo '$(srcdir)/'`move.c + +ar-move.obj: move.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-move.obj `if test -f 'move.c'; then $(CYGPATH_W) 'move.c'; else $(CYGPATH_W) '$(srcdir)/move.c'; fi` + +ar-print.o: print.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-print.o `test -f 'print.c' || echo '$(srcdir)/'`print.c + +ar-print.obj: print.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-print.obj `if test -f 'print.c'; then $(CYGPATH_W) 'print.c'; else $(CYGPATH_W) '$(srcdir)/print.c'; fi` + +ar-replace.o: replace.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-replace.o `test -f 'replace.c' || echo '$(srcdir)/'`replace.c + +ar-replace.obj: replace.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ar_CFLAGS) $(CFLAGS) -c -o ar-replace.obj `if test -f 'replace.c'; then $(CYGPATH_W) 'replace.c'; else $(CYGPATH_W) '$(srcdir)/replace.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-binPROGRAMS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/ar/ar.c b/cctools/ar/ar.c index acbd9cd..b95e9ec 100644 --- a/cctools/ar/ar.c +++ b/cctools/ar/ar.c @@ -103,12 +103,13 @@ main(argc, argv) int argc; char **argv; { - int c, retval, verbose, run_ranlib; + int c, retval, verbose, run_ranlib, toc64; char *p; int (*fcall) __P((char **)); fcall = 0; verbose = 0; + toc64 = 0; progname = argv[0]; run_ranlib = 1; @@ -133,7 +134,7 @@ main(argc, argv) * extended format #1. The new option -L allows ar to use the extended * format and the old -T option causes the truncation of names. */ - while ((c = getopt(argc, argv, "abcdilLmopqrSsTtuVvx")) != -1) { + while ((c = getopt(argc, argv, "abcdilLmopqrSsTtuVvx6")) != -1) { switch(c) { case 'a': options |= AR_A; @@ -194,6 +195,9 @@ main(argc, argv) case 'V': verbose = 1; break; + case '6': + toc64 = 1; + break; case 'v': options |= AR_V; break; @@ -281,6 +285,8 @@ main(argc, argv) add_execute_list("-f"); else add_execute_list("-q"); + if(toc64) + add_execute_list("-toc64"); add_execute_list(archive); if(execute_list(verbose) == 0){ (void)fprintf(stderr, "%s: internal ranlib command failed\n", diff --git a/cctools/ar/archive.c b/cctools/ar/archive.c index 0f41fe9..64278f5 100644 --- a/cctools/ar/archive.c +++ b/cctools/ar/archive.c @@ -78,6 +78,7 @@ static char rcsid[] = "$NetBSD: archive.c,v 1.7 1995/03/26 03:27:46 glass Exp $" #include #include #include +#include /* cctools-port: For bcmp, bzero ... */ #include #include @@ -90,6 +91,10 @@ static char hb[sizeof(HDR) + 1]; /* real header */ int archive_opened_for_writing = 0; +#ifndef DEFFILEMODE +#define DEFFILEMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH +#endif + int open_archive(mode) int mode; @@ -234,8 +239,9 @@ get_arobj(fd) int fd; { struct ar_hdr *hdr; - int len, nr; + size_t len, nr; char *p, buf[20]; + long longval; nr = read(fd, hb, sizeof(HDR)); if (nr != sizeof(HDR)) { @@ -255,8 +261,10 @@ get_arobj(fd) #define OCTAL 8 AR_ATOI(hdr->ar_date, chdr.date, sizeof(hdr->ar_date), DECIMAL); - AR_ATOI(hdr->ar_uid, chdr.uid, sizeof(hdr->ar_uid), DECIMAL); - AR_ATOI(hdr->ar_gid, chdr.gid, sizeof(hdr->ar_gid), DECIMAL); + AR_ATOI(hdr->ar_uid, longval, sizeof(hdr->ar_uid), DECIMAL); + chdr.uid = (uid_t)longval; + AR_ATOI(hdr->ar_gid, longval, sizeof(hdr->ar_gid), DECIMAL); + chdr.gid = (gid_t)longval; AR_ATOI(hdr->ar_mode, chdr.mode, sizeof(hdr->ar_mode), OCTAL); AR_ATOI(hdr->ar_size, chdr.size, sizeof(hdr->ar_size), DECIMAL); @@ -291,7 +299,7 @@ get_arobj(fd) return (1); } -static int already_written; +static size_t already_written; /* * put_arobj -- @@ -302,7 +310,7 @@ put_arobj(cfp, sb) CF *cfp; struct stat *sb; { - unsigned int lname; + size_t lname; char *name; struct ar_hdr *hdr; off_t size; @@ -348,7 +356,8 @@ put_arobj(cfp, sb) sb->st_mode, (int64_t)sb->st_size, ARFMAG); lname = 0; } else if (lname > sizeof(hdr->ar_name) || strchr(name, ' ')) - (void)sprintf(hb, HDR1, AR_EFMT1, (lname + 3) & ~3, + (void)sprintf(hb, HDR1, AR_EFMT1, + (int)((lname + 3) & ~3), (long int)tv_sec, (unsigned int)(u_short)sb->st_uid, (unsigned int)(u_short)sb->st_gid, @@ -370,6 +379,15 @@ put_arobj(cfp, sb) size = chdr.size; } + /* cctools-port */ + if (strlen(hb) != sizeof(HDR)) { + fprintf(stderr, "ar is not working correctly. " + "Please report this issue to the cctools-port " + "project. Thank you.\n"); + exit(1); + } + /* cctools-port end */ + if (write(cfp->wfd, hb, sizeof(HDR)) != sizeof(HDR)) error(cfp->wname); /* @@ -378,13 +396,13 @@ put_arobj(cfp, sb) * which is required for object files in archives. */ if (lname) { - if (write(cfp->wfd, name, lname) != (int)lname) + if (write(cfp->wfd, name, lname) != (ssize_t)lname) error(cfp->wname); already_written = lname; if ((lname % 4) != 0) { static char pad[3] = "\0\0\0"; if (write(cfp->wfd, pad, 4-(lname%4)) != - (int)(4-(lname%4))) + (ssize_t)(4-(lname%4))) error(cfp->wname); already_written += 4 - (lname % 4); } @@ -414,7 +432,8 @@ copy_ar(cfp, size) { static char pad = '\n'; off_t sz; - int from, nr, nw, off, to; + ssize_t nr, nw; + int from, off, to; char buf[8*1024]; nr = 0; diff --git a/cctools/ar/archive.h b/cctools/ar/archive.h index 4b83a11..ea90cec 100644 --- a/cctools/ar/archive.h +++ b/cctools/ar/archive.h @@ -61,6 +61,8 @@ * @(#)archive.h 8.3 (Berkeley) 4/2/94 */ +#include + /* Ar(1) options. */ #define AR_A 0x0001 #define AR_B 0x0002 @@ -111,12 +113,18 @@ typedef struct { char name[MAXNAMLEN + 1]; /* name */ } CHDR; +/* + * cctools-port: + * Replaced 'qd' with 'lld' in format strings + * https://github.com/tpoechtrager/osxcross/issues/216#issuecomment-599044727 + * */ + /* Header format strings. */ -#define HDR1 "%s%-13d%-12ld%-6u%-6u%-8o%-10qd%2s" -#define HDR2 "%-16.16s%-12ld%-6u%-6u%-8o%-10qd%2s" +#define HDR1 "%s%-13d%-12ld%-6u%-6u%-8o%-10lld%2s" +#define HDR2 "%-16.16s%-12ld%-6u%-6u%-8o%-10lld%2s" #define OLDARMAXNAME 15 -#define HDR3 "%-16.15s%-12ld%-6u%-6u%-8o%-10qd%2s" +#define HDR3 "%-16.15s%-12ld%-6u%-6u%-8o%-10lld%2s" #include diff --git a/cctools/ar/contents.c b/cctools/ar/contents.c index 79cb125..4570db3 100644 --- a/cctools/ar/contents.c +++ b/cctools/ar/contents.c @@ -81,9 +81,7 @@ static char rcsid[] = "$OpenBSD: contents.c,v 1.2 1996/06/26 05:31:19 deraadt Ex #include "archive.h" #include "extern.h" -#ifndef HAVE_STRMODE /* cctools-port */ -extern void strmode(int mode, char *p); -#endif +#include "stuff/port.h" /* cctools-port: strmode */ /* * contents -- @@ -107,7 +105,8 @@ contents(argv) goto next; if (options & AR_V) { (void)strmode(chdr.mode, buf); - (void)printf("%s %6d/%-6d %8qd ", + /* cctools-port: replaced 'qd' with 'lld' in format string */ + (void)printf("%s %6d/%-6d %8lld ", buf + 1, chdr.uid, chdr.gid, chdr.size); tp = localtime(&chdr.date); (void)strftime(buf, sizeof(buf), "%b %e %H:%M %Y", tp); diff --git a/cctools/as/Makefile.in b/cctools/as/Makefile.in new file mode 100644 index 0000000..1d6350e --- /dev/null +++ b/cctools/as/Makefile.in @@ -0,0 +1,775 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = as$(EXEEXT) +subdir = as +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_as_OBJECTS = as-driver.$(OBJEXT) +as_OBJECTS = $(am_as_OBJECTS) +as_DEPENDENCIES = $(top_builddir)/libstuff/libstuff.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +as_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(as_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(as_SOURCES) +DIST_SOURCES = $(as_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in COPYING +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = arm i386 x86_64 ppc ppc64 +as_LDADD = \ + $(top_builddir)/libstuff/libstuff.la + +as_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -I$(top_srcdir)/libstuff $(WARNINGS) $(LTO_DEF) -DNeXT_MOD -DASLIBEXECDIR="\"$(ASLIBEXECDIR)/\"" -D__DARWIN_UNIX03 $(ENDIAN_FLAG) +as_SOURCES = driver.c +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps as/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps as/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +as$(EXEEXT): $(as_OBJECTS) $(as_DEPENDENCIES) $(EXTRA_as_DEPENDENCIES) + @rm -f as$(EXEEXT) + $(AM_V_CCLD)$(as_LINK) $(as_OBJECTS) $(as_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +as-driver.o: driver.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(as_CFLAGS) $(CFLAGS) -c -o as-driver.o `test -f 'driver.c' || echo '$(srcdir)/'`driver.c + +as-driver.obj: driver.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(as_CFLAGS) $(CFLAGS) -c -o as-driver.obj `if test -f 'driver.c'; then $(CYGPATH_W) 'driver.c'; else $(CYGPATH_W) '$(srcdir)/driver.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(PROGRAMS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-binPROGRAMS clean-generic clean-libtool \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-binPROGRAMS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/as/app.c b/cctools/as/app.c index be2f63b..9ec697c 100644 --- a/cctools/as/app.c +++ b/cctools/as/app.c @@ -517,7 +517,7 @@ FILE *fp) } int -do_scrub_next_char_from_string() +do_scrub_next_char_from_string(void) { /* State 0: beginning of normal line 1: After first whitespace on normal line (flush more white) diff --git a/cctools/as/app.h b/cctools/as/app.h index 611fc51..9689d0d 100644 --- a/cctools/as/app.h +++ b/cctools/as/app.h @@ -8,7 +8,7 @@ extern void do_scrub_begin( void); extern int do_scrub_next_char( FILE *fp); -extern int do_scrub_next_char_from_string(); +extern int do_scrub_next_char_from_string(void); /* * typedefs and routines to save scrub context so .include can make recursive diff --git a/cctools/as/arm.c b/cctools/as/arm.c index 680225d..ef856a5 100644 --- a/cctools/as/arm.c +++ b/cctools/as/arm.c @@ -3,6 +3,7 @@ #include #include #include +#include /* cctools-port: For bcmp, bzero ... */ #include #include "as.h" #include "flonum.h" @@ -1023,7 +1024,7 @@ arm_reg_alt_syntax (char **ccp, char *start, struct reg_entry *reg, case REG_TYPE_CP: /* For backward compatibility, a bare number is valid here. */ { - uint32_t processor = strtoul (start, ccp, 10); + uint32_t processor = (uint32_t)strtoul(start, ccp, 10); if (*ccp != start && processor <= 15) return processor; } @@ -1127,7 +1128,7 @@ parse_neon_type (struct neon_type *type, char **str) else { parsesize: - thissize = strtoul (ptr, &ptr, 10); + thissize = (uint32_t)strtoul (ptr, &ptr, 10); if (thissize != 8 && thissize != 16 && thissize != 32 && thissize != 64) @@ -1448,7 +1449,7 @@ parse_reg_list (char ** strp) cur_reg = reg; } while (skip_past_comma (&str) != FAIL - || (in_range = 1, *str++ == '-')); + || ((void)(in_range = 1), *str++ == '-')); str--; if (*str++ != '}') @@ -2175,7 +2176,7 @@ create_neon_reg_alias (char *newname, char *p) } } - namelen = nameend - newname; + namelen = (int)(nameend - newname); namebuf = alloca (namelen + 1); strncpy (namebuf, newname, namelen); namebuf[namelen] = '\0'; @@ -2957,7 +2958,7 @@ parse_immediate (char **str, int *val, int min, int max, return FAIL; } - *val = exp.X_add_number; + *val = (int)exp.X_add_number; return SUCCESS; } @@ -3338,7 +3339,7 @@ parse_shifter_operand (char **str, int i) return FAIL; } - value = expr.X_add_number; + value = (int)expr.X_add_number; if (value < 0 || value > 30 || value % 2 != 0) { inst.error = _("invalid rotation"); @@ -3453,7 +3454,7 @@ find_group_reloc_table_entry (char **str, struct group_reloc_table_entry **out) unsigned int i; for (i = 0; i < ARRAY_SIZE (group_reloc_table); i++) { - int length = strlen (group_reloc_table[i].name); + size_t length = strlen (group_reloc_table[i].name); if (strncasecmp (group_reloc_table[i].name, *str, length) == 0 && (*str)[length] == ':') @@ -3603,7 +3604,10 @@ parse_address_main (char **str, int i, int group_relocations, inst.operands[i].preind = 1; if (*p == '+') p++; - else if (*p == '-') p++, inst.operands[i].negative = 1; + else if (*p == '-') { + p++; + inst.operands[i].negative = 1; + } if ((reg = arm_reg_parse (&p, REG_TYPE_RN)) != FAIL) { @@ -3626,7 +3630,7 @@ parse_address_main (char **str, int i, int group_relocations, inst.error = _("alignment must be constant"); return PARSE_OPERAND_FAIL; } - inst.operands[i].imm = exp.X_add_number << 8; + inst.operands[i].imm = (int)(exp.X_add_number << 8); inst.operands[i].immisalign = 1; /* Alignments are not pre-indexes. */ inst.operands[i].preind = 0; @@ -3739,7 +3743,10 @@ parse_address_main (char **str, int i, int group_relocations, } if (*p == '+') p++; - else if (*p == '-') p++, inst.operands[i].negative = 1; + else if (*p == '-') { + p++; + inst.operands[i].negative = 1; + } if ((reg = arm_reg_parse (&p, REG_TYPE_RN)) != FAIL) { @@ -4457,7 +4464,7 @@ parse_operands (char *str, const unsigned char *pattern) enum arm_reg_type rtype; parse_operand_result result; - val = 0; /* cctools-port */ + val = SUCCESS; #define po_char_or_fail(chr) do { \ if (skip_past_char (&str, chr) == FAIL) \ @@ -5408,7 +5415,8 @@ move_or_literal_pool (int i, bfd_boolean thumb_p, bfd_boolean mode_3) } else { - int value = encode_arm_immediate (inst.reloc.exp.X_add_number); + int value = (int)encode_arm_immediate((unsigned int) + inst.reloc.exp.X_add_number); if (value != FAIL) { /* This can be done with a mov instruction. */ @@ -5418,7 +5426,8 @@ move_or_literal_pool (int i, bfd_boolean thumb_p, bfd_boolean mode_3) return 1; } - value = encode_arm_immediate (~inst.reloc.exp.X_add_number); + value = (int)encode_arm_immediate((unsigned int) + ~inst.reloc.exp.X_add_number); if (value != FAIL) { /* This can be done with a mvn instruction. */ @@ -6078,7 +6087,7 @@ do_mov16 (void) inst.instruction |= inst.operands[0].reg << 12; if (inst.reloc.type == BFD_RELOC_UNUSED) { - imm = inst.reloc.exp.X_add_number; + imm = (bfd_vma)inst.reloc.exp.X_add_number; /* The value is in two pieces: 0:11, 16:19. */ inst.instruction |= (imm & 0x00000fff); inst.instruction |= (imm & 0x0000f000) << 4; @@ -7208,7 +7217,7 @@ do_xsc_mra (void) static void encode_thumb32_shifted_operand (int i) { - unsigned int value = inst.reloc.exp.X_add_number; + unsigned int value = (unsigned int)inst.reloc.exp.X_add_number; unsigned int shift = inst.operands[i].shift_kind; constraint (inst.operands[i].immisreg, @@ -7513,8 +7522,8 @@ do_t_add_sub (void) constraint (inst.reloc.exp.X_add_number < 0 || inst.reloc.exp.X_add_number > 0xff, _("immediate value out of range")); - inst.instruction = T2_SUBS_PC_LR - | inst.reloc.exp.X_add_number; + inst.instruction = (uint32_t)(T2_SUBS_PC_LR + | inst.reloc.exp.X_add_number); inst.reloc.type = BFD_RELOC_UNUSED; return; } @@ -8785,7 +8794,7 @@ do_t_mov16 (void) inst.instruction |= inst.operands[0].reg << 8; if (inst.reloc.type == BFD_RELOC_UNUSED) { - imm = inst.reloc.exp.X_add_number; + imm = (bfd_vma)inst.reloc.exp.X_add_number; inst.instruction |= (imm & 0xf000) << 4; inst.instruction |= (imm & 0x0800) << 15; inst.instruction |= (imm & 0x0700) << 4; @@ -9071,7 +9080,7 @@ do_t_pkhbt (void) inst.instruction |= inst.operands[2].reg; if (inst.operands[3].present) { - unsigned int val = inst.reloc.exp.X_add_number; + signed_expr_t val = inst.reloc.exp.X_add_number; constraint (inst.reloc.exp.X_op != O_constant, _("expression too complex")); inst.instruction |= (val & 0x1c) << 10; @@ -9373,7 +9382,7 @@ do_t_simd (void) static void do_t_smc (void) { - unsigned int value = inst.reloc.exp.X_add_number; + unsigned int value = (unsigned int)inst.reloc.exp.X_add_number; constraint (inst.reloc.exp.X_op != O_constant, _("expression too complex")); inst.reloc.type = BFD_RELOC_UNUSED; @@ -13098,7 +13107,7 @@ fix_new_arm (fragS * frag, size, exp->X_add_symbol, exp->X_subtract_symbol, - exp->X_add_number, + (signed_target_addr_t)exp->X_add_number, pc_rel, pcrel_reloc, reloc); @@ -13120,7 +13129,7 @@ output_relax_insn (void) { char * to; symbolS *sym; - int offset; + int32_t offset; /* The size of the instruction is unknown, so tie the debug info to the start of the instruction. */ @@ -13130,11 +13139,11 @@ output_relax_insn (void) { case O_symbol: sym = inst.reloc.exp.X_add_symbol; - offset = inst.reloc.exp.X_add_number; + offset = (int32_t)inst.reloc.exp.X_add_number; break; case O_constant: sym = NULL; - offset = inst.reloc.exp.X_add_number; + offset = (int32_t)inst.reloc.exp.X_add_number; break; default: /* Avoid make_expr_symbol() if their is no subtract symbol and the @@ -13146,7 +13155,7 @@ output_relax_insn (void) (inst.reloc.exp.X_add_symbol->sy_nlist.n_type & N_TYPE) == N_ABS) ) { sym = inst.reloc.exp.X_add_symbol; - offset = inst.reloc.exp.X_add_number; + offset = (int32_t)inst.reloc.exp.X_add_number; } else { @@ -13201,7 +13210,7 @@ output_inst (const char * str) md_number_to_chars (to, inst.instruction, inst.size); if (inst.reloc.type != BFD_RELOC_UNUSED) - fix_new_arm (frag_now, to - frag_now->fr_literal, + fix_new_arm (frag_now, (int)(to - frag_now->fr_literal), inst.size, & inst.reloc.exp, inst.reloc.pc_rel, /* HACK_GUESS */ inst.reloc.pcrel_reloc, inst.reloc.type); @@ -13643,7 +13652,7 @@ md_assemble (char *str) 68 /* N_SLINE */, text_nsect, logical_input_line /* n_desc, line number */, - obstack_next_free(&frags) - frag_now->fr_literal, + (valueT)(obstack_next_free(&frags) - frag_now->fr_literal), frag_now); } /* @@ -13749,7 +13758,7 @@ arm_data_in_code (void) char * arm_canonicalize_symbol_name (char * name) { - int len; + size_t len; if (thumb_mode && (len = strlen (name)) > 5 && streq (name + len - 5, "/data")) @@ -16514,7 +16523,7 @@ md_pcrel_from_section (fixS * fixP, segT seg) case BFD_RELOC_THUMB_PCREL_BRANCH23: case BFD_RELOC_THUMB_PCREL_BRANCH25: case BFD_RELOC_THUMB_PCREL_BLX: - return base + 4; + return (int32_t)base + 4; /* ARM mode branches are offset by +8. However, the Windows CE loader expects the relocation not to take this into account. */ @@ -16537,7 +16546,7 @@ md_pcrel_from_section (fixS * fixP, segT seg) return base + 8; return base; #else - return base + 8; + return (int32_t)base + 8; #endif /* ARM mode loads relative to PC are also offset by +8. Unlike @@ -16548,12 +16557,12 @@ md_pcrel_from_section (fixS * fixP, segT seg) case BFD_RELOC_ARM_HWLITERAL: case BFD_RELOC_ARM_LITERAL: case BFD_RELOC_ARM_CP_OFF_IMM: - return base + 8; + return (int32_t)base + 8; /* Other PC-relative relocations are un-offset. */ default: - return base; + return (int32_t)base; } } @@ -16835,8 +16844,8 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg) { - offsetT value = * valP; - offsetT newval; + valueT value = * valP; + valueT newval; unsigned int newimm; uint32_t temp; int sign; @@ -16958,10 +16967,12 @@ md_apply_fix (fixS * fixP, case BFD_RELOC_ARM_OFFSET_IMM: #ifdef NOTYET if (!fixP->fx_done && seg->use_rela_p) + value = 0; #else - if (!fixP->fx_done && 0) +// The goggles do nothing! +// if (!fixP->fx_done && 0) +// value = 0; #endif - value = 0; case BFD_RELOC_ARM_LITERAL: sign = value >= 0; @@ -17185,9 +17196,12 @@ md_apply_fix (fixS * fixP, if (fixP->fx_r_type == BFD_RELOC_ARM_T32_IMMEDIATE || fixP->fx_r_type == BFD_RELOC_ARM_T32_ADD_IMM) { + offsetT newoff; newimm = encode_thumb32_immediate (value); - if (newimm == (unsigned int) FAIL) - newimm = thumb32_negate_data_op (&newval, value); + if (newimm == (unsigned int) FAIL) { + newimm = thumb32_negate_data_op (&newoff, value); + newval = (valueT)newoff; + } } if (fixP->fx_r_type != BFD_RELOC_ARM_T32_IMMEDIATE && newimm == (unsigned int) FAIL) @@ -18522,7 +18536,7 @@ int nsect) case BFD_RELOC_ARM_ADRL_IMMEDIATE: default: { - valueT newval = val; + valueT newval = (valueT)val; /* Die if we have more bytes than md_apply_fix3 knows how to handle. */ diff --git a/cctools/as/arm/Makefile.in b/cctools/as/arm/Makefile.in new file mode 100644 index 0000000..24f9e3f --- /dev/null +++ b/cctools/as/arm/Makefile.in @@ -0,0 +1,848 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +libexec_PROGRAMS = arm-as$(EXEEXT) +subdir = as/arm +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(libexecdir)" +PROGRAMS = $(libexec_PROGRAMS) +am__dirstamp = $(am__leading_dot)dirstamp +am_arm_as_OBJECTS = ../arm_as-app.$(OBJEXT) ../arm_as-as.$(OBJEXT) \ + ../arm_as-atof-generic.$(OBJEXT) ../arm_as-atof-ieee.$(OBJEXT) \ + ../arm_as-expr.$(OBJEXT) ../arm_as-fixes.$(OBJEXT) \ + ../arm_as-flonum-const.$(OBJEXT) \ + ../arm_as-flonum-copy.$(OBJEXT) \ + ../arm_as-flonum-mult.$(OBJEXT) ../arm_as-frags.$(OBJEXT) \ + ../arm_as-hash.$(OBJEXT) ../arm_as-hex-value.$(OBJEXT) \ + ../arm_as-input-file.$(OBJEXT) ../arm_as-input-scrub.$(OBJEXT) \ + ../arm_as-layout.$(OBJEXT) ../arm_as-messages.$(OBJEXT) \ + ../arm_as-obstack.$(OBJEXT) ../arm_as-read.$(OBJEXT) \ + ../arm_as-sections.$(OBJEXT) ../arm_as-symbols.$(OBJEXT) \ + ../arm_as-write_object.$(OBJEXT) ../arm_as-xmalloc.$(OBJEXT) \ + ../arm_as-dwarf2dbg.$(OBJEXT) ../arm_as-arm.$(OBJEXT) +arm_as_OBJECTS = $(am_arm_as_OBJECTS) +arm_as_DEPENDENCIES = $(top_builddir)/libstuff/libstuff.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +arm_as_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(arm_as_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(arm_as_SOURCES) +DIST_SOURCES = $(arm_as_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +arm_as_LDADD = \ + $(top_builddir)/libstuff/libstuff.la + +arm_as_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -I$(top_srcdir)/libstuff -I$(top_srcdir)/as $(WARNINGS) $(LTO_DEF) -DNeXT_MOD -DASLIBEXECDIR="\"$(ASLIBEXECDIR)/\"" -D__DARWIN_UNIX03 -DARM $(ENDIAN_FLAG) +arm_as_SOURCES = ../app.c ../as.c ../atof-generic.c ../atof-ieee.c ../expr.c ../fixes.c ../flonum-const.c \ + ../flonum-copy.c ../flonum-mult.c ../frags.c ../hash.c ../hex-value.c ../input-file.c \ + ../input-scrub.c ../layout.c ../messages.c ../obstack.c ../read.c ../sections.c \ + ../symbols.c ../write_object.c ../xmalloc.c ../dwarf2dbg.c ../arm.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps as/arm/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps as/arm/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libexecPROGRAMS: $(libexec_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-libexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libexecdir)" && rm -f $$files + +clean-libexecPROGRAMS: + @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +../$(am__dirstamp): + @$(MKDIR_P) .. + @: > ../$(am__dirstamp) +../arm_as-app.$(OBJEXT): ../$(am__dirstamp) +../arm_as-as.$(OBJEXT): ../$(am__dirstamp) +../arm_as-atof-generic.$(OBJEXT): ../$(am__dirstamp) +../arm_as-atof-ieee.$(OBJEXT): ../$(am__dirstamp) +../arm_as-expr.$(OBJEXT): ../$(am__dirstamp) +../arm_as-fixes.$(OBJEXT): ../$(am__dirstamp) +../arm_as-flonum-const.$(OBJEXT): ../$(am__dirstamp) +../arm_as-flonum-copy.$(OBJEXT): ../$(am__dirstamp) +../arm_as-flonum-mult.$(OBJEXT): ../$(am__dirstamp) +../arm_as-frags.$(OBJEXT): ../$(am__dirstamp) +../arm_as-hash.$(OBJEXT): ../$(am__dirstamp) +../arm_as-hex-value.$(OBJEXT): ../$(am__dirstamp) +../arm_as-input-file.$(OBJEXT): ../$(am__dirstamp) +../arm_as-input-scrub.$(OBJEXT): ../$(am__dirstamp) +../arm_as-layout.$(OBJEXT): ../$(am__dirstamp) +../arm_as-messages.$(OBJEXT): ../$(am__dirstamp) +../arm_as-obstack.$(OBJEXT): ../$(am__dirstamp) +../arm_as-read.$(OBJEXT): ../$(am__dirstamp) +../arm_as-sections.$(OBJEXT): ../$(am__dirstamp) +../arm_as-symbols.$(OBJEXT): ../$(am__dirstamp) +../arm_as-write_object.$(OBJEXT): ../$(am__dirstamp) +../arm_as-xmalloc.$(OBJEXT): ../$(am__dirstamp) +../arm_as-dwarf2dbg.$(OBJEXT): ../$(am__dirstamp) +../arm_as-arm.$(OBJEXT): ../$(am__dirstamp) + +arm-as$(EXEEXT): $(arm_as_OBJECTS) $(arm_as_DEPENDENCIES) $(EXTRA_arm_as_DEPENDENCIES) + @rm -f arm-as$(EXEEXT) + $(AM_V_CCLD)$(arm_as_LINK) $(arm_as_OBJECTS) $(arm_as_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f ../*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +../arm_as-app.o: ../app.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-app.o `test -f '../app.c' || echo '$(srcdir)/'`../app.c + +../arm_as-app.obj: ../app.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-app.obj `if test -f '../app.c'; then $(CYGPATH_W) '../app.c'; else $(CYGPATH_W) '$(srcdir)/../app.c'; fi` + +../arm_as-as.o: ../as.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-as.o `test -f '../as.c' || echo '$(srcdir)/'`../as.c + +../arm_as-as.obj: ../as.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-as.obj `if test -f '../as.c'; then $(CYGPATH_W) '../as.c'; else $(CYGPATH_W) '$(srcdir)/../as.c'; fi` + +../arm_as-atof-generic.o: ../atof-generic.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-atof-generic.o `test -f '../atof-generic.c' || echo '$(srcdir)/'`../atof-generic.c + +../arm_as-atof-generic.obj: ../atof-generic.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-atof-generic.obj `if test -f '../atof-generic.c'; then $(CYGPATH_W) '../atof-generic.c'; else $(CYGPATH_W) '$(srcdir)/../atof-generic.c'; fi` + +../arm_as-atof-ieee.o: ../atof-ieee.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-atof-ieee.o `test -f '../atof-ieee.c' || echo '$(srcdir)/'`../atof-ieee.c + +../arm_as-atof-ieee.obj: ../atof-ieee.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-atof-ieee.obj `if test -f '../atof-ieee.c'; then $(CYGPATH_W) '../atof-ieee.c'; else $(CYGPATH_W) '$(srcdir)/../atof-ieee.c'; fi` + +../arm_as-expr.o: ../expr.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-expr.o `test -f '../expr.c' || echo '$(srcdir)/'`../expr.c + +../arm_as-expr.obj: ../expr.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-expr.obj `if test -f '../expr.c'; then $(CYGPATH_W) '../expr.c'; else $(CYGPATH_W) '$(srcdir)/../expr.c'; fi` + +../arm_as-fixes.o: ../fixes.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-fixes.o `test -f '../fixes.c' || echo '$(srcdir)/'`../fixes.c + +../arm_as-fixes.obj: ../fixes.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-fixes.obj `if test -f '../fixes.c'; then $(CYGPATH_W) '../fixes.c'; else $(CYGPATH_W) '$(srcdir)/../fixes.c'; fi` + +../arm_as-flonum-const.o: ../flonum-const.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-flonum-const.o `test -f '../flonum-const.c' || echo '$(srcdir)/'`../flonum-const.c + +../arm_as-flonum-const.obj: ../flonum-const.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-flonum-const.obj `if test -f '../flonum-const.c'; then $(CYGPATH_W) '../flonum-const.c'; else $(CYGPATH_W) '$(srcdir)/../flonum-const.c'; fi` + +../arm_as-flonum-copy.o: ../flonum-copy.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-flonum-copy.o `test -f '../flonum-copy.c' || echo '$(srcdir)/'`../flonum-copy.c + +../arm_as-flonum-copy.obj: ../flonum-copy.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-flonum-copy.obj `if test -f '../flonum-copy.c'; then $(CYGPATH_W) '../flonum-copy.c'; else $(CYGPATH_W) '$(srcdir)/../flonum-copy.c'; fi` + +../arm_as-flonum-mult.o: ../flonum-mult.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-flonum-mult.o `test -f '../flonum-mult.c' || echo '$(srcdir)/'`../flonum-mult.c + +../arm_as-flonum-mult.obj: ../flonum-mult.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-flonum-mult.obj `if test -f '../flonum-mult.c'; then $(CYGPATH_W) '../flonum-mult.c'; else $(CYGPATH_W) '$(srcdir)/../flonum-mult.c'; fi` + +../arm_as-frags.o: ../frags.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-frags.o `test -f '../frags.c' || echo '$(srcdir)/'`../frags.c + +../arm_as-frags.obj: ../frags.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-frags.obj `if test -f '../frags.c'; then $(CYGPATH_W) '../frags.c'; else $(CYGPATH_W) '$(srcdir)/../frags.c'; fi` + +../arm_as-hash.o: ../hash.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-hash.o `test -f '../hash.c' || echo '$(srcdir)/'`../hash.c + +../arm_as-hash.obj: ../hash.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-hash.obj `if test -f '../hash.c'; then $(CYGPATH_W) '../hash.c'; else $(CYGPATH_W) '$(srcdir)/../hash.c'; fi` + +../arm_as-hex-value.o: ../hex-value.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-hex-value.o `test -f '../hex-value.c' || echo '$(srcdir)/'`../hex-value.c + +../arm_as-hex-value.obj: ../hex-value.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-hex-value.obj `if test -f '../hex-value.c'; then $(CYGPATH_W) '../hex-value.c'; else $(CYGPATH_W) '$(srcdir)/../hex-value.c'; fi` + +../arm_as-input-file.o: ../input-file.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-input-file.o `test -f '../input-file.c' || echo '$(srcdir)/'`../input-file.c + +../arm_as-input-file.obj: ../input-file.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-input-file.obj `if test -f '../input-file.c'; then $(CYGPATH_W) '../input-file.c'; else $(CYGPATH_W) '$(srcdir)/../input-file.c'; fi` + +../arm_as-input-scrub.o: ../input-scrub.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-input-scrub.o `test -f '../input-scrub.c' || echo '$(srcdir)/'`../input-scrub.c + +../arm_as-input-scrub.obj: ../input-scrub.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-input-scrub.obj `if test -f '../input-scrub.c'; then $(CYGPATH_W) '../input-scrub.c'; else $(CYGPATH_W) '$(srcdir)/../input-scrub.c'; fi` + +../arm_as-layout.o: ../layout.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-layout.o `test -f '../layout.c' || echo '$(srcdir)/'`../layout.c + +../arm_as-layout.obj: ../layout.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-layout.obj `if test -f '../layout.c'; then $(CYGPATH_W) '../layout.c'; else $(CYGPATH_W) '$(srcdir)/../layout.c'; fi` + +../arm_as-messages.o: ../messages.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-messages.o `test -f '../messages.c' || echo '$(srcdir)/'`../messages.c + +../arm_as-messages.obj: ../messages.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-messages.obj `if test -f '../messages.c'; then $(CYGPATH_W) '../messages.c'; else $(CYGPATH_W) '$(srcdir)/../messages.c'; fi` + +../arm_as-obstack.o: ../obstack.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-obstack.o `test -f '../obstack.c' || echo '$(srcdir)/'`../obstack.c + +../arm_as-obstack.obj: ../obstack.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-obstack.obj `if test -f '../obstack.c'; then $(CYGPATH_W) '../obstack.c'; else $(CYGPATH_W) '$(srcdir)/../obstack.c'; fi` + +../arm_as-read.o: ../read.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-read.o `test -f '../read.c' || echo '$(srcdir)/'`../read.c + +../arm_as-read.obj: ../read.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-read.obj `if test -f '../read.c'; then $(CYGPATH_W) '../read.c'; else $(CYGPATH_W) '$(srcdir)/../read.c'; fi` + +../arm_as-sections.o: ../sections.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-sections.o `test -f '../sections.c' || echo '$(srcdir)/'`../sections.c + +../arm_as-sections.obj: ../sections.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-sections.obj `if test -f '../sections.c'; then $(CYGPATH_W) '../sections.c'; else $(CYGPATH_W) '$(srcdir)/../sections.c'; fi` + +../arm_as-symbols.o: ../symbols.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-symbols.o `test -f '../symbols.c' || echo '$(srcdir)/'`../symbols.c + +../arm_as-symbols.obj: ../symbols.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-symbols.obj `if test -f '../symbols.c'; then $(CYGPATH_W) '../symbols.c'; else $(CYGPATH_W) '$(srcdir)/../symbols.c'; fi` + +../arm_as-write_object.o: ../write_object.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-write_object.o `test -f '../write_object.c' || echo '$(srcdir)/'`../write_object.c + +../arm_as-write_object.obj: ../write_object.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-write_object.obj `if test -f '../write_object.c'; then $(CYGPATH_W) '../write_object.c'; else $(CYGPATH_W) '$(srcdir)/../write_object.c'; fi` + +../arm_as-xmalloc.o: ../xmalloc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-xmalloc.o `test -f '../xmalloc.c' || echo '$(srcdir)/'`../xmalloc.c + +../arm_as-xmalloc.obj: ../xmalloc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-xmalloc.obj `if test -f '../xmalloc.c'; then $(CYGPATH_W) '../xmalloc.c'; else $(CYGPATH_W) '$(srcdir)/../xmalloc.c'; fi` + +../arm_as-dwarf2dbg.o: ../dwarf2dbg.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-dwarf2dbg.o `test -f '../dwarf2dbg.c' || echo '$(srcdir)/'`../dwarf2dbg.c + +../arm_as-dwarf2dbg.obj: ../dwarf2dbg.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-dwarf2dbg.obj `if test -f '../dwarf2dbg.c'; then $(CYGPATH_W) '../dwarf2dbg.c'; else $(CYGPATH_W) '$(srcdir)/../dwarf2dbg.c'; fi` + +../arm_as-arm.o: ../arm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-arm.o `test -f '../arm.c' || echo '$(srcdir)/'`../arm.c + +../arm_as-arm.obj: ../arm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(arm_as_CFLAGS) $(CFLAGS) -c -o ../arm_as-arm.obj `if test -f '../arm.c'; then $(CYGPATH_W) '../arm.c'; else $(CYGPATH_W) '$(srcdir)/../arm.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(libexecdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f ../$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libexecPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libexecPROGRAMS + +.MAKE: install-am install-exec-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libexecPROGRAMS clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-exec-hook install-html install-html-am \ + install-info install-info-am install-libexecPROGRAMS \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-libexecPROGRAMS + +.PRECIOUS: Makefile + +install-exec-hook: + mkdir -p $(DESTDIR)$(libexecdir)/as/arm + mv $(DESTDIR)$(libexecdir)/*arm-as* $(DESTDIR)$(libexecdir)/as/arm/as + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/as/atof-generic.c b/cctools/as/atof-generic.c index 8e1c4c9..1b8e9b5 100644 --- a/cctools/as/atof-generic.c +++ b/cctools/as/atof-generic.c @@ -247,7 +247,7 @@ FLONUM_TYPE *address_of_generic_floating_point_number) FLONUM_TYPE digits_flonum; - precision = (address_of_generic_floating_point_number -> high + precision = (int)(address_of_generic_floating_point_number -> high - address_of_generic_floating_point_number -> low + 1 ); /* Number of destination littlenums. */ diff --git a/cctools/as/atof-ieee.c b/cctools/as/atof-ieee.c index 8edf546..772d47f 100644 --- a/cctools/as/atof-ieee.c +++ b/cctools/as/atof-ieee.c @@ -315,12 +315,13 @@ int exponent_bits) */ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS; littlenum_pointer = generic_floating_point_number.leader; - littlenums_left = 1+generic_floating_point_number.leader - generic_floating_point_number.low; + littlenums_left = (int)(1+generic_floating_point_number.leader - generic_floating_point_number.low); /* Seek (and forget) 1st significant bit */ for (exponent_skippage = 0;! next_bits(1); exponent_skippage ++) ; - exponent_1 = generic_floating_point_number.exponent + generic_floating_point_number.leader + 1 - - generic_floating_point_number.low; + exponent_1 = (int32_t)(generic_floating_point_number.exponent + + generic_floating_point_number.leader + 1 - + generic_floating_point_number.low); /* Radix LITTLENUM_RADIX, point just higher than generic_floating_point_number.leader. */ exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS; /* Radix 2. */ diff --git a/cctools/as/driver.c b/cctools/as/driver.c index 92410c7..c2eadf0 100644 --- a/cctools/as/driver.c +++ b/cctools/as/driver.c @@ -9,6 +9,7 @@ #include "stdio.h" #include "stdlib.h" #include "string.h" +#include /* cctools-port: For bcmp, bzero ... */ #include "libc.h" #include #include @@ -16,12 +17,13 @@ #include "stuff/errors.h" #include "stuff/execute.h" #include "stuff/allocate.h" +#include "stuff/port.h" /* cctools-port: find_clang() */ #include /* used by error calls (exported) */ char *progname = NULL; -char *find_clang(); /* cctools-port */ + int main( @@ -29,8 +31,8 @@ int argc, char **argv, char **envp) { - const char *LIB = "../libexec/as/"; - const char *LOCALLIB = "../local/libexec/as/"; + const char *LIB = ASLIBEXECDIR; + const char *LOCALLIB = ASLIBEXECDIR; const char *AS = "/as"; int i, j; @@ -241,6 +243,7 @@ char **envp) (arch_flag.cputype == CPU_TYPE_X86_64 || arch_flag.cputype == CPU_TYPE_I386 || arch_flag.cputype == CPU_TYPE_ARM64 || + arch_flag.cputype == CPU_TYPE_ARM64_32 || arch_flag.cputype == CPU_TYPE_ARM)){ qflag = TRUE; } @@ -248,6 +251,7 @@ char **envp) (arch_flag.cputype != CPU_TYPE_X86_64 && arch_flag.cputype != CPU_TYPE_I386 && arch_flag.cputype != CPU_TYPE_ARM64 && + arch_flag.cputype != CPU_TYPE_ARM64_32 && arch_flag.cputype != CPU_TYPE_ARM)){ printf("%s: can't specifiy -q with -arch %s\n", progname, arch_flag.name); @@ -264,9 +268,11 @@ char **envp) * in the usual place as the other target assemblers this use of clang * will be removed. */ - if(arch_flag.cputype == CPU_TYPE_ARM64){ + if(arch_flag.cputype == CPU_TYPE_ARM64 || + arch_flag.cputype == CPU_TYPE_ARM64_32){ if(Qflag == TRUE){ - printf("%s: can't specifiy -Q with -arch arm64\n", progname); + printf("%s: can't specifiy -Q with -arch %s\n", progname, + arch_flag.cputype == CPU_TYPE_ARM64 ? "arm64" : "arm64_32"); exit(1); } run_clang = 1; @@ -295,6 +301,7 @@ char **envp) (arch_flag.cputype == CPU_TYPE_X86_64 || arch_flag.cputype == CPU_TYPE_I386 || arch_flag.cputype == CPU_TYPE_ARM64 || + arch_flag.cputype == CPU_TYPE_ARM64_32 || arch_flag.cputype == CPU_TYPE_ARM)){ #if 0 /* cctools port */ as = makestr(prefix, CLANG, NULL); @@ -386,7 +393,7 @@ char **envp) /* * If this assembler exist try to run it else print an error message. */ - as = makestr(prefix, LIB, arch_name, AS, NULL); + as = makestr(LIB, arch_name, AS, NULL); new_argv = allocate((argc + 1) * sizeof(char *)); new_argv[0] = as; j = 1; @@ -408,7 +415,7 @@ char **envp) else exit(1); } - as_local = makestr(prefix, LOCALLIB, arch_name, AS, NULL); + as_local = makestr(LOCALLIB, arch_name, AS, NULL); new_argv[0] = as_local; if(access(as_local, F_OK) == 0){ argv[0] = as_local; @@ -422,7 +429,7 @@ char **envp) arch_flags = get_arch_flags(); count = 0; for(i = 0; arch_flags[i].name != NULL; i++){ - as = makestr(prefix, LIB, arch_flags[i].name, AS, NULL); + as = makestr(LIB, arch_flags[i].name, AS, NULL); if(access(as, F_OK) == 0){ if(count == 0) printf("Installed assemblers are:\n"); @@ -430,7 +437,7 @@ char **envp) count++; } else{ - as_local = makestr(prefix, LOCALLIB, arch_flags[i].name, AS, + as_local = makestr(LOCALLIB, arch_flags[i].name, AS, NULL); if(access(as_local, F_OK) == 0){ if(count == 0) diff --git a/cctools/as/dwarf2dbg.c b/cctools/as/dwarf2dbg.c index 9c4c31e..dafe7ba 100644 --- a/cctools/as/dwarf2dbg.c +++ b/cctools/as/dwarf2dbg.c @@ -30,6 +30,7 @@ #include #include +#include /* cctools-port: For bcmp, bzero ... */ #include #include #include @@ -227,8 +228,8 @@ static void out_opcode (int); static void out_two (int); static void out_four (int); static void out_abbrev (int, int); -static void out_uleb128 (addressT); -static void out_sleb128 (addressT); +static void out_uleb128 (unsigned int); +static void out_sleb128 (int); static offsetT get_frag_fix (fragS *, segT); static void out_set_addr (symbolS *); static int size_inc_line_addr (int, addressT); @@ -268,11 +269,11 @@ emit_expr (expressionS *exp, unsigned int nbytes) p = frag_more ((int) nbytes); fix_new(frag_now, - p - frag_now->fr_literal, + (int)(p - frag_now->fr_literal), nbytes, exp->X_add_symbol, exp->X_subtract_symbol, - exp->X_add_number, + (signed_target_addr_t)exp->X_add_number, 0, 0, 0); @@ -392,7 +393,7 @@ dwarf2_gen_line_info (addressT ofs, struct dwarf2_line_info *loc) line = loc->line; filenum = loc->filenum; - sym = symbol_temp_new (now_seg, ofs, frag_now); + sym = symbol_temp_new (now_seg, (valueT)ofs, frag_now); dwarf2_gen_line_info_1 (sym, loc); } @@ -535,7 +536,8 @@ char *path) static unsigned int get_filenum (char *filename, unsigned int num) { - static unsigned int last_used, last_used_dir_len; + static unsigned int last_used; + static size_t last_used_dir_len; char *file; size_t dir_len; unsigned int i, dir; @@ -686,7 +688,7 @@ dwarf2_directive_file (uintptr_t dummy ATTRIBUTE_UNUSED) return NULL; } - get_filenum (filename, num); + get_filenum (filename, (unsigned int)num); return filename; } @@ -700,17 +702,17 @@ dwarf2_file ( char *filename, offsetT num) { - get_filenum (filename, num); + get_filenum (filename, (unsigned int)num); } void dwarf2_directive_loc (uintptr_t dummy ATTRIBUTE_UNUSED) { - offsetT filenum, line; + unsigned int filenum, line; - filenum = get_absolute_expression (); + filenum = (unsigned int)get_absolute_expression (); SKIP_WHITESPACE (); - line = get_absolute_expression (); + line = (unsigned int)get_absolute_expression (); if (filenum < 1) { @@ -750,14 +752,14 @@ dwarf2_directive_loc (uintptr_t dummy ATTRIBUTE_UNUSED) SKIP_WHITESPACE (); if (ISDIGIT (*input_line_pointer)) { - current.column = get_absolute_expression (); + current.column = (unsigned int)get_absolute_expression (); SKIP_WHITESPACE (); } while (ISALPHA (*input_line_pointer)) { char *p, c; - offsetT value; + unsigned int value; p = input_line_pointer; c = get_symbol_end (); @@ -780,7 +782,7 @@ dwarf2_directive_loc (uintptr_t dummy ATTRIBUTE_UNUSED) else if (strcmp (p, "is_stmt") == 0) { *input_line_pointer = c; - value = get_absolute_expression (); + value = (unsigned int)get_absolute_expression (); if (value == 0) current.flags &= ~DWARF2_FLAG_IS_STMT; else if (value == 1) @@ -794,7 +796,7 @@ dwarf2_directive_loc (uintptr_t dummy ATTRIBUTE_UNUSED) else if (strcmp (p, "isa") == 0) { *input_line_pointer = c; - value = get_absolute_expression (); + value = (unsigned int)get_absolute_expression (); if (value >= 0) current.isa = value; else @@ -824,8 +826,8 @@ dwarf2_directive_loc (uintptr_t dummy ATTRIBUTE_UNUSED) void dwarf2_loc (offsetT filenum, offsetT line) { - current.filenum = filenum; - current.line = line; + current.filenum = (unsigned int)filenum; + current.line = (unsigned int)line; } void @@ -899,7 +901,7 @@ out_four (int data) /* Emit an unsigned "little-endian base 128" number. */ static void -out_uleb128 (addressT value) +out_uleb128 (unsigned int value) { output_leb128 (frag_more (sizeof_leb128 (value, 0)), value, 0); } @@ -907,7 +909,7 @@ out_uleb128 (addressT value) /* Emit a signed "little-endian base 128" number. */ static void -out_sleb128 (addressT value) +out_sleb128 (int value) { output_leb128 (frag_more (sizeof_leb128 (value, 1)), value, 1); } @@ -1017,7 +1019,7 @@ size_inc_line_addr (int line_delta, addressT addr_delta) if (addr_delta == MAX_SPECIAL_ADDR_DELTA) len = 1; else - len = 1 + sizeof_leb128 (addr_delta, 0); + len = 1 + (int)sizeof_leb128((valueT)addr_delta, 0); return len + 3; } @@ -1040,18 +1042,18 @@ size_inc_line_addr (int line_delta, addressT addr_delta) if (addr_delta < 256 + MAX_SPECIAL_ADDR_DELTA) { /* Try using a special opcode. */ - opcode = tmp + addr_delta * DWARF2_LINE_RANGE; + opcode = (unsigned int)(tmp + addr_delta * DWARF2_LINE_RANGE); if (opcode <= 255) return len + 1; /* Try using DW_LNS_const_add_pc followed by special op. */ - opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE; + opcode = (unsigned int)(tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE); if (opcode <= 255) return len + 2; } /* Otherwise use DW_LNS_advance_pc. */ - len += 1 + sizeof_leb128 (addr_delta, 0); + len += 1 + (int)sizeof_leb128 ((valueT)addr_delta, 0); /* DW_LNS_copy or special opcode. */ len += 1; @@ -1083,7 +1085,8 @@ emit_inc_line_addr (int line_delta, addressT addr_delta, char *p, int len) else { *p++ = DW_LNS_advance_pc; - p += output_leb128 (p, addr_delta, 0); + p += + (int)output_leb128 (p, (valueT)addr_delta, 0); } *p++ = DW_LNS_extended_op; @@ -1122,7 +1125,7 @@ emit_inc_line_addr (int line_delta, addressT addr_delta, char *p, int len) if (addr_delta < 256 + MAX_SPECIAL_ADDR_DELTA) { /* Try using a special opcode. */ - opcode = tmp + addr_delta * DWARF2_LINE_RANGE; + opcode = (unsigned int)(tmp + addr_delta * DWARF2_LINE_RANGE); if (opcode <= 255) { *p++ = opcode; @@ -1130,7 +1133,7 @@ emit_inc_line_addr (int line_delta, addressT addr_delta, char *p, int len) } /* Try using DW_LNS_const_add_pc followed by special op. */ - opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE; + opcode = (unsigned int)(tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE); if (opcode <= 255) { *p++ = DW_LNS_const_add_pc; @@ -1141,7 +1144,7 @@ emit_inc_line_addr (int line_delta, addressT addr_delta, char *p, int len) /* Otherwise use DW_LNS_advance_pc. */ *p++ = DW_LNS_advance_pc; - p += output_leb128 (p, addr_delta, 0); + p += (int)output_leb128 (p, (valueT)addr_delta, 0); if (need_copy) *p++ = DW_LNS_copy; @@ -1472,7 +1475,7 @@ process_entries (segT seg, struct line_entry *e) out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs); else { - lab = symbol_temp_new (seg, frag_ofs, frag); + lab = symbol_temp_new (seg, (valueT)frag_ofs, frag); relax_inc_line_addr (INT_MAX, lab, last_lab); } @@ -1492,7 +1495,7 @@ out_file_list (void) for (i = 1; i < dirs_in_use; ++i) { size = strlen (dirs[i]) + 1; - cp = frag_more (size); + cp = frag_more ((int)size); memcpy (cp, dirs[i], size); } /* Terminate it. */ @@ -1509,7 +1512,7 @@ out_file_list (void) } size = strlen (files[i].filename) + 1; - cp = frag_more (size); + cp = frag_more ((int)size); memcpy (cp, files[i].filename, size); out_uleb128 (files[i].dir); /* directory number */ @@ -1698,7 +1701,7 @@ struct frchain *ranges_section) s->text_start = beg; frag = last_frag_for_seg (s->seg); - end = symbol_temp_new (s->seg, get_frag_fix (frag, s->seg), frag); + end = symbol_temp_new (s->seg, (valueT)get_frag_fix (frag, s->seg), frag); s->text_end = end; memset(&expr, '\0', sizeof(expr)); @@ -1752,7 +1755,7 @@ struct frchain *info_section) section_set(aranges_section); /* Length of the compilation unit. */ - out_four (size - 4); + out_four ((int)size - 4); /* Version. */ out_two (2); @@ -1786,7 +1789,7 @@ struct frchain *info_section) s->text_start = beg; frag = last_frag_for_seg (s->seg); - end = symbol_temp_new (s->seg, get_frag_fix (frag, s->seg), frag); + end = symbol_temp_new (s->seg, (valueT)get_frag_fix (frag, s->seg), frag); s->text_end = end; memset(&expr, '\0', sizeof(expr)); @@ -1840,8 +1843,9 @@ struct frchain * abbrev_section) { if (DWARF2_FORMAT () == dwarf2_format_32bit) out_abbrev (DW_AT_ranges, DW_FORM_data4); - else - out_abbrev (DW_AT_ranges, DW_FORM_data8); +// The goggles do nothing +// else +// out_abbrev (DW_AT_ranges, DW_FORM_data8); } out_abbrev (DW_AT_name, DW_FORM_string); out_abbrev (DW_AT_comp_dir, DW_FORM_string); @@ -1989,12 +1993,12 @@ struct frchain *ranges_section) abort (); if (files[1].dir) { - len = strlen (dirs[files[1].dir]); + len = (int)strlen (dirs[files[1].dir]); p = frag_more (len + 1); memcpy (p, dirs[files[1].dir], len); INSERT_DIR_SEPARATOR (p, len); } - len = strlen (files[1].filename) + 1; + len = (int)strlen (files[1].filename) + 1; p = frag_more (len); memcpy (p, files[1].filename, len); @@ -2004,13 +2008,13 @@ struct frchain *ranges_section) #else comp_dir = getcwd(xmalloc(MAXPATHLEN + 1), MAXPATHLEN + 1); /* cctools-port: getwd() -> getcwd() */ #endif - len = strlen (comp_dir) + 1; + len = (int)strlen (comp_dir) + 1; p = frag_more (len); memcpy (p, comp_dir, len); if(apple_flags != NULL){ /* DW_AT_APPLE_flags */ - len = strlen (apple_flags) + 1; + len = (int)strlen (apple_flags) + 1; p = frag_more (len); memcpy (p, apple_flags, len); } @@ -2018,7 +2022,7 @@ struct frchain *ranges_section) /* DW_AT_producer */ sprintf (producer, "%s %s, %s", APPLE_INC_VERSION, apple_version, version_string); - len = strlen (producer) + 1; + len = (int)strlen (producer) + 1; p = frag_more (len); memcpy (p, producer, len); @@ -2049,7 +2053,7 @@ struct frchain *ranges_section) out_uleb128 (2); /* DW_AT_name */ - len = strlen (subs->name) + 1; + len = (int)strlen (subs->name) + 1; p = frag_more (len); memcpy (p, subs->name, len); @@ -2091,7 +2095,7 @@ struct frchain *ranges_section) { n_sect = subs->symbol->sy_nlist.n_sect; frag = last_frag_for_seg (n_sect); - end = symbol_temp_new (n_sect, get_frag_fix (frag, n_sect), frag); + end = symbol_temp_new (n_sect, (valueT)get_frag_fix(frag,n_sect),frag); } memset(&expr, '\0', sizeof(expr)); expr.X_op = O_symbol; diff --git a/cctools/as/expr.c b/cctools/as/expr.c index 375187f..9f8fb90 100644 --- a/cctools/as/expr.c +++ b/cctools/as/expr.c @@ -1365,7 +1365,7 @@ expressionS *expressionP) /* Deliver result here. */ while(!fail && frag != NULL && frag != add_symbol->sy_frag){ if(frag->fr_type == rs_align) - size = rnd(size + frag->fr_fix, + size = rnd32(size + frag->fr_fix, 1 << frag->fr_offset); else if(frag->fr_type == rs_fill) size += frag->fr_fix + diff --git a/cctools/as/fixes.c b/cctools/as/fixes.c index 32a685b..c55620a 100644 --- a/cctools/as/fixes.c +++ b/cctools/as/fixes.c @@ -133,7 +133,7 @@ fix_new_exp (fragS *frag, /* Which frag? */ { symbolS *add = NULL; symbolS *sub = NULL; - offsetT off = 0; + signed_target_addr_t off = 0; switch (exp->X_op) { @@ -187,7 +187,7 @@ fix_new_exp (fragS *frag, /* Which frag? */ add = exp->X_add_symbol; /* Fall through. */ case O_constant: - off = exp->X_add_number; + off = (signed_target_addr_t)exp->X_add_number; break; default: diff --git a/cctools/as/flonum-copy.c b/cctools/as/flonum-copy.c index 13c8090..12cc68c 100644 --- a/cctools/as/flonum-copy.c +++ b/cctools/as/flonum-copy.c @@ -25,8 +25,8 @@ flonum_copy( FLONUM_TYPE *in, FLONUM_TYPE *out) { - int in_length; /* 0 origin */ - int out_length; /* 0 origin */ + long in_length; /* 0 origin */ + long out_length; /* 0 origin */ out -> sign = in -> sign; in_length = in -> leader - in -> low; @@ -61,14 +61,14 @@ FLONUM_TYPE *out) } else { - int shorten; /* 1-origin. Number of littlenums we drop. */ + long shorten; /* 1-origin. Number of littlenums we drop. */ shorten = in_length - out_length; /* Assume out_length >= 0 ! */ memcpy((char *)(out->low), (char *)(in->low + shorten), (int)((out_length + 1) * sizeof(LITTLENUM_TYPE))); out -> leader = out -> high; - out -> exponent = in -> exponent + shorten; + out -> exponent = (int32_t)(in -> exponent + shorten); } } /* if any significant bits */ } diff --git a/cctools/as/flonum-mult.c b/cctools/as/flonum-mult.c index e490d04..9a62de1 100644 --- a/cctools/as/flonum-mult.c +++ b/cctools/as/flonum-mult.c @@ -78,21 +78,21 @@ const_FLONUM_TYPE *a, FLONUM_TYPE *b, FLONUM_TYPE *product) { - int size_of_a; /* 0 origin */ - int size_of_b; /* 0 origin */ - int size_of_product; /* 0 origin */ - int size_of_sum; /* 0 origin */ - int extra_product_positions;/* 1 origin */ + long size_of_a; /* 0 origin */ + long size_of_b; /* 0 origin */ + long size_of_product; /* 0 origin */ + long size_of_sum; /* 0 origin */ + long extra_product_positions;/* 1 origin */ uint32_t work; uint32_t carry; int32_t exponent; LITTLENUM_TYPE * q; int32_t significant; /* TRUE when we emit a non-0 littlenum */ /* ForTran accent follows. */ - int P; /* Scan product low-order -> high. */ - int N; /* As in sum above. */ - int A; /* Which [] of a? */ - int B; /* Which [] of b? */ + long P; /* Scan product low-order -> high. */ + long N; /* As in sum above. */ + long A; /* Which [] of a? */ + long B; /* Which [] of b? */ if((a->sign!='-' && a->sign!='+') || (b->sign!='-' && b->sign!='+')) { /* ... diff --git a/cctools/as/frags.c b/cctools/as/frags.c index dd6cba8..9c8c9f6 100644 --- a/cctools/as/frags.c +++ b/cctools/as/frags.c @@ -18,6 +18,7 @@ along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include +#include /* cctools-port: for intptr_t */ #include "as.h" #include "sections.h" #include "obstack.h" @@ -67,7 +68,7 @@ unsigned int nchars) } if ((int)(obstack_room(&frags)) < nchars) { unsigned int n,oldn; - int32_t oldc; + size_t oldc; frag_wane (frag_now); frag_new (0); @@ -113,14 +114,16 @@ int old_frags_var_max_size) /* Number of chars (already allocated on obstack register frchainS * frchP; int32_t tmp; /* JF */ + if(frags.chunk_size == 0){ know(flagseen['n']); as_fatal("with -n a section directive must be seen before assembly " "can begin"); } - - frag_now->fr_fix = (char *) (obstack_next_free (&frags)) - - (frag_now->fr_literal) - old_frags_var_max_size; + /* cctools-port: Added (intptr_t) cast to silence warning */ + frag_now->fr_fix = (int)(intptr_t)((char *) (obstack_next_free (&frags)) - + (long)(frag_now->fr_literal) - + old_frags_var_max_size); /* Fix up old frag's fr_fix. */ (void)obstack_finish (&frags); @@ -132,7 +135,7 @@ int old_frags_var_max_size) /* Number of chars (already allocated on obstack former_last_fragP = frchP->frch_last; know (former_last_fragP); know (former_last_fragP == frag_now); - obstack_blank (&frags, SIZEOF_STRUCT_FRAG); + obstack_blank (&frags, (int)SIZEOF_STRUCT_FRAG); /* We expect this will begin at a correct */ /* boundary for a struct. */ tmp=obstack_alignment_mask(&frags); diff --git a/cctools/as/i386.c b/cctools/as/i386.c index 40fa36f..13bdc7f 100644 --- a/cctools/as/i386.c +++ b/cctools/as/i386.c @@ -886,7 +886,7 @@ static void set_code_flag ( uintptr_t value) { - flag_code = value; + flag_code = (enum flag_code)value; cpu_arch_flags &= ~(Cpu64 | CpuNo64); cpu_arch_flags |= (flag_code == CODE_64BIT ? Cpu64 : CpuNo64); #if NeXT_MOD @@ -908,7 +908,7 @@ static void set_16bit_gcc_code_flag ( uintptr_t new_code_flag) { - flag_code = new_code_flag; + flag_code = (enum flag_code)new_code_flag; cpu_arch_flags &= ~(Cpu64 | CpuNo64); cpu_arch_flags |= (flag_code == CODE_64BIT ? Cpu64 : CpuNo64); stackop_size = LONG_MNEM_SUFFIX; @@ -941,7 +941,7 @@ uintptr_t syntax_flag) } demand_empty_rest_of_line (); - intel_syntax = syntax_flag; + intel_syntax = (int)syntax_flag; if (ask_naked_reg == 0) #ifdef NeXT_MOD @@ -1785,7 +1785,7 @@ md_assemble (line) 68 /* N_SLINE */, text_nsect, logical_input_line /* n_desc, line number */, - obstack_next_free(&frags) - frag_now->fr_literal, + (valueT)(obstack_next_free(&frags) - frag_now->fr_literal), frag_now); } #endif /* NeXT_MOD */ @@ -3444,13 +3444,13 @@ output_branch () } p = frag_more (4); #if ARCH64 - fix_new (frag_now, p - frag_now->fr_literal, 4, + fix_new (frag_now, (int)(p - frag_now->fr_literal), 4, i.op[0].disps->X_add_symbol, i.op[0].disps->X_subtract_symbol, i.op[0].disps->X_add_number, 1, 1, X86_64_RELOC_BRANCH); #else - fix_new (frag_now, p - frag_now->fr_literal, 4, + fix_new (frag_now, (int)(p - frag_now->fr_literal), 4, i.op[0].disps->X_add_symbol, i.op[0].disps->X_subtract_symbol, - i.op[0].disps->X_add_number, 1, 1, 0); + (int)(i.op[0].disps->X_add_number), 1, 1, 0); #endif } else #endif @@ -3488,11 +3488,12 @@ output_branch () #endif #if !ARCH64 - frag_var (rs_machine_dependent, 5, 1, subtype, sym, off, p); + frag_var (rs_machine_dependent, 5, 1, subtype, sym, (int)off, p); #else /* 1 possible extra opcode + 4 byte displacement go in var part. Pass reloc in fr_var. */ - frag_var (rs_machine_dependent, 5, i.reloc[0], subtype, sym, off, p); + frag_var (rs_machine_dependent, 5, i.reloc[0], subtype, sym, + (int)off, p); #endif } } @@ -3559,23 +3560,23 @@ output_jump () !is_local_symbol(i.op[0].disps->X_add_symbol) || flagseen ['L'])) #if ARCH64 - fixP = fix_new (frag_now, p - frag_now->fr_literal, size, + fixP = fix_new (frag_now, (int)(p - frag_now->fr_literal), size, i.op[0].disps->X_add_symbol, i.op[0].disps->X_subtract_symbol, i.op[0].disps->X_add_number, 1, 1, X86_64_RELOC_BRANCH); #else - fixP = fix_new (frag_now, p - frag_now->fr_literal, size, + fixP = fix_new (frag_now, (int)(p - frag_now->fr_literal), size, i.op[0].disps->X_add_symbol, i.op[0].disps->X_subtract_symbol, - i.op[0].disps->X_add_number, 1, 1, 0); + (int)i.op[0].disps->X_add_number, 1, 1, 0); #endif else #if ARCH64 - fixP = fix_new (frag_now, p - frag_now->fr_literal, size, + fixP = fix_new (frag_now, (int)(p - frag_now->fr_literal), size, i.op[0].disps->X_add_symbol, i.op[0].disps->X_subtract_symbol, i.op[0].disps->X_add_number, 1, 0, X86_64_RELOC_BRANCH); #else - fixP = fix_new (frag_now, p - frag_now->fr_literal, size, + fixP = fix_new (frag_now, (int)(p - frag_now->fr_literal), size, i.op[0].disps->X_add_symbol, i.op[0].disps->X_subtract_symbol, - i.op[0].disps->X_add_number, 1, 0, 0); + (int)i.op[0].disps->X_add_number, 1, 0, 0); #endif #else fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size, @@ -3647,15 +3648,15 @@ output_interseg_jump () else { #ifdef NeXT_MOD #if ARCH64 - fix_new (frag_now, p - frag_now->fr_literal, size, + fix_new (frag_now, (int)(p - frag_now->fr_literal), size, i.op[1].imms->X_add_symbol, i.op[1].imms->X_subtract_symbol, i.op[1].imms->X_add_number, 0, 0, X86_64_RELOC_BRANCH); #else - fix_new (frag_now, p - frag_now->fr_literal, size, + fix_new (frag_now, (int)(p - frag_now->fr_literal), size, i.op[1].imms->X_add_symbol, i.op[1].imms->X_subtract_symbol, - i.op[1].imms->X_add_number, 0, 0, 0); + (int)i.op[1].imms->X_add_number, 0, 0, 0); #endif #else fix_new_exp (frag_now, p - frag_now->fr_literal, size, @@ -3903,9 +3904,9 @@ output_disp (insn_start_frag, insn_start_off) p = frag_more (size); #if !ARCH64 - fix_new (frag_now, p - frag_now->fr_literal, size, + fix_new (frag_now, (int)(p - frag_now->fr_literal), size, i.op[n].disps->X_add_symbol, i.op[n].disps->X_subtract_symbol, - i.op[n].disps->X_add_number, 0, 0, i.reloc[n]); + (int)i.op[n].disps->X_add_number, 0, 0, i.reloc[n]); #else #ifdef NeXT_MOD /* @@ -3920,7 +3921,7 @@ output_disp (insn_start_frag, insn_start_off) i.reloc[n] == NO_RELOC && i.op[n].disps->X_add_symbol != NULL && i.op[n].disps->X_subtract_symbol != NULL){ - fix_new (frag_now, p - frag_now->fr_literal, size, + fix_new (frag_now, (int)(p - frag_now->fr_literal), size, i.op[n].disps->X_add_symbol, i.op[n].disps->X_subtract_symbol, i.op[n].disps->X_add_number, pcrel, 0, @@ -3942,7 +3943,7 @@ output_disp (insn_start_frag, insn_start_off) i.op[n].disps->X_add_symbol != NULL && i.op[n].disps->X_add_symbol->expression != NULL && i.op[n].disps->X_subtract_symbol == NULL){ - fix_new (frag_now, p - frag_now->fr_literal, size, + fix_new (frag_now, (int)(p - frag_now->fr_literal), size, i.op[n].disps->X_add_symbol, NULL, i.op[n].disps->X_add_number, pcrel, 0, X86_64_RELOC_UNSIGNED); @@ -3983,7 +3984,7 @@ output_disp (insn_start_frag, insn_start_off) } #endif #ifdef NeXT_MOD - fix_new (frag_now, p - frag_now->fr_literal, size, + fix_new (frag_now, (int)(p - frag_now->fr_literal), size, i.op[n].disps->X_add_symbol, i.op[n].disps->X_subtract_symbol, i.op[n].disps->X_add_number, pcrel, 0, reloc_type); #else @@ -4053,10 +4054,10 @@ output_imm (insn_start_frag, insn_start_off) p = frag_more (size); #if !ARCH64 - fix_new (frag_now, p - frag_now->fr_literal, size, + fix_new (frag_now, (int)(p - frag_now->fr_literal), size, i.op[n].imms->X_add_symbol, i.op[n].imms->X_subtract_symbol, - i.op[n].imms->X_add_number, 0, 0, 0); + (int)i.op[n].imms->X_add_number, 0, 0, 0); #else #ifdef NeXT_MOD /* @@ -4071,7 +4072,7 @@ output_imm (insn_start_frag, insn_start_off) i.reloc[n] == NO_RELOC && i.op[n].imms->X_add_symbol != NULL && i.op[n].imms->X_subtract_symbol != NULL){ - fix_new (frag_now, p - frag_now->fr_literal, size, + fix_new (frag_now, (int)(p - frag_now->fr_literal), size, i.op[n].imms->X_add_symbol, i.op[n].imms->X_subtract_symbol, i.op[n].imms->X_add_number, 0, 0, @@ -4156,7 +4157,7 @@ output_imm (insn_start_frag, insn_start_off) } #endif #ifdef NeXT_MOD - fix_new (frag_now, p - frag_now->fr_literal, size, + fix_new (frag_now, (int)(p - frag_now->fr_literal), size, i.op[n].imms->X_add_symbol, i.op[n].imms->X_subtract_symbol, i.op[n].imms->X_add_number, 0, 0, reloc_type); @@ -4244,7 +4245,7 @@ lex_got (reloc, adjust) { int len; - len = strlen (gotrel[j].str); + len = (int)strlen (gotrel[j].str); if (strncasecmp (cp + 1, gotrel[j].str, len) == 0) { if (gotrel[j].rel[(unsigned int) flag_code] != 0) @@ -4265,7 +4266,7 @@ lex_got (reloc, adjust) errors like foo@GOTOFF1 will be detected. */ /* The length of the first part of our input line. */ - first = cp - input_line_pointer; + first = (int)(cp - input_line_pointer); /* The second part goes from after the reloc token until (and including) an end_of_line char. Don't use strlen @@ -4277,7 +4278,7 @@ lex_got (reloc, adjust) for (cp = past_reloc; !is_end_of_line[(unsigned char) *cp++]; ) #endif ; - second = cp - past_reloc; + second = (int)(cp - past_reloc); /* Allocate and copy string. The trailing NUL shouldn't be necessary, but be safe. */ @@ -4819,7 +4820,7 @@ i386_operand (operand_string) char *operand_string; { const reg_entry *r; - char *end_op; + char *end_op = NULL; char *op_string = operand_string; if (is_space_char (*op_string)) @@ -5423,6 +5424,8 @@ int md_long_jump_size = 5; /* Size of relocation record. */ const int md_reloc_size = 8; +void md_create_short_jump (char *ptr, addressT from_addr, addressT to_addr, fragS *, symbolS *to_symbol); + void md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) char *ptr; @@ -5438,6 +5441,8 @@ md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) md_number_to_chars (ptr + 1, (valueT) offset, 1); } +void md_create_long_jump (char *ptr, addressT from_addr, addressT to_addr, fragS *, symbolS *to_symbol); + void md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) char *ptr; @@ -5878,6 +5883,8 @@ md_parse_option (c, arg) return 1; } +void md_show_usage (FILE *stream); + void md_show_usage (stream) FILE *stream; @@ -6004,6 +6011,8 @@ md_undefined_symbol (name) /* Round up a section size to the appropriate boundary. */ +valueT md_section_align (segT segment, valueT size); + valueT md_section_align (segment, size) segT segment ATTRIBUTE_UNUSED; @@ -6038,7 +6047,7 @@ md_pcrel_from (fixP) #endif fixS *fixP; { - return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address; + return (int32_t)(fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address); } #ifndef I386COFF @@ -6176,7 +6185,7 @@ x86_64_fixup_symbol(fixS *fix, int nsect, symbolS **sym) if (prev_symbol != NULL) { /* Replace sym and adjust offset. */ - offset = (*sym)->sy_value - prev_symbol->sy_value; + offset = (int32_t)((*sym)->sy_value - prev_symbol->sy_value); *sym = prev_symbol; } else if (fix->fx_pcrel) diff --git a/cctools/as/i386/Makefile.in b/cctools/as/i386/Makefile.in new file mode 100644 index 0000000..baaaa66 --- /dev/null +++ b/cctools/as/i386/Makefile.in @@ -0,0 +1,849 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +libexec_PROGRAMS = i386-as$(EXEEXT) +subdir = as/i386 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(libexecdir)" +PROGRAMS = $(libexec_PROGRAMS) +am__dirstamp = $(am__leading_dot)dirstamp +am_i386_as_OBJECTS = ../i386_as-app.$(OBJEXT) ../i386_as-as.$(OBJEXT) \ + ../i386_as-atof-generic.$(OBJEXT) \ + ../i386_as-atof-ieee.$(OBJEXT) ../i386_as-expr.$(OBJEXT) \ + ../i386_as-fixes.$(OBJEXT) ../i386_as-flonum-const.$(OBJEXT) \ + ../i386_as-flonum-copy.$(OBJEXT) \ + ../i386_as-flonum-mult.$(OBJEXT) ../i386_as-frags.$(OBJEXT) \ + ../i386_as-hash.$(OBJEXT) ../i386_as-hex-value.$(OBJEXT) \ + ../i386_as-input-file.$(OBJEXT) \ + ../i386_as-input-scrub.$(OBJEXT) ../i386_as-layout.$(OBJEXT) \ + ../i386_as-messages.$(OBJEXT) ../i386_as-obstack.$(OBJEXT) \ + ../i386_as-read.$(OBJEXT) ../i386_as-sections.$(OBJEXT) \ + ../i386_as-symbols.$(OBJEXT) ../i386_as-write_object.$(OBJEXT) \ + ../i386_as-xmalloc.$(OBJEXT) ../i386_as-dwarf2dbg.$(OBJEXT) \ + ../i386_as-i386.$(OBJEXT) +i386_as_OBJECTS = $(am_i386_as_OBJECTS) +i386_as_DEPENDENCIES = $(top_builddir)/libstuff/libstuff.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +i386_as_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(i386_as_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(i386_as_SOURCES) +DIST_SOURCES = $(i386_as_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +i386_as_LDADD = \ + $(top_builddir)/libstuff/libstuff.la + +i386_as_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -I$(top_srcdir)/libstuff -I$(top_srcdir)/as $(WARNINGS) $(LTO_DEF) -DNeXT_MOD -DASLIBEXECDIR="\"$(ASLIBEXECDIR)/\"" -D__DARWIN_UNIX03 -DI386 -Di486 -Di586 -Di686 -UPPC $(ENDIAN_FLAG) +i386_as_SOURCES = ../app.c ../as.c ../atof-generic.c ../atof-ieee.c ../expr.c ../fixes.c ../flonum-const.c \ + ../flonum-copy.c ../flonum-mult.c ../frags.c ../hash.c ../hex-value.c ../input-file.c \ + ../input-scrub.c ../layout.c ../messages.c ../obstack.c ../read.c ../sections.c \ + ../symbols.c ../write_object.c ../xmalloc.c ../dwarf2dbg.c ../i386.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps as/i386/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps as/i386/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libexecPROGRAMS: $(libexec_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-libexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libexecdir)" && rm -f $$files + +clean-libexecPROGRAMS: + @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +../$(am__dirstamp): + @$(MKDIR_P) .. + @: > ../$(am__dirstamp) +../i386_as-app.$(OBJEXT): ../$(am__dirstamp) +../i386_as-as.$(OBJEXT): ../$(am__dirstamp) +../i386_as-atof-generic.$(OBJEXT): ../$(am__dirstamp) +../i386_as-atof-ieee.$(OBJEXT): ../$(am__dirstamp) +../i386_as-expr.$(OBJEXT): ../$(am__dirstamp) +../i386_as-fixes.$(OBJEXT): ../$(am__dirstamp) +../i386_as-flonum-const.$(OBJEXT): ../$(am__dirstamp) +../i386_as-flonum-copy.$(OBJEXT): ../$(am__dirstamp) +../i386_as-flonum-mult.$(OBJEXT): ../$(am__dirstamp) +../i386_as-frags.$(OBJEXT): ../$(am__dirstamp) +../i386_as-hash.$(OBJEXT): ../$(am__dirstamp) +../i386_as-hex-value.$(OBJEXT): ../$(am__dirstamp) +../i386_as-input-file.$(OBJEXT): ../$(am__dirstamp) +../i386_as-input-scrub.$(OBJEXT): ../$(am__dirstamp) +../i386_as-layout.$(OBJEXT): ../$(am__dirstamp) +../i386_as-messages.$(OBJEXT): ../$(am__dirstamp) +../i386_as-obstack.$(OBJEXT): ../$(am__dirstamp) +../i386_as-read.$(OBJEXT): ../$(am__dirstamp) +../i386_as-sections.$(OBJEXT): ../$(am__dirstamp) +../i386_as-symbols.$(OBJEXT): ../$(am__dirstamp) +../i386_as-write_object.$(OBJEXT): ../$(am__dirstamp) +../i386_as-xmalloc.$(OBJEXT): ../$(am__dirstamp) +../i386_as-dwarf2dbg.$(OBJEXT): ../$(am__dirstamp) +../i386_as-i386.$(OBJEXT): ../$(am__dirstamp) + +i386-as$(EXEEXT): $(i386_as_OBJECTS) $(i386_as_DEPENDENCIES) $(EXTRA_i386_as_DEPENDENCIES) + @rm -f i386-as$(EXEEXT) + $(AM_V_CCLD)$(i386_as_LINK) $(i386_as_OBJECTS) $(i386_as_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f ../*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +../i386_as-app.o: ../app.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-app.o `test -f '../app.c' || echo '$(srcdir)/'`../app.c + +../i386_as-app.obj: ../app.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-app.obj `if test -f '../app.c'; then $(CYGPATH_W) '../app.c'; else $(CYGPATH_W) '$(srcdir)/../app.c'; fi` + +../i386_as-as.o: ../as.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-as.o `test -f '../as.c' || echo '$(srcdir)/'`../as.c + +../i386_as-as.obj: ../as.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-as.obj `if test -f '../as.c'; then $(CYGPATH_W) '../as.c'; else $(CYGPATH_W) '$(srcdir)/../as.c'; fi` + +../i386_as-atof-generic.o: ../atof-generic.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-atof-generic.o `test -f '../atof-generic.c' || echo '$(srcdir)/'`../atof-generic.c + +../i386_as-atof-generic.obj: ../atof-generic.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-atof-generic.obj `if test -f '../atof-generic.c'; then $(CYGPATH_W) '../atof-generic.c'; else $(CYGPATH_W) '$(srcdir)/../atof-generic.c'; fi` + +../i386_as-atof-ieee.o: ../atof-ieee.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-atof-ieee.o `test -f '../atof-ieee.c' || echo '$(srcdir)/'`../atof-ieee.c + +../i386_as-atof-ieee.obj: ../atof-ieee.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-atof-ieee.obj `if test -f '../atof-ieee.c'; then $(CYGPATH_W) '../atof-ieee.c'; else $(CYGPATH_W) '$(srcdir)/../atof-ieee.c'; fi` + +../i386_as-expr.o: ../expr.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-expr.o `test -f '../expr.c' || echo '$(srcdir)/'`../expr.c + +../i386_as-expr.obj: ../expr.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-expr.obj `if test -f '../expr.c'; then $(CYGPATH_W) '../expr.c'; else $(CYGPATH_W) '$(srcdir)/../expr.c'; fi` + +../i386_as-fixes.o: ../fixes.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-fixes.o `test -f '../fixes.c' || echo '$(srcdir)/'`../fixes.c + +../i386_as-fixes.obj: ../fixes.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-fixes.obj `if test -f '../fixes.c'; then $(CYGPATH_W) '../fixes.c'; else $(CYGPATH_W) '$(srcdir)/../fixes.c'; fi` + +../i386_as-flonum-const.o: ../flonum-const.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-flonum-const.o `test -f '../flonum-const.c' || echo '$(srcdir)/'`../flonum-const.c + +../i386_as-flonum-const.obj: ../flonum-const.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-flonum-const.obj `if test -f '../flonum-const.c'; then $(CYGPATH_W) '../flonum-const.c'; else $(CYGPATH_W) '$(srcdir)/../flonum-const.c'; fi` + +../i386_as-flonum-copy.o: ../flonum-copy.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-flonum-copy.o `test -f '../flonum-copy.c' || echo '$(srcdir)/'`../flonum-copy.c + +../i386_as-flonum-copy.obj: ../flonum-copy.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-flonum-copy.obj `if test -f '../flonum-copy.c'; then $(CYGPATH_W) '../flonum-copy.c'; else $(CYGPATH_W) '$(srcdir)/../flonum-copy.c'; fi` + +../i386_as-flonum-mult.o: ../flonum-mult.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-flonum-mult.o `test -f '../flonum-mult.c' || echo '$(srcdir)/'`../flonum-mult.c + +../i386_as-flonum-mult.obj: ../flonum-mult.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-flonum-mult.obj `if test -f '../flonum-mult.c'; then $(CYGPATH_W) '../flonum-mult.c'; else $(CYGPATH_W) '$(srcdir)/../flonum-mult.c'; fi` + +../i386_as-frags.o: ../frags.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-frags.o `test -f '../frags.c' || echo '$(srcdir)/'`../frags.c + +../i386_as-frags.obj: ../frags.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-frags.obj `if test -f '../frags.c'; then $(CYGPATH_W) '../frags.c'; else $(CYGPATH_W) '$(srcdir)/../frags.c'; fi` + +../i386_as-hash.o: ../hash.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-hash.o `test -f '../hash.c' || echo '$(srcdir)/'`../hash.c + +../i386_as-hash.obj: ../hash.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-hash.obj `if test -f '../hash.c'; then $(CYGPATH_W) '../hash.c'; else $(CYGPATH_W) '$(srcdir)/../hash.c'; fi` + +../i386_as-hex-value.o: ../hex-value.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-hex-value.o `test -f '../hex-value.c' || echo '$(srcdir)/'`../hex-value.c + +../i386_as-hex-value.obj: ../hex-value.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-hex-value.obj `if test -f '../hex-value.c'; then $(CYGPATH_W) '../hex-value.c'; else $(CYGPATH_W) '$(srcdir)/../hex-value.c'; fi` + +../i386_as-input-file.o: ../input-file.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-input-file.o `test -f '../input-file.c' || echo '$(srcdir)/'`../input-file.c + +../i386_as-input-file.obj: ../input-file.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-input-file.obj `if test -f '../input-file.c'; then $(CYGPATH_W) '../input-file.c'; else $(CYGPATH_W) '$(srcdir)/../input-file.c'; fi` + +../i386_as-input-scrub.o: ../input-scrub.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-input-scrub.o `test -f '../input-scrub.c' || echo '$(srcdir)/'`../input-scrub.c + +../i386_as-input-scrub.obj: ../input-scrub.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-input-scrub.obj `if test -f '../input-scrub.c'; then $(CYGPATH_W) '../input-scrub.c'; else $(CYGPATH_W) '$(srcdir)/../input-scrub.c'; fi` + +../i386_as-layout.o: ../layout.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-layout.o `test -f '../layout.c' || echo '$(srcdir)/'`../layout.c + +../i386_as-layout.obj: ../layout.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-layout.obj `if test -f '../layout.c'; then $(CYGPATH_W) '../layout.c'; else $(CYGPATH_W) '$(srcdir)/../layout.c'; fi` + +../i386_as-messages.o: ../messages.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-messages.o `test -f '../messages.c' || echo '$(srcdir)/'`../messages.c + +../i386_as-messages.obj: ../messages.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-messages.obj `if test -f '../messages.c'; then $(CYGPATH_W) '../messages.c'; else $(CYGPATH_W) '$(srcdir)/../messages.c'; fi` + +../i386_as-obstack.o: ../obstack.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-obstack.o `test -f '../obstack.c' || echo '$(srcdir)/'`../obstack.c + +../i386_as-obstack.obj: ../obstack.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-obstack.obj `if test -f '../obstack.c'; then $(CYGPATH_W) '../obstack.c'; else $(CYGPATH_W) '$(srcdir)/../obstack.c'; fi` + +../i386_as-read.o: ../read.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-read.o `test -f '../read.c' || echo '$(srcdir)/'`../read.c + +../i386_as-read.obj: ../read.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-read.obj `if test -f '../read.c'; then $(CYGPATH_W) '../read.c'; else $(CYGPATH_W) '$(srcdir)/../read.c'; fi` + +../i386_as-sections.o: ../sections.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-sections.o `test -f '../sections.c' || echo '$(srcdir)/'`../sections.c + +../i386_as-sections.obj: ../sections.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-sections.obj `if test -f '../sections.c'; then $(CYGPATH_W) '../sections.c'; else $(CYGPATH_W) '$(srcdir)/../sections.c'; fi` + +../i386_as-symbols.o: ../symbols.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-symbols.o `test -f '../symbols.c' || echo '$(srcdir)/'`../symbols.c + +../i386_as-symbols.obj: ../symbols.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-symbols.obj `if test -f '../symbols.c'; then $(CYGPATH_W) '../symbols.c'; else $(CYGPATH_W) '$(srcdir)/../symbols.c'; fi` + +../i386_as-write_object.o: ../write_object.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-write_object.o `test -f '../write_object.c' || echo '$(srcdir)/'`../write_object.c + +../i386_as-write_object.obj: ../write_object.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-write_object.obj `if test -f '../write_object.c'; then $(CYGPATH_W) '../write_object.c'; else $(CYGPATH_W) '$(srcdir)/../write_object.c'; fi` + +../i386_as-xmalloc.o: ../xmalloc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-xmalloc.o `test -f '../xmalloc.c' || echo '$(srcdir)/'`../xmalloc.c + +../i386_as-xmalloc.obj: ../xmalloc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-xmalloc.obj `if test -f '../xmalloc.c'; then $(CYGPATH_W) '../xmalloc.c'; else $(CYGPATH_W) '$(srcdir)/../xmalloc.c'; fi` + +../i386_as-dwarf2dbg.o: ../dwarf2dbg.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-dwarf2dbg.o `test -f '../dwarf2dbg.c' || echo '$(srcdir)/'`../dwarf2dbg.c + +../i386_as-dwarf2dbg.obj: ../dwarf2dbg.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-dwarf2dbg.obj `if test -f '../dwarf2dbg.c'; then $(CYGPATH_W) '../dwarf2dbg.c'; else $(CYGPATH_W) '$(srcdir)/../dwarf2dbg.c'; fi` + +../i386_as-i386.o: ../i386.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-i386.o `test -f '../i386.c' || echo '$(srcdir)/'`../i386.c + +../i386_as-i386.obj: ../i386.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(i386_as_CFLAGS) $(CFLAGS) -c -o ../i386_as-i386.obj `if test -f '../i386.c'; then $(CYGPATH_W) '../i386.c'; else $(CYGPATH_W) '$(srcdir)/../i386.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(libexecdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f ../$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libexecPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libexecPROGRAMS + +.MAKE: install-am install-exec-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libexecPROGRAMS clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-exec-hook install-html install-html-am \ + install-info install-info-am install-libexecPROGRAMS \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-libexecPROGRAMS + +.PRECIOUS: Makefile + +install-exec-hook: + mkdir -p $(DESTDIR)$(libexecdir)/as/i386 + mv $(DESTDIR)$(libexecdir)/*i386-as* $(DESTDIR)$(libexecdir)/as/i386/as + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/as/input-file.c b/cctools/as/input-file.c index f7ec600..4bbd177 100644 --- a/cctools/as/input-file.c +++ b/cctools/as/input-file.c @@ -29,6 +29,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include +#include /* cctools-port: For bcmp, bzero ... */ #include #include #include "input-file.h" @@ -151,7 +152,7 @@ char *where, /* Where to place 1st character of new buffer. */ int *give_next_size) { char * return_value; /* -> Last char of what we read, + 1. */ - register int size; + register size_t size; *give_next_size = BUFFER_SIZE; if (f_in == (FILE *)0) diff --git a/cctools/as/input-scrub.c b/cctools/as/input-scrub.c index 69fc696..159ee8f 100644 --- a/cctools/as/input-scrub.c +++ b/cctools/as/input-scrub.c @@ -141,7 +141,7 @@ char *filename) if (filename[0]) { char *p; - int len; + long len; p = strrchr(filename, '/'); if (p != NULL && p[1] != '\0') @@ -197,7 +197,7 @@ get_more: ++ p; if (p <= buffer_start + BEFORE_SIZE) { - int new; + long new; new = limit - (buffer_start + BEFORE_SIZE + partial_size); partial_size += new; @@ -219,7 +219,7 @@ get_more: goto get_more; } partial_where = p; - partial_size = limit - p; + partial_size = (int)(limit - p); memcpy(save_source, partial_where, (int)AFTER_SIZE); memcpy(partial_where, AFTER_STRING, (int)AFTER_SIZE); } diff --git a/cctools/as/layout.c b/cctools/as/layout.c index ca561f4..2dced07 100644 --- a/cctools/as/layout.c +++ b/cctools/as/layout.c @@ -117,8 +117,8 @@ void) * If there is any current frag close it off. */ if(frag_now != NULL && frag_now->fr_fix == 0){ - frag_now->fr_fix = obstack_next_free(&frags) - - frag_now->fr_literal; + frag_now->fr_fix = (int32_t)(obstack_next_free(&frags) - + frag_now->fr_literal); frag_wane(frag_now); } @@ -139,7 +139,7 @@ void) /* * Make a fresh frag for the last frag. */ - frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG); + frag_now = (fragS *)obstack_alloc(&frags, (int)SIZEOF_STRUCT_FRAG); memset(frag_now, '\0', SIZEOF_STRUCT_FRAG); frag_now->fr_next = NULL; (void)obstack_finish(&frags); @@ -165,7 +165,7 @@ void) { struct frchain *frchainP; fragS *fragP; - relax_addressT slide, tmp; + uint64_t slide, tmp; symbolS *symbolP; uint32_t nbytes, fill_size, repeat_expression, partial_bytes, layout_pass; uint32_t section_type; @@ -179,8 +179,8 @@ void) * If there is any current frag close it off. */ if(frag_now != NULL && frag_now->fr_fix == 0){ - frag_now->fr_fix = obstack_next_free(&frags) - - frag_now->fr_literal; + frag_now->fr_fix = (int32_t)(obstack_next_free(&frags) - + frag_now->fr_literal); frag_wane(frag_now); } @@ -201,7 +201,7 @@ void) /* * Make a fresh frag for the last frag. */ - frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG); + frag_now = (fragS *)obstack_alloc(&frags, (int)SIZEOF_STRUCT_FRAG); memset(frag_now, '\0', SIZEOF_STRUCT_FRAG); frag_now->fr_next = NULL; (void)obstack_finish(&frags); @@ -346,9 +346,9 @@ void) * as the fill_size * repeat_expression + partial_bytes. */ know(fragP->fr_next != NULL); - nbytes = fragP->fr_next->fr_address - - fragP->fr_address - - fragP->fr_fix; + nbytes = (uint32_t)(fragP->fr_next->fr_address - + fragP->fr_address - + fragP->fr_fix); if((int)nbytes < 0){ as_warn("rs_org invalid, dot past value by %d bytes", nbytes); @@ -448,8 +448,8 @@ void) value += expression->X_add_number; } else{ - value = fragP->fr_symbol->sy_nlist.n_value + - fragP->fr_address; + value = (valueT)(fragP->fr_symbol->sy_nlist.n_value + + fragP->fr_address); } #endif @@ -901,7 +901,7 @@ down: * a relocation entry if required. */ md_number_to_imm((unsigned char *)place, value, size, fixP, nsect); - fixP->fx_value = value; + fixP->fx_value = (int32_t)value; /* * If this is a non-lazy pointer section and this fix is for a @@ -1093,13 +1093,13 @@ int nsect) int32_t aim; #endif /* !defined(ARM) */ - int32_t growth; - uint32_t was_address; + uint64_t growth; + relax_addressT was_address; int32_t offset; symbolS *symbolP; int32_t target; - int32_t after; - uint32_t oldoff, newoff; + uint64_t after; + relax_addressT oldoff, newoff; int ret; ret = 0; @@ -1121,7 +1121,7 @@ int nsect) break; case rs_align: - offset = relax_align (address, (int) fragP->fr_offset); + offset = (int32_t)relax_align (address, (int) fragP->fr_offset); /* * If a maximum number of bytes to fill was specified for this * align (stored in fr_subtype) then check to see if this align @@ -1182,9 +1182,9 @@ int nsect) #ifdef ARM fragP->relax_marker ^= 1; #endif /* ARM */ - was_address = fragP->fr_address; + was_address = (relax_addressT)fragP->fr_address; fragP->fr_address += stretch; - address = fragP->fr_address; + address = (relax_addressT)fragP->fr_address; symbolP = fragP->fr_symbol; offset = fragP->fr_offset; switch(fragP->fr_type){ @@ -1258,7 +1258,7 @@ int nsect) is_down_range(fragP, symbolP->sy_frag)) target += stretch; } - aim = target - address - fragP->fr_fix; + aim = (int32_t)(target - address - fragP->fr_fix); if(aim < 0){ /* Look backwards. */ for(next_state = this_type->rlx_more; next_state; ){ @@ -1316,13 +1316,13 @@ int nsect) value += expression->X_add_number; } else{ - value = fragP->fr_symbol->sy_nlist.n_value + - fragP->fr_address; + value = (valueT)(fragP->fr_symbol->sy_nlist.n_value + + fragP->fr_address); } #endif size = sizeof_leb128 (value, fragP->fr_subtype); growth = size - fragP->fr_offset; - fragP->fr_offset = size; + fragP->fr_offset = (int32_t)size; } break; diff --git a/cctools/as/messages.c b/cctools/as/messages.c index 001a2a8..e56befa 100644 --- a/cctools/as/messages.c +++ b/cctools/as/messages.c @@ -236,5 +236,6 @@ const char *format, void sprint_value (char *buf, signed_expr_t val) { - sprintf (buf, "%qd", val); + /* cctools-port: Replaced 'qd' with 'lld' in format string */ + sprintf (buf, "%lld", val); } diff --git a/cctools/as/obstack.c b/cctools/as/obstack.c index 8da0b00..fdad59f 100644 --- a/cctools/as/obstack.c +++ b/cctools/as/obstack.c @@ -58,7 +58,7 @@ struct obstack *h, int size, int alignment, void *(*chunkfun)(size_t n), -void (*freefun)() ) +void (*freefun)(void*) ) { register struct _obstack_chunk* chunk; /* points to new chunk */ @@ -81,8 +81,8 @@ void (*freefun)() ) size = 4096 - extra; } - h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; - h->freefun = freefun; + h->chunkfun = (void* (*)(size_t))chunkfun; + h->freefun = (void (*)(void*))freefun; h->chunk_size = size; h->alignment_mask = alignment - 1; @@ -107,14 +107,14 @@ int length) register struct _obstack_chunk* old_chunk = h->chunk; register struct _obstack_chunk* new_chunk; register int32_t new_size; - register int obj_size = h->next_free - h->object_base; + register int obj_size = (int)(h->next_free - h->object_base); register int i; int already; /* Compute size for new chunk. */ new_size = (obj_size + length) + (obj_size >> 3) + 100; if (new_size < h->chunk_size) - new_size = h->chunk_size; + new_size = (int32_t)h->chunk_size; /* Allocate and initialize the new chunk. */ new_chunk = h->chunk = (*h->chunkfun) (new_size); @@ -145,7 +145,7 @@ int length) h->next_free = h->object_base + obj_size; } -#ifdef DEBUG +#ifdef DEBUG_DEAD_CODE /* Return nonzero if object OBJ has been allocated from obstack H. This is here for debugging. If you use it in a program, you are probably losing. */ @@ -187,7 +187,7 @@ POINTER obj) while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj)) { plp = lp -> prev; - (*h->freefun) (lp); + (*h->freefun)(lp); lp = plp; } if (lp) diff --git a/cctools/as/obstack.h b/cctools/as/obstack.h index 4b166db..63f830e 100644 --- a/cctools/as/obstack.h +++ b/cctools/as/obstack.h @@ -134,8 +134,8 @@ struct obstack /* control current object in current chunk */ char *chunk_limit; /* address of char after current chunk */ int temp; /* Temporary for some macros. */ int alignment_mask; /* Mask of alignment for each object. */ - struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */ - void (*freefun) (); /* User's function to free a chunk. */ + void *(*chunkfun)(size_t); /* User's fcn to allocate a chunk.*/ + void (*freefun)(void*); /* User's function to free a chunk. */ }; #ifdef __STDC__ @@ -177,7 +177,8 @@ int obstack_alignment_mask (struct obstack *obstack); int obstack_chunk_size (struct obstack *obstack); void _obstack_begin (struct obstack *h, int size, int alignment, - void * (*chunkfun)(size_t n), void (*freefun)()); + void * (*chunkfun)(size_t n), + void (*freefun)(void*)); void _obstack_newchunk (struct obstack *h, int length); #endif /* __STDC__ */ diff --git a/cctools/as/ppc/Makefile.in b/cctools/as/ppc/Makefile.in new file mode 100644 index 0000000..81ffa14 --- /dev/null +++ b/cctools/as/ppc/Makefile.in @@ -0,0 +1,848 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +libexec_PROGRAMS = ppc-as$(EXEEXT) +subdir = as/ppc +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(libexecdir)" +PROGRAMS = $(libexec_PROGRAMS) +am__dirstamp = $(am__leading_dot)dirstamp +am_ppc_as_OBJECTS = ../ppc_as-app.$(OBJEXT) ../ppc_as-as.$(OBJEXT) \ + ../ppc_as-atof-generic.$(OBJEXT) ../ppc_as-atof-ieee.$(OBJEXT) \ + ../ppc_as-expr.$(OBJEXT) ../ppc_as-fixes.$(OBJEXT) \ + ../ppc_as-flonum-const.$(OBJEXT) \ + ../ppc_as-flonum-copy.$(OBJEXT) \ + ../ppc_as-flonum-mult.$(OBJEXT) ../ppc_as-frags.$(OBJEXT) \ + ../ppc_as-hash.$(OBJEXT) ../ppc_as-hex-value.$(OBJEXT) \ + ../ppc_as-input-file.$(OBJEXT) ../ppc_as-input-scrub.$(OBJEXT) \ + ../ppc_as-layout.$(OBJEXT) ../ppc_as-messages.$(OBJEXT) \ + ../ppc_as-obstack.$(OBJEXT) ../ppc_as-read.$(OBJEXT) \ + ../ppc_as-sections.$(OBJEXT) ../ppc_as-symbols.$(OBJEXT) \ + ../ppc_as-write_object.$(OBJEXT) ../ppc_as-xmalloc.$(OBJEXT) \ + ../ppc_as-dwarf2dbg.$(OBJEXT) ../ppc_as-ppc.$(OBJEXT) +ppc_as_OBJECTS = $(am_ppc_as_OBJECTS) +ppc_as_DEPENDENCIES = $(top_builddir)/libstuff/libstuff.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +ppc_as_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ppc_as_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(ppc_as_SOURCES) +DIST_SOURCES = $(ppc_as_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ppc_as_LDADD = \ + $(top_builddir)/libstuff/libstuff.la + +ppc_as_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -I$(top_srcdir)/libstuff -I$(top_srcdir)/as $(WARNINGS) $(LTO_DEF) -DNeXT_MOD -DASLIBEXECDIR="\"$(ASLIBEXECDIR)/\"" -D__DARWIN_UNIX03 -DPPC $(ENDIAN_FLAG) +ppc_as_SOURCES = ../app.c ../as.c ../atof-generic.c ../atof-ieee.c ../expr.c ../fixes.c ../flonum-const.c \ + ../flonum-copy.c ../flonum-mult.c ../frags.c ../hash.c ../hex-value.c ../input-file.c \ + ../input-scrub.c ../layout.c ../messages.c ../obstack.c ../read.c ../sections.c \ + ../symbols.c ../write_object.c ../xmalloc.c ../dwarf2dbg.c ../ppc.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps as/ppc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps as/ppc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libexecPROGRAMS: $(libexec_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-libexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libexecdir)" && rm -f $$files + +clean-libexecPROGRAMS: + @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +../$(am__dirstamp): + @$(MKDIR_P) .. + @: > ../$(am__dirstamp) +../ppc_as-app.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-as.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-atof-generic.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-atof-ieee.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-expr.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-fixes.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-flonum-const.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-flonum-copy.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-flonum-mult.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-frags.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-hash.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-hex-value.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-input-file.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-input-scrub.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-layout.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-messages.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-obstack.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-read.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-sections.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-symbols.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-write_object.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-xmalloc.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-dwarf2dbg.$(OBJEXT): ../$(am__dirstamp) +../ppc_as-ppc.$(OBJEXT): ../$(am__dirstamp) + +ppc-as$(EXEEXT): $(ppc_as_OBJECTS) $(ppc_as_DEPENDENCIES) $(EXTRA_ppc_as_DEPENDENCIES) + @rm -f ppc-as$(EXEEXT) + $(AM_V_CCLD)$(ppc_as_LINK) $(ppc_as_OBJECTS) $(ppc_as_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f ../*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +../ppc_as-app.o: ../app.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-app.o `test -f '../app.c' || echo '$(srcdir)/'`../app.c + +../ppc_as-app.obj: ../app.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-app.obj `if test -f '../app.c'; then $(CYGPATH_W) '../app.c'; else $(CYGPATH_W) '$(srcdir)/../app.c'; fi` + +../ppc_as-as.o: ../as.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-as.o `test -f '../as.c' || echo '$(srcdir)/'`../as.c + +../ppc_as-as.obj: ../as.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-as.obj `if test -f '../as.c'; then $(CYGPATH_W) '../as.c'; else $(CYGPATH_W) '$(srcdir)/../as.c'; fi` + +../ppc_as-atof-generic.o: ../atof-generic.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-atof-generic.o `test -f '../atof-generic.c' || echo '$(srcdir)/'`../atof-generic.c + +../ppc_as-atof-generic.obj: ../atof-generic.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-atof-generic.obj `if test -f '../atof-generic.c'; then $(CYGPATH_W) '../atof-generic.c'; else $(CYGPATH_W) '$(srcdir)/../atof-generic.c'; fi` + +../ppc_as-atof-ieee.o: ../atof-ieee.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-atof-ieee.o `test -f '../atof-ieee.c' || echo '$(srcdir)/'`../atof-ieee.c + +../ppc_as-atof-ieee.obj: ../atof-ieee.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-atof-ieee.obj `if test -f '../atof-ieee.c'; then $(CYGPATH_W) '../atof-ieee.c'; else $(CYGPATH_W) '$(srcdir)/../atof-ieee.c'; fi` + +../ppc_as-expr.o: ../expr.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-expr.o `test -f '../expr.c' || echo '$(srcdir)/'`../expr.c + +../ppc_as-expr.obj: ../expr.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-expr.obj `if test -f '../expr.c'; then $(CYGPATH_W) '../expr.c'; else $(CYGPATH_W) '$(srcdir)/../expr.c'; fi` + +../ppc_as-fixes.o: ../fixes.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-fixes.o `test -f '../fixes.c' || echo '$(srcdir)/'`../fixes.c + +../ppc_as-fixes.obj: ../fixes.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-fixes.obj `if test -f '../fixes.c'; then $(CYGPATH_W) '../fixes.c'; else $(CYGPATH_W) '$(srcdir)/../fixes.c'; fi` + +../ppc_as-flonum-const.o: ../flonum-const.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-flonum-const.o `test -f '../flonum-const.c' || echo '$(srcdir)/'`../flonum-const.c + +../ppc_as-flonum-const.obj: ../flonum-const.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-flonum-const.obj `if test -f '../flonum-const.c'; then $(CYGPATH_W) '../flonum-const.c'; else $(CYGPATH_W) '$(srcdir)/../flonum-const.c'; fi` + +../ppc_as-flonum-copy.o: ../flonum-copy.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-flonum-copy.o `test -f '../flonum-copy.c' || echo '$(srcdir)/'`../flonum-copy.c + +../ppc_as-flonum-copy.obj: ../flonum-copy.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-flonum-copy.obj `if test -f '../flonum-copy.c'; then $(CYGPATH_W) '../flonum-copy.c'; else $(CYGPATH_W) '$(srcdir)/../flonum-copy.c'; fi` + +../ppc_as-flonum-mult.o: ../flonum-mult.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-flonum-mult.o `test -f '../flonum-mult.c' || echo '$(srcdir)/'`../flonum-mult.c + +../ppc_as-flonum-mult.obj: ../flonum-mult.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-flonum-mult.obj `if test -f '../flonum-mult.c'; then $(CYGPATH_W) '../flonum-mult.c'; else $(CYGPATH_W) '$(srcdir)/../flonum-mult.c'; fi` + +../ppc_as-frags.o: ../frags.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-frags.o `test -f '../frags.c' || echo '$(srcdir)/'`../frags.c + +../ppc_as-frags.obj: ../frags.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-frags.obj `if test -f '../frags.c'; then $(CYGPATH_W) '../frags.c'; else $(CYGPATH_W) '$(srcdir)/../frags.c'; fi` + +../ppc_as-hash.o: ../hash.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-hash.o `test -f '../hash.c' || echo '$(srcdir)/'`../hash.c + +../ppc_as-hash.obj: ../hash.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-hash.obj `if test -f '../hash.c'; then $(CYGPATH_W) '../hash.c'; else $(CYGPATH_W) '$(srcdir)/../hash.c'; fi` + +../ppc_as-hex-value.o: ../hex-value.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-hex-value.o `test -f '../hex-value.c' || echo '$(srcdir)/'`../hex-value.c + +../ppc_as-hex-value.obj: ../hex-value.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-hex-value.obj `if test -f '../hex-value.c'; then $(CYGPATH_W) '../hex-value.c'; else $(CYGPATH_W) '$(srcdir)/../hex-value.c'; fi` + +../ppc_as-input-file.o: ../input-file.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-input-file.o `test -f '../input-file.c' || echo '$(srcdir)/'`../input-file.c + +../ppc_as-input-file.obj: ../input-file.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-input-file.obj `if test -f '../input-file.c'; then $(CYGPATH_W) '../input-file.c'; else $(CYGPATH_W) '$(srcdir)/../input-file.c'; fi` + +../ppc_as-input-scrub.o: ../input-scrub.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-input-scrub.o `test -f '../input-scrub.c' || echo '$(srcdir)/'`../input-scrub.c + +../ppc_as-input-scrub.obj: ../input-scrub.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-input-scrub.obj `if test -f '../input-scrub.c'; then $(CYGPATH_W) '../input-scrub.c'; else $(CYGPATH_W) '$(srcdir)/../input-scrub.c'; fi` + +../ppc_as-layout.o: ../layout.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-layout.o `test -f '../layout.c' || echo '$(srcdir)/'`../layout.c + +../ppc_as-layout.obj: ../layout.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-layout.obj `if test -f '../layout.c'; then $(CYGPATH_W) '../layout.c'; else $(CYGPATH_W) '$(srcdir)/../layout.c'; fi` + +../ppc_as-messages.o: ../messages.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-messages.o `test -f '../messages.c' || echo '$(srcdir)/'`../messages.c + +../ppc_as-messages.obj: ../messages.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-messages.obj `if test -f '../messages.c'; then $(CYGPATH_W) '../messages.c'; else $(CYGPATH_W) '$(srcdir)/../messages.c'; fi` + +../ppc_as-obstack.o: ../obstack.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-obstack.o `test -f '../obstack.c' || echo '$(srcdir)/'`../obstack.c + +../ppc_as-obstack.obj: ../obstack.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-obstack.obj `if test -f '../obstack.c'; then $(CYGPATH_W) '../obstack.c'; else $(CYGPATH_W) '$(srcdir)/../obstack.c'; fi` + +../ppc_as-read.o: ../read.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-read.o `test -f '../read.c' || echo '$(srcdir)/'`../read.c + +../ppc_as-read.obj: ../read.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-read.obj `if test -f '../read.c'; then $(CYGPATH_W) '../read.c'; else $(CYGPATH_W) '$(srcdir)/../read.c'; fi` + +../ppc_as-sections.o: ../sections.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-sections.o `test -f '../sections.c' || echo '$(srcdir)/'`../sections.c + +../ppc_as-sections.obj: ../sections.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-sections.obj `if test -f '../sections.c'; then $(CYGPATH_W) '../sections.c'; else $(CYGPATH_W) '$(srcdir)/../sections.c'; fi` + +../ppc_as-symbols.o: ../symbols.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-symbols.o `test -f '../symbols.c' || echo '$(srcdir)/'`../symbols.c + +../ppc_as-symbols.obj: ../symbols.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-symbols.obj `if test -f '../symbols.c'; then $(CYGPATH_W) '../symbols.c'; else $(CYGPATH_W) '$(srcdir)/../symbols.c'; fi` + +../ppc_as-write_object.o: ../write_object.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-write_object.o `test -f '../write_object.c' || echo '$(srcdir)/'`../write_object.c + +../ppc_as-write_object.obj: ../write_object.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-write_object.obj `if test -f '../write_object.c'; then $(CYGPATH_W) '../write_object.c'; else $(CYGPATH_W) '$(srcdir)/../write_object.c'; fi` + +../ppc_as-xmalloc.o: ../xmalloc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-xmalloc.o `test -f '../xmalloc.c' || echo '$(srcdir)/'`../xmalloc.c + +../ppc_as-xmalloc.obj: ../xmalloc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-xmalloc.obj `if test -f '../xmalloc.c'; then $(CYGPATH_W) '../xmalloc.c'; else $(CYGPATH_W) '$(srcdir)/../xmalloc.c'; fi` + +../ppc_as-dwarf2dbg.o: ../dwarf2dbg.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-dwarf2dbg.o `test -f '../dwarf2dbg.c' || echo '$(srcdir)/'`../dwarf2dbg.c + +../ppc_as-dwarf2dbg.obj: ../dwarf2dbg.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-dwarf2dbg.obj `if test -f '../dwarf2dbg.c'; then $(CYGPATH_W) '../dwarf2dbg.c'; else $(CYGPATH_W) '$(srcdir)/../dwarf2dbg.c'; fi` + +../ppc_as-ppc.o: ../ppc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-ppc.o `test -f '../ppc.c' || echo '$(srcdir)/'`../ppc.c + +../ppc_as-ppc.obj: ../ppc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc_as_CFLAGS) $(CFLAGS) -c -o ../ppc_as-ppc.obj `if test -f '../ppc.c'; then $(CYGPATH_W) '../ppc.c'; else $(CYGPATH_W) '$(srcdir)/../ppc.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(libexecdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f ../$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libexecPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libexecPROGRAMS + +.MAKE: install-am install-exec-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libexecPROGRAMS clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-exec-hook install-html install-html-am \ + install-info install-info-am install-libexecPROGRAMS \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-libexecPROGRAMS + +.PRECIOUS: Makefile + +install-exec-hook: + mkdir -p $(DESTDIR)$(libexecdir)/as/ppc + mv $(DESTDIR)$(libexecdir)/*ppc-as* $(DESTDIR)$(libexecdir)/as/ppc/as + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/as/ppc64/Makefile.in b/cctools/as/ppc64/Makefile.in new file mode 100644 index 0000000..b60014d --- /dev/null +++ b/cctools/as/ppc64/Makefile.in @@ -0,0 +1,851 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +libexec_PROGRAMS = ppc64-as$(EXEEXT) +subdir = as/ppc64 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(libexecdir)" +PROGRAMS = $(libexec_PROGRAMS) +am__dirstamp = $(am__leading_dot)dirstamp +am_ppc64_as_OBJECTS = ../ppc64_as-app.$(OBJEXT) \ + ../ppc64_as-as.$(OBJEXT) ../ppc64_as-atof-generic.$(OBJEXT) \ + ../ppc64_as-atof-ieee.$(OBJEXT) ../ppc64_as-expr.$(OBJEXT) \ + ../ppc64_as-fixes.$(OBJEXT) ../ppc64_as-flonum-const.$(OBJEXT) \ + ../ppc64_as-flonum-copy.$(OBJEXT) \ + ../ppc64_as-flonum-mult.$(OBJEXT) ../ppc64_as-frags.$(OBJEXT) \ + ../ppc64_as-hash.$(OBJEXT) ../ppc64_as-hex-value.$(OBJEXT) \ + ../ppc64_as-input-file.$(OBJEXT) \ + ../ppc64_as-input-scrub.$(OBJEXT) ../ppc64_as-layout.$(OBJEXT) \ + ../ppc64_as-messages.$(OBJEXT) ../ppc64_as-obstack.$(OBJEXT) \ + ../ppc64_as-read.$(OBJEXT) ../ppc64_as-sections.$(OBJEXT) \ + ../ppc64_as-symbols.$(OBJEXT) \ + ../ppc64_as-write_object.$(OBJEXT) \ + ../ppc64_as-xmalloc.$(OBJEXT) ../ppc64_as-dwarf2dbg.$(OBJEXT) \ + ../ppc64_as-ppc.$(OBJEXT) +ppc64_as_OBJECTS = $(am_ppc64_as_OBJECTS) +ppc64_as_DEPENDENCIES = $(top_builddir)/libstuff/libstuff.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +ppc64_as_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ppc64_as_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(ppc64_as_SOURCES) +DIST_SOURCES = $(ppc64_as_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ppc64_as_LDADD = \ + $(top_builddir)/libstuff/libstuff.la + +ppc64_as_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -I$(top_srcdir)/libstuff -I$(top_srcdir)/as $(WARNINGS) $(LTO_DEF) -DNeXT_MOD -DASLIBEXECDIR="\"$(ASLIBEXECDIR)/\"" -D__DARWIN_UNIX03 -DPPC -DARCH64 $(ENDIAN_FLAG) +ppc64_as_SOURCES = ../app.c ../as.c ../atof-generic.c ../atof-ieee.c ../expr.c ../fixes.c ../flonum-const.c \ + ../flonum-copy.c ../flonum-mult.c ../frags.c ../hash.c ../hex-value.c ../input-file.c \ + ../input-scrub.c ../layout.c ../messages.c ../obstack.c ../read.c ../sections.c \ + ../symbols.c ../write_object.c ../xmalloc.c ../dwarf2dbg.c ../ppc.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps as/ppc64/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps as/ppc64/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libexecPROGRAMS: $(libexec_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-libexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libexecdir)" && rm -f $$files + +clean-libexecPROGRAMS: + @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +../$(am__dirstamp): + @$(MKDIR_P) .. + @: > ../$(am__dirstamp) +../ppc64_as-app.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-as.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-atof-generic.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-atof-ieee.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-expr.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-fixes.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-flonum-const.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-flonum-copy.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-flonum-mult.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-frags.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-hash.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-hex-value.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-input-file.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-input-scrub.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-layout.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-messages.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-obstack.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-read.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-sections.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-symbols.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-write_object.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-xmalloc.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-dwarf2dbg.$(OBJEXT): ../$(am__dirstamp) +../ppc64_as-ppc.$(OBJEXT): ../$(am__dirstamp) + +ppc64-as$(EXEEXT): $(ppc64_as_OBJECTS) $(ppc64_as_DEPENDENCIES) $(EXTRA_ppc64_as_DEPENDENCIES) + @rm -f ppc64-as$(EXEEXT) + $(AM_V_CCLD)$(ppc64_as_LINK) $(ppc64_as_OBJECTS) $(ppc64_as_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f ../*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +../ppc64_as-app.o: ../app.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-app.o `test -f '../app.c' || echo '$(srcdir)/'`../app.c + +../ppc64_as-app.obj: ../app.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-app.obj `if test -f '../app.c'; then $(CYGPATH_W) '../app.c'; else $(CYGPATH_W) '$(srcdir)/../app.c'; fi` + +../ppc64_as-as.o: ../as.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-as.o `test -f '../as.c' || echo '$(srcdir)/'`../as.c + +../ppc64_as-as.obj: ../as.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-as.obj `if test -f '../as.c'; then $(CYGPATH_W) '../as.c'; else $(CYGPATH_W) '$(srcdir)/../as.c'; fi` + +../ppc64_as-atof-generic.o: ../atof-generic.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-atof-generic.o `test -f '../atof-generic.c' || echo '$(srcdir)/'`../atof-generic.c + +../ppc64_as-atof-generic.obj: ../atof-generic.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-atof-generic.obj `if test -f '../atof-generic.c'; then $(CYGPATH_W) '../atof-generic.c'; else $(CYGPATH_W) '$(srcdir)/../atof-generic.c'; fi` + +../ppc64_as-atof-ieee.o: ../atof-ieee.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-atof-ieee.o `test -f '../atof-ieee.c' || echo '$(srcdir)/'`../atof-ieee.c + +../ppc64_as-atof-ieee.obj: ../atof-ieee.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-atof-ieee.obj `if test -f '../atof-ieee.c'; then $(CYGPATH_W) '../atof-ieee.c'; else $(CYGPATH_W) '$(srcdir)/../atof-ieee.c'; fi` + +../ppc64_as-expr.o: ../expr.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-expr.o `test -f '../expr.c' || echo '$(srcdir)/'`../expr.c + +../ppc64_as-expr.obj: ../expr.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-expr.obj `if test -f '../expr.c'; then $(CYGPATH_W) '../expr.c'; else $(CYGPATH_W) '$(srcdir)/../expr.c'; fi` + +../ppc64_as-fixes.o: ../fixes.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-fixes.o `test -f '../fixes.c' || echo '$(srcdir)/'`../fixes.c + +../ppc64_as-fixes.obj: ../fixes.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-fixes.obj `if test -f '../fixes.c'; then $(CYGPATH_W) '../fixes.c'; else $(CYGPATH_W) '$(srcdir)/../fixes.c'; fi` + +../ppc64_as-flonum-const.o: ../flonum-const.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-flonum-const.o `test -f '../flonum-const.c' || echo '$(srcdir)/'`../flonum-const.c + +../ppc64_as-flonum-const.obj: ../flonum-const.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-flonum-const.obj `if test -f '../flonum-const.c'; then $(CYGPATH_W) '../flonum-const.c'; else $(CYGPATH_W) '$(srcdir)/../flonum-const.c'; fi` + +../ppc64_as-flonum-copy.o: ../flonum-copy.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-flonum-copy.o `test -f '../flonum-copy.c' || echo '$(srcdir)/'`../flonum-copy.c + +../ppc64_as-flonum-copy.obj: ../flonum-copy.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-flonum-copy.obj `if test -f '../flonum-copy.c'; then $(CYGPATH_W) '../flonum-copy.c'; else $(CYGPATH_W) '$(srcdir)/../flonum-copy.c'; fi` + +../ppc64_as-flonum-mult.o: ../flonum-mult.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-flonum-mult.o `test -f '../flonum-mult.c' || echo '$(srcdir)/'`../flonum-mult.c + +../ppc64_as-flonum-mult.obj: ../flonum-mult.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-flonum-mult.obj `if test -f '../flonum-mult.c'; then $(CYGPATH_W) '../flonum-mult.c'; else $(CYGPATH_W) '$(srcdir)/../flonum-mult.c'; fi` + +../ppc64_as-frags.o: ../frags.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-frags.o `test -f '../frags.c' || echo '$(srcdir)/'`../frags.c + +../ppc64_as-frags.obj: ../frags.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-frags.obj `if test -f '../frags.c'; then $(CYGPATH_W) '../frags.c'; else $(CYGPATH_W) '$(srcdir)/../frags.c'; fi` + +../ppc64_as-hash.o: ../hash.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-hash.o `test -f '../hash.c' || echo '$(srcdir)/'`../hash.c + +../ppc64_as-hash.obj: ../hash.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-hash.obj `if test -f '../hash.c'; then $(CYGPATH_W) '../hash.c'; else $(CYGPATH_W) '$(srcdir)/../hash.c'; fi` + +../ppc64_as-hex-value.o: ../hex-value.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-hex-value.o `test -f '../hex-value.c' || echo '$(srcdir)/'`../hex-value.c + +../ppc64_as-hex-value.obj: ../hex-value.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-hex-value.obj `if test -f '../hex-value.c'; then $(CYGPATH_W) '../hex-value.c'; else $(CYGPATH_W) '$(srcdir)/../hex-value.c'; fi` + +../ppc64_as-input-file.o: ../input-file.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-input-file.o `test -f '../input-file.c' || echo '$(srcdir)/'`../input-file.c + +../ppc64_as-input-file.obj: ../input-file.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-input-file.obj `if test -f '../input-file.c'; then $(CYGPATH_W) '../input-file.c'; else $(CYGPATH_W) '$(srcdir)/../input-file.c'; fi` + +../ppc64_as-input-scrub.o: ../input-scrub.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-input-scrub.o `test -f '../input-scrub.c' || echo '$(srcdir)/'`../input-scrub.c + +../ppc64_as-input-scrub.obj: ../input-scrub.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-input-scrub.obj `if test -f '../input-scrub.c'; then $(CYGPATH_W) '../input-scrub.c'; else $(CYGPATH_W) '$(srcdir)/../input-scrub.c'; fi` + +../ppc64_as-layout.o: ../layout.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-layout.o `test -f '../layout.c' || echo '$(srcdir)/'`../layout.c + +../ppc64_as-layout.obj: ../layout.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-layout.obj `if test -f '../layout.c'; then $(CYGPATH_W) '../layout.c'; else $(CYGPATH_W) '$(srcdir)/../layout.c'; fi` + +../ppc64_as-messages.o: ../messages.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-messages.o `test -f '../messages.c' || echo '$(srcdir)/'`../messages.c + +../ppc64_as-messages.obj: ../messages.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-messages.obj `if test -f '../messages.c'; then $(CYGPATH_W) '../messages.c'; else $(CYGPATH_W) '$(srcdir)/../messages.c'; fi` + +../ppc64_as-obstack.o: ../obstack.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-obstack.o `test -f '../obstack.c' || echo '$(srcdir)/'`../obstack.c + +../ppc64_as-obstack.obj: ../obstack.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-obstack.obj `if test -f '../obstack.c'; then $(CYGPATH_W) '../obstack.c'; else $(CYGPATH_W) '$(srcdir)/../obstack.c'; fi` + +../ppc64_as-read.o: ../read.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-read.o `test -f '../read.c' || echo '$(srcdir)/'`../read.c + +../ppc64_as-read.obj: ../read.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-read.obj `if test -f '../read.c'; then $(CYGPATH_W) '../read.c'; else $(CYGPATH_W) '$(srcdir)/../read.c'; fi` + +../ppc64_as-sections.o: ../sections.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-sections.o `test -f '../sections.c' || echo '$(srcdir)/'`../sections.c + +../ppc64_as-sections.obj: ../sections.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-sections.obj `if test -f '../sections.c'; then $(CYGPATH_W) '../sections.c'; else $(CYGPATH_W) '$(srcdir)/../sections.c'; fi` + +../ppc64_as-symbols.o: ../symbols.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-symbols.o `test -f '../symbols.c' || echo '$(srcdir)/'`../symbols.c + +../ppc64_as-symbols.obj: ../symbols.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-symbols.obj `if test -f '../symbols.c'; then $(CYGPATH_W) '../symbols.c'; else $(CYGPATH_W) '$(srcdir)/../symbols.c'; fi` + +../ppc64_as-write_object.o: ../write_object.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-write_object.o `test -f '../write_object.c' || echo '$(srcdir)/'`../write_object.c + +../ppc64_as-write_object.obj: ../write_object.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-write_object.obj `if test -f '../write_object.c'; then $(CYGPATH_W) '../write_object.c'; else $(CYGPATH_W) '$(srcdir)/../write_object.c'; fi` + +../ppc64_as-xmalloc.o: ../xmalloc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-xmalloc.o `test -f '../xmalloc.c' || echo '$(srcdir)/'`../xmalloc.c + +../ppc64_as-xmalloc.obj: ../xmalloc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-xmalloc.obj `if test -f '../xmalloc.c'; then $(CYGPATH_W) '../xmalloc.c'; else $(CYGPATH_W) '$(srcdir)/../xmalloc.c'; fi` + +../ppc64_as-dwarf2dbg.o: ../dwarf2dbg.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-dwarf2dbg.o `test -f '../dwarf2dbg.c' || echo '$(srcdir)/'`../dwarf2dbg.c + +../ppc64_as-dwarf2dbg.obj: ../dwarf2dbg.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-dwarf2dbg.obj `if test -f '../dwarf2dbg.c'; then $(CYGPATH_W) '../dwarf2dbg.c'; else $(CYGPATH_W) '$(srcdir)/../dwarf2dbg.c'; fi` + +../ppc64_as-ppc.o: ../ppc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-ppc.o `test -f '../ppc.c' || echo '$(srcdir)/'`../ppc.c + +../ppc64_as-ppc.obj: ../ppc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ppc64_as_CFLAGS) $(CFLAGS) -c -o ../ppc64_as-ppc.obj `if test -f '../ppc.c'; then $(CYGPATH_W) '../ppc.c'; else $(CYGPATH_W) '$(srcdir)/../ppc.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(libexecdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f ../$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libexecPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libexecPROGRAMS + +.MAKE: install-am install-exec-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libexecPROGRAMS clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-exec-hook install-html install-html-am \ + install-info install-info-am install-libexecPROGRAMS \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-libexecPROGRAMS + +.PRECIOUS: Makefile + + +install-exec-hook: + mkdir -p $(DESTDIR)$(libexecdir)/as/ppc64 + mv $(DESTDIR)$(libexecdir)/*ppc64-as* $(DESTDIR)$(libexecdir)/as/ppc64/as + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/as/read.c b/cctools/as/read.c index 698daf9..d9e1d26 100644 --- a/cctools/as/read.c +++ b/cctools/as/read.c @@ -746,7 +746,7 @@ char *buffer) /* 1st character of each buffer of lines is here. */ 100 /* N_SO */, text_nsect, 0, - obstack_next_free(&frags) - frag_now->fr_literal, + (int)(obstack_next_free(&frags) - frag_now->fr_literal), frag_now); symbolP = symbol_new( "int:t1=r1;-2147483648;2147483647;", @@ -790,7 +790,7 @@ char *buffer) /* 1st character of each buffer of lines is here. */ 132 /* N_SOL */, text_nsect, 0, - obstack_next_free(&frags) - frag_now->fr_literal, + (int)(obstack_next_free(&frags) - frag_now->fr_literal), frag_now); } } @@ -824,7 +824,7 @@ char *buffer) /* 1st character of each buffer of lines is here. */ 100 /* N_SO */, text_nsect, 0, - obstack_next_free(&frags) - frag_now->fr_literal, + (int)(obstack_next_free(&frags) - frag_now->fr_literal), frag_now); } } @@ -1425,8 +1425,8 @@ char **buffer) tmp_buf = NULL; if(ends == NULL){ /* The matching #NO_APP\n for the #APP\n wasn't in this buffer. */ - int tmp_len; - int num; + long tmp_len; + long num; /* * First create a temporary place (tmp_buf of size tmp_len) to @@ -1602,7 +1602,7 @@ void s_align_bytes( uintptr_t arg) { - s_align(arg, 1); + s_align((int)arg, 1); } /* @@ -1614,7 +1614,7 @@ void s_align_ptwo( uintptr_t arg) { - s_align(arg, 0); + s_align((int)arg, 0); } /* @@ -1646,10 +1646,10 @@ int bytes_p) power_of_2_alignment = 0; if(bytes_p == 0){ - power_of_2_alignment = get_absolute_expression(); + power_of_2_alignment = (int)get_absolute_expression(); } else{ - byte_alignment = get_absolute_expression(); + byte_alignment = (int)get_absolute_expression(); if(byte_alignment != 0){ for(i = 0; (byte_alignment & 1) == 0; i++) byte_alignment >>= 1; @@ -1672,12 +1672,12 @@ int bytes_p) if(*input_line_pointer == ','){ input_line_pointer ++; if(*input_line_pointer != ','){ - temp_fill = get_absolute_expression (); + temp_fill = (int32_t)get_absolute_expression (); fill_specified = 1; } if(*input_line_pointer == ','){ input_line_pointer ++; - max_bytes_to_fill = get_absolute_expression (); + max_bytes_to_fill = (int32_t)get_absolute_expression (); } } @@ -1810,7 +1810,7 @@ uintptr_t value) #define MAX_ALIGNMENT (15) if(*input_line_pointer == ','){ input_line_pointer++; - power_of_2_alignment = get_absolute_expression(); + power_of_2_alignment = (int)get_absolute_expression(); if(power_of_2_alignment > MAX_ALIGNMENT) as_warn("Alignment too large: %d. assumed.", power_of_2_alignment = MAX_ALIGNMENT); @@ -1877,7 +1877,7 @@ uintptr_t value) } else{ input_line_pointer++; - temp = get_absolute_expression(); + temp = (int)get_absolute_expression(); *p = 0; symbolP = symbol_find_or_make(name); *p = c; @@ -1921,7 +1921,8 @@ uintptr_t value) 132 /* N_SOL */, text_nsect, 0, - obstack_next_free(&frags) - frag_now->fr_literal, + (int)(obstack_next_free(&frags) - + frag_now->fr_literal), frag_now); } } @@ -1983,7 +1984,7 @@ uintptr_t value) as_bad(".fill repeat <= 0, .fill ignored"); temp_size = 0; } - temp_fill = get_absolute_expression(); + temp_fill = (int32_t)get_absolute_expression(); /* * Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes) * but emits no error message because it seems a legal thing to do. @@ -2118,7 +2119,8 @@ uintptr_t value) c = get_symbol_end(); indirect_symbol_new(name, frag_now, - obstack_next_free(&frags) - frag_now->fr_literal); + (int)(obstack_next_free(&frags) - + frag_now->fr_literal)); *input_line_pointer = c; demand_empty_rest_of_line(); @@ -2165,7 +2167,7 @@ uintptr_t value) align = 0; if(*input_line_pointer == ','){ input_line_pointer++; - align = get_absolute_expression(); + align = (int)get_absolute_expression(); if(align > MAX_ALIGNMENT){ as_warn("Alignment too large: %d. assumed.", MAX_ALIGNMENT); align = MAX_ALIGNMENT; @@ -2188,7 +2190,7 @@ uintptr_t value) } bss->frch_root->fr_address = rnd(bss->frch_root->fr_address, 1 << align); - symbolP->sy_value = bss->frch_root->fr_address; + symbolP->sy_value = (uint32_t)bss->frch_root->fr_address; symbolP->sy_type = N_SECT; symbolP->sy_other = bss->frch_nsect; symbolP->sy_frag = bss->frch_root; @@ -2319,7 +2321,7 @@ uintptr_t value) segment = get_known_segmented_expression(&exp); if(*input_line_pointer == ','){ input_line_pointer ++; - temp_fill = get_absolute_expression (); + temp_fill = (int32_t)get_absolute_expression (); } else temp_fill = 0; @@ -2332,7 +2334,7 @@ uintptr_t value) 1, (relax_substateT)0, exp.X_add_symbol, - exp.X_add_number, + (int32_t)exp.X_add_number, (char *)0); *p = temp_fill; demand_empty_rest_of_line(); @@ -2386,7 +2388,7 @@ uintptr_t value) 1, (relax_substateT)0, exp.X_add_symbol, - exp.X_add_number, + (int32_t)exp.X_add_number, (char *)0); *ptr = 0; *end_name = delim; @@ -2460,7 +2462,7 @@ uintptr_t value) /* Just like .fill, but temp_size = 1 */ if(get_absolute_expression_and_terminator(&temp_repeat) == ','){ - temp_fill = get_absolute_expression(); + temp_fill = (int32_t)get_absolute_expression(); } else{ input_line_pointer--; /* Backup over what was not a ','. */ @@ -2631,7 +2633,8 @@ uintptr_t value) }while(!(is_end_of_line(g))); u = input_line_pointer - 1; *u = 0; - sizeof_stub = strtoul(sizeof_stub_name, &endp, 0); + sizeof_stub = (uint32_t)strtoul(sizeof_stub_name, + &endp, 0); if(*endp != '\0'){ as_bad("size of stub section: %s not a proper " "number", sizeof_stub_name); @@ -2692,7 +2695,7 @@ uintptr_t value) if(value == S_THREAD_LOCAL_ZEROFILL){ directive = "tbss"; - frcP = section_new("__DATA", "__thread_bss", value, 0, 0); + frcP = section_new("__DATA", "__thread_bss", (uint32_t)value, 0, 0); if(frcP->frch_root == NULL){ frcP->frch_root = xmalloc(SIZEOF_STRUCT_FRAG); frcP->frch_last = frcP->frch_root; @@ -2746,7 +2749,7 @@ uintptr_t value) return; } - frcP = section_new(segname, sectname, value, 0, 0); + frcP = section_new(segname, sectname, (uint32_t)value, 0, 0); if(frcP->frch_root == NULL){ frcP->frch_root = xmalloc(SIZEOF_STRUCT_FRAG); frcP->frch_last = frcP->frch_root; @@ -2784,7 +2787,7 @@ uintptr_t value) align = 0; if(*input_line_pointer == ','){ input_line_pointer++; - align = get_absolute_expression(); + align = (int)get_absolute_expression(); if(align > MAX_ALIGNMENT){ as_warn("Alignment too large: %d. assumed.", MAX_ALIGNMENT); align = MAX_ALIGNMENT; @@ -2807,7 +2810,7 @@ uintptr_t value) if((symbolP->sy_type & N_TYPE) == N_UNDF && symbolP->sy_value == 0){ frcP->frch_root->fr_address = rnd(frcP->frch_root->fr_address, 1 << align); - symbolP->sy_value = frcP->frch_root->fr_address; + symbolP->sy_value = (uint32_t)frcP->frch_root->fr_address; symbolP->sy_type = N_SECT | (symbolP->sy_type & (N_EXT | N_PEXT)); symbolP->sy_other = frcP->frch_nsect; symbolP->sy_frag = frcP->frch_root; @@ -3056,7 +3059,8 @@ uintptr_t value) 132 /* N_SOL */, text_nsect, 0, - obstack_next_free(&frags) - frag_now->fr_literal, + (int)(obstack_next_free(&frags) - + frag_now->fr_literal), frag_now); } } @@ -3164,8 +3168,8 @@ uintptr_t what) /* d == .stabd, n == .stabn, and s == .stabs */ switch(what){ case 'd': symbolP->sy_name = NULL; /* .stabd feature. */ - symbolP->sy_value = obstack_next_free(&frags) - - frag_now->fr_literal; + symbolP->sy_value = (int)(obstack_next_free(&frags) - + frag_now->fr_literal); symbolP->sy_frag = frag_now; break; @@ -3298,14 +3302,14 @@ symbolS *symbolP) as_bad("Complex expression. Absolute segment assumed." ); symbolP->sy_type = N_ABS | ext; symbolP->sy_other = 0; /* NO_SECT */ - symbolP->sy_value = exp.X_add_number; + symbolP->sy_value = (uint32_t)exp.X_add_number; symbolP->sy_frag = &zero_address_frag; break; case SEG_ABSOLUTE: symbolP->sy_type = N_ABS | ext; symbolP->sy_other = 0; /* NO_SECT */ - symbolP->sy_value = exp.X_add_number; + symbolP->sy_value = (uint32_t)exp.X_add_number; symbolP->sy_frag = &zero_address_frag; symbolP->expression = NULL; break; @@ -3313,7 +3317,7 @@ symbolS *symbolP) case SEG_SECT: symbolP->sy_type = N_SECT | ext; symbolP->sy_other = exp.X_add_symbol->sy_other; - symbolP->sy_value = exp.X_add_number + exp.X_add_symbol->sy_value; + symbolP->sy_value = (uint32_t)exp.X_add_number + exp.X_add_symbol->sy_value; symbolP->sy_frag = exp.X_add_symbol->sy_frag; break; @@ -3390,7 +3394,7 @@ uintptr_t nbytes) /* nbytes == 1 for .byte, 2 for .word, 4 for .long, 8 for .qua while(c == ','){ #ifdef TC_PARSE_CONS_EXPRESSION - segment = TC_PARSE_CONS_EXPRESSION(&exp, nbytes); + segment = TC_PARSE_CONS_EXPRESSION(&exp, (int)nbytes); #else segment = expression(&exp); /* At least scan over the expression */ #endif @@ -3404,7 +3408,7 @@ uintptr_t nbytes) /* nbytes == 1 for .byte, 2 for .word, 4 for .long, 8 for .qua segment = SEG_ABSOLUTE; /* Leave exp .X_add_number alone. */ } - p = frag_more(nbytes); + p = frag_more((int)nbytes); switch(segment){ case SEG_BIG: /* @@ -3421,13 +3425,13 @@ uintptr_t nbytes) /* nbytes == 1 for .byte, 2 for .word, 4 for .long, 8 for .qua for(i = 0; i < exp.X_add_number; ++i) sum = (sum << LITTLENUM_NUMBER_OF_BITS) + generic_bignum[(exp.X_add_number - 1) - i]; - md_number_to_chars(p, sum, nbytes); + md_number_to_chars(p, sum, (int)nbytes); } else { as_bad("%s number illegal. Absolute 0 assumed.", exp.X_add_number > 0 ? "Bignum" : "Floating-Point"); - md_number_to_chars(p, (int32_t)0, nbytes); + md_number_to_chars(p, (int32_t)0, (int)nbytes); } break; @@ -3444,9 +3448,9 @@ uintptr_t nbytes) /* nbytes == 1 for .byte, 2 for .word, 4 for .long, 8 for .qua /* Leading bits contain both 0s & 1s. */ as_bad("Value 0x%llx truncated to 0x%llx.", get, use); } - dwarf2_emit_insn(nbytes); + dwarf2_emit_insn((int)nbytes); /* put bytes in right order. */ - md_number_to_chars(p, use, nbytes); + md_number_to_chars(p, use, (int)nbytes); break; case SEG_DIFFSECT: @@ -3454,16 +3458,16 @@ uintptr_t nbytes) /* nbytes == 1 for .byte, 2 for .word, 4 for .long, 8 for .qua case SEG_SECT: #ifdef TC_CONS_FIX_NEW TC_CONS_FIX_NEW(frag_now, - p - frag_now->fr_literal, - nbytes, + (unsigned int)(p - frag_now->fr_literal), + (unsigned int)nbytes, &exp); #else fixP = fix_new(frag_now, - p - frag_now->fr_literal, - nbytes, + (int)(p - frag_now->fr_literal), + (int)nbytes, exp.X_add_symbol, exp.X_subtract_symbol, - exp.X_add_number, + (int)exp.X_add_number, 0, 0, 0); @@ -3686,7 +3690,7 @@ uintptr_t float_type) /* 'f':.ffloat ... 'F':.float ... */ if(input_line_pointer[0] == '0' && isalpha(input_line_pointer[1])) input_line_pointer+=2; - err = md_atof(float_type, temp, &length); + err = md_atof((int)float_type, temp, &length); know(length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT); know(length > 0); if(err != NULL && *err != '\0'){ @@ -3761,7 +3765,7 @@ emit_leb128_expr (expressionS *exp, int sign) { /* If we've got a constant, emit the thing directly right now. */ - valueT value = exp->X_add_number; + valueT value = (valueT)exp->X_add_number; int size; char *p; @@ -3799,8 +3803,8 @@ emit_leb128_expr (expressionS *exp, int sign) *expression = *exp; sym->expression = expression; sym->sy_frag = &zero_address_frag; - frag_var (rs_leb128, sizeof_leb128 ( ((valueT) (~(valueT) 0) >> 1), 0), 0, sign, - sym, 0, (char *) NULL); + frag_var (rs_leb128, sizeof_leb128 ( ((valueT) (~(valueT) 0) >> 1), 0), + 0, sign, sym, 0, (char *) NULL); frchain_now->has_rs_leb128s = TRUE; #endif @@ -3823,7 +3827,7 @@ uintptr_t sign) do { expression (&exp); - emit_leb128_expr (&exp, sign); + emit_leb128_expr (&exp, (int)sign); } while (*input_line_pointer++ == ','); @@ -4049,7 +4053,7 @@ void) } exp.X_add_number = 0; } - return(exp.X_add_number); + return (signed_target_addr_t)exp.X_add_number; } /* @@ -4062,7 +4066,7 @@ char /* return terminator */ get_absolute_expression_and_terminator( int32_t *val_pointer) /* return value of expression */ { - *val_pointer = get_absolute_expression(); + *val_pointer = (int32_t)get_absolute_expression(); return(*input_line_pointer++); } @@ -4187,7 +4191,7 @@ char *sym_name) 1, (relax_substateT)0, exp.X_add_symbol, - exp.X_add_number, + (int32_t)exp.X_add_number, (char *)0); *p = 0; return; @@ -4223,7 +4227,7 @@ uintptr_t value) if(the_cond_state.ignore) totally_ignore_line(); else{ - the_cond_state.cond_met = get_absolute_expression(); + the_cond_state.cond_met = (int)get_absolute_expression(); the_cond_state.ignore = !the_cond_state.cond_met; demand_empty_rest_of_line(); } @@ -4255,7 +4259,7 @@ uintptr_t value) totally_ignore_line(); } else{ - the_cond_state.cond_met = get_absolute_expression(); + the_cond_state.cond_met = (int)get_absolute_expression(); the_cond_state.ignore = !the_cond_state.cond_met; demand_empty_rest_of_line(); } @@ -4459,6 +4463,7 @@ char *macro_contents) /* copy each argument to a object in the macro obstack */ nargs = 0; + c = '\0'; for(index = 0; index < 10; index ++){ if(*input_line_pointer == ' ') ++input_line_pointer; @@ -4870,7 +4875,7 @@ uintptr_t value) { int length; - inlineasm_checks = value; + inlineasm_checks = (int)value; inlineasm_file_name = NULL; inlineasm_line_number = 0; inlineasm_column_number = 0; @@ -4881,11 +4886,11 @@ uintptr_t value) SKIP_WHITESPACE(); if(*input_line_pointer == ','){ input_line_pointer++; - inlineasm_line_number = get_absolute_expression(); + inlineasm_line_number = (int)get_absolute_expression(); SKIP_WHITESPACE(); if(*input_line_pointer == ','){ input_line_pointer++; - inlineasm_column_number = get_absolute_expression(); + inlineasm_column_number =(int)get_absolute_expression(); } } } @@ -5132,7 +5137,7 @@ int sizeof_leb128 (valueT value, int sign) { if (sign) - return sizeof_sleb128_32 ((offsetT) value); + return sizeof_sleb128_32 (value); else return sizeof_uleb128_32 (value); } @@ -5164,7 +5169,7 @@ output_sleb128 (char *p, offsetT value) } while (more); - return p - orig; + return (int)(p - orig); } static inline int @@ -5184,7 +5189,7 @@ output_uleb128 (char *p, valueT value) } while (value != 0); - return p - orig; + return (int)(p - orig); } int diff --git a/cctools/as/sections.c b/cctools/as/sections.c index c343d9d..827e1fe 100644 --- a/cctools/as/sections.c +++ b/cctools/as/sections.c @@ -175,8 +175,8 @@ uint32_t sizeof_stub) * If there is any current frag in the old section close it off. */ if(frag_now != NULL){ - frag_now->fr_fix = obstack_next_free(&frags) - - frag_now->fr_literal; + frag_now->fr_fix = (int32_t)(obstack_next_free(&frags) - + frag_now->fr_literal); frag_wane(frag_now); } @@ -217,7 +217,8 @@ uint32_t sizeof_stub) /* * Make a fresh frag for the section. */ - frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG); + frag_now = (fragS *)obstack_alloc(&frags, + (int)SIZEOF_STRUCT_FRAG); memset(frag_now, '\0', SIZEOF_STRUCT_FRAG); frag_now->fr_next = NULL; @@ -262,7 +263,8 @@ uint32_t sizeof_stub) /* * Make a fresh frag for the new section. */ - frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG); + frag_now = (fragS *)obstack_alloc(&frags, + (int)SIZEOF_STRUCT_FRAG); memset(frag_now, '\0', SIZEOF_STRUCT_FRAG); frag_now->fr_next = NULL; diff --git a/cctools/as/symbols.c b/cctools/as/symbols.c index e5d76b5..ceec8b2 100644 --- a/cctools/as/symbols.c +++ b/cctools/as/symbols.c @@ -19,6 +19,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include +#include /* cctools-port: For bcmp, bzero ... */ #include #include "as.h" #include "hash.h" @@ -335,11 +336,11 @@ struct frag *frag) /* For sy_frag. */ { register symbolS * symbolP; register char * preserved_copy_of_name; - register unsigned int name_length; + register size_t name_length; char * p; name_length = strlen(name) + 1; - obstack_grow(¬es,name,name_length); + obstack_grow(¬es,name,(int)name_length); p=obstack_finish(¬es); /* obstack_1done( ¬es, name, name_length, &p ); */ preserved_copy_of_name = p; @@ -460,7 +461,8 @@ int local_colon)/* non-zero if called from local_colon() */ && symbolP -> sy_value == 0) { symbolP -> sy_frag = frag_now; - symbolP -> sy_value = obstack_next_free(& frags) - frag_now -> fr_literal; + symbolP -> sy_value = (uint32_t)(obstack_next_free(& frags) - + frag_now -> fr_literal); know( N_UNDF == 0 ); symbolP -> sy_type |= N_SECT; /* keep N_EXT bit */ symbolP -> sy_other = frchain_now->frch_nsect; @@ -603,7 +605,7 @@ make_stab_for_symbol( symbolS *symbolP) { symbolS *stab; - int stabnamelen; + size_t stabnamelen; char *stabname; if(symbolP->sy_name[0] == 'L') @@ -694,7 +696,7 @@ uint32_t offset) /* Offset from frag address. */ { isymbolS *isymbolP; char *preserved_copy_of_name; - uint32_t name_length; + size_t name_length; char *p; struct frag *fr_next; symbolS *symbolP; @@ -722,7 +724,7 @@ uint32_t offset) /* Offset from frag address. */ } name_length = strlen(name) + 1; - obstack_grow(¬es, name, name_length); + obstack_grow(¬es, name, (int)name_length); p = obstack_finish(¬es); preserved_copy_of_name = p; p = obstack_alloc(¬es, sizeof(struct indirect_symbol)); @@ -882,7 +884,7 @@ struct frag *frag) symbolS * symbol_temp_new_now(void) { - return(symbol_temp_new(now_seg, frag_now_fix(), frag_now)); + return(symbol_temp_new(now_seg, (valueT)frag_now_fix(), frag_now)); } symbolS * @@ -898,7 +900,7 @@ symbolS *sym) { sym->sy_type = N_SECT; sym->sy_other = now_seg; - sym->sy_value = frag_now_fix(); + sym->sy_value = (uint32_t)frag_now_fix(); sym->sy_frag = frag_now; } diff --git a/cctools/as/write_object.c b/cctools/as/write_object.c index ed4ca76..c7895ba 100644 --- a/cctools/as/write_object.c +++ b/cctools/as/write_object.c @@ -45,6 +45,7 @@ #include "messages.h" #include "xmalloc.h" #include "input-scrub.h" +#include "stuff/write64.h" #if defined(I386) && defined(ARCH64) #include "i386.h" #endif @@ -193,9 +194,11 @@ char *out_file_name) */ nsects = 0; for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ - frchainP->frch_section.addr = frchainP->frch_root->fr_address; - frchainP->frch_section.size = frchainP->frch_last->fr_address - - frchainP->frch_root->fr_address; + frchainP->frch_section.addr = (uint32_t) + frchainP->frch_root->fr_address; + frchainP->frch_section.size = (uint32_t) + (frchainP->frch_last->fr_address - + frchainP->frch_root->fr_address); nsects++; } @@ -283,9 +286,10 @@ char *out_file_name) break; } if(p != NULL) - i = p->frch_section.addr - frchainP->frch_section.addr; + i = (uint32_t)(p->frch_section.addr - + frchainP->frch_section.addr); else - i = frchainP->frch_section.size; + i = (uint32_t)frchainP->frch_section.size; reloc_segment.filesize += i; frchainP->frch_section.offset = offset; offset += i; @@ -300,7 +304,7 @@ char *out_file_name) reloc_segment.vmsize = frchainP->frch_section.addr + frchainP->frch_section.size; } - offset = rnd(offset, sizeof(int32_t)); + offset = rnd32(offset, sizeof(int32_t)); /* * Count the number of relocation entries for each section. @@ -315,7 +319,7 @@ char *out_file_name) /* * Fill in the offset to the relocation entries of the sections. */ - offset = rnd(offset, sizeof(int32_t)); + offset = rnd32(offset, sizeof(int32_t)); reloff = offset; nrelocs = 0; for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ @@ -377,7 +381,7 @@ char *out_file_name) symbol_table.stroff = 0; else symbol_table.stroff = offset; - symbol_table.strsize = rnd(strsize, sizeof(uint32_t)); + symbol_table.strsize = rnd32(strsize, sizeof(uint32_t)); offset += rnd(strsize, sizeof(uint32_t)); /* @@ -641,7 +645,7 @@ char *out_file_name) } if((fd = open(out_file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) as_fatal("can't create output file: %s", out_file_name); - if(write(fd, output_addr, output_size) != (int)output_size) + if(write64(fd, output_addr, output_size) != (ssize_t)output_size) as_fatal("can't write output file"); if(close(fd) == -1) as_fatal("can't close output file"); @@ -1121,6 +1125,9 @@ uint32_t debug_section) uint32_t left21, right14; #endif +/* the pragmas that follow silence a noisy clang warning */ +#pragma unused (sri) +#pragma unused (sectdiff) /* * If fx_addsy is NULL then this fix needs no relocation entry. */ @@ -1171,8 +1178,8 @@ uint32_t debug_section) fixP->fx_size); } riP->r_pcrel = fixP->fx_pcrel; - riP->r_address = fixP->fx_frag->fr_address + fixP->fx_where - - sect_addr; + riP->r_address = (int32_t)(fixP->fx_frag->fr_address + fixP->fx_where - + sect_addr); #ifdef ARM if(fixP->fx_r_type == ARM_RELOC_LO16 || fixP->fx_r_type == ARM_RELOC_HI16 || @@ -1258,6 +1265,8 @@ uint32_t debug_section) riP->r_type = X86_64_RELOC_UNSIGNED; return(2 * sizeof(struct relocation_info)); #endif +/* the #if that follows is to silence a noisy "unreachable code" warning */ +#if defined(ARM) || defined(SPARC) || defined(HPPA) || defined (PPC) #ifdef PPC if(fixP->fx_r_type == PPC_RELOC_HI16) sectdiff = PPC_RELOC_HI16_SECTDIFF; @@ -1384,6 +1393,7 @@ uint32_t debug_section) #endif *riP = *((struct relocation_info *)&sri); return(2 * sizeof(struct relocation_info)); +#endif /* unreachable code */ } /* * Determine if this is left as a local relocation entry or must be diff --git a/cctools/as/x86_64/Makefile.in b/cctools/as/x86_64/Makefile.in new file mode 100644 index 0000000..3d1207f --- /dev/null +++ b/cctools/as/x86_64/Makefile.in @@ -0,0 +1,852 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +libexec_PROGRAMS = x86_64-as$(EXEEXT) +subdir = as/x86_64 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(libexecdir)" +PROGRAMS = $(libexec_PROGRAMS) +am__dirstamp = $(am__leading_dot)dirstamp +am_x86_64_as_OBJECTS = ../x86_64_as-app.$(OBJEXT) \ + ../x86_64_as-as.$(OBJEXT) ../x86_64_as-atof-generic.$(OBJEXT) \ + ../x86_64_as-atof-ieee.$(OBJEXT) ../x86_64_as-expr.$(OBJEXT) \ + ../x86_64_as-fixes.$(OBJEXT) \ + ../x86_64_as-flonum-const.$(OBJEXT) \ + ../x86_64_as-flonum-copy.$(OBJEXT) \ + ../x86_64_as-flonum-mult.$(OBJEXT) \ + ../x86_64_as-frags.$(OBJEXT) ../x86_64_as-hash.$(OBJEXT) \ + ../x86_64_as-hex-value.$(OBJEXT) \ + ../x86_64_as-input-file.$(OBJEXT) \ + ../x86_64_as-input-scrub.$(OBJEXT) \ + ../x86_64_as-layout.$(OBJEXT) ../x86_64_as-messages.$(OBJEXT) \ + ../x86_64_as-obstack.$(OBJEXT) ../x86_64_as-read.$(OBJEXT) \ + ../x86_64_as-sections.$(OBJEXT) ../x86_64_as-symbols.$(OBJEXT) \ + ../x86_64_as-write_object.$(OBJEXT) \ + ../x86_64_as-xmalloc.$(OBJEXT) \ + ../x86_64_as-dwarf2dbg.$(OBJEXT) ../x86_64_as-i386.$(OBJEXT) +x86_64_as_OBJECTS = $(am_x86_64_as_OBJECTS) +x86_64_as_DEPENDENCIES = $(top_builddir)/libstuff/libstuff.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +x86_64_as_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(x86_64_as_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(x86_64_as_SOURCES) +DIST_SOURCES = $(x86_64_as_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +x86_64_as_LDADD = \ + $(top_builddir)/libstuff/libstuff.la + +x86_64_as_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -I$(top_srcdir)/libstuff -I$(top_srcdir)/as $(WARNINGS) $(LTO_DEF) -DNeXT_MOD -DASLIBEXECDIR="\"$(ASLIBEXECDIR)/\"" -D__DARWIN_UNIX03 -DI386 -Di486 -Di586 -Di686 -DARCH64 $(ENDIAN_FLAG) +x86_64_as_SOURCES = ../app.c ../as.c ../atof-generic.c ../atof-ieee.c ../expr.c ../fixes.c ../flonum-const.c \ + ../flonum-copy.c ../flonum-mult.c ../frags.c ../hash.c ../hex-value.c ../input-file.c \ + ../input-scrub.c ../layout.c ../messages.c ../obstack.c ../read.c ../sections.c \ + ../symbols.c ../write_object.c ../xmalloc.c ../dwarf2dbg.c ../i386.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps as/x86_64/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps as/x86_64/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libexecPROGRAMS: $(libexec_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-libexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libexecdir)" && rm -f $$files + +clean-libexecPROGRAMS: + @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +../$(am__dirstamp): + @$(MKDIR_P) .. + @: > ../$(am__dirstamp) +../x86_64_as-app.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-as.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-atof-generic.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-atof-ieee.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-expr.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-fixes.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-flonum-const.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-flonum-copy.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-flonum-mult.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-frags.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-hash.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-hex-value.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-input-file.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-input-scrub.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-layout.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-messages.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-obstack.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-read.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-sections.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-symbols.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-write_object.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-xmalloc.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-dwarf2dbg.$(OBJEXT): ../$(am__dirstamp) +../x86_64_as-i386.$(OBJEXT): ../$(am__dirstamp) + +x86_64-as$(EXEEXT): $(x86_64_as_OBJECTS) $(x86_64_as_DEPENDENCIES) $(EXTRA_x86_64_as_DEPENDENCIES) + @rm -f x86_64-as$(EXEEXT) + $(AM_V_CCLD)$(x86_64_as_LINK) $(x86_64_as_OBJECTS) $(x86_64_as_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f ../*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +../x86_64_as-app.o: ../app.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-app.o `test -f '../app.c' || echo '$(srcdir)/'`../app.c + +../x86_64_as-app.obj: ../app.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-app.obj `if test -f '../app.c'; then $(CYGPATH_W) '../app.c'; else $(CYGPATH_W) '$(srcdir)/../app.c'; fi` + +../x86_64_as-as.o: ../as.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-as.o `test -f '../as.c' || echo '$(srcdir)/'`../as.c + +../x86_64_as-as.obj: ../as.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-as.obj `if test -f '../as.c'; then $(CYGPATH_W) '../as.c'; else $(CYGPATH_W) '$(srcdir)/../as.c'; fi` + +../x86_64_as-atof-generic.o: ../atof-generic.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-atof-generic.o `test -f '../atof-generic.c' || echo '$(srcdir)/'`../atof-generic.c + +../x86_64_as-atof-generic.obj: ../atof-generic.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-atof-generic.obj `if test -f '../atof-generic.c'; then $(CYGPATH_W) '../atof-generic.c'; else $(CYGPATH_W) '$(srcdir)/../atof-generic.c'; fi` + +../x86_64_as-atof-ieee.o: ../atof-ieee.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-atof-ieee.o `test -f '../atof-ieee.c' || echo '$(srcdir)/'`../atof-ieee.c + +../x86_64_as-atof-ieee.obj: ../atof-ieee.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-atof-ieee.obj `if test -f '../atof-ieee.c'; then $(CYGPATH_W) '../atof-ieee.c'; else $(CYGPATH_W) '$(srcdir)/../atof-ieee.c'; fi` + +../x86_64_as-expr.o: ../expr.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-expr.o `test -f '../expr.c' || echo '$(srcdir)/'`../expr.c + +../x86_64_as-expr.obj: ../expr.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-expr.obj `if test -f '../expr.c'; then $(CYGPATH_W) '../expr.c'; else $(CYGPATH_W) '$(srcdir)/../expr.c'; fi` + +../x86_64_as-fixes.o: ../fixes.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-fixes.o `test -f '../fixes.c' || echo '$(srcdir)/'`../fixes.c + +../x86_64_as-fixes.obj: ../fixes.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-fixes.obj `if test -f '../fixes.c'; then $(CYGPATH_W) '../fixes.c'; else $(CYGPATH_W) '$(srcdir)/../fixes.c'; fi` + +../x86_64_as-flonum-const.o: ../flonum-const.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-flonum-const.o `test -f '../flonum-const.c' || echo '$(srcdir)/'`../flonum-const.c + +../x86_64_as-flonum-const.obj: ../flonum-const.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-flonum-const.obj `if test -f '../flonum-const.c'; then $(CYGPATH_W) '../flonum-const.c'; else $(CYGPATH_W) '$(srcdir)/../flonum-const.c'; fi` + +../x86_64_as-flonum-copy.o: ../flonum-copy.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-flonum-copy.o `test -f '../flonum-copy.c' || echo '$(srcdir)/'`../flonum-copy.c + +../x86_64_as-flonum-copy.obj: ../flonum-copy.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-flonum-copy.obj `if test -f '../flonum-copy.c'; then $(CYGPATH_W) '../flonum-copy.c'; else $(CYGPATH_W) '$(srcdir)/../flonum-copy.c'; fi` + +../x86_64_as-flonum-mult.o: ../flonum-mult.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-flonum-mult.o `test -f '../flonum-mult.c' || echo '$(srcdir)/'`../flonum-mult.c + +../x86_64_as-flonum-mult.obj: ../flonum-mult.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-flonum-mult.obj `if test -f '../flonum-mult.c'; then $(CYGPATH_W) '../flonum-mult.c'; else $(CYGPATH_W) '$(srcdir)/../flonum-mult.c'; fi` + +../x86_64_as-frags.o: ../frags.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-frags.o `test -f '../frags.c' || echo '$(srcdir)/'`../frags.c + +../x86_64_as-frags.obj: ../frags.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-frags.obj `if test -f '../frags.c'; then $(CYGPATH_W) '../frags.c'; else $(CYGPATH_W) '$(srcdir)/../frags.c'; fi` + +../x86_64_as-hash.o: ../hash.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-hash.o `test -f '../hash.c' || echo '$(srcdir)/'`../hash.c + +../x86_64_as-hash.obj: ../hash.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-hash.obj `if test -f '../hash.c'; then $(CYGPATH_W) '../hash.c'; else $(CYGPATH_W) '$(srcdir)/../hash.c'; fi` + +../x86_64_as-hex-value.o: ../hex-value.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-hex-value.o `test -f '../hex-value.c' || echo '$(srcdir)/'`../hex-value.c + +../x86_64_as-hex-value.obj: ../hex-value.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-hex-value.obj `if test -f '../hex-value.c'; then $(CYGPATH_W) '../hex-value.c'; else $(CYGPATH_W) '$(srcdir)/../hex-value.c'; fi` + +../x86_64_as-input-file.o: ../input-file.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-input-file.o `test -f '../input-file.c' || echo '$(srcdir)/'`../input-file.c + +../x86_64_as-input-file.obj: ../input-file.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-input-file.obj `if test -f '../input-file.c'; then $(CYGPATH_W) '../input-file.c'; else $(CYGPATH_W) '$(srcdir)/../input-file.c'; fi` + +../x86_64_as-input-scrub.o: ../input-scrub.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-input-scrub.o `test -f '../input-scrub.c' || echo '$(srcdir)/'`../input-scrub.c + +../x86_64_as-input-scrub.obj: ../input-scrub.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-input-scrub.obj `if test -f '../input-scrub.c'; then $(CYGPATH_W) '../input-scrub.c'; else $(CYGPATH_W) '$(srcdir)/../input-scrub.c'; fi` + +../x86_64_as-layout.o: ../layout.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-layout.o `test -f '../layout.c' || echo '$(srcdir)/'`../layout.c + +../x86_64_as-layout.obj: ../layout.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-layout.obj `if test -f '../layout.c'; then $(CYGPATH_W) '../layout.c'; else $(CYGPATH_W) '$(srcdir)/../layout.c'; fi` + +../x86_64_as-messages.o: ../messages.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-messages.o `test -f '../messages.c' || echo '$(srcdir)/'`../messages.c + +../x86_64_as-messages.obj: ../messages.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-messages.obj `if test -f '../messages.c'; then $(CYGPATH_W) '../messages.c'; else $(CYGPATH_W) '$(srcdir)/../messages.c'; fi` + +../x86_64_as-obstack.o: ../obstack.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-obstack.o `test -f '../obstack.c' || echo '$(srcdir)/'`../obstack.c + +../x86_64_as-obstack.obj: ../obstack.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-obstack.obj `if test -f '../obstack.c'; then $(CYGPATH_W) '../obstack.c'; else $(CYGPATH_W) '$(srcdir)/../obstack.c'; fi` + +../x86_64_as-read.o: ../read.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-read.o `test -f '../read.c' || echo '$(srcdir)/'`../read.c + +../x86_64_as-read.obj: ../read.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-read.obj `if test -f '../read.c'; then $(CYGPATH_W) '../read.c'; else $(CYGPATH_W) '$(srcdir)/../read.c'; fi` + +../x86_64_as-sections.o: ../sections.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-sections.o `test -f '../sections.c' || echo '$(srcdir)/'`../sections.c + +../x86_64_as-sections.obj: ../sections.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-sections.obj `if test -f '../sections.c'; then $(CYGPATH_W) '../sections.c'; else $(CYGPATH_W) '$(srcdir)/../sections.c'; fi` + +../x86_64_as-symbols.o: ../symbols.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-symbols.o `test -f '../symbols.c' || echo '$(srcdir)/'`../symbols.c + +../x86_64_as-symbols.obj: ../symbols.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-symbols.obj `if test -f '../symbols.c'; then $(CYGPATH_W) '../symbols.c'; else $(CYGPATH_W) '$(srcdir)/../symbols.c'; fi` + +../x86_64_as-write_object.o: ../write_object.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-write_object.o `test -f '../write_object.c' || echo '$(srcdir)/'`../write_object.c + +../x86_64_as-write_object.obj: ../write_object.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-write_object.obj `if test -f '../write_object.c'; then $(CYGPATH_W) '../write_object.c'; else $(CYGPATH_W) '$(srcdir)/../write_object.c'; fi` + +../x86_64_as-xmalloc.o: ../xmalloc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-xmalloc.o `test -f '../xmalloc.c' || echo '$(srcdir)/'`../xmalloc.c + +../x86_64_as-xmalloc.obj: ../xmalloc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-xmalloc.obj `if test -f '../xmalloc.c'; then $(CYGPATH_W) '../xmalloc.c'; else $(CYGPATH_W) '$(srcdir)/../xmalloc.c'; fi` + +../x86_64_as-dwarf2dbg.o: ../dwarf2dbg.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-dwarf2dbg.o `test -f '../dwarf2dbg.c' || echo '$(srcdir)/'`../dwarf2dbg.c + +../x86_64_as-dwarf2dbg.obj: ../dwarf2dbg.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-dwarf2dbg.obj `if test -f '../dwarf2dbg.c'; then $(CYGPATH_W) '../dwarf2dbg.c'; else $(CYGPATH_W) '$(srcdir)/../dwarf2dbg.c'; fi` + +../x86_64_as-i386.o: ../i386.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-i386.o `test -f '../i386.c' || echo '$(srcdir)/'`../i386.c + +../x86_64_as-i386.obj: ../i386.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(x86_64_as_CFLAGS) $(CFLAGS) -c -o ../x86_64_as-i386.obj `if test -f '../i386.c'; then $(CYGPATH_W) '../i386.c'; else $(CYGPATH_W) '$(srcdir)/../i386.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(libexecdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f ../$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libexecPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libexecPROGRAMS + +.MAKE: install-am install-exec-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libexecPROGRAMS clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-exec-hook install-html install-html-am \ + install-info install-info-am install-libexecPROGRAMS \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-libexecPROGRAMS + +.PRECIOUS: Makefile + +install-exec-hook: + mkdir -p $(DESTDIR)$(libexecdir)/as/x86_64 + mv $(DESTDIR)$(libexecdir)/*x86_64-as* $(DESTDIR)$(libexecdir)/as/x86_64/as + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/autogen.sh b/cctools/autogen.sh index 9258d0d..ca899f5 100755 --- a/cctools/autogen.sh +++ b/cctools/autogen.sh @@ -19,7 +19,7 @@ fi export LIBTOOLIZE mkdir -p m4 -$LIBTOOLIZE -c -i +$LIBTOOLIZE -c -i --force aclocal -I m4 autoconf diff --git a/cctools/compile b/cctools/compile new file mode 100755 index 0000000..23fcba0 --- /dev/null +++ b/cctools/compile @@ -0,0 +1,348 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 1999-2020 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN* | MSYS*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/* | msys/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/cctools/config.guess b/cctools/config.guess new file mode 100755 index 0000000..ba6af63 --- /dev/null +++ b/cctools/config.guess @@ -0,0 +1,1486 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2018 Free Software Foundation, Inc. + +timestamp='2018-07-18' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# +# Please send patches to . + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2018 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +tmp= +# shellcheck disable=SC2172 +trap 'test -z "$tmp" || rm -fr "$tmp"' 1 2 13 15 +trap 'exitcode=$?; test -z "$tmp" || rm -fr "$tmp"; exit $exitcode' 0 + +set_cc_for_build() { + : "${TMPDIR=/tmp}" + # shellcheck disable=SC2039 + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } + dummy=$tmp/dummy + case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in + ,,) echo "int x;" > "$dummy.c" + for driver in cc gcc c89 c99 ; do + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD="$driver" + break + fi + done + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; + esac +} + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "$UNAME_SYSTEM" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + set_cc_for_build + cat <<-EOF > "$dummy.c" + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ + echo unknown)` + case "$UNAME_MACHINE_ARCH" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-unknown + ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case "$UNAME_MACHINE_ARCH" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "$UNAME_VERSION" in + Debian*) + release='-gnu' + ;; + *) + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "$machine-${os}${release}${abi-}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" + exit ;; + *:ekkoBSD:*:*) + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" + exit ;; + *:SolidBSD:*:*) + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:MirBSD:*:*) + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:Sortix:*:*) + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE=alpha ;; + "EV4.5 (21064)") + UNAME_MACHINE=alpha ;; + "LCA4 (21066/21068)") + UNAME_MACHINE=alpha ;; + "EV5 (21164)") + UNAME_MACHINE=alphaev5 ;; + "EV5.6 (21164A)") + UNAME_MACHINE=alphaev56 ;; + "EV5.6 (21164PC)") + UNAME_MACHINE=alphapca56 ;; + "EV5.7 (21164PC)") + UNAME_MACHINE=alphapca57 ;; + "EV6 (21264)") + UNAME_MACHINE=alphaev6 ;; + "EV6.7 (21264A)") + UNAME_MACHINE=alphaev67 ;; + "EV6.8CB (21264C)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8AL (21264B)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8CX (21264D)") + UNAME_MACHINE=alphaev68 ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE=alphaev69 ;; + "EV7 (21364)") + UNAME_MACHINE=alphaev7 ;; + "EV7.9 (21364A)") + UNAME_MACHINE=alphaev79 ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo "$UNAME_MACHINE"-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo "$UNAME_MACHINE"-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix"$UNAME_RELEASE" + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux"$UNAME_RELEASE" + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + UNAME_REL="`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + case `isainfo -b` in + 32) + echo i386-pc-solaris2"$UNAME_REL" + ;; + 64) + echo x86_64-pc-solaris2"$UNAME_REL" + ;; + esac + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos"$UNAME_RELEASE" + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos"$UNAME_RELEASE" + ;; + sun4) + echo sparc-sun-sunos"$UNAME_RELEASE" + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos"$UNAME_RELEASE" + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint"$UNAME_RELEASE" + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint"$UNAME_RELEASE" + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint"$UNAME_RELEASE" + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten"$UNAME_RELEASE" + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten"$UNAME_RELEASE" + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix"$UNAME_RELEASE" + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix"$UNAME_RELEASE" + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix"$UNAME_RELEASE" + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos"$UNAME_RELEASE" + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] + then + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] + then + echo m88k-dg-dgux"$UNAME_RELEASE" + else + echo m88k-dg-dguxbcs"$UNAME_RELEASE" + fi + else + echo i586-dg-dgux"$UNAME_RELEASE" + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + fi + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + fi + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "$sc_cpu_version" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "$sc_kernel_bits" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "$HP_ARCH" = "" ]; then + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ "$HP_ARCH" = hppa2.0w ] + then + set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH=hppa2.0w + else + HP_ARCH=hppa64 + fi + fi + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" + exit ;; + 3050*:HI-UX:*:*) + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo "$UNAME_MACHINE"-unknown-osf1mk + else + echo "$UNAME_MACHINE"-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi"$UNAME_RELEASE" + exit ;; + *:BSD/OS:*:*) + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" + exit ;; + arm*:FreeBSD:*:*) + UNAME_PROCESSOR=`uname -p` + set_cc_for_build + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi + else + echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf + fi + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case "$UNAME_PROCESSOR" in + amd64) + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; + esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" + exit ;; + i*:CYGWIN*:*) + echo "$UNAME_MACHINE"-pc-cygwin + exit ;; + *:MINGW64*:*) + echo "$UNAME_MACHINE"-pc-mingw64 + exit ;; + *:MINGW*:*) + echo "$UNAME_MACHINE"-pc-mingw32 + exit ;; + *:MSYS*:*) + echo "$UNAME_MACHINE"-pc-msys + exit ;; + i*:PW*:*) + echo "$UNAME_MACHINE"-pc-pw32 + exit ;; + *:Interix*:*) + case "$UNAME_MACHINE" in + x86) + echo i586-pc-interix"$UNAME_RELEASE" + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix"$UNAME_RELEASE" + exit ;; + IA64) + echo ia64-unknown-interix"$UNAME_RELEASE" + exit ;; + esac ;; + i*:UWIN*:*) + echo "$UNAME_MACHINE"-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + *:GNU:*:*) + # the GNU system + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" + exit ;; + *:Minix:*:*) + echo "$UNAME_MACHINE"-unknown-minix + exit ;; + aarch64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arm*:Linux:*:*) + set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi + else + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + cris:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + crisv32:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + e2k:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + frv:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + hexagon:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + i*86:Linux:*:*) + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + exit ;; + ia64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m32r*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m68*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" + test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } + ;; + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-"$LIBC" + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-"$LIBC" + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-"$LIBC" + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-"$LIBC" + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-"$LIBC" + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-"$LIBC" + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" + exit ;; + sh64*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + sh*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + tile*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + vax:Linux:*:*) + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" + exit ;; + x86_64:Linux:*:*) + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + exit ;; + xtensa*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo "$UNAME_MACHINE"-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo "$UNAME_MACHINE"-unknown-stop + exit ;; + i*86:atheos:*:*) + echo "$UNAME_MACHINE"-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo "$UNAME_MACHINE"-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos"$UNAME_RELEASE" + exit ;; + i*86:*DOS:*:*) + echo "$UNAME_MACHINE"-pc-msdosdjgpp + exit ;; + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" + else + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" + else + echo "$UNAME_MACHINE"-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos"$UNAME_RELEASE" + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos"$UNAME_RELEASE" + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos"$UNAME_RELEASE" + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos"$UNAME_RELEASE" + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv"$UNAME_RELEASE" + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo "$UNAME_MACHINE"-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo "$UNAME_MACHINE"-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux"$UNAME_RELEASE" + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv"$UNAME_RELEASE" + else + echo mips-unknown-sysv"$UNAME_RELEASE" + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux"$UNAME_RELEASE" + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux"$UNAME_RELEASE" + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux"$UNAME_RELEASE" + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux"$UNAME_RELEASE" + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux"$UNAME_RELEASE" + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux"$UNAME_RELEASE" + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux"$UNAME_RELEASE" + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody"$UNAME_RELEASE" + exit ;; + *:Rhapsody:*:*) + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = x86; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + # shellcheck disable=SC2154 + if test "$cputype" = 386; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo "$UNAME_MACHINE"-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux"$UNAME_RELEASE" + exit ;; + *:DragonFly:*:*) + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "$UNAME_MACHINE" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" + exit ;; + i*86:rdos:*:*) + echo "$UNAME_MACHINE"-pc-rdos + exit ;; + i*86:AROS:*:*) + echo "$UNAME_MACHINE"-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo "$UNAME_MACHINE"-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; +esac + +echo "$0: unable to guess system type" >&2 + +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <&2 </dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/cctools/config.sub b/cctools/config.sub new file mode 100755 index 0000000..64f9b14 --- /dev/null +++ b/cctools/config.sub @@ -0,0 +1,1806 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2018 Free Software Foundation, Inc. + +timestamp='2018-07-13' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS + +Canonicalize a configuration name. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2018 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo "$1" + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Split fields of configuration type +IFS="-" read -r field1 field2 field3 field4 <&2 + exit 1 + ;; + *-*-*-*) + basic_machine=$field1-$field2 + os=$field3-$field4 + ;; + *-*-*) + # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two + # parts + maybe_os=$field2-$field3 + case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc \ + | linux-newlib* | linux-musl* | linux-uclibc* | uclinux-uclibc* \ + | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ + | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ + | storm-chaos* | os2-emx* | rtmk-nova*) + basic_machine=$field1 + os=$maybe_os + ;; + android-linux) + basic_machine=$field1-unknown + os=linux-android + ;; + *) + basic_machine=$field1-$field2 + os=$field3 + ;; + esac + ;; + *-*) + # Second component is usually, but not always the OS + case $field2 in + # Prevent following clause from handling this valid os + sun*os*) + basic_machine=$field1 + os=$field2 + ;; + # Manufacturers + dec* | mips* | sequent* | encore* | pc532* | sgi* | sony* \ + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ + | convergent* | ncr* | news | 32* | 3600* | 3100* | hitachi* \ + | c[123]* | convex* | sun | crds | omron* | dg | ultra | tti* \ + | harris | dolphin | highlevel | gould | cbm | ns | masscomp \ + | apple | axis | knuth | cray | microblaze* \ + | sim | cisco | oki | wec | wrs | winbond) + basic_machine=$field1-$field2 + os= + ;; + *) + basic_machine=$field1 + os=$field2 + ;; + esac + ;; + *) + # Convert single-component short-hands not valid as part of + # multi-component configurations. + case $field1 in + 386bsd) + basic_machine=i386-pc + os=bsd + ;; + a29khif) + basic_machine=a29k-amd + os=udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=scout + ;; + am29k) + basic_machine=a29k-none + os=bsd + ;; + amdahl) + basic_machine=580-amdahl + os=sysv + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=bsd + ;; + aros) + basic_machine=i386-pc + os=aros + ;; + aux) + basic_machine=m68k-apple + os=aux + ;; + balance) + basic_machine=ns32k-sequent + os=dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=linux + ;; + cegcc) + basic_machine=arm-unknown + os=cegcc + ;; + cray) + basic_machine=j90-cray + os=unicos + ;; + craynv) + basic_machine=craynv-cray + os=unicosmp + ;; + delta88) + basic_machine=m88k-motorola + os=sysv3 + ;; + dicos) + basic_machine=i686-pc + os=dicos + ;; + djgpp) + basic_machine=i586-pc + os=msdosdjgpp + ;; + ebmon29k) + basic_machine=a29k-amd + os=ebmon + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=ose + ;; + gmicro) + basic_machine=tron-gmicro + os=sysv + ;; + go32) + basic_machine=i386-pc + os=go32 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=hms + ;; + harris) + basic_machine=m88k-harris + os=sysv3 + ;; + hp300bsd) + basic_machine=m68k-hp + os=bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=hpux + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=proelf + ;; + i386mach) + basic_machine=i386-mach + os=mach + ;; + vsta) + basic_machine=i386-unknown + os=vsta + ;; + isi68 | isi) + basic_machine=m68k-isi + os=sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=linux + ;; + magnum | m3230) + basic_machine=mips-mips + os=sysv + ;; + merlin) + basic_machine=ns32k-utek + os=sysv + ;; + mingw64) + basic_machine=x86_64-pc + os=mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=mingw32ce + ;; + monitor) + basic_machine=m68k-rom68k + os=coff + ;; + morphos) + basic_machine=powerpc-unknown + os=morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=moxiebox + ;; + msdos) + basic_machine=i386-pc + os=msdos + ;; + msys) + basic_machine=i686-pc + os=msys + ;; + mvs) + basic_machine=i370-ibm + os=mvs + ;; + nacl) + basic_machine=le32-unknown + os=nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=newsos + ;; + news1000) + basic_machine=m68030-sony + os=newsos + ;; + necv70) + basic_machine=v70-nec + os=sysv + ;; + nh3000) + basic_machine=m68k-harris + os=cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=cxux + ;; + nindy960) + basic_machine=i960-intel + os=nindy + ;; + mon960) + basic_machine=i960-intel + os=mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=nonstopux + ;; + os400) + basic_machine=powerpc-ibm + os=os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=ose + ;; + os68k) + basic_machine=m68k-none + os=os68k + ;; + paragon) + basic_machine=i860-intel + os=osf + ;; + parisc) + basic_machine=hppa-unknown + os=linux + ;; + pw32) + basic_machine=i586-unknown + os=pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=rdos + ;; + rdos32) + basic_machine=i386-pc + os=rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=coff + ;; + sa29200) + basic_machine=a29k-amd + os=udi + ;; + sei) + basic_machine=mips-sei + os=seiux + ;; + sps7) + basic_machine=m68k-bull + os=sysv2 + ;; + stratus) + basic_machine=i860-stratus + os=sysv4 + ;; + sun2os3) + basic_machine=m68000-sun + os=sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=solaris2 + ;; + sv1) + basic_machine=sv1-cray + os=unicos + ;; + symmetry) + basic_machine=i386-sequent + os=dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=unicos + ;; + t90) + basic_machine=t90-cray + os=unicos + ;; + toad1) + basic_machine=pdp10-xkl + os=tops20 + ;; + tpf) + basic_machine=s390x-ibm + os=tpf + ;; + udi29k) + basic_machine=a29k-amd + os=udi + ;; + ultra3) + basic_machine=a29k-nyu + os=sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=none + ;; + vaxv) + basic_machine=vax-dec + os=sysv + ;; + vms) + basic_machine=vax-dec + os=vms + ;; + vxworks960) + basic_machine=i960-wrs + os=vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=vxworks + ;; + xbox) + basic_machine=i686-pc + os=mingw32 + ;; + ymp) + basic_machine=ymp-cray + os=unicos + ;; + *) + basic_machine=$1 + os= + ;; + esac + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv6m | armv[78][arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper | csky \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nfp \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ + | pyramid \ + | riscv | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | wasm32 \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=${os:-none} + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) + ;; + m9s12z | m68hcs12z | hcs12z | s12z) + basic_machine=s12z-unknown + os=${os:-none} + ;; + ms1) + basic_machine=mt-unknown + ;; + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=${os:-none} + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | csky-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | e2k-* | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | moxie-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nfp-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ + | pyramid-* \ + | riscv-* | riscv32-* | riscv64-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | wasm32-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + abacus) + basic_machine=abacus-unknown + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + asmjs) + basic_machine=asmjs-unknown + ;; + blackfin-*) + basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=cnk + ;; + c54x-*) + basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=${os:-unicos} + ;; + convex-c1) + basic_machine=c1-convex + os=bsd + ;; + convex-c2) + basic_machine=c2-convex + os=bsd + ;; + convex-c32) + basic_machine=c32-convex + os=bsd + ;; + convex-c34) + basic_machine=c34-convex + os=bsd + ;; + convex-c38) + basic_machine=c38-convex + os=bsd + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=${os:-elf} + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=${os:-elf} + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=${os:-bosx} + ;; + dpx2*) + basic_machine=m68k-bull + os=sysv3 + ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=$os"spe" + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + elxsi) + basic_machine=elxsi-elxsi + os=${os:-bsd} + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=hiuxwe2 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=sysv32 + ;; + i*86v4*) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=sysv4 + ;; + i*86v) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=sysv + ;; + i*86sol2) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=solaris2 + ;; + j90 | j90-cray) + basic_machine=j90-cray + os=${os:-unicos} + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + irix*) + ;; + *) + os=irix4 + ;; + esac + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` + ;; + m68knommu-*) + basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=linux + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=mint + ;; + mips3*-*) + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown + ;; + ms1-*) + basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=newsos + ;; + next | m*-next) + basic_machine=m68k-next + case $os in + nextstep* ) + ;; + ns2*) + os=nextstep2 + ;; + *) + os=nextstep3 + ;; + esac + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + nsv-tandem) + basic_machine=nsv-tandem + ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=hiuxwe2 + ;; + parisc-*) + basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=${os:-elf} + ;; + sequent) + basic_machine=i386-sequent + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + simso-wrs) + basic_machine=sparclite-wrs + os=vxworks + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + tile*) + basic_machine=$basic_machine-unknown + os=linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + w65*) + basic_machine=w65-wdc + os=none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=proelf + ;; + x64) + basic_machine=x86_64-pc + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` + ;; + none) + basic_machine=none-none + os=${os:-none} + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *) + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x$os != x ] +then +case $os in + # First match some system type aliases that might get confused + # with valid system types. + # solaris* is a basic system type, with this one exception. + auroraux) + os=auroraux + ;; + bluegene*) + os=cnk + ;; + solaris1 | solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + solaris) + os=solaris2 + ;; + unixware*) + os=sysv4.2uw + ;; + gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # es1800 is here to avoid being matched by es* (a different OS) + es1800*) + os=ose + ;; + # Some version numbers need modification + chorusos*) + os=chorusos + ;; + isc) + os=isc2.2 + ;; + sco6) + os=sco5v6 + ;; + sco5) + os=sco3.2v5 + ;; + sco4) + os=sco3.2v4 + ;; + sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + ;; + sco3.2v[4-9]* | sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + ;; + scout) + # Don't match below + ;; + sco*) + os=sco3.2v2 + ;; + psos*) + os=psos + ;; + # Now accept the basic system types. + # The portable systems comes first. + # Each alternative MUST end in a * to match a version number. + # sysv* is not here because it comes later, after sysvr4. + gnu* | bsd* | mach* | minix* | genix* | ultrix* | irix* \ + | *vms* | esix* | aix* | cnk* | sunos | sunos[34]*\ + | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ + | sym* | kopensolaris* | plan9* \ + | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ + | aos* | aros* | cloudabi* | sortix* \ + | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ + | clix* | riscos* | uniplus* | iris* | rtu* | xenix* \ + | knetbsd* | mirbsd* | netbsd* \ + | bitrig* | openbsd* | solidbsd* | libertybsd* \ + | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \ + | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ + | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ + | udi* | eabi* | lites* | ieee* | go32* | aux* | hcos* \ + | chorusrdb* | cegcc* | glidix* \ + | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ + | midipix* | mingw32* | mingw64* | linux-gnu* | linux-android* \ + | linux-newlib* | linux-musl* | linux-uclibc* \ + | uxpv* | beos* | mpeix* | udk* | moxiebox* \ + | interix* | uwin* | mks* | rhapsody* | darwin* \ + | openstep* | oskit* | conix* | pw32* | nonstopux* \ + | storm-chaos* | tops10* | tenex* | tops20* | its* \ + | os2* | vos* | palmos* | uclinux* | nucleus* \ + | morphos* | superux* | rtmk* | windiss* \ + | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ + | skyos* | haiku* | rdos* | toppers* | drops* | es* \ + | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ + | midnightbsd*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=nto-$os + ;; + esac + ;; + hiux*) + os=hiuxwe2 + ;; + nto-qnx*) + ;; + nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + sim | xray | os68k* | v88r* \ + | windows* | osx | abug | netware* | os9* \ + | macos* | mpw* | magic* | mmixware* | mon960* | lnews*) + ;; + linux-dietlibc) + os=linux-dietlibc + ;; + linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + lynx*178) + os=lynxos178 + ;; + lynx*5) + os=lynxos5 + ;; + lynx*) + os=lynxos + ;; + mac*) + os=`echo "$os" | sed -e 's|mac|macos|'` + ;; + opened*) + os=openedition + ;; + os400*) + os=os400 + ;; + sunos5*) + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` + ;; + sunos6*) + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` + ;; + wince*) + os=wince + ;; + utek*) + os=bsd + ;; + dynix*) + os=bsd + ;; + acis*) + os=aos + ;; + atheos*) + os=atheos + ;; + syllable*) + os=syllable + ;; + 386bsd) + os=bsd + ;; + ctix* | uts*) + os=sysv + ;; + nova*) + os=rtmk-nova + ;; + ns2) + os=nextstep2 + ;; + nsk*) + os=nsk + ;; + # Preserve the version number of sinix5. + sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + sinix*) + os=sysv4 + ;; + tpf*) + os=tpf + ;; + triton*) + os=sysv3 + ;; + oss*) + os=sysv3 + ;; + svr4*) + os=sysv4 + ;; + svr3) + os=sysv3 + ;; + sysvr4) + os=sysv4 + ;; + # This must come after sysvr4. + sysv*) + ;; + ose*) + os=ose + ;; + *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) + os=mint + ;; + zvmoe) + os=zvmoe + ;; + dicos*) + os=dicos + ;; + pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=eabi + ;; + *) + os=elf + ;; + esac + ;; + nacl*) + ;; + ios) + ;; + none) + ;; + *-eabi) + ;; + *) + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=elf + ;; + spu-*) + os=elf + ;; + *-acorn) + os=riscix1.2 + ;; + arm*-rebel) + os=linux + ;; + arm*-semi) + os=aout + ;; + c4x-* | tic4x-*) + os=coff + ;; + c8051-*) + os=elf + ;; + clipper-intergraph) + os=clix + ;; + hexagon-*) + os=elf + ;; + tic54x-*) + os=coff + ;; + tic55x-*) + os=coff + ;; + tic6x-*) + os=coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=tops20 + ;; + pdp11-*) + os=none + ;; + *-dec | vax-*) + os=ultrix4.2 + ;; + m68*-apollo) + os=domain + ;; + i386-sun) + os=sunos4.0.2 + ;; + m68000-sun) + os=sunos3 + ;; + m68*-cisco) + os=aout + ;; + mep-*) + os=elf + ;; + mips*-cisco) + os=elf + ;; + mips*-*) + os=elf + ;; + or32-*) + os=coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=sysv3 + ;; + sparc-* | *-sun) + os=sunos4.1.1 + ;; + pru-*) + os=elf + ;; + *-be) + os=beos + ;; + *-ibm) + os=aix + ;; + *-knuth) + os=mmixware + ;; + *-wec) + os=proelf + ;; + *-winbond) + os=proelf + ;; + *-oki) + os=proelf + ;; + *-hp) + os=hpux + ;; + *-hitachi) + os=hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=sysv + ;; + *-cbm) + os=amigaos + ;; + *-dg) + os=dgux + ;; + *-dolphin) + os=sysv3 + ;; + m68k-ccur) + os=rtu + ;; + m88k-omron*) + os=luna + ;; + *-next) + os=nextstep + ;; + *-sequent) + os=ptx + ;; + *-crds) + os=unos + ;; + *-ns) + os=genix + ;; + i370-*) + os=mvs + ;; + *-gould) + os=sysv + ;; + *-highlevel) + os=bsd + ;; + *-encore) + os=bsd + ;; + *-sgi) + os=irix + ;; + *-siemens) + os=sysv4 + ;; + *-masscomp) + os=rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=uxpv + ;; + *-rom68k) + os=coff + ;; + *-*bug) + os=coff + ;; + *-apple) + os=macos + ;; + *-atari*) + os=mint + ;; + *-wrs) + os=vxworks + ;; + *) + os=none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + riscix*) + vendor=acorn + ;; + sunos*) + vendor=sun + ;; + cnk*|-aix*) + vendor=ibm + ;; + beos*) + vendor=be + ;; + hpux*) + vendor=hp + ;; + mpeix*) + vendor=hp + ;; + hiux*) + vendor=hitachi + ;; + unos*) + vendor=crds + ;; + dgux*) + vendor=dg + ;; + luna*) + vendor=omron + ;; + genix*) + vendor=ns + ;; + clix*) + vendor=intergraph + ;; + mvs* | opened*) + vendor=ibm + ;; + os400*) + vendor=ibm + ;; + ptx*) + vendor=sequent + ;; + tpf*) + vendor=ibm + ;; + vxsim* | vxworks* | windiss*) + vendor=wrs + ;; + aux*) + vendor=apple + ;; + hms*) + vendor=hitachi + ;; + mpw* | macos*) + vendor=apple + ;; + *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) + vendor=atari + ;; + vos*) + vendor=stratus + ;; + esac + basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` + ;; +esac + +echo "$basic_machine-$os" +exit + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/cctools/configure b/cctools/configure new file mode 100755 index 0000000..f50b4fc --- /dev/null +++ b/cctools/configure @@ -0,0 +1,20572 @@ +#! /bin/sh +# From configure.ac Revision: 1.37 . +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for cctools 949.0.1. +# +# Report bugs to . +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: t.poechtrager@gmail.com about your system, including +$0: any error possibly output before this message. Then +$0: install a modern shell, or manually run the script +$0: under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='cctools' +PACKAGE_TARNAME='cctools' +PACKAGE_VERSION='949.0.1' +PACKAGE_STRING='cctools 949.0.1' +PACKAGE_BUGREPORT='t.poechtrager@gmail.com' +PACKAGE_URL='' + +ac_unique_file="APPLE_LICENSE" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +ENDIAN_FLAG +TAPI_DEF +TAPI_LIB +XAR_LIB +FTS_LIB +LLVM_LIB_DIR +LLVM_INCLUDE_DIR +LTO_LIB +LTO_RPATH +LTO_DEF +LLVM_CONFIG +OBJCWARNINGS +WARNINGS +GCC_LIB +CXXABI_LIB +REALLOCF_LIB +MATH_LIB +UUID_LIB +EXECINFO_LIB +PTHREAD_FLAGS +DL_LIB +PROGRAM_PREFIX +ASLIBEXECDIR +HOST_AR +HOST_RANLIB +CCASFLAGS +CCAS +ac_ct_OBJC +OBJCFLAGS +OBJC +CXXCPP +ac_ct_CXX +CXXFLAGS +CXX +CPP +LT_SYS_LIBRARY_PATH +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +ac_ct_AR +AR +DLLTOOL +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +SED +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +LIBTOOL +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +ISDARWIN_FALSE +ISDARWIN_TRUE +target_os +target_vendor +target_cpu +target +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_maintainer_mode +enable_static +enable_shared +with_pic +enable_fast_install +with_aix_soname +with_gnu_ld +with_sysroot +enable_libtool_lock +enable_lto_support +with_llvm_config +enable_xar_support +with_libxar +enable_tapi_support +with_libtapi +enable_clang_as +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +LT_SYS_LIBRARY_PATH +CPP +CXX +CXXFLAGS +CCC +CXXCPP +OBJC +OBJCFLAGS +CCAS +CCASFLAGS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures cctools 949.0.1 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/cctools] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of cctools 949.0.1:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-maintainer-mode + enable make rules and dependencies not useful (and + sometimes confusing) to the casual installer + --enable-static[=PKGS] build static libraries [default=no] + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --enable-lto-support enable link time optimization support + --enable-xar-support enable xar support + --enable-tapi-support enable tapi support + --disable-clang-as do not use clang for assembling + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). + --with-llvm-config llvm config tool + --with-libxar path to the XAR library + --with-libtapi path to the apple tapi library + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. + CPP C preprocessor + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CXXCPP C++ preprocessor + OBJC Objective C compiler command + OBJCFLAGS Objective C compiler flags + CCAS assembler compiler command (defaults to CC) + CCASFLAGS assembler compiler flags (defaults to CFLAGS) + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +cctools configure 949.0.1 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_cxx_try_cpp LINENO +# ------------------------ +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_cpp + +# ac_fn_cxx_try_link LINENO +# ------------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_link + +# ac_fn_objc_try_compile LINENO +# ----------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_objc_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_objc_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_objc_try_compile + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## -------------------------------------- ## +## Report this to t.poechtrager@gmail.com ## +## -------------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by cctools $as_me 949.0.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 +$as_echo_n "checking target system type... " >&6; } +if ${ac_cv_target+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 +$as_echo "$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + + + if false; then + ISDARWIN_TRUE= + ISDARWIN_FALSE='#' +else + ISDARWIN_TRUE='#' + ISDARWIN_FALSE= +fi + + +isdarwin=no + +if test "x$CFLAGS" = "x"; then + CFLAGS="-O3" +fi + +if test "x$CXXFLAGS" = "x"; then + CXXFLAGS="-O3" +fi + +if test "x$OBJCFLAGS" = "x"; then + OBJCFLAGS="-O3" +fi + +CXXFLAGS="$CXXFLAGS -std=c++0x" + +if test "x$build" = "x$host"; then + CFLAGS="$CFLAGS -isystem /usr/local/include -isystem /usr/pkg/include" + CXXFLAGS="$CXXFLAGS -isystem /usr/local/include -isystem /usr/pkg/include" + LDFLAGS="$LDFLAGS -L/usr/local/lib -L/usr/pkg/lib" +fi + +CWARNINGS="" +OBJCWARNINGS="" +CXXWARNINGS="" +EXTRAFLAGS="" +EXTRACXXFLAGS="" +WARNINGS="" + +case $host_os in + darwin* ) + isdarwin=yes + if true; then + ISDARWIN_TRUE= + ISDARWIN_FALSE='#' +else + ISDARWIN_TRUE='#' + ISDARWIN_FALSE= +fi + + ;; + cygwin* ) + echo "Cygwin is no longer supported." 1>&2 + exit 1 + ;; +esac + +if test "x$CC" = "x"; then + if test "x$build" != "x$host"; then + CC="${host_alias}-clang" + else + CC=clang + fi +fi + +if test "x$CXX" = "x"; then + if test "x$build" != "x$host"; then + CXX="${host_alias}-clang++" + else + CXX=clang++ + fi +fi + +CCVERSION="`$CC --version`" +CXXVERSION="`$CXX --version`" + +case "$CCVERSION" in + *clang* ) + WARNINGS="$WARNINGS -Wall -Wno-long-long -Wno-import -Wno-format -Wno-deprecated -Wno-unused-variable" + WARNINGS="$WARNINGS -Wno-unused-private-field -Wno-unused-function -Wno-invalid-offsetof" + WARNINGS="$WARNINGS -Wno-int-conversion -Wno-char-subscripts" + OBJCWARNINGS="-Wall -Wno-objc-root-class -Wno-deprecated-objc-isa-usage" + ;; + * ) + echo "You must compile this project with clang. Other compilers are no longer supported." 2>&1 + exit 1 + ;; +esac + +EXTRAFLAGS="$EXTRAFLAGS -DLD64_VERSION_NUM=512.4" + +case "$CXXVERSION" in + *clang* ) + if test "x$isdarwin" = "xyes"; then + CXXFLAGS="$CXXFLAGS -stdlib=libc++" + fi + EXTRACXXFLAGS="$EXTRACXXFLAGS -fblocks" + ;; +esac + +case $host_cpu in + powerpc) + EXTRAFLAGS="$EXTRAFLAGS -D__ppc__" + ;; + powerpc64*) + EXTRAFLAGS="$EXTRAFLAGS -D__ppc__ -D__ppc64__" + ;; + arm64*|aarch64) + EXTRAFLAGS="$EXTRAFLAGS -D__arm64__" + ;; + arm*) + EXTRAFLAGS="$EXTRAFLAGS -D__arm__" + ;; +esac + +if test "x$EXTRAFLAGS" != "x"; then + CFLAGS="$CFLAGS $EXTRAFLAGS" + OBJCFLAGS="$OBJCFLAGS $EXTRAFLAGS" + CXXFLAGS="$CXXFLAGS $EXTRAFLAGS" +fi + +if test "xEXTRACXXFLAGS" != "x"; then + CXXFLAGS="$CXXFLAGS $EXTRACXXFLAGS" +fi + +CPP="$CC -E" +OBJC="$CC" + +# FIXME 'subdir-objects' breaks dependency tracking +am__api_version='1.16' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='cctools' + VERSION='949.0.1' + + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar plaintar pax cpio none' + +# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5 +$as_echo_n "checking whether UID '$am_uid' is supported by ustar format... " >&6; } + if test $am_uid -le $am_max_uid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5 +$as_echo_n "checking whether GID '$am_gid' is supported by ustar format... " >&6; } + if test $am_gid -le $am_max_gid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5 +$as_echo_n "checking how to create a ustar tar archive... " >&6; } + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_ustar-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + { echo "$as_me:$LINENO: $_am_tar --version" >&5 + ($_am_tar --version) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && break + done + am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x ustar -w "$$tardir"' + am__tar_='pax -L -x ustar -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H ustar -L' + am__tar_='find "$tardir" -print | cpio -o -H ustar -L' + am__untar='cpio -i -H ustar -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_ustar}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 + (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + rm -rf conftest.dir + if test -s conftest.tar; then + { echo "$as_me:$LINENO: $am__untar &5 + ($am__untar &5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + { echo "$as_me:$LINENO: cat conftest.dir/file" >&5 + (cat conftest.dir/file) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + grep GrepMe conftest.dir/file >/dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + if ${am_cv_prog_tar_ustar+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_prog_tar_ustar=$_am_tool +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5 +$as_echo "$am_cv_prog_tar_ustar" >&6; } + + + + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + + + + + + + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.6.42-b88ce-dirty' +macro_revision='2.4.6.42' + + + + + + + + + + + + + +ltmain=$ac_aux_dir/ltmain.sh + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case $ECHO in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n "$lt_cv_sys_max_cmd_len"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test yes != "$GCC"; then + reload_cmds=false + fi + ;; + darwin*) + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} + + + + + + +# Use ARFLAGS variable as AR's operation code to sync the variable naming with +# Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have +# higher priority because thats what people were doing historically (setting +# ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS +# variable obsoleted/removed. + +test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr} +lt_ar_flags=$AR_FLAGS + + + + + + +# Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override +# by AR_FLAGS because that was never working and AR_FLAGS is about to die. + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++ or ICC, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +$as_echo "$with_sysroot" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +$as_echo_n "checking for a working dd... " >&6; } +if ${ac_cv_path_lt_DD+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in dd; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +$as_echo "$ac_cv_path_lt_DD" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +$as_echo_n "checking how to truncate binary pipes... " >&6; } +if ${lt_cv_truncate_bin+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +$as_echo "$lt_cv_truncate_bin" >&6; } + + + + + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR $AR_FLAGS libconftest.a conftest.o" >&5 + $AR $AR_FLAGS libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[012][,.]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options +# Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_static=no +fi + + + + + + + + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + pic_mode=default +fi + + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test "${with_aix_soname+set}" = set; then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else + if ${lt_cv_with_aix_soname+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +$as_echo "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC and +# ICC, which need '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC=$CC +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test yes = "$GCC"; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + lt_prog_compiler_pic='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works"; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works"; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++ or Intel C++ Compiler. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='$wl--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + file_list_spec='@' + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test no = "$ld_shlibs"; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++ or Intel C++ Compiler. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl* | icl*) + # Native MSVC or ICC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC and ICC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + else + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + file_list_spec='@' + ;; + + osf3*) + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='$wl-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='$wl-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test no = "$ld_shlibs" && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl* | *,icl*) + # Native MSVC or ICC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC and ICC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test yes = "$hardcode_automatic"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen=shl_load +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen=dlopen +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -z "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + old_striplib="$STRIP --strip-debug" + striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + case $host_os in + darwin*) + # FIXME - insert some real tests, host_os isn't really good enough + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ;; + freebsd*) + if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then + old_striplib="$STRIP --strip-debug" + striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac + fi +fi + + + + + + + + + + + + + # Report what library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC=$lt_save_CC + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in clang + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in clang +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in clang++ + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in clang++ +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if ${ac_cv_cxx_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if ${ac_cv_prog_cxx_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +func_stripname_cnf () +{ + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;; + esac +} # func_stripname_cnf + + if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if ${ac_cv_prog_CXXCPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +else + _lt_caught_CXX_error=yes +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +archive_cmds_need_lc_CXX=no +allow_undefined_flag_CXX= +always_export_symbols_CXX=no +archive_expsym_cmds_CXX= +compiler_needs_object_CXX=no +export_dynamic_flag_spec_CXX= +hardcode_direct_CXX=no +hardcode_direct_absolute_CXX=no +hardcode_libdir_flag_spec_CXX= +hardcode_libdir_separator_CXX= +hardcode_minus_L_CXX=no +hardcode_shlibpath_var_CXX=unsupported +hardcode_automatic_CXX=no +inherit_rpath_CXX=no +module_cmds_CXX= +module_expsym_cmds_CXX= +link_all_deplibs_CXX=unknown +old_archive_cmds_CXX=$old_archive_cmds +reload_flag_CXX=$reload_flag +reload_cmds_CXX=$reload_cmds +no_undefined_flag_CXX= +whole_archive_flag_spec_CXX= +enable_shared_with_static_runtimes_CXX=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +objext_CXX=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + + # save warnings/boilerplate of simple test code + ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + + ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + compiler_CXX=$CC + func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' + else + lt_prog_compiler_no_builtin_flag_CXX= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec_CXX= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + ld_shlibs_CXX=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_CXX='' + hardcode_direct_CXX=yes + hardcode_direct_absolute_CXX=yes + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + file_list_spec_CXX='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct_CXX=no + hardcode_direct_absolute_CXX=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct_CXX=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_CXX=yes + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_libdir_separator_CXX= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec_CXX='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + always_export_symbols_CXX=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + no_undefined_flag_CXX='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath__CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath__CXX +fi + + hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" + + archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag_CXX="-z nodefs" + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath__CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath__CXX +fi + + hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_CXX=' $wl-bernotok' + allow_undefined_flag_CXX=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_CXX='$convenience' + fi + archive_cmds_need_lc_CXX=yes + archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_CXX=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs_CXX=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl* | ,icl* | no,icl*) + # Native MSVC or ICC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_CXX=' ' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=yes + file_list_spec_CXX='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' + enable_shared_with_static_runtimes_CXX=yes + # Don't use ranlib + old_postinstall_cmds_CXX='chmod 644 $oldlib' + postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_CXX='-L$libdir' + export_dynamic_flag_spec_CXX='$wl--export-all-symbols' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=no + enable_shared_with_static_runtimes_CXX=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_CXX=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + + + archive_cmds_need_lc_CXX=no + hardcode_direct_CXX=no + hardcode_automatic_CXX=yes + hardcode_shlibpath_var_CXX=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec_CXX='' + fi + link_all_deplibs_CXX=yes + allow_undefined_flag_CXX=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds_CXX="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + if test yes != "$lt_cv_apple_cc_single_mod"; then + archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi + + else + ld_shlibs_CXX=no + fi + + ;; + + os2*) + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_minus_L_CXX=yes + allow_undefined_flag_CXX=unsupported + shrext_cmds=.dll + archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes_CXX=yes + file_list_spec_CXX='@' + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + ld_shlibs_CXX=no + ;; + + freebsd-elf*) + archive_cmds_need_lc_CXX=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + ld_shlibs_CXX=yes + ;; + + haiku*) + archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs_CXX=yes + ;; + + hpux9*) + hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' + hardcode_libdir_separator_CXX=: + export_dynamic_flag_spec_CXX='$wl-E' + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' + hardcode_libdir_separator_CXX=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + export_dynamic_flag_spec_CXX='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + ;; + *) + hardcode_direct_CXX=yes + hardcode_direct_absolute_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + interix[3-9]*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + export_dynamic_flag_spec_CXX='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_CXX='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + link_all_deplibs_CXX=yes + ;; + esac + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + hardcode_libdir_separator_CXX=: + inherit_rpath_CXX=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [1-5].* | *pgcpp\ [1-5].*) + prelink_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + old_archive_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + archive_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + hardcode_libdir_flag_spec_CXX='-R$libdir' + whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object_CXX=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + ld_shlibs_CXX=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + hardcode_direct_absolute_CXX=yes + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + export_dynamic_flag_spec_CXX='$wl-E' + whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + ld_shlibs_CXX=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + case $host in + osf3*) + allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' + archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + ;; + *) + allow_undefined_flag_CXX=' -expect_unresolved \*' + archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + ;; + esac + + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + archive_cmds_need_lc_CXX=yes + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_shlibpath_var_CXX=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' + ;; + esac + link_all_deplibs_CXX=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + no_undefined_flag_CXX=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir' + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_CXX='$wl-z,text' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_CXX='$wl-z,text' + allow_undefined_flag_CXX='$wl-z,nodefs' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='$wl-R,$libdir' + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + export_dynamic_flag_spec_CXX='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ + '"$old_archive_cmds_CXX" + reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ + '"$reload_cmds_CXX" + ;; + *) + archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 +$as_echo "$ld_shlibs_CXX" >&6; } + test no = "$ld_shlibs_CXX" && can_build_shared=no + + GCC_CXX=$GXX + LD_CXX=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + # Dependencies to place before and after the object being linked: +predep_objects_CXX= +postdep_objects_CXX= +predeps_CXX= +postdeps_CXX= +compiler_lib_search_path_CXX= + +cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF + + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$compiler_lib_search_path_CXX"; then + compiler_lib_search_path_CXX=$prev$p + else + compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$postdeps_CXX"; then + postdeps_CXX=$prev$p + else + postdeps_CXX="${postdeps_CXX} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$predep_objects_CXX"; then + predep_objects_CXX=$p + else + predep_objects_CXX="$predep_objects_CXX $p" + fi + else + if test -z "$postdep_objects_CXX"; then + postdep_objects_CXX=$p + else + postdep_objects_CXX="$postdep_objects_CXX $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling CXX test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +case $host_os in +interix[3-9]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + predep_objects_CXX= + postdep_objects_CXX= + postdeps_CXX= + ;; +esac + + +case " $postdeps_CXX " in +*" -lc "*) archive_cmds_need_lc_CXX=no ;; +esac + compiler_lib_search_dirs_CXX= +if test -n "${compiler_lib_search_path_CXX}"; then + compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lt_prog_compiler_wl_CXX= +lt_prog_compiler_pic_CXX= +lt_prog_compiler_static_CXX= + + + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + fi + lt_prog_compiler_pic_CXX='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic_CXX='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static_CXX='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_CXX='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + lt_prog_compiler_pic_CXX= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static_CXX= + ;; + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_CXX=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic_CXX='-fPIC -shared' + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + else + case $host_os in + aix[4-9]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + else + lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; + dgux*) + case $cc_basename in + ec++*) + lt_prog_compiler_pic_CXX='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + lt_prog_compiler_pic_CXX='+Z' + fi + ;; + aCC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_CXX='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + lt_prog_compiler_wl_CXX='--backend -Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + lt_prog_compiler_static_CXX='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fpic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-qpic' + lt_prog_compiler_static_CXX='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + lt_prog_compiler_pic_CXX='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic_CXX='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + lt_prog_compiler_wl_CXX='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + lt_prog_compiler_pic_CXX='-pic' + ;; + cxx*) + # Digital/Compaq C++ + lt_prog_compiler_wl_CXX='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + lt_prog_compiler_pic_CXX='-pic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + lcc*) + # Lucid + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + lt_prog_compiler_pic_CXX='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + lt_prog_compiler_can_build_shared_CXX=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_CXX= + ;; + *) + lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } +lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } +if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works_CXX=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works_CXX=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then + case $lt_prog_compiler_pic_CXX in + "" | " "*) ;; + *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; + esac +else + lt_prog_compiler_pic_CXX= + lt_prog_compiler_can_build_shared_CXX=no +fi + +fi + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works_CXX=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works_CXX=yes + fi + else + lt_cv_prog_compiler_static_works_CXX=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then + : +else + lt_prog_compiler_static_CXX= +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + case $host_os in + aix[4-9]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + export_symbols_cmds_CXX=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl* | icl*) + exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + ;; + esac + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 +$as_echo "$ld_shlibs_CXX" >&6; } +test no = "$ld_shlibs_CXX" && can_build_shared=no + +with_gnu_ld_CXX=$with_gnu_ld + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_CXX" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_CXX=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds_CXX in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_CXX + pic_flag=$lt_prog_compiler_pic_CXX + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_CXX + allow_undefined_flag_CXX= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc_CXX=no + else + lt_cv_archive_cmds_need_lc_CXX=yes + fi + allow_undefined_flag_CXX=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } + archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl* | *,icl*) + # Native MSVC or ICC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC and ICC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec_CXX='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action_CXX= +if test -n "$hardcode_libdir_flag_spec_CXX" || + test -n "$runpath_var_CXX" || + test yes = "$hardcode_automatic_CXX"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct_CXX" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" && + test no != "$hardcode_minus_L_CXX"; then + # Linking always hardcodes the temporary library directory. + hardcode_action_CXX=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_CXX=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_CXX=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 +$as_echo "$hardcode_action_CXX" >&6; } + +if test relink = "$hardcode_action_CXX" || + test yes = "$inherit_rpath_CXX"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +ac_ext=m +ac_cpp='$OBJCPP $CPPFLAGS' +ac_compile='$OBJC -c $OBJCFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$OBJC -o conftest$ac_exeext $OBJCFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_objc_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in clang + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJC"; then + ac_cv_prog_OBJC="$OBJC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJC=$ac_cv_prog_OBJC +if test -n "$OBJC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJC" >&5 +$as_echo "$OBJC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$OBJC" && break + done +fi +if test -z "$OBJC"; then + ac_ct_OBJC=$OBJC + for ac_prog in clang +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJC"; then + ac_cv_prog_ac_ct_OBJC="$ac_ct_OBJC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJC=$ac_cv_prog_ac_ct_OBJC +if test -n "$ac_ct_OBJC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJC" >&5 +$as_echo "$ac_ct_OBJC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_OBJC" && break +done + + if test "x$ac_ct_OBJC" = x; then + OBJC="gcc" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJC=$ac_ct_OBJC + fi +fi + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for Objective C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU Objective C compiler" >&5 +$as_echo_n "checking whether we are using the GNU Objective C compiler... " >&6; } +if ${ac_cv_objc_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_objc_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_objc_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objc_compiler_gnu" >&5 +$as_echo "$ac_cv_objc_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GOBJC=yes +else + GOBJC= +fi +ac_test_OBJCFLAGS=${OBJCFLAGS+set} +ac_save_OBJCFLAGS=$OBJCFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $OBJC accepts -g" >&5 +$as_echo_n "checking whether $OBJC accepts -g... " >&6; } +if ${ac_cv_prog_objc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_objc_werror_flag=$ac_objc_werror_flag + ac_objc_werror_flag=yes + ac_cv_prog_objc_g=no + OBJCFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_objc_try_compile "$LINENO"; then : + ac_cv_prog_objc_g=yes +else + OBJCFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_objc_try_compile "$LINENO"; then : + +else + ac_objc_werror_flag=$ac_save_objc_werror_flag + OBJCFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_objc_try_compile "$LINENO"; then : + ac_cv_prog_objc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_objc_werror_flag=$ac_save_objc_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_objc_g" >&5 +$as_echo "$ac_cv_prog_objc_g" >&6; } +if test "$ac_test_OBJCFLAGS" = set; then + OBJCFLAGS=$ac_save_OBJCFLAGS +elif test $ac_cv_prog_objc_g = yes; then + if test "$GOBJC" = yes; then + OBJCFLAGS="-g -O2" + else + OBJCFLAGS="-g" + fi +else + if test "$GOBJC" = yes; then + OBJCFLAGS="-O2" + else + OBJCFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +# By default we simply use the C compiler to build assembly code. + +test "${CCAS+set}" = set || CCAS=$CC +test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_HOST_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HOST_RANLIB"; then + ac_cv_prog_HOST_RANLIB="$HOST_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_HOST_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +HOST_RANLIB=$ac_cv_prog_HOST_RANLIB +if test -n "$HOST_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HOST_RANLIB" >&5 +$as_echo "$HOST_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_HOST_RANLIB"; then + ac_ct_HOST_RANLIB=$HOST_RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_HOST_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_HOST_RANLIB"; then + ac_cv_prog_ac_ct_HOST_RANLIB="$ac_ct_HOST_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_HOST_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_HOST_RANLIB=$ac_cv_prog_ac_ct_HOST_RANLIB +if test -n "$ac_ct_HOST_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_HOST_RANLIB" >&5 +$as_echo "$ac_ct_HOST_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_HOST_RANLIB" = x; then + HOST_RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + HOST_RANLIB=$ac_ct_HOST_RANLIB + fi +else + HOST_RANLIB="$ac_cv_prog_HOST_RANLIB" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_HOST_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HOST_AR"; then + ac_cv_prog_HOST_AR="$HOST_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_HOST_AR="${ac_tool_prefix}ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +HOST_AR=$ac_cv_prog_HOST_AR +if test -n "$HOST_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HOST_AR" >&5 +$as_echo "$HOST_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_HOST_AR"; then + ac_ct_HOST_AR=$HOST_AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_HOST_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_HOST_AR"; then + ac_cv_prog_ac_ct_HOST_AR="$ac_ct_HOST_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_HOST_AR="ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_HOST_AR=$ac_cv_prog_ac_ct_HOST_AR +if test -n "$ac_ct_HOST_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_HOST_AR" >&5 +$as_echo "$ac_ct_HOST_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_HOST_AR" = x; then + HOST_AR=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + HOST_AR=$ac_ct_HOST_AR + fi +else + HOST_AR="$ac_cv_prog_HOST_AR" +fi + + +#for libstuff emulated.c +case $target_cpu in + powerpc) + +$as_echo "#define EMULATED_HOST_CPU_TYPE 18" >>confdefs.h + + +$as_echo "#define EMULATED_HOST_CPU_SUBTYPE 100" >>confdefs.h + + ;; + powerpc64*) + +$as_echo "#define EMULATED_HOST_CPU_TYPE 16777234" >>confdefs.h + + +$as_echo "#define EMULATED_HOST_CPU_SUBTYPE 0" >>confdefs.h + + ;; + i?86) + +$as_echo "#define EMULATED_HOST_CPU_TYPE 7" >>confdefs.h + + +$as_echo "#define EMULATED_HOST_CPU_SUBTYPE 10" >>confdefs.h + + ;; + x86_64|amd64) + +$as_echo "#define EMULATED_HOST_CPU_TYPE 16777223" >>confdefs.h + + +$as_echo "#define EMULATED_HOST_CPU_SUBTYPE 3" >>confdefs.h + + ;; + arm64*|aarch64) + +$as_echo "#define EMULATED_HOST_CPU_TYPE 16777228" >>confdefs.h + + +$as_echo "#define EMULATED_HOST_CPU_SUBTYPE 0" >>confdefs.h + + ;; + arm*) + +$as_echo "#define EMULATED_HOST_CPU_TYPE 12" >>confdefs.h + + +$as_echo "#define EMULATED_HOST_CPU_SUBTYPE 0" >>confdefs.h + + ;; + *) + as_fn_error $? "Unsupported target $target_cpu" "$LINENO" 5 + ;; +esac + +# as reported, some users may use llvm-c/Disassembler.h instead of a local copy in include dir. +# add these macros to avoid compilation failures. + +$as_echo "#define __STDC_LIMIT_MACROS 1" >>confdefs.h + +$as_echo "#define __STDC_CONSTANT_MACROS 1" >>confdefs.h + + +ASLIBEXECDIR='${libexecdir}/as' + + +# set PROGRAM PREFIX +if test "$target_alias"; then + PROGRAM_PREFIX='${target_alias}-' + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + DL_LIB=-ldl +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5 +$as_echo_n "checking for pthread_create in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_pthread_create+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_create (); +int +main () +{ +return pthread_create (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread_pthread_create=yes +else + ac_cv_lib_pthread_pthread_create=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5 +$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; } +if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then : + PTHREAD_FLAGS=-pthread +fi + + + +for ac_header in execinfo.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "execinfo.h" "ac_cv_header_execinfo_h" "$ac_includes_default" +if test "x$ac_cv_header_execinfo_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EXECINFO_H 1 +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for backtrace in -lexecinfo" >&5 +$as_echo_n "checking for backtrace in -lexecinfo... " >&6; } +if ${ac_cv_lib_execinfo_backtrace+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lexecinfo $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char backtrace (); +int +main () +{ +return backtrace (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_execinfo_backtrace=yes +else + ac_cv_lib_execinfo_backtrace=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_execinfo_backtrace" >&5 +$as_echo "$ac_cv_lib_execinfo_backtrace" >&6; } +if test "x$ac_cv_lib_execinfo_backtrace" = xyes; then : + EXECINFO_LIB=-lexecinfo +fi + +fi + +done + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_random in -luuid" >&5 +$as_echo_n "checking for uuid_generate_random in -luuid... " >&6; } +if ${ac_cv_lib_uuid_uuid_generate_random+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-luuid $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char uuid_generate_random (); +int +main () +{ +return uuid_generate_random (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_uuid_uuid_generate_random=yes +else + ac_cv_lib_uuid_uuid_generate_random=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate_random" >&5 +$as_echo "$ac_cv_lib_uuid_uuid_generate_random" >&6; } +if test "x$ac_cv_lib_uuid_uuid_generate_random" = xyes; then : + + for ac_header in uuid/uuid.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default" +if test "x$ac_cv_header_uuid_uuid_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UUID_UUID_H 1 +_ACEOF + UUID_LIB=-luuid +fi + +done + +fi + + + +for ac_func in strmode utimens utimensat +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in bcopy bcmp bzero index rindex +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +### Check how to access struct stat's tv_nsec field. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for st_mtimespec.tv_nsec in struct stat" >&5 +$as_echo_n "checking for st_mtimespec.tv_nsec in struct stat... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + struct stat st; + st.st_mtimespec.tv_nsec = 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_STAT_ST_MTIMESPEC 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for st_mtim.tv_nsec in struct stat" >&5 +$as_echo_n "checking for st_mtim.tv_nsec in struct stat... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + struct stat st; + st.st_mtim.tv_nsec = 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_STAT_ST_MTIM 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +### Check for log2 in -lm + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for log2 in -lm" >&5 +$as_echo_n "checking for log2 in -lm... " >&6; } +if ${ac_cv_lib_m_log2+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char log2 (); +int +main () +{ +return log2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_log2=yes +else + ac_cv_lib_m_log2=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_log2" >&5 +$as_echo "$ac_cv_lib_m_log2" >&6; } +if test "x$ac_cv_lib_m_log2" = xyes; then : + + MATH_LIB="-lm" + +fi + + + + +### Check for reallocf in -lc, -lbsd + +for ac_header in bsd/stdlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "bsd/stdlib.h" "ac_cv_header_bsd_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_bsd_stdlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_BSD_STDLIB_H 1 +_ACEOF + +fi + +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for reallocf in -lc" >&5 +$as_echo_n "checking for reallocf in -lc... " >&6; } +if ${ac_cv_lib_c_reallocf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char reallocf (); +int +main () +{ +return reallocf (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_c_reallocf=yes +else + ac_cv_lib_c_reallocf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_reallocf" >&5 +$as_echo "$ac_cv_lib_c_reallocf" >&6; } +if test "x$ac_cv_lib_c_reallocf" = xyes; then : + + REALLOCF_LIB="" + $as_echo "#define HAVE_REALLOCF 1" >>confdefs.h + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for reallocf in -lbsd" >&5 +$as_echo_n "checking for reallocf in -lbsd... " >&6; } +if ${ac_cv_lib_bsd_reallocf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbsd $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char reallocf (); +int +main () +{ +return reallocf (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bsd_reallocf=yes +else + ac_cv_lib_bsd_reallocf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_reallocf" >&5 +$as_echo "$ac_cv_lib_bsd_reallocf" >&6; } +if test "x$ac_cv_lib_bsd_reallocf" = xyes; then : + + REALLOCF_LIB=-lbsd + $as_echo "#define HAVE_REALLOCF 1" >>confdefs.h + + +fi + + +fi + + + + +### Check for clock_gettime + +ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime" +if test "x$ac_cv_func_clock_gettime" = xyes; then : + $as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h + +fi + + +### Check for write64 + +ac_fn_c_check_func "$LINENO" "write64" "ac_cv_func_write64" +if test "x$ac_cv_func_write64" = xyes; then : + $as_echo "#define HAVE_WRITE64 1" >>confdefs.h + +fi + + +### Check for __cxa_demangle in various C++ ABI libs ### + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __cxa_demangle in -lc++abi" >&5 +$as_echo_n "checking for __cxa_demangle in -lc++abi... " >&6; } +if ${ac_cv_lib_cppabi___cxa_demangle+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc++abi $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __cxa_demangle (); +int +main () +{ +return __cxa_demangle (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_cppabi___cxa_demangle=yes +else + ac_cv_lib_cppabi___cxa_demangle=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cppabi___cxa_demangle" >&5 +$as_echo "$ac_cv_lib_cppabi___cxa_demangle" >&6; } +if test "x$ac_cv_lib_cppabi___cxa_demangle" = xyes; then : + CXXABI_LIB=-lc++abi +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __cxa_demangle in -lc++" >&5 +$as_echo_n "checking for __cxa_demangle in -lc++... " >&6; } +if ${ac_cv_lib_cpp___cxa_demangle+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc++ $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __cxa_demangle (); +int +main () +{ +return __cxa_demangle (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_cpp___cxa_demangle=yes +else + ac_cv_lib_cpp___cxa_demangle=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cpp___cxa_demangle" >&5 +$as_echo "$ac_cv_lib_cpp___cxa_demangle" >&6; } +if test "x$ac_cv_lib_cpp___cxa_demangle" = xyes; then : + CXXABI_LIB=-lc++ +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __cxa_demangle in -lsupc++" >&5 +$as_echo_n "checking for __cxa_demangle in -lsupc++... " >&6; } +if ${ac_cv_lib_supcpp___cxa_demangle+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsupc++ $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __cxa_demangle (); +int +main () +{ +return __cxa_demangle (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_supcpp___cxa_demangle=yes +else + ac_cv_lib_supcpp___cxa_demangle=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_supcpp___cxa_demangle" >&5 +$as_echo "$ac_cv_lib_supcpp___cxa_demangle" >&6; } +if test "x$ac_cv_lib_supcpp___cxa_demangle" = xyes; then : + CXXABI_LIB=-lsupc++ +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __cxa_demangle in -lstdc++" >&5 +$as_echo_n "checking for __cxa_demangle in -lstdc++... " >&6; } +if ${ac_cv_lib_stdcpp___cxa_demangle+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lstdc++ $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __cxa_demangle (); +int +main () +{ +return __cxa_demangle (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_stdcpp___cxa_demangle=yes +else + ac_cv_lib_stdcpp___cxa_demangle=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_stdcpp___cxa_demangle" >&5 +$as_echo "$ac_cv_lib_stdcpp___cxa_demangle" >&6; } +if test "x$ac_cv_lib_stdcpp___cxa_demangle" = xyes; then : + CXXABI_LIB=-lstdc++ +else + exit 1 +fi + + +fi + + +fi + + +fi + + + + +### Check for __gcc_personality_v0 in -lgcc (NetBSD needs this) + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __gcc_personality_v0 in -lgcc" >&5 +$as_echo_n "checking for __gcc_personality_v0 in -lgcc... " >&6; } +if ${ac_cv_lib_gcc___gcc_personality_v0+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __gcc_personality_v0 (); +int +main () +{ +return __gcc_personality_v0 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_gcc___gcc_personality_v0=yes +else + ac_cv_lib_gcc___gcc_personality_v0=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gcc___gcc_personality_v0" >&5 +$as_echo "$ac_cv_lib_gcc___gcc_personality_v0" >&6; } +if test "x$ac_cv_lib_gcc___gcc_personality_v0" = xyes; then : + + GCC_LIB="-lgcc" + +fi + + + + +### Check for supported warning options ### + +ORIGCFLAGS=$CFLAGS +CFLAGS="$CFLAGS -Werror -Wno-shift-negative-value" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wno-shift-negative-value" >&5 +$as_echo_n "checking whether $CC supports -Wno-shift-negative-value... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int dummy; +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + WARNINGS="$WARNINGS -Wno-shift-negative-value" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +CFLAGS=$ORIGCFLAGS + +ORIGCFLAGS=$CFLAGS +CFLAGS="$CFLAGS -Werror -Wno-misleading-indentation" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wno-misleading-indentation" >&5 +$as_echo_n "checking whether $CC supports -Wno-misleading-indentation... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int dummy; +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + WARNINGS="$WARNINGS -Wno-misleading-indentation" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +CFLAGS=$ORIGCFLAGS + +WARNINGS=$WARNINGS + +OBJCWARNINGS=$OBJCWARNINGS + + +### Check for libLTO ### + +ORIGLDFLAGS=$LDFLAGS +LDFLAGS="$LDFLAGS -Wl,-rpath,/usr/local/lib,--enable-new-dtags" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ld supports -rpath,,--enable-new-dtags" >&5 +$as_echo_n "checking whether ld supports -rpath,,--enable-new-dtags... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(){} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + rpathlink=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LDFLAGS=$ORIGLDFLAGS + + + # Check whether --enable-lto-support was given. +if test "${enable_lto_support+set}" = set; then : + enableval=$enable_lto_support; +else + enable_lto_support=yes +fi + + + +# Check whether --with-llvm-config was given. +if test "${with_llvm_config+set}" = set; then : + withval=$with_llvm_config; LLVM_CONFIG=$with_llvm_config +else + LLVM_CONFIG=no +fi + + + if test "x$enable_lto_support" = "xyes"; then + if test "x$LLVM_CONFIG" = "xno"; then + for ac_prog in llvm-config \ + llvm-config-9.0 llvm-config-8.0 \ + llvm-config-7.0 llvm-config-6.0 \ + llvm-config-5.0 llvm-config-4.0 \ + llvm-config-3.9 llvm-config-3.8 llvm-config-3.7 \ + llvm-config-3.6 llvm-config-3.5 llvm-config-3.4 \ + llvm-config-3.3 llvm-config-3.2 llvm-config-3.1 \ + llvm-config90 llvm-config80 \ + llvm-config70 llvm-config60 \ + llvm-config50 llvm-config40 \ + llvm-config39 llvm-config38 llvm-config37 llvm-config36 \ + llvm-config35 llvm-config34 llvm-config33 llvm-config32 \ + llvm-config31 +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_LLVM_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $LLVM_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_LLVM_CONFIG="$LLVM_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_LLVM_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +LLVM_CONFIG=$ac_cv_path_LLVM_CONFIG +if test -n "$LLVM_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LLVM_CONFIG" >&5 +$as_echo "$LLVM_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$LLVM_CONFIG" && break +done +test -n "$LLVM_CONFIG" || LLVM_CONFIG="no" + + fi + + if test "x$LLVM_CONFIG" != "xno"; then + LLVM_INCLUDE_DIR="`${LLVM_CONFIG} --includedir`" + LLVM_LIB_DIR="`${LLVM_CONFIG} --libdir`" + + ORIGLDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -L${LLVM_LIB_DIR}" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lto_get_version in -lLTO" >&5 +$as_echo_n "checking for lto_get_version in -lLTO... " >&6; } +if ${ac_cv_lib_LTO_lto_get_version+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lLTO $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char lto_get_version (); +int +main () +{ +return lto_get_version (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_LTO_lto_get_version=yes +else + ac_cv_lib_LTO_lto_get_version=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_LTO_lto_get_version" >&5 +$as_echo "$ac_cv_lib_LTO_lto_get_version" >&6; } +if test "x$ac_cv_lib_LTO_lto_get_version" = xyes; then : + + LTO_LIB="-L${LLVM_LIB_DIR} -lLTO" + if test "x$rpathlink" = "xyes"; then + LTO_RPATH="-Wl,-rpath,$LLVM_LIB_DIR,--enable-new-dtags" + fi + if test "x$isdarwin" = "xyes"; then + LTO_RPATH="-Wl,-rpath,$LLVM_LIB_DIR" + fi + LTO_DEF=-DLTO_SUPPORT + # DO NOT include the LLVM include dir directly, + # it may cause the build to fail. + cp -f $LLVM_INCLUDE_DIR/llvm-c/lto.h `dirname ${0}`/include/llvm-c + if test -e $LLVM_INCLUDE_DIR/llvm-c/ExternC.h; then + cp -f $LLVM_INCLUDE_DIR/llvm-c/ExternC.h `dirname ${0}`/include/llvm-c + fi + + + + +fi + + + LDFLAGS=$ORIGLDFLAGS + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: llvm-config not found, disabling LTO support" >&5 +$as_echo "$as_me: WARNING: llvm-config not found, disabling LTO support" >&2;} + fi + fi + + + + + +LDFLAGS="$LDFLAGS $LTO_RPATH" + +### Check for libfts (musl) ### + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fts_open in -lfts" >&5 +$as_echo_n "checking for fts_open in -lfts... " >&6; } +if ${ac_cv_lib_fts_fts_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lfts $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char fts_open (); +int +main () +{ +return fts_open (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_fts_fts_open=yes +else + ac_cv_lib_fts_fts_open=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fts_fts_open" >&5 +$as_echo "$ac_cv_lib_fts_fts_open" >&6; } +if test "x$ac_cv_lib_fts_fts_open" = xyes; then : + + for ac_header in fts.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "fts.h" "ac_cv_header_fts_h" "$ac_includes_default" +if test "x$ac_cv_header_fts_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FTS_H 1 +_ACEOF + FTS_LIB=-lfts +fi + +done + +fi + + + +### Check for XAR ### + +# Check whether --enable-xar-support was given. +if test "${enable_xar_support+set}" = set; then : + enableval=$enable_xar_support; +else + enable_xar_support=yes +fi + + +if test "x$LTO_LIB" != "x"; then + if test "x$enable_xar_support" = "xyes"; then + +# Check whether --with-libxar was given. +if test "${with_libxar+set}" = set; then : + withval=$with_libxar; XAR_DIR=$with_libxar +else + XAR_DIR="" +fi + + + if test "x$XAR_DIR" = "xno"; then + XAR_DIR="" + fi + + if test "x$XAR_DIR" != "x"; then + CXXFLAGS="$CXXFLAGS -isystem $XAR_DIR/include" + CPPFLAGS="$CPPFLAGS -isystem $XAR_DIR/include" + test -d "$XAR_DIR/lib" && LDFLAGS="$LDFLAGS -L$XAR_DIR/lib" + test -d "$XAR_DIR/lib64" && LDFLAGS="$LDFLAGS -L$XAR_DIR/lib64" + test -d "$XAR_DIR/lib32" && LDFLAGS="$LDFLAGS -L$XAR_DIR/lib32" + if test "x$rpathlink" = "xyes"; then + XAR_RPATH="-Wl,-rpath,$XAR_DIR/lib,--enable-new-dtags" + XAR_RPATH="$XAR_RPATH -Wl,-rpath,$XAR_DIR/lib64,--enable-new-dtags" + XAR_RPATH="$XAR_RPATH -Wl,-rpath,$XAR_DIR/lib32,--enable-new-dtags" + LDFLAGS="$LDFLAGS $XAR_RPATH" + fi + if test "x$isdarwin" = "xyes"; then + XAR_RPATH="-Wl,-rpath,$XAR_DIR/lib" + LDFLAGS="$LDFLAGS $XAR_RPATH" + fi + fi + + XAR_LIB="" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xar_prop_create in -lxar" >&5 +$as_echo_n "checking for xar_prop_create in -lxar... " >&6; } +if ${ac_cv_lib_xar_xar_prop_create+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lxar $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char xar_prop_create (); +int +main () +{ +return xar_prop_create (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_xar_xar_prop_create=yes +else + ac_cv_lib_xar_xar_prop_create=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xar_xar_prop_create" >&5 +$as_echo "$ac_cv_lib_xar_xar_prop_create" >&6; } +if test "x$ac_cv_lib_xar_xar_prop_create" = xyes; then : + + for ac_header in xar/xar.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "xar/xar.h" "ac_cv_header_xar_xar_h" "$ac_includes_default" +if test "x$ac_cv_header_xar_xar_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_XAR_XAR_H 1 +_ACEOF + XAR_LIB=-lxar +fi + +done + +fi + + + fi +fi + +### Check for Apple TAPI library ### + +# Check whether --enable-tapi-support was given. +if test "${enable_tapi_support+set}" = set; then : + enableval=$enable_tapi_support; +else + enable_tapi_support=yes +fi + + +if test "x$enable_tapi_support" = "xyes"; then + +# Check whether --with-libtapi was given. +if test "${with_libtapi+set}" = set; then : + withval=$with_libtapi; LIBTAPI_DIR=$with_libtapi +else + LIBTAPI_DIR="" +fi + + + if test "x$LIBTAPI_DIR" = "xno"; then + LIBTAPI_DIR="" + fi + if test "x$LIBTAPI_DIR" != "x"; then + CXXFLAGS="$CXXFLAGS -isystem $LIBTAPI_DIR/include" + CPPFLAGS="$CPPFLAGS -isystem $LIBTAPI_DIR/include" + test -d "$LIBTAPI_DIR/lib" && LDFLAGS="$LDFLAGS -L$LIBTAPI_DIR/lib" + test -d "$LIBTAPI_DIR/lib64" && LDFLAGS="$LDFLAGS -L$LIBTAPI_DIR/lib64" + test -d "$LIBTAPI_DIR/lib32" && LDFLAGS="$LDFLAGS -L$LIBTAPI_DIR/lib32" + if test "x$rpathlink" = "xyes"; then + LIBTAPI_RPATH="-Wl,-rpath,$LIBTAPI_DIR/lib,--enable-new-dtags" + LIBTAPI_RPATH="$LIBTAPI_RPATH -Wl,-rpath,$LIBTAPI_DIR/lib64,--enable-new-dtags" + LIBTAPI_RPATH="$LIBTAPI_RPATH -Wl,-rpath,$LIBTAPI_DIR/lib32,--enable-new-dtags" + LDFLAGS="$LDFLAGS $LIBTAPI_RPATH" + fi + if test "x$isdarwin" = "xyes"; then + LIBTAPI_RPATH="-Wl,-rpath,$LIBTAPI_DIR/lib" + LDFLAGS="$LDFLAGS $LIBTAPI_RPATH" + fi + fi + + TAPI_LIB="" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking tapi/tapi.h and libtapi support" >&5 +$as_echo_n "checking tapi/tapi.h and libtapi support... " >&6; } +if ${cctools_cv_tapi_support+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + save_LIBS="$LIBS" + LIBS="$LIBS -ltapi" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +return tapi::APIVersion::getMajor(); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + cctools_cv_tapi_support=yes +else + cctools_cv_tapi_support=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$save_LIBS" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cctools_cv_tapi_support" >&5 +$as_echo "$cctools_cv_tapi_support" >&6; } + + if test $cctools_cv_tapi_support = yes; then + TAPI_LIB=-ltapi + TAPI_DEF=-DTAPI_SUPPORT + else + if test "x$LIBTAPI_DIR" != "x"; then + as_fn_error $? "-- ERROR: Failed TAPI checks in $LIBTAPI_DIR" "$LINENO" 5 + exit 1 + fi + echo "" + echo "### Building without TAPI support ###" + echo "### See README.md -> DEPENDENCIES ###" + echo "" + fi + + + +fi + +### Check whether we want to use clang as assembler ### + +# Check whether --enable-clang-as was given. +if test "${enable_clang_as+set}" = set; then : + enableval=$enable_clang_as; +else + enable_clang_as=yes +fi + + +if test "x$enable_clang_as" != "xyes"; then + CFLAGS="$CFLAGS -DDISABLE_CLANG_AS" +fi + +### Check endianness ### + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + ENDIAN_FLAG=-D__BIG_ENDIAN__=1 +;; #( + no) + ENDIAN_FLAG=-D__LITTLE_ENDIAN__=1 + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + + + +ac_config_files="$ac_config_files Makefile libstuff/Makefile libmacho/Makefile" + +ac_config_files="$ac_config_files ar/Makefile" + +ac_config_files="$ac_config_files as/Makefile" + +ac_config_files="$ac_config_files as/arm/Makefile" + +ac_config_files="$ac_config_files as/i386/Makefile" + +ac_config_files="$ac_config_files as/x86_64/Makefile" + +ac_config_files="$ac_config_files as/ppc/Makefile" + +ac_config_files="$ac_config_files as/ppc64/Makefile" + +ac_config_files="$ac_config_files man/Makefile" + +ac_config_files="$ac_config_files misc/Makefile" + +ac_config_files="$ac_config_files otool/Makefile" + +ac_config_files="$ac_config_files efitools/Makefile" + +ac_config_files="$ac_config_files libobjc2/Makefile" + +ac_config_files="$ac_config_files ld64/Makefile" + +ac_config_files="$ac_config_files ld64/doc/man/Makefile" + +ac_config_files="$ac_config_files ld64/src/Makefile" + +ac_config_files="$ac_config_files ld64/src/3rd/Makefile" + +ac_config_files="$ac_config_files ld64/src/3rd/BlocksRuntime/Makefile" + +ac_config_files="$ac_config_files ld64/src/ld/Makefile" + +ac_config_files="$ac_config_files ld64/src/ld/parsers/Makefile" + +ac_config_files="$ac_config_files ld64/src/ld/passes/Makefile" + +ac_config_files="$ac_config_files ld64/src/other/Makefile" + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +ac_script=' +:mline +/\\$/{ + N + s,\\\n,, + b mline +} +t clear +:clear +s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g +t quote +s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g +t quote +b any +:quote +s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g +s/\[/\\&/g +s/\]/\\&/g +s/\$/$$/g +H +:any +${ + g + s/^\n// + s/\n/ /g + p +} +' +DEFS=`sed -n "$ac_script" confdefs.h` + + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +if test -z "${ISDARWIN_TRUE}" && test -z "${ISDARWIN_FALSE}"; then + as_fn_error $? "conditional \"ISDARWIN\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ISDARWIN_TRUE}" && test -z "${ISDARWIN_FALSE}"; then + as_fn_error $? "conditional \"ISDARWIN\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by cctools $as_me 949.0.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +cctools config.status 949.0.1 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h | --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +lt_ar_flags='`$ECHO "$lt_ar_flags" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' +predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' +postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' +predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' +postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' +LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' +reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' +reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' +GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' +inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' +link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' +always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' +exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' +predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' +postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' +predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' +postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ +nm_file_list_spec \ +lt_cv_truncate_bin \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib \ +compiler_lib_search_dirs \ +predep_objects \ +postdep_objects \ +predeps \ +postdeps \ +compiler_lib_search_path \ +LD_CXX \ +reload_flag_CXX \ +compiler_CXX \ +lt_prog_compiler_no_builtin_flag_CXX \ +lt_prog_compiler_pic_CXX \ +lt_prog_compiler_wl_CXX \ +lt_prog_compiler_static_CXX \ +lt_cv_prog_compiler_c_o_CXX \ +export_dynamic_flag_spec_CXX \ +whole_archive_flag_spec_CXX \ +compiler_needs_object_CXX \ +with_gnu_ld_CXX \ +allow_undefined_flag_CXX \ +no_undefined_flag_CXX \ +hardcode_libdir_flag_spec_CXX \ +hardcode_libdir_separator_CXX \ +exclude_expsyms_CXX \ +include_expsyms_CXX \ +file_list_spec_CXX \ +compiler_lib_search_dirs_CXX \ +predep_objects_CXX \ +postdep_objects_CXX \ +predeps_CXX \ +postdeps_CXX \ +compiler_lib_search_path_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path \ +reload_cmds_CXX \ +old_archive_cmds_CXX \ +old_archive_from_new_cmds_CXX \ +old_archive_from_expsyms_cmds_CXX \ +archive_cmds_CXX \ +archive_expsym_cmds_CXX \ +module_cmds_CXX \ +module_expsym_cmds_CXX \ +export_symbols_cmds_CXX \ +prelink_cmds_CXX \ +postlink_cmds_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' + +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile' + + + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "libstuff/Makefile") CONFIG_FILES="$CONFIG_FILES libstuff/Makefile" ;; + "libmacho/Makefile") CONFIG_FILES="$CONFIG_FILES libmacho/Makefile" ;; + "ar/Makefile") CONFIG_FILES="$CONFIG_FILES ar/Makefile" ;; + "as/Makefile") CONFIG_FILES="$CONFIG_FILES as/Makefile" ;; + "as/arm/Makefile") CONFIG_FILES="$CONFIG_FILES as/arm/Makefile" ;; + "as/i386/Makefile") CONFIG_FILES="$CONFIG_FILES as/i386/Makefile" ;; + "as/x86_64/Makefile") CONFIG_FILES="$CONFIG_FILES as/x86_64/Makefile" ;; + "as/ppc/Makefile") CONFIG_FILES="$CONFIG_FILES as/ppc/Makefile" ;; + "as/ppc64/Makefile") CONFIG_FILES="$CONFIG_FILES as/ppc64/Makefile" ;; + "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; + "misc/Makefile") CONFIG_FILES="$CONFIG_FILES misc/Makefile" ;; + "otool/Makefile") CONFIG_FILES="$CONFIG_FILES otool/Makefile" ;; + "efitools/Makefile") CONFIG_FILES="$CONFIG_FILES efitools/Makefile" ;; + "libobjc2/Makefile") CONFIG_FILES="$CONFIG_FILES libobjc2/Makefile" ;; + "ld64/Makefile") CONFIG_FILES="$CONFIG_FILES ld64/Makefile" ;; + "ld64/doc/man/Makefile") CONFIG_FILES="$CONFIG_FILES ld64/doc/man/Makefile" ;; + "ld64/src/Makefile") CONFIG_FILES="$CONFIG_FILES ld64/src/Makefile" ;; + "ld64/src/3rd/Makefile") CONFIG_FILES="$CONFIG_FILES ld64/src/3rd/Makefile" ;; + "ld64/src/3rd/BlocksRuntime/Makefile") CONFIG_FILES="$CONFIG_FILES ld64/src/3rd/BlocksRuntime/Makefile" ;; + "ld64/src/ld/Makefile") CONFIG_FILES="$CONFIG_FILES ld64/src/ld/Makefile" ;; + "ld64/src/ld/parsers/Makefile") CONFIG_FILES="$CONFIG_FILES ld64/src/ld/parsers/Makefile" ;; + "ld64/src/ld/passes/Makefile") CONFIG_FILES="$CONFIG_FILES ld64/src/ld/passes/Makefile" ;; + "ld64/src/other/Makefile") CONFIG_FILES="$CONFIG_FILES ld64/src/other/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + + +eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "libtool":C) + + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +# The names of the tagged configurations supported by this script. +available_tags='CXX ' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive (by configure). +lt_ar_flags=$lt_ar_flags + +# Flags to create an archive. +AR_FLAGS=\${ARFLAGS-"\$lt_ar_flags"} + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and where our libraries should be installed. +lt_sysroot=$lt_sysroot + +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects +postdep_objects=$lt_postdep_objects +predeps=$lt_predeps +postdeps=$lt_postdeps + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path + +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain=$ac_aux_dir/ltmain.sh + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + + cat <<_LT_EOF >> "$ofile" + +# ### BEGIN LIBTOOL TAG CONFIG: CXX + +# The linker used to build libraries. +LD=$lt_LD_CXX + +# How to create reloadable object files. +reload_flag=$lt_reload_flag_CXX +reload_cmds=$lt_reload_cmds_CXX + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds_CXX + +# A language specific compiler. +CC=$lt_compiler_CXX + +# Is the compiler the GNU compiler? +with_gcc=$GCC_CXX + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_CXX + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_CXX + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_CXX + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_CXX + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object_CXX + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds_CXX +archive_expsym_cmds=$lt_archive_expsym_cmds_CXX + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds_CXX +module_expsym_cmds=$lt_module_expsym_cmds_CXX + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld_CXX + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_CXX + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_CXX + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct_CXX + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute_CXX + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L_CXX + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic_CXX + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath_CXX + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_CXX + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols_CXX + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_CXX + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_CXX + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_CXX + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds_CXX + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds_CXX + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec_CXX + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_CXX + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects_CXX +postdep_objects=$lt_postdep_objects_CXX +predeps=$lt_predeps_CXX +postdeps=$lt_postdeps_CXX + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_CXX + +# ### END LIBTOOL TAG CONFIG: CXX +_LT_EOF + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/cctools/configure.ac b/cctools/configure.ac index a6a3dd4..94ade4d 100644 --- a/cctools/configure.ac +++ b/cctools/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([cctools], [886], [t.poechtrager@gmail.com]) +AC_INIT([cctools], [949.0.1], [t.poechtrager@gmail.com]) AC_CANONICAL_BUILD AC_CANONICAL_HOST @@ -9,7 +9,6 @@ AC_ARG_PROGRAM AM_CONDITIONAL([ISDARWIN], [false]) isdarwin=no -iscygwin=no if test "x$CFLAGS" = "x"; then CFLAGS="-O3" @@ -43,69 +42,25 @@ case $host_os in isdarwin=yes AM_CONDITIONAL([ISDARWIN], [true]) ;; - openbsd* ) - XCC="egcc" - XCXX="eg++" - ;; cygwin* ) - iscygwin=yes - # https://github.com/tpoechtrager/osxcross/issues/87 - EXTRAFLAGS="-D__LARGE64_FILES -D_GNU_SOURCE -fno-PIC" - WARNINGS="-Wno-attributes" - XCC="gcc" - XCXX="g++" + echo "Cygwin is no longer supported." 1>&2 + exit 1 ;; esac -if test "x$isdarwin" = "xno"; then - case $host_cpu in - arm* ) - # clang miscompiles ld64 on arm - if test "x$isdarwin" = "xno"; then - XCC="gcc" - XCXX="g++" - fi - ;; - esac -fi - -if test "x$XCC" = "x"; then - XCC="clang" -fi - -if test "x$XCXX" = "x"; then - XCXX="clang++" -fi - if test "x$CC" = "x"; then if test "x$build" != "x$host"; then - CC="${host_alias}-${XCC}" - which $CC 2>/dev/null 1>&2 - if test $? -ne 0; then - CC="${host_alias}-gcc" - fi + CC="${host_alias}-clang" else - CC=$XCC - which $CC 2>/dev/null 1>&2 - if test $? -ne 0; then - CC="gcc" - fi + CC=clang fi fi if test "x$CXX" = "x"; then if test "x$build" != "x$host"; then - CXX="${host_alias}-${XCXX}" - which $CXX 2>/dev/null 1>&2 - if test $? -ne 0; then - CXX="${host_alias}-g++" - fi + CXX="${host_alias}-clang++" else - CXX=$XCXX - which $CXX 2>/dev/null 1>&2 - if test $? -ne 0; then - CXX="g++" - fi + CXX=clang++ fi fi @@ -120,26 +75,19 @@ case "$CCVERSION" in OBJCWARNINGS="-Wall -Wno-objc-root-class -Wno-deprecated-objc-isa-usage" ;; * ) - WARNINGS="$WARNINGS -Wall -Wno-format -Wno-enum-compare -Wno-unused-result -Wno-unused-variable" - WARNINGS="$WARNINGS -Wno-unused-but-set-variable -Wno-deprecated -Wno-deprecated-declarations" - WARNINGS="$WARNINGS -Wno-char-subscripts -Wno-strict-aliasing" - OBJCWARNINGS="-Wall" - CFLAGS="$CFLAGS -std=gnu99 -D__private_extern__=" - CXXFLAGS="$CXXFLAGS -D__private_extern__=" + echo "You must compile this project with clang. Other compilers are no longer supported." 2>&1 + exit 1 ;; esac +EXTRAFLAGS="$EXTRAFLAGS -DLD64_VERSION_NUM=512.4" + case "$CXXVERSION" in *clang* ) if test "x$isdarwin" = "xyes"; then CXXFLAGS="$CXXFLAGS -stdlib=libc++" fi - # can't use -fblocks on cyggwin due to a clang driver bug - if test "x$iscygwin" = "xno"; then - EXTRACXXFLAGS="$EXTRACXXFLAGS -fblocks" - else - EXTRAFLAGS="$EXTRAFLAGS -integrated-as" - fi + EXTRACXXFLAGS="$EXTRACXXFLAGS -fblocks" ;; esac @@ -154,21 +102,6 @@ case $host_cpu in EXTRAFLAGS="$EXTRAFLAGS -D__arm64__" ;; arm*) - case "$CXXVERSION" in - *clang* ) - echo "" >&2 - echo "clang is known to miscompile ld64 on arm platforms:" >&2 - echo "https://github.com/tpoechtrager/cctools-port/issues/1#issuecomment-59118615" >&2 - if test "x$isdarwin" = "xno"; then - echo "" >&2 - echo "please use gcc instead; CC=gcc CXX=g++ ./configure" >&2 - echo "" >&2 - exit 1 - fi - echo "" >&2 - sleep 2 - ;; - esac EXTRAFLAGS="$EXTRAFLAGS -D__arm__" ;; esac @@ -268,7 +201,65 @@ AC_CHECK_LIB([uuid],[uuid_generate_random],[ AC_CHECK_HEADERS([uuid/uuid.h], [UUID_LIB=-luuid])], []) AC_SUBST(UUID_LIB) -AC_CHECK_FUNCS([strmode]) +AC_CHECK_FUNCS([strmode utimens utimensat]) +AC_CHECK_FUNCS([bcopy bcmp bzero index rindex]) + +### Check how to access struct stat's tv_nsec field. +AC_MSG_CHECKING(for st_mtimespec.tv_nsec in struct stat) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[ + struct stat st; + st.st_mtimespec.tv_nsec = 0; + ]])], + [AC_DEFINE(HAVE_STAT_ST_MTIMESPEC, 1, [struct stat has st_mtimespec.tv_nsec]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) + +AC_MSG_CHECKING(for st_mtim.tv_nsec in struct stat) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[ + struct stat st; + st.st_mtim.tv_nsec = 0; + ]])], + [AC_DEFINE(HAVE_STAT_ST_MTIM, 1, [struct stat has st_mtim.tv_nsec]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) + +### Check for log2 in -lm + +AC_CHECK_LIB([m], [log2], [ + MATH_LIB="-lm" +]) + +AC_SUBST(MATH_LIB) + +### Check for reallocf in -lc, -lbsd + +AC_CHECK_HEADERS([bsd/stdlib.h], []) + +AC_CHECK_LIB([c],[reallocf],[ + REALLOCF_LIB="" + AC_DEFINE(HAVE_REALLOCF, 1) + ],[ + AC_CHECK_LIB([bsd],[reallocf],[ + REALLOCF_LIB=-lbsd + AC_DEFINE(HAVE_REALLOCF, 1) + ],[]) +]) + +AC_SUBST(REALLOCF_LIB) + +### Check for clock_gettime + +AC_CHECK_FUNC([clock_gettime],[AC_DEFINE(HAVE_CLOCK_GETTIME, 1)]) + +### Check for write64 + +AC_CHECK_FUNC([write64],[AC_DEFINE(HAVE_WRITE64, 1)]) ### Check for __cxa_demangle in various C++ ABI libs ### @@ -282,6 +273,14 @@ AC_CHECK_LIB([c++abi],[__cxa_demangle],[CXXABI_LIB=-lc++abi],[ AC_SUBST(CXXABI_LIB) +### Check for __gcc_personality_v0 in -lgcc (NetBSD needs this) + +AC_CHECK_LIB([gcc], [__gcc_personality_v0], [ + GCC_LIB="-lgcc" +]) + +AC_SUBST(GCC_LIB) + ### Check for supported warning options ### ORIGCFLAGS=$CFLAGS @@ -295,6 +294,17 @@ AC_COMPILE_IFELSE( ) CFLAGS=$ORIGCFLAGS +ORIGCFLAGS=$CFLAGS +CFLAGS="$CFLAGS -Werror -Wno-misleading-indentation" +AC_MSG_CHECKING([whether $CC supports -Wno-misleading-indentation]) +AC_COMPILE_IFELSE( + [AC_LANG_SOURCE([[int dummy;]])], + [WARNINGS="$WARNINGS -Wno-misleading-indentation" + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])] +) +CFLAGS=$ORIGCFLAGS + AC_SUBST([WARNINGS], [$WARNINGS]) AC_SUBST([OBJCWARNINGS], [$OBJCWARNINGS]) @@ -312,17 +322,121 @@ AC_LINK_IFELSE( LDFLAGS=$ORIGLDFLAGS CHECK_LLVM - LDFLAGS="$LDFLAGS $LTO_RPATH" -### Check for libxar ### +### Check for libfts (musl) ### -if test "x$LLVM_CONFIG" != "xno"; then +AC_CHECK_LIB([fts],[fts_open],[ + AC_CHECK_HEADERS([fts.h], [FTS_LIB=-lfts])], []) +AC_SUBST(FTS_LIB) -AC_CHECK_LIB([xar],[xar_prop_create],[ - AC_CHECK_HEADERS([xar/xar.h], [XAR_LIB=-lxar])], []) -AC_SUBST(XAR_LIB) +### Check for XAR ### +AC_ARG_ENABLE([xar-support], +AS_HELP_STRING([--enable-xar-support], + [enable xar support]), +[], [enable_xar_support=yes]) + +if test "x$LTO_LIB" != "x"; then + if test "x$enable_xar_support" = "xyes"; then + AC_ARG_WITH([libxar], + AS_HELP_STRING([--with-libxar], + [path to the XAR library]), + [XAR_DIR=$with_libxar], [XAR_DIR=""]) + + if test "x$XAR_DIR" = "xno"; then + XAR_DIR="" + fi + + if test "x$XAR_DIR" != "x"; then + CXXFLAGS="$CXXFLAGS -isystem $XAR_DIR/include" + CPPFLAGS="$CPPFLAGS -isystem $XAR_DIR/include" + test -d "$XAR_DIR/lib" && LDFLAGS="$LDFLAGS -L$XAR_DIR/lib" + test -d "$XAR_DIR/lib64" && LDFLAGS="$LDFLAGS -L$XAR_DIR/lib64" + test -d "$XAR_DIR/lib32" && LDFLAGS="$LDFLAGS -L$XAR_DIR/lib32" + if test "x$rpathlink" = "xyes"; then + XAR_RPATH="-Wl,-rpath,$XAR_DIR/lib,--enable-new-dtags" + XAR_RPATH="$XAR_RPATH -Wl,-rpath,$XAR_DIR/lib64,--enable-new-dtags" + XAR_RPATH="$XAR_RPATH -Wl,-rpath,$XAR_DIR/lib32,--enable-new-dtags" + LDFLAGS="$LDFLAGS $XAR_RPATH" + fi + if test "x$isdarwin" = "xyes"; then + XAR_RPATH="-Wl,-rpath,$XAR_DIR/lib" + LDFLAGS="$LDFLAGS $XAR_RPATH" + fi + fi + + XAR_LIB="" + + AC_CHECK_LIB([xar],[xar_prop_create],[ + AC_CHECK_HEADERS([xar/xar.h], [XAR_LIB=-lxar])], []) + AC_SUBST(XAR_LIB) + fi +fi + +### Check for Apple TAPI library ### + +AC_ARG_ENABLE([tapi-support], +AS_HELP_STRING([--enable-tapi-support], + [enable tapi support]), +[], [enable_tapi_support=yes]) + +if test "x$enable_tapi_support" = "xyes"; then + AC_ARG_WITH([libtapi], + AS_HELP_STRING([--with-libtapi], + [path to the apple tapi library]), + [LIBTAPI_DIR=$with_libtapi], [LIBTAPI_DIR=""]) + + if test "x$LIBTAPI_DIR" = "xno"; then + LIBTAPI_DIR="" + fi + if test "x$LIBTAPI_DIR" != "x"; then + CXXFLAGS="$CXXFLAGS -isystem $LIBTAPI_DIR/include" + CPPFLAGS="$CPPFLAGS -isystem $LIBTAPI_DIR/include" + test -d "$LIBTAPI_DIR/lib" && LDFLAGS="$LDFLAGS -L$LIBTAPI_DIR/lib" + test -d "$LIBTAPI_DIR/lib64" && LDFLAGS="$LDFLAGS -L$LIBTAPI_DIR/lib64" + test -d "$LIBTAPI_DIR/lib32" && LDFLAGS="$LDFLAGS -L$LIBTAPI_DIR/lib32" + if test "x$rpathlink" = "xyes"; then + LIBTAPI_RPATH="-Wl,-rpath,$LIBTAPI_DIR/lib,--enable-new-dtags" + LIBTAPI_RPATH="$LIBTAPI_RPATH -Wl,-rpath,$LIBTAPI_DIR/lib64,--enable-new-dtags" + LIBTAPI_RPATH="$LIBTAPI_RPATH -Wl,-rpath,$LIBTAPI_DIR/lib32,--enable-new-dtags" + LDFLAGS="$LDFLAGS $LIBTAPI_RPATH" + fi + if test "x$isdarwin" = "xyes"; then + LIBTAPI_RPATH="-Wl,-rpath,$LIBTAPI_DIR/lib" + LDFLAGS="$LDFLAGS $LIBTAPI_RPATH" + fi + fi + + TAPI_LIB="" + AC_CACHE_CHECK([tapi/tapi.h and libtapi support],[cctools_cv_tapi_support], + AC_LANG_PUSH([C++]) + save_LIBS="$LIBS" + LIBS="$LIBS -ltapi" + AC_TRY_LINK([#include ], + [return tapi::APIVersion::getMajor();], + [cctools_cv_tapi_support=yes], + [cctools_cv_tapi_support=no]) + LIBS="$save_LIBS" + AC_LANG_POP([C++]) + ) + + if test $cctools_cv_tapi_support = yes; then + TAPI_LIB=-ltapi + TAPI_DEF=-DTAPI_SUPPORT + else + if test "x$LIBTAPI_DIR" != "x"; then + AC_MSG_ERROR([-- ERROR: Failed TAPI checks in $LIBTAPI_DIR]) + exit 1 + fi + echo "" + echo "### Building without TAPI support ###" + echo "### See README.md -> DEPENDENCIES ###" + echo "" + fi + + AC_SUBST(TAPI_LIB) + AC_SUBST(TAPI_DEF) fi ### Check whether we want to use clang as assembler ### @@ -342,7 +456,7 @@ AC_C_BIGENDIAN([AC_SUBST([ENDIAN_FLAG],[-D__BIG_ENDIAN__=1])], [AC_SUBST([ENDIAN_FLAG],[-D__LITTLE_ENDIAN__=1])]) -AC_CONFIG_FILES([Makefile libstuff/Makefile]) +AC_CONFIG_FILES([Makefile libstuff/Makefile libmacho/Makefile]) AC_CONFIG_FILES([ar/Makefile]) AC_CONFIG_FILES([as/Makefile]) AC_CONFIG_FILES([as/arm/Makefile]) @@ -350,15 +464,13 @@ AC_CONFIG_FILES([as/i386/Makefile]) AC_CONFIG_FILES([as/x86_64/Makefile]) AC_CONFIG_FILES([as/ppc/Makefile]) AC_CONFIG_FILES([as/ppc64/Makefile]) -#AC_CONFIG_FILES([man/Makefile]) +AC_CONFIG_FILES([man/Makefile]) AC_CONFIG_FILES([misc/Makefile]) AC_CONFIG_FILES([otool/Makefile]) - -if test "x$isdarwin" != "xyes"; then - AC_CONFIG_FILES([libobjc2/Makefile]) -fi - +AC_CONFIG_FILES([efitools/Makefile]) +AC_CONFIG_FILES([libobjc2/Makefile]) AC_CONFIG_FILES([ld64/Makefile]) +AC_CONFIG_FILES([ld64/doc/man/Makefile]) AC_CONFIG_FILES([ld64/src/Makefile]) AC_CONFIG_FILES([ld64/src/3rd/Makefile]) AC_CONFIG_FILES([ld64/src/3rd/BlocksRuntime/Makefile]) diff --git a/cctools/efitools/Makefile.am b/cctools/efitools/Makefile.am new file mode 100644 index 0000000..7e9db17 --- /dev/null +++ b/cctools/efitools/Makefile.am @@ -0,0 +1,15 @@ +bin_PROGRAMS = \ + makerelocs \ + mtoc \ + mtor + +LDADD = \ + $(top_builddir)/libstuff/libstuff.la \ + $(REALLOCF_LIB) \ + $(DL_LIB) + +AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -I$(top_srcdir)/libstuff $(WARNINGS) $(LTO_DEF) -D__DARWIN_UNIX03 $(ENDIAN_FLAG) + +makerelocs_SOURCES= makerelocs.c +mtoc_SOURCES= mtoc.c +mtor_SOURCES= mtor.c diff --git a/cctools/efitools/Makefile.in b/cctools/efitools/Makefile.in new file mode 100644 index 0000000..1daed90 --- /dev/null +++ b/cctools/efitools/Makefile.in @@ -0,0 +1,674 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = makerelocs$(EXEEXT) mtoc$(EXEEXT) mtor$(EXEEXT) +subdir = efitools +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_makerelocs_OBJECTS = makerelocs.$(OBJEXT) +makerelocs_OBJECTS = $(am_makerelocs_OBJECTS) +makerelocs_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +makerelocs_DEPENDENCIES = $(top_builddir)/libstuff/libstuff.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +am_mtoc_OBJECTS = mtoc.$(OBJEXT) +mtoc_OBJECTS = $(am_mtoc_OBJECTS) +mtoc_LDADD = $(LDADD) +mtoc_DEPENDENCIES = $(top_builddir)/libstuff/libstuff.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am_mtor_OBJECTS = mtor.$(OBJEXT) +mtor_OBJECTS = $(am_mtor_OBJECTS) +mtor_LDADD = $(LDADD) +mtor_DEPENDENCIES = $(top_builddir)/libstuff/libstuff.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(makerelocs_SOURCES) $(mtoc_SOURCES) $(mtor_SOURCES) +DIST_SOURCES = $(makerelocs_SOURCES) $(mtoc_SOURCES) $(mtor_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +LDADD = \ + $(top_builddir)/libstuff/libstuff.la \ + $(REALLOCF_LIB) \ + $(DL_LIB) + +AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -I$(top_srcdir)/libstuff $(WARNINGS) $(LTO_DEF) -D__DARWIN_UNIX03 $(ENDIAN_FLAG) +makerelocs_SOURCES = makerelocs.c +mtoc_SOURCES = mtoc.c +mtor_SOURCES = mtor.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps efitools/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps efitools/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +makerelocs$(EXEEXT): $(makerelocs_OBJECTS) $(makerelocs_DEPENDENCIES) $(EXTRA_makerelocs_DEPENDENCIES) + @rm -f makerelocs$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(makerelocs_OBJECTS) $(makerelocs_LDADD) $(LIBS) + +mtoc$(EXEEXT): $(mtoc_OBJECTS) $(mtoc_DEPENDENCIES) $(EXTRA_mtoc_DEPENDENCIES) + @rm -f mtoc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(mtoc_OBJECTS) $(mtoc_LDADD) $(LIBS) + +mtor$(EXEEXT): $(mtor_OBJECTS) $(mtor_DEPENDENCIES) $(EXTRA_mtor_DEPENDENCIES) + @rm -f mtor$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(mtor_OBJECTS) $(mtor_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-binPROGRAMS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/efitools/makerelocs.c b/cctools/efitools/makerelocs.c index 190a188..4d608e4 100644 --- a/cctools/efitools/makerelocs.c +++ b/cctools/efitools/makerelocs.c @@ -31,6 +31,7 @@ #include "stuff/ofile.h" #include "stuff/errors.h" #include "stuff/reloc.h" +#include "stuff/write64.h" #include "coff/base_relocs.h" #include "coff/bytesex.h" #include "mach-o/x86_64/reloc.h" @@ -474,7 +475,8 @@ char *out) target_byte_sex); } // write out the block then start a new one - write(f, fb, size); + if (write64(f, fb, size) != size) + fatal("failed to write block"); entries = 0; blockcnt++; @@ -501,7 +503,8 @@ char *out) swap_base_relocation_entry(b, entries, target_byte_sex); } /* write out the last block */ - write(f, fb, size); + if (write64(f, fb, size) != size) + fatal("failed to write last block"); blockcnt++; close(f); diff --git a/cctools/efitools/mtoc.c b/cctools/efitools/mtoc.c index 2ef3588..5acab70 100644 --- a/cctools/efitools/mtoc.c +++ b/cctools/efitools/mtoc.c @@ -35,6 +35,7 @@ #include "stuff/allocate.h" #include "stuff/reloc.h" #include "stuff/rnd.h" +#include "stuff/write64.h" #include "coff/ms_dos_stub.h" #include "coff/filehdr.h" @@ -58,6 +59,9 @@ static enum bool swapped; /* the size of the pecoff output file */ static uint32_t output_size = 0; +static uint32_t majorVersion = 0; +static uint32_t minorVersion = 0; + /* * The headers, and elements of them in the pecoff output file. */ @@ -339,7 +343,7 @@ char **envp) "option"); usage(); } - section_alignment = strtoul(argv[i+1], &endp, 16); + section_alignment = (uint32_t)strtoul(argv[i+1], &endp, 16); if(*endp != '\0') fatal("argument for -section_alignment %s not a proper " "hexadecimal number", argv[i+1]); @@ -363,7 +367,7 @@ char **envp) warning("no argument specified for -align option"); usage(); } - file_alignment = strtoul(argv[i+1], &endp, 16); + file_alignment = (uint32_t)strtoul(argv[i+1], &endp, 16); if(*endp != '\0') fatal("argument for -align %s not a proper hexadecimal " "number", argv[i+1]); @@ -383,6 +387,18 @@ char **envp) section_alignment = file_alignment; i++; } + else if(strcmp(argv[i], "-version") == 0){ + if(i + 1 >= argc){ + warning("no argument specified for -version option"); + usage(); + } + if (sscanf(argv[i+1], "%u.%u", &majorVersion, + &minorVersion) != 2){ + warning("invalid argument specified for -version option"); + usage(); + } + i++; + } else if(input == NULL) input = argv[i]; else if(output == NULL) @@ -438,7 +454,8 @@ usage( void) { fprintf(stderr, "Usage: %s [-subsystem type] " - "[-section_alignment hexvalue] [-align hexvalue] [-d debug_filename] " + "[-section_alignment hexvalue] [-align hexvalue] " + "[-version major.minor] [-ddebug_filename] " "[-u debug_guid] input_Mach-O output_pecoff\n", progname); exit(EXIT_FAILURE); } @@ -669,7 +686,6 @@ struct arch *arch) switch(arch->object->mh_cputype){ case CPU_TYPE_I386: switch((int)flavor){ - i386_thread_state_t *cpu; case i386_THREAD_STATE: #if i386_THREAD_STATE == 1 case -1: @@ -678,9 +694,12 @@ struct arch *arch) #if i386_THREAD_STATE == -1 case 1: #endif /* i386_THREAD_STATE == -1 */ - cpu = (i386_thread_state_t *)state; - entry = cpu->eip; - state += sizeof(i386_thread_state_t); + { + i386_thread_state_t *cpu = + (i386_thread_state_t *)state; + entry = cpu->eip; + state += sizeof(i386_thread_state_t); + } break; default: state += count * sizeof(uint32_t); @@ -689,11 +708,13 @@ struct arch *arch) break; case CPU_TYPE_ARM: switch(flavor){ - arm_thread_state_t *cpu; case ARM_THREAD_STATE: - cpu = (arm_thread_state_t *)state; - entry = cpu->__pc; - state += sizeof(arm_thread_state_t); + { + arm_thread_state_t *cpu = + (arm_thread_state_t *)state; + entry = cpu->__pc; + state += sizeof(arm_thread_state_t); + } break; default: state += count * sizeof(uint32_t); @@ -776,7 +797,7 @@ struct arch *arch) scnhdrs[j].s_vsize = sg->vmsize; #endif scnhdrs[j].s_vaddr = sg->vmaddr; - scnhdrs[j].s_size = rnd(sg->filesize, file_alignment); + scnhdrs[j].s_size = rnd32(sg->filesize, file_alignment); scnhdrs[j].s_relptr = 0; scnhdrs[j].s_lnnoptr = 0; scnhdrs[j].s_nlnno = 0; @@ -794,7 +815,7 @@ struct arch *arch) scnhdrs[j].s_vsize = sg->vmsize; #endif scnhdrs[j].s_vaddr = sg->vmaddr; - scnhdrs[j].s_size = rnd(sg->filesize, file_alignment); + scnhdrs[j].s_size = rnd32(sg->filesize, file_alignment); scnhdrs[j].s_relptr = 0; scnhdrs[j].s_lnnoptr = 0; scnhdrs[j].s_nlnno = 0; @@ -841,7 +862,7 @@ struct arch *arch) strcpy(scnhdrs[j].s_name, ".import"); scnhdrs[j].s_vsize = sg->vmsize; scnhdrs[j].s_vaddr = sg->vmaddr; - scnhdrs[j].s_size = rnd(sg->filesize, file_alignment); + scnhdrs[j].s_size = rnd32(sg->filesize, file_alignment); scnhdrs[j].s_relptr = 0; scnhdrs[j].s_lnnoptr = 0; scnhdrs[j].s_nlnno = 0; @@ -882,9 +903,9 @@ struct arch *arch) if(reloc_size != 0){ strcpy(scnhdrs[j].s_name, ".reloc"); scnhdrs[j].s_vsize = reloc_size; - reloc_addr = rnd(reloc_addr, section_alignment); + reloc_addr = rnd32(reloc_addr, section_alignment); scnhdrs[j].s_vaddr = reloc_addr; - scnhdrs[j].s_size = rnd(reloc_size, file_alignment); + scnhdrs[j].s_size = rnd32(reloc_size, file_alignment); scnhdrs[j].s_relptr = 0; scnhdrs[j].s_lnnoptr = 0; scnhdrs[j].s_nlnno = 0; @@ -897,14 +918,14 @@ struct arch *arch) debug_addr = reloc_addr + reloc_scnhdr->s_size; } else{ - debug_addr = rnd(reloc_addr, section_alignment); + debug_addr = rnd32(reloc_addr, section_alignment); } if(debug_filename != NULL){ strcpy(scnhdrs[j].s_name, ".debug"); scnhdrs[j].s_vsize = debug_size; scnhdrs[j].s_vaddr = debug_addr; - scnhdrs[j].s_size = rnd(debug_size, file_alignment); + scnhdrs[j].s_size = rnd32(debug_size, file_alignment); scnhdrs[j].s_relptr = 0; scnhdrs[j].s_lnnoptr = 0; scnhdrs[j].s_nlnno = 0; @@ -1015,11 +1036,17 @@ struct arch *arch) #ifdef x86_THREAD_STATE64 case CPU_TYPE_X86_64: switch(flavor){ - x86_thread_state64_t *cpu64; case x86_THREAD_STATE64: - cpu64 = (x86_thread_state64_t *)state; - entry = cpu64->rip; - state += sizeof(x86_thread_state64_t); + { + x86_thread_state64_t *cpu64 = + (x86_thread_state64_t *)state; + /* + * The aouthdr_64 struct only allows for a + * 32-bit entry point. + */ + entry = (uint32_t)cpu64->rip; + state += sizeof(x86_thread_state64_t); + } break; default: state += count * sizeof(uint32_t); @@ -1030,11 +1057,17 @@ struct arch *arch) #ifdef ARM_THREAD_STATE64 case CPU_TYPE_ARM64: switch(flavor){ - arm_thread_state64_t *cpu64; case ARM_THREAD_STATE64: - cpu64 = (arm_thread_state64_t *)state; - entry = cpu64->__pc; - state += sizeof(arm_thread_state64_t); + { + arm_thread_state64_t *cpu64 = + (arm_thread_state64_t *)state; + /* + * The aouthdr_64 struct only allows for a + * 32-bit entry point. + */ + entry = (uint32_t)cpu64->__pc; + state += sizeof(arm_thread_state64_t); + } break; default: state += count * sizeof(uint32_t); @@ -1111,9 +1144,10 @@ struct arch *arch) #ifndef HACK_TO_MATCH_TEST_CASE if(strcmp(sg64->segname, SEG_TEXT) == 0){ strcpy(scnhdrs[j].s_name, ".text"); - scnhdrs[j].s_vsize = sg64->vmsize; - scnhdrs[j].s_vaddr = sg64->vmaddr; - scnhdrs[j].s_size = rnd(sg64->filesize, file_alignment); + scnhdrs[j].s_vsize = (uint32_t)sg64->vmsize; + scnhdrs[j].s_vaddr = (uint32_t)sg64->vmaddr; + scnhdrs[j].s_size = (uint32_t)rnd64(sg64->filesize, + file_alignment); scnhdrs[j].s_relptr = 0; scnhdrs[j].s_lnnoptr = 0; scnhdrs[j].s_nlnno = 0; @@ -1125,9 +1159,10 @@ struct arch *arch) } else if(strcmp(sg64->segname, SEG_DATA) == 0){ strcpy(scnhdrs[j].s_name, ".data"); - scnhdrs[j].s_vsize = sg64->vmsize; - scnhdrs[j].s_vaddr = sg64->vmaddr; - scnhdrs[j].s_size = rnd(sg64->filesize, file_alignment); + scnhdrs[j].s_vsize = (uint32_t)sg64->vmsize; + scnhdrs[j].s_vaddr = (uint32_t)sg64->vmaddr; + scnhdrs[j].s_size = (uint32_t)rnd64(sg64->filesize, + file_alignment); scnhdrs[j].s_relptr = 0; scnhdrs[j].s_lnnoptr = 0; scnhdrs[j].s_nlnno = 0; @@ -1176,8 +1211,8 @@ struct arch *arch) strcpy(scnhdrs[j].s_name, ".reloc"); scnhdrs[j].s_vsize = reloc_size; reloc_addr = rnd(reloc_addr, section_alignment); - scnhdrs[j].s_vaddr = reloc_addr; - scnhdrs[j].s_size = rnd(reloc_size, file_alignment); + scnhdrs[j].s_vaddr = (uint32_t)reloc_addr; + scnhdrs[j].s_size = rnd32(reloc_size, file_alignment); scnhdrs[j].s_relptr = 0; scnhdrs[j].s_lnnoptr = 0; scnhdrs[j].s_nlnno = 0; @@ -1198,8 +1233,8 @@ struct arch *arch) if(debug_filename != NULL){ strcpy(scnhdrs[j].s_name, ".debug"); scnhdrs[j].s_vsize = debug_size; - scnhdrs[j].s_vaddr = debug_addr; - scnhdrs[j].s_size = rnd(debug_size, file_alignment); + scnhdrs[j].s_vaddr = (uint32_t)debug_addr; + scnhdrs[j].s_size = rnd32(debug_size, file_alignment); scnhdrs[j].s_relptr = 0; scnhdrs[j].s_lnnoptr = 0; scnhdrs[j].s_nlnno = 0; @@ -1244,7 +1279,7 @@ struct ofile *ofile) header_size += sizeof(struct aouthdr); else header_size += sizeof(struct aouthdr_64); - header_size = rnd(header_size, file_alignment); + header_size = rnd32(header_size, file_alignment); #ifdef HACK_TO_MATCH_TEST_CASE /* for some unknown reason the header size is 0x488 not 0x400 */ if(ofile->mh64 != NULL) @@ -1305,7 +1340,7 @@ struct ofile *ofile) #ifdef HACK_TO_MATCH_TEST_CASE if(ofile->mh != NULL) #endif - offset = rnd(offset, file_alignment); + offset = rnd32(offset, file_alignment); #ifdef HACK_TO_MATCH_TEST_CASE else{ /* for some unknown reason the next offset is moved up @@ -1368,7 +1403,7 @@ struct ofile *ofile) else filehdr.f_timdat = 0x47671e62; #else - filehdr.f_timdat = time(NULL); + filehdr.f_timdat = (uint32_t)time(NULL); #endif filehdr.f_symptr = syment_offset; filehdr.f_nsyms = nsyments; @@ -1395,9 +1430,9 @@ struct ofile *ofile) aouthdr.tsize = 0; aouthdr.dsize = 0; aouthdr.bsize = 0; - aouthdr.SizeOfImage = rnd(header_size, section_alignment); + aouthdr.SizeOfImage = rnd32(header_size, section_alignment); for(i = 0; i < nscns; i++){ - aouthdr.SizeOfImage += rnd(scnhdrs[i].s_vsize, section_alignment); + aouthdr.SizeOfImage += rnd32(scnhdrs[i].s_vsize, section_alignment); } aouthdr.entry = entry; @@ -1422,8 +1457,8 @@ struct ofile *ofile) aouthdr.FileAlignment = file_alignment; aouthdr.MajorOperatingSystemVersion = 0; aouthdr.MinorOperatingSystemVersion = 0; - aouthdr.MajorImageVersion = 0; - aouthdr.MinorImageVersion = 0; + aouthdr.MajorImageVersion = majorVersion; + aouthdr.MinorImageVersion = minorVersion; aouthdr.MajorSubsystemVersion = 0; aouthdr.MinorSubsystemVersion = 0; aouthdr.Win32VersionValue = 0; @@ -1462,7 +1497,7 @@ struct ofile *ofile) aouthdr64.dsize = 0; aouthdr64.bsize = 0; - aouthdr64.SizeOfImage = rnd(header_size, section_alignment); + aouthdr64.SizeOfImage = rnd32(header_size, section_alignment); for(i = 0; i < nscns; i++){ aouthdr64.SizeOfImage += rnd(scnhdrs[i].s_vsize, section_alignment); } @@ -1471,7 +1506,10 @@ struct ofile *ofile) just a quick hack to match the PECOFF file */ aouthdr64.dsize = 0x200; #endif - + /* + * The aouthdr_64 struct only allows for a + * 32-bit entry point. + */ aouthdr64.entry = entry; #ifdef HACK_TO_MATCH_TEST_CASE aouthdr64.entry = 0x4a2; @@ -1496,8 +1534,8 @@ struct ofile *ofile) aouthdr64.FileAlignment = file_alignment; aouthdr64.MajorOperatingSystemVersion = 0; aouthdr64.MinorOperatingSystemVersion = 0; - aouthdr64.MajorImageVersion = 0; - aouthdr64.MinorImageVersion = 0; + aouthdr64.MajorImageVersion = majorVersion; + aouthdr64.MinorImageVersion = minorVersion; aouthdr64.MajorSubsystemVersion = 0; aouthdr64.MinorSubsystemVersion = 0; aouthdr64.Win32VersionValue = 0; @@ -1654,7 +1692,7 @@ char *out) if(f == -1) system_fatal("Can't create output file: %s", out); - if(write(f, buf, output_size) != output_size) + if(write64(f, buf, output_size) != (ssize_t)output_size) system_fatal("Can't write output file: %s", out); if(close(f) == -1) @@ -2015,7 +2053,7 @@ struct arch *arch) if((syms64[i].n_type & N_STAB) == 0 && syms64[i].n_un.n_strx != 0 && strcmp(strs + syms64[i].n_un.n_strx, entry_point) == 0){ - entry = syms64[i].n_value; + entry = (uint32_t)syms64[i].n_value; break; } } @@ -2163,11 +2201,11 @@ struct arch *arch) swap_relocation_info(relocs, s64[j].nreloc, host_byte_sex); if(arch->object->mh_cputype == CPU_TYPE_X86_64) - gather_base_reloc_info(s64[j].addr, relocs, + gather_base_reloc_info((uint32_t)s64[j].addr, relocs, s64[j].nreloc, CPU_TYPE_X86_64, 3, X86_64_RELOC_UNSIGNED, IMAGE_REL_BASED_DIR64); else if(arch->object->mh_cputype == CPU_TYPE_ARM64) - gather_base_reloc_info(s64[j].addr, relocs, + gather_base_reloc_info((uint32_t)s64[j].addr, relocs, s64[j].nreloc, CPU_TYPE_ARM64, 3, ARM64_RELOC_UNSIGNED, IMAGE_REL_BASED_DIR64); if((s64[j].flags & SECTION_TYPE) == @@ -2188,21 +2226,25 @@ struct arch *arch) if(swapped) swap_relocation_info(relocs, dyst->nlocrel, host_byte_sex); if(arch->object->mh_cputype == CPU_TYPE_I386) - gather_base_reloc_info(first_addr, relocs, dyst->nlocrel, - CPU_TYPE_I386, 2, GENERIC_RELOC_VANILLA, - IMAGE_REL_BASED_HIGHLOW); + gather_base_reloc_info((uint32_t)first_addr, relocs, + dyst->nlocrel, CPU_TYPE_I386, 2, + GENERIC_RELOC_VANILLA, + IMAGE_REL_BASED_HIGHLOW); else if(arch->object->mh_cputype == CPU_TYPE_ARM) - gather_base_reloc_info(first_addr, relocs, dyst->nlocrel, - CPU_TYPE_ARM, 2, GENERIC_RELOC_VANILLA, - IMAGE_REL_BASED_HIGHLOW); + gather_base_reloc_info((uint32_t)first_addr, relocs, + dyst->nlocrel, CPU_TYPE_ARM, 2, + GENERIC_RELOC_VANILLA, + IMAGE_REL_BASED_HIGHLOW); else if(arch->object->mh_cputype == CPU_TYPE_X86_64) - gather_base_reloc_info(first_addr, relocs, dyst->nlocrel, - CPU_TYPE_X86_64, 3, X86_64_RELOC_UNSIGNED, - IMAGE_REL_BASED_DIR64); + gather_base_reloc_info((uint32_t)first_addr, relocs, + dyst->nlocrel, CPU_TYPE_X86_64, 3, + X86_64_RELOC_UNSIGNED, + IMAGE_REL_BASED_DIR64); else if(arch->object->mh_cputype == CPU_TYPE_ARM64) - gather_base_reloc_info(first_addr, relocs, dyst->nlocrel, - CPU_TYPE_ARM64, 3, ARM64_RELOC_UNSIGNED, - IMAGE_REL_BASED_DIR64); + gather_base_reloc_info((uint32_t)first_addr, relocs, + dyst->nlocrel, CPU_TYPE_ARM64, 3, + ARM64_RELOC_UNSIGNED, + IMAGE_REL_BASED_DIR64); } /* if(dyst != NULL && dyst->nextrel != 0) @@ -2322,7 +2364,7 @@ void) int blockcnt; int i, entries; uint64_t base; - int size; + int size, s_size, pad; char *fb; struct base_relocation_block_header *h; struct base_relocation_entry *b; @@ -2366,7 +2408,7 @@ void) b = (struct base_relocation_entry *) (fb + sizeof(struct base_relocation_block_header)); for(i = 0; i < nbase_reloc; i++){ - offset = base_relocs[i].addr - base; + offset = (uint32_t)(base_relocs[i].addr - base); if(offset >= MAX_BLOCK_OFFSET) { /* add padding if needed */ if((entries % 2) != 0){ @@ -2374,7 +2416,7 @@ void) b[entries].offset = 0; entries++; } - h->page_rva = base; + h->page_rva = (uint32_t)base; size = sizeof(struct base_relocation_block_header) + entries * sizeof(struct base_relocation_entry); h->block_size = size; @@ -2392,7 +2434,7 @@ void) entries = 0; blockcnt++; base = base_relocs[i].addr & ~BLOCK_MASK; - offset = base_relocs[i].addr - base; + offset = (uint32_t)(base_relocs[i].addr - base); } b[entries].type = base_relocs[i].type; b[entries].offset = offset; @@ -2405,7 +2447,7 @@ void) b[entries].offset = 0; entries++; } - h->page_rva = base; + h->page_rva = (uint32_t)base; size = sizeof(struct base_relocation_block_header) + entries * sizeof(struct base_relocation_entry); h->block_size = size; @@ -2419,6 +2461,15 @@ void) memcpy(reloc_contents + reloc_size, fb, size); reloc_size += size; + /* + * The make the relocs buffer the s_size rounded to file_alignment and + * zero out the padding + */ + s_size = rnd32(reloc_size, file_alignment); + pad = s_size - reloc_size; + reloc_contents = reallocate(reloc_contents, s_size); + memset(reloc_contents + reloc_size, '\0', pad); + blockcnt++; free(fb); } @@ -2447,7 +2498,7 @@ create_debug( struct arch *arch) { char *p; - uint32_t i, ncmds; + uint32_t i, ncmds, s_size; struct load_command *lc; struct uuid_command *uuid; @@ -2459,9 +2510,14 @@ struct arch *arch) */ debug_size = sizeof(struct debug_directory_entry) + sizeof(struct mtoc_debug_info) + - strlen(debug_filename) + 1; - debug_contents = allocate(debug_size); - memset(debug_contents, '\0', debug_size); + (uint32_t)strlen(debug_filename) + 1; + /* + * The make the debug buffer the s_size rounded to the file_alignment + * and also zero out the padding + */ + s_size = rnd32(debug_size, file_alignment); + debug_contents = allocate(s_size); + memset(debug_contents, '\0', s_size); /* * Set up pointers to all the parts to be filled in. */ @@ -2472,12 +2528,12 @@ struct arch *arch) p += sizeof(struct mtoc_debug_info); dde->Characteristics = 0; - dde->TimeDateStamp = time(NULL); + dde->TimeDateStamp = (uint32_t)time(NULL); dde->MajorVersion = 0; dde->MinorVersion = 0; dde->Type = IMAGE_DEBUG_TYPE_CODEVIEW; dde->SizeOfData = sizeof(struct mtoc_debug_info) + - strlen(debug_filename) + 1; + (uint32_t)strlen(debug_filename) + 1; /* * These two will be filled in later when address and offsets * are known. diff --git a/cctools/efitools/mtor.c b/cctools/efitools/mtor.c new file mode 100644 index 0000000..37467e4 --- /dev/null +++ b/cctools/efitools/mtor.c @@ -0,0 +1,810 @@ +/* + * Copyright (c) 2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include "stuff/breakout.h" +#include "stuff/errors.h" +#include "stuff/ofile.h" +#include "stuff/write64.h" +#include "stuff/port.h" /* cctools-port */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* used by error routines as the name of this program */ +char *progname = NULL; + +/* command-line flags */ +struct flags { + enum bool verbose; + enum bool dry_run; + enum bool start; + enum bool no_bss; + uint64_t start_addr; + const char* data_lma_sym; + const char* data_size_sym; + uint64_t data_lma_loc; + uint64_t data_size_loc; +} g_flags; + +struct segentry { + char* segname; + uint64_t vmaddr; + uint64_t vmsize; + uint64_t fileoff; + uint64_t filesize; + uint64_t out_fileoff; + uint64_t out_filesize; +}; + +struct sectentry { + struct segentry* seg; + char* segname; + char* sectname; + uint64_t addr; + uint64_t size; + uint64_t offset; + uint32_t align; + uint32_t flags; +}; + +struct symbol { + char* name; + uint8_t n_type; + uint8_t n_sect; + uint64_t n_value; +}; + +struct segentry* g_segs = NULL; +struct sectentry* g_sects = NULL; +struct symbol* g_syms = NULL; +uint32_t g_nseg = 0; +uint32_t g_nsect = 0; +uint32_t g_nsym = 0; + +static void get_segments(const struct ofile* ofile, + struct segentry** o_segs, uint32_t* o_nseg, + struct sectentry** o_sects, uint32_t* o_nsect); +static void get_symbols(const struct ofile* ofile, + struct symbol** o_syms, uint32_t* o_nsym); +static void find_data_symbols(const struct ofile* ofile); +static void process(const struct ofile* ofile, const char* output); +static void usage(void); + +/* apple_version is created by the libstuff/Makefile */ +extern char apple_version[]; +char *apple_version_str = apple_version; + +/* + * The mtor(1) tool makes a raw binary file from a fully linked Mach-O + * MH_PRELOAD file. These are meant to be in-core images in either a + * ready-to-run layout, or with an embedded startup that knows how to + * relocate/re-layout the image at runtime. + * + * mtor [-nv] [-start] [-no_bss] input_Mach-O output_raw + * + * Caveat mtor: input files must contain one architecture. + */ + +int main(int argc, char **argv) +{ + enum bool read_options = TRUE; + char* input = NULL; + char* output = NULL; + + progname = *argv++; + argc--; + + memset(&g_flags, 0, sizeof(g_flags)); + + if (argc == 0) + usage(); + + /* parse args */ + while (argc > 0) + { + if (read_options && *argv && '-' == **argv) + { + if (0 == strcmp("-h", *argv) || + 0 == strcmp("-help", *argv)) + { + usage(); + } + else if (0 == strcmp(*argv, "-no_bss")) + { + g_flags.no_bss = TRUE; + } + else if (0 == strcmp("-o", *argv) || + 0 == strcmp("-output", *argv)) + { + argv++; argc--; + if (!*argv) { + warning("one output file must be specified"); + usage(); + } + if (output) { + warning("only one output file must be specified"); + usage(); + } + output = strdup(*argv); + } + else if (0 == strcmp("-packdata", *argv)) + { + if (g_flags.data_lma_sym) { + warning("-packdata specified more than once"); + usage(); + } + + argv++; argc--; + if (!*argv) { + warning("data lma symbol name must be specified"); + usage(); + } + g_flags.data_lma_sym = strdup(*argv); + + argv++; argc--; + if (!*argv) { + warning("data size symbol name must be specified"); + usage(); + } + g_flags.data_size_sym = strdup(*argv); + } + else if (0 == strcmp(*argv, "-start") || + 0 == strcmp(*argv, "-image_base") || + 0 == strcmp(*argv, "-seg1addr")) + { + const char* option = *argv; + argv++; argc--; + + if (!*argv) { + warning("one start address must be specified for %s", + option); + usage(); + } + + if (g_flags.start) { + warning("only one start address must be specified"); + usage(); + } + + char *endp; + g_flags.start_addr = (uint64_t)strtoull(*argv, &endp, 16); + if (*endp != '\0') { + fatal("%s not a proper hexadecimal number", *argv); + } + + g_flags.start = TRUE; + } + else if (0 == strcmp("-version", *argv)) + { + printf("%s\n", apple_version_str); + + if (argc < 2) + exit(EXIT_SUCCESS); + } + else if (0 == strcmp("--", *argv)) + { + read_options = FALSE; + } + else { + for (int j = 1; (*argv)[j]; ++j) + { + if ('n' == (*argv)[j]) { + g_flags.verbose = TRUE; + g_flags.dry_run = TRUE; + } + else if ('v' == (*argv)[j]) { + g_flags.verbose = TRUE; + } + else { + warning("unknown flag -%c", (*argv)[j]); + usage(); + } + } + } + } + else { + if (input) { + warning("only one input file must be specified"); + usage(); + } + + input = strdup(*argv); + } + + argv++; argc--; + } + + /* check for required parameters */ + if (!input) { + warning("no input file specified"); + usage(); + } + if (!output) { + warning("no output file specified"); + usage(); + } + + /* breakout the file for processing */ + struct arch *archs; + uint32_t narchs; + struct ofile *ofile = breakout(input, &archs, &narchs, FALSE); + if (errors || !ofile) + return(EXIT_FAILURE); + + /* checkout the file for symbol table replacement processing */ + checkout(archs, narchs); + + /* perform other input checking */ + if (OFILE_FAT == ofile->file_type) + fatal("file: %s is a fat file (%s only operates on Mach-O files, " + "use lipo(1) on it to get a Mach-O file)", input, progname); + if (OFILE_Mach_O != archs->type) + fatal("input file: %s must be a Mach-O file", input); + if (NULL != archs->object->mh){ + if (MH_PRELOAD != archs->object->mh->filetype) { + fatal("input file: %s must be an MH_PRELOAD file type", + archs->file_name); + } + } else { + if (MH_PRELOAD != archs->object->mh64->filetype) { + fatal("input file: %s must be an MH_PRELOAD file type", + archs->file_name); + } + } + + get_segments(ofile, &g_segs, &g_nseg, &g_sects, &g_nsect); + get_symbols(ofile, &g_syms, &g_nsym); + find_data_symbols(ofile); + + /* do it! */ + process(ofile, output); + + /* clean up */ + free_archs(archs, narchs); + ofile_unmap(ofile); + free(input); + free(output); + + /* exit */ + if (!errors) + return(EXIT_SUCCESS); + else + return(EXIT_FAILURE); +} + +static void get_segments(const struct ofile* ofile, + struct segentry** o_segs, uint32_t* o_nseg, + struct sectentry** o_sects, uint32_t* o_nsect) +{ + uint32_t nseg = 0; + uint32_t nsect = 0; + + *o_segs = NULL; + *o_sects = NULL; + *o_nseg = 0; + *o_nsect = 0; + + /* count the segments and sections */ + uint32_t ncmds = ofile->mh ? ofile->mh->ncmds : ofile->mh64->ncmds; + unsigned char* p = (unsigned char*)(ofile->load_commands); + for (uint32_t i = 0; i < ncmds; ++i) + { + struct load_command* lc = (struct load_command*)p; + p += lc->cmdsize; + + if (LC_SEGMENT == lc->cmd) + { + struct segment_command* sg = (struct segment_command*)lc; + nseg += 1; + nsect += sg->nsects; + } + else if (LC_SEGMENT_64 == lc->cmd) + { + struct segment_command_64* sg = (struct segment_command_64*)lc; + nseg += 1; + nsect += sg->nsects; + } + } + + /* + * build the segment and section lists. + */ + struct segentry* segs = calloc(nseg, sizeof(*segs)); + struct sectentry* sects = calloc(nsect, sizeof(*sects)); + uint32_t iseg = 0; + uint32_t isect = 0; + p = (unsigned char*)(ofile->load_commands); + for (uint32_t i = 0; i < ncmds; ++i) + { + struct load_command* lc = (struct load_command*)p; + p += lc->cmdsize; + + if (LC_SEGMENT == lc->cmd) + { + struct segentry* segentry = &segs[iseg++]; + + struct segment_command* sg = (struct segment_command*)lc; + + segentry->segname = strdup(sg->segname); + segentry->vmaddr = sg->vmaddr; + segentry->vmsize = sg->vmsize; + segentry->fileoff = sg->fileoff; + segentry->filesize = sg->filesize; + + unsigned char* q = (unsigned char*)(sg + 1); + for (uint32_t j = 0; j < sg->nsects; ++j) + { + sects = reallocf(sects, sizeof(struct sectentry) * (nsect + 1)); + struct sectentry* sectentry = §s[isect++]; + + struct section* sc = (struct section*)q; + q += sizeof(struct section); + + if (0 != strcmp(sg->segname, sc->segname)) { + warning("input file %s: %s section %s points to different " + "section name: %s\n", ofile->file_name, sg->segname, + sc->sectname, sc->segname); + } + + sectentry->seg = segentry; + sectentry->sectname = strdup(sc->sectname); + sectentry->segname = strdup(sg->segname); + sectentry->addr = sc->addr; + sectentry->size = sc->size; + sectentry->offset = sc->offset; + sectentry->align = sc->align; + sectentry->flags = sc->flags; + } + } + else if (LC_SEGMENT_64 == lc->cmd) + { + struct segentry* segentry = &segs[iseg++]; + + struct segment_command_64* sg = (struct segment_command_64*)lc; + + segentry->segname = strdup(sg->segname); + segentry->vmaddr = sg->vmaddr; + segentry->vmsize = sg->vmsize; + segentry->fileoff = sg->fileoff; + segentry->filesize = sg->filesize; + + unsigned char* q = (unsigned char*)(sg + 1); + for (uint32_t j = 0; j < sg->nsects; ++j) + { + sects = reallocf(sects, sizeof(struct sectentry) * (nsect + 1)); + struct sectentry* sectentry = §s[isect++]; + + struct section_64* sc = (struct section_64*)q; + q += sizeof(struct section_64); + + if (0 != strcmp(sg->segname, sc->segname)) { + warning("input file %s: %s section %s points to different " + "section name: %s\n", ofile->file_name, sg->segname, + sc->sectname, sc->segname); + } + + sectentry->seg = segentry; + sectentry->sectname = strdup(sc->sectname); + sectentry->segname = strdup(sg->segname); + sectentry->addr = sc->addr; + sectentry->size = sc->size; + sectentry->offset = sc->offset; + sectentry->align = sc->align; + sectentry->flags = sc->flags; + } + } + } + + *o_segs = segs; + *o_nseg = nseg; + *o_sects = sects; + *o_nsect = nsect; +} + +static void get_symbols(const struct ofile* ofile, + struct symbol** o_syms, uint32_t* o_nsym) +{ + struct symtab_command* st = NULL; + + *o_syms = NULL; + *o_nsym = 0; + + /* + * find the symbol table, if any. + */ + uint32_t ncmds = ofile->mh ? ofile->mh->ncmds : ofile->mh64->ncmds; + unsigned char* p = (unsigned char*)(ofile->load_commands); + for (uint32_t i = 0; i < ncmds; ++i) + { + struct load_command* lc = (struct load_command*)p; + p += lc->cmdsize; + + if (LC_SYMTAB == lc->cmd) + { + if (st) { + fatal("input file: %s contains multiple symbol tables", + ofile->file_name); + } + st = (struct symtab_command*)lc; + } + } + + if (!st) + return; + + struct symbol* syms = calloc(st->nsyms, sizeof(struct symbol)); + + /* + * record the symbols + */ + if (ofile->mh) { + struct nlist* nl = (struct nlist*)(ofile->file_addr + st->symoff); + char* strings = (char*)ofile->file_addr + st->stroff; + for (uint32_t i = 0; i < st->nsyms; ++i) { + if (nl[i].n_un.n_strx) + syms[i].name = strdup((char*)(strings + nl[i].n_un.n_strx)); + else + syms[i].name = strdup(""); + syms[i].n_type = nl[i].n_type; + syms[i].n_sect = nl[i].n_sect; + syms[i].n_value = nl[i].n_value; + } + } + else if (ofile->mh64) { + struct nlist_64* nl = (struct nlist_64*)(ofile->file_addr + st->symoff); + char* strings = (char*)ofile->file_addr + st->stroff; + for (uint32_t i = 0; i < st->nsyms; ++i) { + if (nl[i].n_un.n_strx) + syms[i].name = strdup((char*)(strings + nl[i].n_un.n_strx)); + else + syms[i].name = strdup(""); + syms[i].n_type = nl[i].n_type; + syms[i].n_sect = nl[i].n_sect; + syms[i].n_value = nl[i].n_value; + } + } + + *o_syms = syms; + *o_nsym = st->nsyms; +} + +static int find_symbol(const struct ofile* ofile, const struct symbol* sym, + const char* name, uint64_t* o_value) +{ + if (0 == strcmp(sym->name, name) && + 0 == (sym->n_type & N_STAB)) + { +// if (sym->n_type & N_STAB) { +// fatal("input file %s: symbol %s is a STAB symbol", +// ofile->file_name, name); +// } + if (*o_value != 0) { + fatal("input file %s: contains multiple %s Mach-O symbols", + ofile->file_name, name); + } + if ((sym->n_type & N_SECT) != N_SECT) { + fatal("input file %s: symbol %s is not directly defined", + ofile->file_name, name); + } + uint32_t sectord = sym->n_sect; + if (sectord == 0) { + fatal("input file %s: symbol %s is not in any section", + ofile->file_name, name); + } + if (sectord > g_nsect) { + fatal("input file %s: symbol %s has a bad section ordinal " + "(%d > %d)", ofile->file_name, name, sectord, g_nsect); + } + struct sectentry* section = &g_sects[sectord-1]; + if (strcmp(SEG_TEXT, section->segname)) { + fatal("input file %s: symbol %s is not in __TEXT segment: (%s, %s)", + ofile->file_name, name, section->segname, section->sectname); + } + if (0 == sym->n_value) { + fatal("input file %s: symbol %s has no storage (n_value)", + ofile->file_name, name); + } + uint64_t offset = section->seg->fileoff + sym->n_value; + uint32_t value = *(uint32_t*)(ofile->file_addr + offset); + if (value) { + warning("input file %s symbol %s has non-zero value: 0x%08x", + ofile->file_name, name, value); + } + + *o_value = sym->n_value; + return 0; + } + return -1; +} + +static void find_data_symbols(const struct ofile* ofile) +{ + if (!g_flags.data_lma_sym || !g_flags.data_size_sym) + return; + + for (uint32_t i = 0; i < g_nsym; ++i) { + find_symbol(ofile, &g_syms[i], g_flags.data_lma_sym, + &g_flags.data_lma_loc); + find_symbol(ofile, &g_syms[i], g_flags.data_size_sym, + &g_flags.data_size_loc); + if (g_flags.data_lma_loc && g_flags.data_size_loc) { + break; + } + } + + if (!g_flags.data_lma_loc || !g_flags.data_size_loc) { + if (!g_flags.data_lma_loc) + error("input file %s: symbol not found: %s", + ofile->file_name, g_flags.data_lma_sym); + if (!g_flags.data_size_loc) + error("input file %s: symbol not found: %s", + ofile->file_name, g_flags.data_size_sym); + exit(EXIT_FAILURE); + } +} + +/* + * process() computes both the source regions of the input file and the + * destination regions of the output file based on the input file and program + * arguments. + * + * The output file represents the Mach-O file's layout in memory. As such, the + * __TEXT and __DATA segments will move from fileoff within the input file to + * vmaddr within the output file. The -start option can be used to override + * the starting location of segment data within the output file. If necessary, + * the output file will be zero-padded to the start of the __TEXT segment. + * + * By default the entire contents of __TEXT and DATA will be copied. The + * -no_bss option can be used to omit the bss and other S_ZEROFILL sections + * from the __DATA segment. __DATA segments truncated in this way will not be + * aligned to page boundaries. + * + * Caveat mtor: The mtor tool cannot relink the input file. Sections and + * segments cannot be re-padded to new page alignments or moved in any way + * other than to slide them all as a group. Make sure the input file is as + * correct as possible by specifying -seg1addr and -segalign to ld(1). + */ + +void process(const struct ofile* ofile, const char* output) +{ + /* + * Locate the text and data segments. Assume / require there to be one + * text segment, and no more than one data segment. + */ + struct segentry* text = NULL; + struct segentry* data = NULL; + for (uint32_t i = 0; i < g_nseg; ++i) + { + struct segentry* seg = &g_segs[i]; + if (0 == strcmp(SEG_TEXT, seg->segname)) { + if (text) { + fatal("input file %s contains multiple __TEXT segments", + ofile->file_name); + } + text = seg; + } + else if (0 == strcmp(SEG_DATA, seg->segname)) { + if (data) { + fatal("input file %s contains multiple __DATA segments", + ofile->file_name); + } + data = seg; + } + } + + if (!text) { + error("input file: %s does not contain __TEXT", ofile->file_name); + exit(EXIT_FAILURE); + } + + /* + * compute the vmaddr adjustment necessary to start the + * segments at the requested start address. + */ + int64_t startadj = 0; + if (g_flags.start) { + startadj = g_flags.start_addr - text->vmaddr; + } + + /* + * verify the sections will still be aligned and compute the remaining + * data size after omitting / truncating any bss sections (if requested). + */ + uint64_t datasize = 0; + uint64_t bsssize = 0; + for (uint32_t i = 0; i < g_nsect; ++i) { + struct sectentry* sect = &g_sects[i]; + if ((sect->addr + startadj) % (1 << sect->align)) { + error("input file: %s section %.16s,%.16s addr " + "0x%08llx cannot be aligned to 2^%d (%d)", + ofile->file_name, sect->segname, sect->sectname, + sect->addr + startadj, sect->align, + 1 << sect->align); + } + + if (sect->seg == data) { + if (((sect->flags & SECTION_TYPE) == S_ZEROFILL) || + 0 == strcmp(sect->sectname, "__common") || + 0 == strcmp(sect->sectname, "__bss")) { + if (g_flags.no_bss) + break; + else + bsssize += sect->size; + } + + datasize += sect->size; + } + } + + /* + * set compute the destination fileoff and filesizes + * + * if we're writing out bss we're going to lie a little bit here and + * reserve space for the bss data even though the Mach-O does not really + * include this data. This is kind of a hack ... + */ + text->out_fileoff = text->vmaddr + startadj; + text->out_filesize = text->vmsize; + if (data) { + if (g_flags.data_lma_sym) { /* pack data */ + data->out_fileoff = text->out_fileoff + text->out_filesize; + } + else { + data->out_fileoff = data->vmaddr + startadj; + } + data->out_filesize = datasize; + } + + /* + * determine the size of the final file by measuring the extent of the + * __TEXT and __DATA segments. + */ + size_t output_size = 0; + if (text->vmaddr + text->vmsize > output_size) + output_size = text->out_fileoff + text->out_filesize; + if (data && (data->vmaddr + data->vmsize > output_size)) + output_size = data->out_fileoff + data->out_filesize; + + /* allocate an output buffer */ + unsigned char* buf = calloc(1, output_size); + if (!buf) + fatal("Can't allocate buffer for output file (size = %lu)", + output_size); + + /* + * copy the segments into the buffer. __DATA may be omitted / truncated + * if no_bss + */ + for (uint32_t i = 0; i < g_nseg; ++i) { + struct segentry* seg = &g_segs[i]; + + if (seg != text && seg != data) + break; + + if (g_flags.verbose) { + printf("writing %.16s at VMA: 0x%08llx-0x%08llx LMA: " + "0x%08llx-0x%08llx\n", seg->segname, + seg->vmaddr, seg->vmaddr + seg->vmsize, + seg->out_fileoff, seg->out_fileoff + seg->out_filesize); + } + + if (!g_flags.dry_run) { + /* + * The Mach-O file does not actually include bss data on disk. + * If we are including bss in the raw data we will need to avoid + * trying to copy bss off disk; otherwise we'll end up pulling in + * fragments of linkedit or we'll spill over our buffer. + * + * Note that if we are not copying bss, this adjustment has already + * been baked into the out_filesize. + */ + uint64_t size = seg->out_filesize; + if (seg == data) { + size -= bsssize; + } + + /* + * When copying __DATA, the segment filesize will be non-zero in + * the case where there exist non-bss / zerofill sections. But if + * all the __DATA sections are bss / zerofill, the filesize will + * be zero. So, only copy __DATA from the input file if it has a + * non-zero filesize. + */ + if (size) { + memcpy(buf + seg->out_fileoff, ofile->file_addr + seg->fileoff, + size); + } + } + } + + /* poke the packdata values into the text segment */ + if (g_flags.data_lma_sym) { /* pack data */ + uint32_t* addr; + addr = (uint32_t*)(buf + text->out_fileoff + g_flags.data_lma_loc); + *addr = (uint32_t)(data ? data->out_fileoff : 0); + addr = (uint32_t*)(buf + text->out_fileoff + g_flags.data_size_loc); + *addr = (uint32_t)(data ? data->out_filesize : 0); + } + + /* write the raw output file safely */ + if (!g_flags.dry_run) { + const char* suffix = ".XXXXXX"; + size_t tempsize = strlen(output) + strlen(suffix) + 1; + char* tempname = calloc(1, tempsize); + if (!tempname) + fatal("Can't allocate buffer for output filename (size = %lu)", + tempsize); + + if (snprintf(tempname, tempsize, "%s%s", output, suffix) != tempsize -1) + fatal("Can't create temporary name for output file %s", output); + + int fd = mkstemp(tempname); + if (-1 == fd) { + system_fatal("Can't create temporary file: %s", tempname); + } + + if (write64(fd, buf, output_size) != output_size) { + system_fatal("Can't write temporary file: %s", tempname); + } + + if (fchmod(fd, 0644) == -1) { + system_fatal("Can't chmod temporary file: %s", tempname); + } + + if (close(fd) == -1) { + system_fatal("Can't close temporary file: %s", tempname); + } + + if (rename(tempname, output) == -1) { + system_fatal("Can't write output file: %s", output); + } + } + + free(buf); +} + +static void usage(void) +{ + const char* basename = strrchr(progname, '/'); + if (basename) + basename++; + else + basename = progname; + + fprintf(stderr, + "usage: %s [-nv] [-no_bss] [-start ] " + "[-packdata ] " + "-output \n", basename); + fprintf(stderr, + " %s -help [-version]\n", basename); + fprintf(stderr, + " %s -version\n", basename); + exit(EXIT_FAILURE); +} diff --git a/cctools/gprof/gprof.c b/cctools/gprof/gprof.c index 9da161c..7965d29 100644 --- a/cctools/gprof/gprof.c +++ b/cctools/gprof/gprof.c @@ -1205,7 +1205,7 @@ char *sumfile) data.type = GMONTYPE_SAMPLES; data.size = sample_sets[i].sampbytes + sizeof(header); if(write(fd, &data, sizeof(struct gmon_data)) != - sizeof(struct gmon_data)) + sizeof(struct gmon_data)) fatal("can't write gmon_data struct to gmon.sum file: %s", sumfile); @@ -1245,7 +1245,7 @@ char *sumfile) } } if(write(fd, &data, sizeof(struct gmon_data)) != - sizeof(struct gmon_data)) + sizeof(struct gmon_data)) fatal("can't write gmon_data struct to gmon.sum file: %s", sumfile); @@ -1256,7 +1256,7 @@ char *sumfile) arc_order.raw_count = arcp->arc_count; arc_order.raw_order = arcp->arc_order; if(write(fd, &arc_order, sizeof(struct rawarc_order)) != - sizeof(struct rawarc_order)) + sizeof(struct rawarc_order)) fatal("can't write arc to gmon.sum file: %s", sumfile); #ifdef DEBUG if(debug & SAMPLEDEBUG){ diff --git a/cctools/include/Makefile b/cctools/include/Makefile index 89f45c9..63d96ff 100644 --- a/cctools/include/Makefile +++ b/cctools/include/Makefile @@ -1,6 +1,13 @@ # Note that the macros are not used for the install target any more with the # change to the install(1) program. Edit the install commands. +# +# TAPI supports installapi per default. Allow B&I to change the default and +# print a status message to the log file. +# +SUPPORTS_TEXT_BASED_API ?= YES +$(info SUPPORTS_TEXT_BASED_API=$(SUPPORTS_TEXT_BASED_API)) + ifneq "" "$(wildcard /bin/mkdirs)" MKDIRS = /bin/mkdirs else @@ -36,6 +43,7 @@ OTHER_SRCS = notes gnu/symseg.h \ stuff/SymLoc.h stuff/dylib_roots.h stuff/guess_short_name.h \ stuff/macosx_deployment_target.h stuff/symbol_list.h \ stuff/symbol.h stuff/unix_standard_mode.h \ + stuff/write64.h \ coff/base_relocs.h coff/bytesex.h coff/ms_dos_stub.h \ coff/filehdr.h coff/aouthdr.h coff/scnhdr.h coff/syment.h \ coff/debug_directory.h elf/dwarf2.h llvm-c/Disassembler.h \ @@ -60,13 +68,13 @@ GAS_MISSING_SRCS = mach/m68k/thread_status.h \ mach/ppc/thread_status.h \ mach/ppc/_structs.h -MISSING_SRCS = mach/machine.h \ +MISSING_SRCS = mach/machine.h mach/slot_name.h \ architecture/i386/fpu.h architecture/i386/frame.h \ i386/eflags.h mach/i386/_structs.h mach/i386/fp_reg.h \ mach/i386/thread_state.h mach/i386/thread_status.h \ standalone/libsa.h \ $(GAS_MISSING_SRCS) - + nextstep_INCDIR = /NextDeveloper/Headers nextstep_LOCINCDIR = /LocalDeveloper/Headers @@ -107,6 +115,79 @@ installGASsrc: chmod 755 $(SRCROOT) gnutar cf - $(GAS_SRC_FILES) | (cd $(SRCROOT); gnutar xf -) +# This is a bit of a hack as 'tapi installapi' should take the RC_CFLAGS or +# RC_ARCHS as there is no way to make up the -target options from the +# RC_* buildit options. +ifeq "$(RC_MACOS)" "YES" + TAPI_TARGET_ARCHS := -target x86_64-apple-macos10.14 \ + -target i386-apple-macos10.14 \ + -target-variant x86_64-apple-ios12.0-macabi +else + # keep -arch and add version-min for non-OSX toolchains + TAPI_TARGET_ARCHS := $(patsubst %,-arch %,$(RC_ARCHS)) + TAPI_TARGET_ARCHS += $(RC_MIN_VERSION_OPTION) +endif + +TAPI_COMMON_OPTS = $(TAPI_TARGET_ARCHS) \ + -isysroot $(SDKROOT) -I$(SRCROOT)/include \ + -extra-public-header $(SRCROOT)/include/mach/slot_name.h \ + -exclude-private-header $(DSTROOT)/usr/local/include/cbt/libsyminfo.h \ + -exclude-public-header $(DSTROOT)/usr/include/mach-o/ldsyms.h \ + -exclude-public-header $(DSTROOT)/usr/include/mach-o/nlist.h \ + -dynamiclib -install_name /usr/lib/system/libmacho.dylib \ + -compatibility_version 1 \ + -current_version $(RC_ProjectSourceVersion) \ + -o $(OBJROOT)/libmacho.tbd + +DYLIBDIR = /usr/lib/system + +TAPI_VERIFY_OPTS := $(TAPI_COMMON_OPTS) \ + --verify-mode=Pedantic \ + --verify-against=$(DSTROOT)$(DYLIBDIR)/libmacho.dylib \ + -umbrella System +# -fapplication-extension + +installapi: install + $(MKDIRS) $(DSTROOT)$(DYLIBDIR) + $(MKDIRS) $(OBJROOT) + @echo + @echo ++++++++++++++++++++++ + @echo + Running InstallAPI + + @echo ++++++++++++++++++++++ + @echo + + @if [ "$(SUPPORTS_TEXT_BASED_API)" != "YES" ]; then \ + echo -n "installapi for target 'tapi' was requested, " \ + echo "but SUPPORTS_TEXT_BASED_API has been disabled."; \ + exit 1; \ + fi + + xcrun --sdk $(SDKROOT) tapi installapi $(TAPI_COMMON_OPTS) $(DSTROOT) + + install -d -m 0755 $(DSTROOT)$(DYLIBDIR) + install -c -m 0444 $(OBJROOT)/libmacho.tbd \ + $(DSTROOT)$(DYLIBDIR)/libmacho.tbd + +# This is again a bit of a hack, as libmacho.dylib would need be built first +# for this to work which is not even done for installhdrs. But it shows the +# command with the needed $(TAPI_VERIFY_OPTS) that could work. +installapi-verify: + $(MKDIRS) $(DSTROOT)$(DYLIBDIR) + $(MKDIRS) $(OBJROOT) + @echo + @echo +++++++++++++++++++++++++++++++++ + @echo + Running InstallAPI and Verify + + @echo +++++++++++++++++++++++++++++++++ + @echo + + @if [ "$(SUPPORTS_TEXT_BASED_API)" != "YES" ]; then \ + echo -n "installapi for target 'tapi' was requested, " \ + echo "but SUPPORTS_TEXT_BASED_API has been disabled."; \ + exit 1; \ + fi + + xcrun --sdk $(SDKROOT) tapi installapi $(TAPI_VERIFY_OPTS) $(DSTROOT) + install: dirs $(RC_OS)_install teflon_install macos_install: common_install @@ -156,17 +237,22 @@ common_install: cd mach-o/m88k; \ install -c -m 444 ${IFLAGS} reloc.h swap.h \ ${DSTROOT}${$(RC_OS)_LOCINCDIR}/mach-o/m88k - cd mach-o; \ - install -c -m 444 ${IFLAGS} rld.h rld_state.h \ - ${DSTROOT}${$(RC_OS)_LOCINCDIR}/mach-o + if [ $(OLD_RLD_STUFF) ]; \ + then \ + cd mach-o; install -c -m 444 ${IFLAGS} rld.h rld_state.h \ + ${DSTROOT}${$(RC_OS)_LOCINCDIR}/mach-o ; \ + fi if [ $(OLD_DYLD_STUFF) ]; \ then \ cd mach-o; install -c -m 444 ${IFLAGS} dyld_gdb.h dyld_priv.h \ ${DSTROOT}${$(RC_OS)_LOCINCDIR}/mach-o ; \ fi - cd mach-o; \ - install -c -m 444 ${IFLAGS} sarld.h kld.h redo_prebinding.h \ - ${DSTROOT}${$(RC_OS)_LOCINCDIR}/mach-o + if [ $(OLD_RLD_STUFF) ]; \ + then \ + cd mach-o; \ + install -c -m 444 ${IFLAGS} sarld.h kld.h redo_prebinding.h \ + ${DSTROOT}${$(RC_OS)_LOCINCDIR}/mach-o ; \ + fi cd stuff; \ install -c -m 444 ${IFLAGS} bool.h \ ${DSTROOT}${$(RC_OS)_LOCINCDIR}/dyld diff --git a/cctools/include/foreign/Availability.h b/cctools/include/foreign/Availability.h index 8c3a833..55d9d6d 100644 --- a/cctools/include/foreign/Availability.h +++ b/cctools/include/foreign/Availability.h @@ -1,4 +1,19 @@ //fake headers #ifdef __APPLE__ #include_next + +/* + * If anyone wants to run the linker *on* iOS devices then + * it must be a jailbroken device anyway and thus I don't + * care about prohibited APIs. + */ +#undef __IOS_PROHIBITED +#define __IOS_PROHIBITED + +#undef __TVOS_PROHIBITED +#define __TVOS_PROHIBITED + +#undef __WATCHOS_PROHIBITED +#define __WATCHOS_PROHIBITED + #endif /* __APPLE__ */ diff --git a/cctools/include/foreign/dirent.h b/cctools/include/foreign/dirent.h new file mode 100644 index 0000000..0a8027e --- /dev/null +++ b/cctools/include/foreign/dirent.h @@ -0,0 +1,5 @@ +#include_next + +#ifndef MAXNAMLEN +#define MAXNAMLEN NAME_MAX /* DragonFlyBSD and Android */ +#endif diff --git a/cctools/include/foreign/i386/types.h b/cctools/include/foreign/i386/types.h index 37b22d0..1b8466e 100644 --- a/cctools/include/foreign/i386/types.h +++ b/cctools/include/foreign/i386/types.h @@ -67,7 +67,7 @@ #define _MACHTYPES_H_ #ifndef __ASSEMBLER__ -#if defined(__NetBSD__) || defined(__OpenBSD__) +#if defined(__NetBSD__) #include_next /* __cpu_simple_lock_t */ #endif /* __NetBSD__ || __OpenBSD__ */ #ifdef __DragonFly__ @@ -79,48 +79,101 @@ * Basic integral types. Omit the typedef if * not possible for a machine/compiler combination. */ +/* cctools-port: replaced types with compiler defines */ + +#ifdef __GLIBC__ +#ifdef __ARM_32BIT_STATE +/* Heck, why is asm/types.h (glibc) defining this type wrong?! + It's supposed to be 'unsigned int' */ +#undef __UINTPTR_TYPE__ +#define __UINTPTR_TYPE__ unsigned int +#endif +#endif + +#if defined(__clang_major__) && __clang_major__ == 3 && \ + __clang_minor__ == 4 +#ifndef __UINT8_TYPE__ +#define __UINT8_TYPE__ unsigned char +#endif + +#ifndef __UINT16_TYPE__ +#define __UINT16_TYPE__ unsigned __INT16_TYPE__ +#endif + +#ifndef __UINT32_TYPE__ +#define __UINT32_TYPE__ unsigned __INT32_TYPE__ +#endif + +#ifndef __UINT64_TYPE__ +#define __UINT64_TYPE__ unsigned __INT64_TYPE__ +#endif + +#ifndef __UINTPTR_TYPE__ +#define __UINTPTR_TYPE__ unsigned __INTPTR_TYPE__ +#endif + +/* + clang 3.4: + + $ clang -target x86_64-unknown-linux -dM -E - < /dev/null|grep __INT8_TYPE__ + #define __INT8_TYPE__ char + + clang 3.5: + + $ clang -target x86_64-unknown-linux -dM -E - < /dev/null|grep __INT8_TYPE__ + #define __INT8_TYPE__ signed char + + */ + +#undef __INT8_TYPE__ +#define __INT8_TYPE__ signed char +#endif /* clang 3.4 */ + #ifndef _INT8_T #define _INT8_T -typedef __signed char int8_t; +typedef __INT8_TYPE__ int8_t; #endif -typedef unsigned char u_int8_t; +typedef __UINT8_TYPE__ u_int8_t; + #ifndef _INT16_T #define _INT16_T -typedef short int16_t; +typedef __INT16_TYPE__ int16_t; #endif -typedef unsigned short u_int16_t; +typedef __UINT16_TYPE__ u_int16_t; + #ifndef _INT32_T #define _INT32_T -typedef int int32_t; +typedef __INT32_TYPE__ int32_t; #endif -typedef unsigned int u_int32_t; +typedef __UINT32_TYPE__ u_int32_t; + #ifndef _INT64_T #define _INT64_T -#if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) -typedef long long int64_t; -#else -typedef long int64_t; -#endif /* ! __NetBSD__ && !__OpenBSD__ && !__DragonFly__ */ +typedef __INT64_TYPE__ int64_t; #endif -#if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) -typedef unsigned long long u_int64_t; -#else -typedef unsigned long u_int64_t; -#endif /* ! __NetBSD__ && !__OpenBSD__ && !__DragonFly__ */ +typedef __UINT64_TYPE__ u_int64_t; +#ifdef __OpenBSD__ /* cctools-port: whatever ... */ #if __LP64__ -typedef int64_t register_t; + typedef long register_t; #else -typedef int32_t register_t; + typedef long long register_t; #endif +#else +#if __LP64__ + typedef int64_t register_t; +#else + typedef int32_t register_t; +#endif +#endif /* __OpenBSD__ */ #ifndef _INTPTR_T #define _INTPTR_T -typedef __darwin_intptr_t intptr_t; +typedef __INTPTR_TYPE__ intptr_t; #endif #ifndef _UINTPTR_T #define _UINTPTR_T -typedef unsigned long uintptr_t; +typedef __UINTPTR_TYPE__ uintptr_t; #endif #if !defined(_ANSI_SOURCE) && (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)) diff --git a/cctools/include/foreign/mach/i386/vm_param.h b/cctools/include/foreign/mach/i386/vm_param.h index 1f9da2f..abd089c 100644 --- a/cctools/include/foreign/mach/i386/vm_param.h +++ b/cctools/include/foreign/mach/i386/vm_param.h @@ -95,7 +95,8 @@ #define I386_PGBYTES 4096 /* bytes per 80386 page */ #define I386_PGSHIFT 12 /* bitshift for pages */ -#undef PAGE_SIZE /* Cygwin */ +#undef PAGE_SIZE /* cctools-port */ +#undef PAGE_MASK #define PAGE_SIZE I386_PGBYTES #define PAGE_SHIFT I386_PGSHIFT #define PAGE_MASK (PAGE_SIZE - 1) diff --git a/cctools/include/foreign/mach/machine.h b/cctools/include/foreign/mach/machine.h index 431d3c9..138f57f 100644 --- a/cctools/include/foreign/mach/machine.h +++ b/cctools/include/foreign/mach/machine.h @@ -76,12 +76,12 @@ typedef integer_t cpu_threadtype_t; #define CPU_STATE_NICE 3 - /* * Capability bits used in the definition of cpu_type. */ -#define CPU_ARCH_MASK 0xff000000 /* mask for architecture bits */ -#define CPU_ARCH_ABI64 0x01000000 /* 64 bit ABI */ +#define CPU_ARCH_MASK 0xff000000 /* mask for architecture bits */ +#define CPU_ARCH_ABI64 0x01000000 /* 64 bit ABI */ +#define CPU_ARCH_ABI64_32 0x02000000 /* ABI for 64-bit hardware with 32-bit types; LP32 */ /* * Machine types known by all. diff --git a/cctools/include/foreign/strings.h b/cctools/include/foreign/strings.h new file mode 100644 index 0000000..e49d38a --- /dev/null +++ b/cctools/include/foreign/strings.h @@ -0,0 +1,40 @@ +#include_next + +#undef bcmp +#undef bzero +#undef bcopy + +#ifndef HAVE_BCMP +static inline int bcmp(const void *s1, const void *s2, size_t n) +{ + return __builtin_memcmp(s1, s2, n); +} +#endif + +#ifndef HAVE_BZERO +static inline void bzero(void *s, size_t n) +{ + __builtin_memset(s, '\0', n); +} +#endif + +#ifndef HAVE_BCOPY +static inline void bcopy(const void *src, void *dest, size_t n) +{ + __builtin_memcpy(dest, src, n); +} +#endif + +#ifndef HAVE_INDEX +static inline char *index(const char *s, int c) +{ + return __builtin_strchr(s, c); +} +#endif + +#ifndef HAVE_RINDEX +static inline char *rindex(const char *s, int c) +{ + return __builtin_strrchr(s, c); +} +#endif diff --git a/cctools/include/foreign/sys/dirent.h b/cctools/include/foreign/sys/dirent.h deleted file mode 100644 index 77f8554..0000000 --- a/cctools/include/foreign/sys/dirent.h +++ /dev/null @@ -1,5 +0,0 @@ -#include_next - -#ifndef MAXNAMLEN -#define MAXNAMLEN NAME_MAX /* DragonFly BSD */ -#endif diff --git a/cctools/include/foreign/sys/sysctl.h b/cctools/include/foreign/sys/sysctl.h deleted file mode 100644 index 30749d1..0000000 --- a/cctools/include/foreign/sys/sysctl.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __CYGWIN__ -#include_next -#else -#ifndef __SYSCTL_H__ -#define __SYSCTL_H__ - -#include -#include /* stderr */ - -#define CTL_KERN 1 -#define KERN_OSRELEASE 2 - -static inline -int sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp, - const void *newp, size_t newlen) -{ - /* fprintf(stderr, "sysctl() not implented\n"); */ - errno = EINVAL; - return -1; -} -#endif /* __SYSCTL_H__ */ -#endif /* ! __CYGWIN__ */ diff --git a/cctools/include/mach-o/arch.h b/cctools/include/mach-o/arch.h index 7b3c6ae..9488316 100644 --- a/cctools/include/mach-o/arch.h +++ b/cctools/include/mach-o/arch.h @@ -72,6 +72,36 @@ extern const NXArchInfo *NXGetArchInfoFromName(const char *name); extern const NXArchInfo *NXGetArchInfoFromCpuType(cpu_type_t cputype, cpu_subtype_t cpusubtype); +/* The above interfaces that return pointers to NXArchInfo structs in normal + * cases returns a pointer from the array returned in NXGetAllArchInfos(). + * In some cases when the cputype is CPU_TYPE_I386 or CPU_TYPE_POWERPC it will + * retun malloc(3)'ed NXArchInfo struct which contains a string in the + * description field also a malloc(3)'ed pointer. To allow programs not to + * leak memory they can call NXFreeArchInfo() on pointers returned from the + * above interfaces. Since this is a new API on older systems can use the + * code below. Going forward the above interfaces will only return pointers + * from the array returned in NXGetAllArchInfos(). + */ +extern void NXFreeArchInfo(const NXArchInfo *x); + +/* The code that can be used for NXFreeArchInfo() when it is not available is: + * + * static void NXFreeArchInfo( + * const NXArchInfo *x) + * { + * const NXArchInfo *p; + * + * p = NXGetAllArchInfos(); + * while(p->name != NULL){ + * if(x == p) + * return; + * p++; + * } + * free((char *)x->description); + * free((NXArchInfo *)x); + * } + */ + /* NXFindBestFatArch() is passed a cputype and cpusubtype and a set of * fat_arch structs and selects the best one that matches (if any) and returns * a pointer to that fat_arch struct (or NULL). The fat_arch structs must be @@ -86,6 +116,21 @@ extern struct fat_arch *NXFindBestFatArch(cpu_type_t cputype, struct fat_arch *fat_archs, uint32_t nfat_archs); +/* NXFindBestFatArch_64() is passed a cputype and cpusubtype and a set of + * fat_arch_64 structs and selects the best one that matches (if any) and + * returns a pointer to that fat_arch_64 struct (or NULL). The fat_arch_64 + * structs must be in the host byte order and correct such that the fat_archs64 + * really points to enough memory for nfat_arch structs. It is possible that + * this routine could fail if new cputypes or cpusubtypes are added and an old + * version of this routine is used. But if there is an exact match between the + * cputype and cpusubtype and one of the fat_arch_64 structs this routine will + * always succeed. + */ +extern struct fat_arch_64 *NXFindBestFatArch_64(cpu_type_t cputype, + cpu_subtype_t cpusubtype, + struct fat_arch_64 *fat_archs64, + uint32_t nfat_archs); + /* NXCombineCpuSubtypes() returns the resulting cpusubtype when combining two * different cpusubtypes for the specified cputype. If the two cpusubtypes * can't be combined (the specific subtypes are mutually exclusive) -1 is diff --git a/cctools/include/mach-o/arm64/reloc.h b/cctools/include/mach-o/arm64/reloc.h index 0a98f18..6be5c8d 100644 --- a/cctools/include/mach-o/arm64/reloc.h +++ b/cctools/include/mach-o/arm64/reloc.h @@ -20,6 +20,10 @@ * * @APPLE_LICENSE_HEADER_END@ */ + +#ifndef _MACHO_ARM64_RELOC_H_ +#define _MACHO_ARM64_RELOC_H_ + /* * Relocation types used in the arm64 implementation. */ @@ -37,5 +41,28 @@ enum reloc_type_arm64 ARM64_RELOC_TLVP_LOAD_PAGE21, // pc-rel distance to page of TLVP slot ARM64_RELOC_TLVP_LOAD_PAGEOFF12, // offset within page of TLVP slot, // scaled by r_length - ARM64_RELOC_ADDEND // must be followed by PAGE21 or PAGEOFF12 + ARM64_RELOC_ADDEND, // must be followed by PAGE21 or PAGEOFF12 + + // An arm64e authenticated pointer. + // + // Represents a pointer to a symbol (like ARM64_RELOC_UNSIGNED). + // Additionally, the resulting pointer is signed. The signature is + // specified in the target location: the addend is restricted to the lower + // 32 bits (instead of the full 64 bits for ARM64_RELOC_UNSIGNED): + // + // |63|62|61-51|50-49| 48 |47 - 32|31 - 0| + // | 1| 0| 0 | key | addr | discriminator | addend | + // + // The key is one of: + // IA: 00 IB: 01 + // DA: 10 DB: 11 + // + // The discriminator field is used as extra signature diversification. + // + // The addr field indicates whether the target address should be blended + // into the discriminator. + // + ARM64_RELOC_AUTHENTICATED_POINTER, }; + +#endif /* #ifndef _MACHO_ARM64_RELOC_H_ */ diff --git a/cctools/include/mach-o/fat.h b/cctools/include/mach-o/fat.h index e2bcf43..98a7312 100644 --- a/cctools/include/mach-o/fat.h +++ b/cctools/include/mach-o/fat.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2016 Apple, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -49,7 +49,7 @@ #define FAT_CIGAM 0xbebafeca /* NXSwapLong(FAT_MAGIC) */ struct fat_header { - uint32_t magic; /* FAT_MAGIC */ + uint32_t magic; /* FAT_MAGIC or FAT_MAGIC_64 */ uint32_t nfat_arch; /* number of structs that follow */ }; @@ -61,4 +61,23 @@ struct fat_arch { uint32_t align; /* alignment as a power of 2 */ }; +/* + * The support for the 64-bit fat file format described here is a work in + * progress and not yet fully supported in all the Apple Developer Tools. + * + * When a slice is greater than 4mb or an offset to a slice is greater than 4mb + * then the 64-bit fat file format is used. + */ +#define FAT_MAGIC_64 0xcafebabf +#define FAT_CIGAM_64 0xbfbafeca /* NXSwapLong(FAT_MAGIC_64) */ + +struct fat_arch_64 { + cpu_type_t cputype; /* cpu specifier (int) */ + cpu_subtype_t cpusubtype; /* machine specifier (int) */ + uint64_t offset; /* file offset to this object file */ + uint64_t size; /* size of this object file */ + uint32_t align; /* alignment as a power of 2 */ + uint32_t reserved; /* reserved */ +}; + #endif /* _MACH_O_FAT_H_ */ diff --git a/cctools/include/mach-o/i386/swap.h b/cctools/include/mach-o/i386/swap.h index 09e322f..2f4623b 100644 --- a/cctools/include/mach-o/i386/swap.h +++ b/cctools/include/mach-o/i386/swap.h @@ -23,6 +23,8 @@ #include #include +struct i386_float_state; + extern void swap_i386_thread_state( i386_thread_state_t *cpu, enum NXByteOrder target_byte_order); diff --git a/cctools/include/mach-o/loader.h b/cctools/include/mach-o/loader.h index 7458c2c..193d424 100644 --- a/cctools/include/mach-o/loader.h +++ b/cctools/include/mach-o/loader.h @@ -210,6 +210,22 @@ struct mach_header_64 { #define MH_APP_EXTENSION_SAFE 0x02000000 /* The code was linked for use in an application extension. */ +#define MH_NLIST_OUTOFSYNC_WITH_DYLDINFO 0x04000000 /* The external symbols + listed in the nlist symbol table do + not include all the symbols listed in + the dyld info. */ + +#define MH_SIM_SUPPORT 0x08000000 /* Allow LC_MIN_VERSION_MACOS and + LC_BUILD_VERSION load commands with + the platforms macOS, macCatalyst, + iOSSimulator, tvOSSimulator and + watchOSSimulator. */ + +#define MH_DYLIB_IN_CACHE 0x80000000 /* Only for use on dylibs. When this bit + is set, the dylib is part of the dyld + shared cache, rather than loose in + the filesystem. */ + /* * The load commands directly follow the mach_header. The total size of all * of the commands is given by the sizeofcmds field in the mach_header. All @@ -302,6 +318,10 @@ struct load_command { #define LC_LINKER_OPTIMIZATION_HINT 0x2E /* optimization hints in MH_OBJECT files */ #define LC_VERSION_MIN_TVOS 0x2F /* build for AppleTV min OS version */ #define LC_VERSION_MIN_WATCHOS 0x30 /* build for Watch min OS version */ +#define LC_NOTE 0x31 /* arbitrary data included within a Mach-O file */ +#define LC_BUILD_VERSION 0x32 /* build for platform min OS version */ +#define LC_DYLD_EXPORTS_TRIE (0x33 | LC_REQ_DYLD) /* used with linkedit_data_command, payload is trie */ +#define LC_DYLD_CHAINED_FIXUPS (0x34 | LC_REQ_DYLD) /* used with linkedit_data_command */ /* * A variable length string in a load command is represented by an lc_str @@ -379,6 +399,9 @@ struct segment_command_64 { /* for 64-bit architectures */ first page of the segment is not protected. All other pages of the segment are protected. */ +#define SG_READ_ONLY 0x10 /* This segment is made read-only after fixups */ + + /* * A segment is made up of zero or more sections. Non-MH_OBJECT files have @@ -504,6 +527,8 @@ struct section_64 { /* for 64-bit architectures */ #define S_THREAD_LOCAL_INIT_FUNCTION_POINTERS 0x15 /* functions to call to initialize TLV values */ +#define S_INIT_FUNC_OFFSETS 0x16 /* 32-bit offsets to + initializers */ /* * Constants for the section attributes part of the flags field of a section @@ -765,14 +790,14 @@ struct dylinker_command { * Thread commands contain machine-specific data structures suitable for * use in the thread state primitives. The machine specific data structures * follow the struct thread_command as follows. - * Each flavor of machine specific data structure is preceded by an unsigned - * long constant for the flavor of that data structure, an uint32_t - * that is the count of longs of the size of the state data structure and then + * Each flavor of machine specific data structure is preceded by an uint32_t + * constant for the flavor of that data structure, an uint32_t that is the + * count of uint32_t's of the size of the state data structure and then * the state data structure follows. This triple may be repeated for many * flavors. The constants for the flavors, counts and state data structure * definitions are expected to be in the header file . * These machine specific data structures sizes must be multiples of - * 4 bytes The cmdsize reflects the total size of the thread_command + * 4 bytes. The cmdsize reflects the total size of the thread_command * and all of the sizes of the constants for the flavors, counts and state * data structures. * @@ -786,7 +811,7 @@ struct thread_command { uint32_t cmd; /* LC_THREAD or LC_UNIXTHREAD */ uint32_t cmdsize; /* total size of this command */ /* uint32_t flavor flavor of thread state */ - /* uint32_t count count of longs in thread state */ + /* uint32_t count count of uint32_t's in thread state */ /* struct XXX_thread_state state thread state for this flavor */ /* ... */ }; @@ -1161,9 +1186,11 @@ struct rpath_command { */ struct linkedit_data_command { uint32_t cmd; /* LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, - LC_FUNCTION_STARTS, LC_DATA_IN_CODE, - LC_DYLIB_CODE_SIGN_DRS or - LC_LINKER_OPTIMIZATION_HINT. */ + LC_FUNCTION_STARTS, LC_DATA_IN_CODE, + LC_DYLIB_CODE_SIGN_DRS, + LC_LINKER_OPTIMIZATION_HINT, + LC_DYLD_EXPORTS_TRIE, or + LC_DYLD_CHAINED_FIXUPS. */ uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */ uint32_t dataoff; /* file offset of data in __LINKEDIT segment */ uint32_t datasize; /* file size of data in __LINKEDIT segment */ @@ -1211,6 +1238,46 @@ struct version_min_command { uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ }; +/* + * The build_version_command contains the min OS version on which this + * binary was built to run for its platform. The list of known platforms and + * tool values following it. + */ +struct build_version_command { + uint32_t cmd; /* LC_BUILD_VERSION */ + uint32_t cmdsize; /* sizeof(struct build_version_command) plus */ + /* ntools * sizeof(struct build_tool_version) */ + uint32_t platform; /* platform */ + uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ + uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ + uint32_t ntools; /* number of tool entries following this */ +}; + +struct build_tool_version { + uint32_t tool; /* enum for the tool */ + uint32_t version; /* version number of the tool */ +}; + +/* Known values for the platform field above. */ +#define PLATFORM_MACOS 1 +#define PLATFORM_IOS 2 +#define PLATFORM_TVOS 3 +#define PLATFORM_WATCHOS 4 +#define PLATFORM_BRIDGEOS 5 +#define PLATFORM_IOSMAC 6 +#if (!defined(PLATFORM_MACCATALYST)) +#define PLATFORM_MACCATALYST 6 +#endif +#define PLATFORM_IOSSIMULATOR 7 +#define PLATFORM_TVOSSIMULATOR 8 +#define PLATFORM_WATCHOSSIMULATOR 9 +#define PLATFORM_DRIVERKIT 10 + +/* Known values for the tool field above. */ +#define TOOL_CLANG 1 +#define TOOL_SWIFT 2 +#define TOOL_LD 3 + /* * The dyld_info_command contains the file offsets and sizes of * the new compressed form of the information dyld needs to @@ -1297,18 +1364,18 @@ struct dyld_info_command { * the exported symbol information for the string so far. * If there is no exported symbol, the node starts with a zero byte. * If there is exported info, it follows the length. - * - * First is a uleb128 containing flags. Normally, it is followed by + * + * First is a uleb128 containing flags. Normally, it is followed by * a uleb128 encoded offset which is location of the content named * by the symbol from the mach_header for the image. If the flags * is EXPORT_SYMBOL_FLAGS_REEXPORT, then following the flags is * a uleb128 encoded library ordinal, then a zero terminated * UTF8 string. If the string is zero length, then the symbol * is re-export from the specified dylib with the same name. - * If the flags is EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER, then following - * the flags is two uleb128s: the stub offset and the resolver offset. - * The stub is used by non-lazy pointers. The resolver is used - * by lazy pointers and must be called to get the actual address to use. + * If the flags is EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER, then following + * the flags is two uleb128s: the stub offset and the resolver offset. + * The stub is used by non-lazy pointers. The resolver is used + * by lazy pointers and must be called to get the actual address to use. * * After the optional exported symbol information is a byte of * how many edges (0-255) that this node has leaving it, @@ -1352,6 +1419,7 @@ struct dyld_info_command { #define BIND_SPECIAL_DYLIB_SELF 0 #define BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE -1 #define BIND_SPECIAL_DYLIB_FLAT_LOOKUP -2 +#define BIND_SPECIAL_DYLIB_WEAK_LOOKUP -3 #define BIND_SYMBOL_FLAGS_WEAK_IMPORT 0x1 #define BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION 0x8 @@ -1371,6 +1439,9 @@ struct dyld_info_command { #define BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB 0xA0 #define BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED 0xB0 #define BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0xC0 +#define BIND_OPCODE_THREADED 0xD0 +#define BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB 0x00 +#define BIND_SUBOPCODE_THREADED_APPLY 0x01 /* @@ -1380,6 +1451,7 @@ struct dyld_info_command { #define EXPORT_SYMBOL_FLAGS_KIND_MASK 0x03 #define EXPORT_SYMBOL_FLAGS_KIND_REGULAR 0x00 #define EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL 0x01 +#define EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE 0x02 #define EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION 0x04 #define EXPORT_SYMBOL_FLAGS_REEXPORT 0x08 #define EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER 0x10 @@ -1490,4 +1562,16 @@ struct tlv_descriptor unsigned long offset; }; +/* + * LC_NOTE commands describe a region of arbitrary data included in a Mach-O + * file. Its initial use is to record extra data in MH_CORE files. + */ +struct note_command { + uint32_t cmd; /* LC_NOTE */ + uint32_t cmdsize; /* sizeof(struct note_command) */ + char data_owner[16]; /* owner name for this LC_NOTE */ + uint64_t offset; /* file offset of this data */ + uint64_t size; /* length of data region */ +}; + #endif /* _MACHO_LOADER_H_ */ diff --git a/cctools/include/mach-o/nlist.h b/cctools/include/mach-o/nlist.h index 133e36b..96b0cd5 100644 --- a/cctools/include/mach-o/nlist.h +++ b/cctools/include/mach-o/nlist.h @@ -302,6 +302,12 @@ struct nlist_64 { */ #define N_ALT_ENTRY 0x0200 +/* + * The N_COLD_FUNC bit of the n_desc field indicates that the symbol is used + * infrequently and the linker should order it towards the end of the section. + */ +#define N_COLD_FUNC 0x0400 + #ifndef __STRICT_BSD__ #ifdef __cplusplus extern "C" { diff --git a/cctools/include/mach-o/ranlib.h b/cctools/include/mach-o/ranlib.h index 66a1f09..ec86752 100644 --- a/cctools/include/mach-o/ranlib.h +++ b/cctools/include/mach-o/ranlib.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2016 Apple, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -49,9 +49,9 @@ /* * Structure of the __.SYMDEF table of contents for an archive. - * __.SYMDEF begins with a long giving the size in bytes of the ranlib + * __.SYMDEF begins with a uint32_t giving the size in bytes of the ranlib * structures which immediately follow, and then continues with a string - * table consisting of a long giving the number of bytes of strings which + * table consisting of a uint32_t giving the number of bytes of strings which * follow and then the strings themselves. The ran_strx fields index the * string table whose first byte is numbered 0. */ @@ -64,4 +64,27 @@ struct ranlib { } ran_un; uint32_t ran_off; /* library member at this offset */ }; + +#define SYMDEF_64 "__.SYMDEF_64" +#define SYMDEF_64_SORTED "__.SYMDEF_64 SORTED" + +/* + * The support for the 64-bit table of contents described here is a work in + * progress and not yet fully supported in all the Apple Developer Tools. + * + * When an archive offset to a library member is more than 32-bits then this is + * the structure of the __.SYMDEF_64 table of contents for an archive. + * __.SYMDEF_64 begins with a uint64_t giving the size in bytes of the ranlib + * structures which immediately follow, and then continues with a string + * table consisting of a uint64_t giving the number of bytes of strings which + * follow and then the strings themselves. The ran_strx fields index the + * string table whose first byte is numbered 0. + */ + +struct ranlib_64 { + union { + uint64_t ran_strx; /* string table index of */ + } ran_un; + uint64_t ran_off; /* library member at this offset */ +}; #endif /* _MACH_O_RANLIB_H_ */ diff --git a/cctools/include/mach-o/stab.h b/cctools/include/mach-o/stab.h index 0c89939..8d45631 100644 --- a/cctools/include/mach-o/stab.h +++ b/cctools/include/mach-o/stab.h @@ -97,7 +97,10 @@ #define N_ENSYM 0x4e /* end nsect sym: 0,,n_sect,0,address */ #define N_SSYM 0x60 /* structure elt: name,,NO_SECT,type,struct_offset */ #define N_SO 0x64 /* source file name: name,,n_sect,0,address */ -#define N_OSO 0x66 /* object file name: name,,0,0,st_mtime */ +#define N_OSO 0x66 /* object file name: name,,(see below),0,st_mtime */ + /* historically N_OSO set n_sect to 0. The N_OSO + * n_sect may instead hold the low byte of the + * cpusubtype value from the Mach-O header. */ #define N_LSYM 0x80 /* local sym: name,,NO_SECT,type,offset */ #define N_BINCL 0x82 /* include file beginning: name,,NO_SECT,0,sum */ #define N_SOL 0x84 /* #included file name: name,,n_sect,0,address */ diff --git a/cctools/include/mach-o/swap.h b/cctools/include/mach-o/swap.h index 5b5130f..5d1bd78 100644 --- a/cctools/include/mach-o/swap.h +++ b/cctools/include/mach-o/swap.h @@ -44,6 +44,11 @@ extern void swap_fat_arch( uint32_t nfat_arch, enum NXByteOrder target_byte_order); +extern void swap_fat_arch_64( + struct fat_arch_64 *fat_archs64, + uint32_t nfat_arch, + enum NXByteOrder target_byte_order); + extern void swap_mach_header( struct mach_header *mh, enum NXByteOrder target_byte_order); @@ -186,6 +191,19 @@ extern void swap_source_version_command( struct source_version_command *sv, enum NXByteOrder target_byte_sex); +extern void swap_note_command( + struct note_command *nc, + enum NXByteOrder target_byte_sex); + +extern void swap_build_version_command( + struct build_version_command *bv, + enum NXByteOrder target_byte_sex); + +extern void swap_build_tool_version( + struct build_tool_version *bt, + uint32_t ntools, + enum NXByteOrder target_byte_sex); + extern void swap_prebind_cksum_command( struct prebind_cksum_command *cksum_cmd, enum NXByteOrder target_byte_sex); @@ -214,6 +232,11 @@ extern void swap_ranlib( uint32_t nranlibs, enum NXByteOrder target_byte_order); +extern void swap_ranlib_64( + struct ranlib_64 *ranlibs, + uint64_t nranlibs, + enum NXByteOrder target_byte_order); + extern void swap_relocation_info( struct relocation_info *relocs, uint32_t nrelocs, diff --git a/cctools/include/mach/i386/_structs.h b/cctools/include/mach/i386/_structs.h index 9dd3f44..a412572 100644 --- a/cctools/include/mach/i386/_structs.h +++ b/cctools/include/mach/i386/_structs.h @@ -32,6 +32,9 @@ #ifndef _MACH_I386__STRUCTS_H_ #define _MACH_I386__STRUCTS_H_ +#include /* __DARWIN_UNIX03 */ +#include /* __uint8_t */ + /* * i386 is the structure that is exported to user threads for * use in status/mutate calls. This structure should never change. @@ -219,6 +222,52 @@ _STRUCT_XMM_REG }; #endif /* !__DARWIN_UNIX03 */ +/* defn of 256 bit YMM regs */ + +#if __DARWIN_UNIX03 +#define _STRUCT_YMM_REG struct __darwin_ymm_reg +_STRUCT_YMM_REG +{ + char __ymm_reg[32]; +}; +#else /* !__DARWIN_UNIX03 */ +#define _STRUCT_YMM_REG struct ymm_reg +_STRUCT_YMM_REG +{ + char ymm_reg[32]; +}; +#endif /* !__DARWIN_UNIX03 */ + +/* defn of 512 bit ZMM regs */ + +#if __DARWIN_UNIX03 +#define _STRUCT_ZMM_REG struct __darwin_zmm_reg +_STRUCT_ZMM_REG +{ + char __zmm_reg[64]; +}; +#else /* !__DARWIN_UNIX03 */ +#define _STRUCT_ZMM_REG struct zmm_reg +_STRUCT_ZMM_REG +{ + char zmm_reg[64]; +}; +#endif /* !__DARWIN_UNIX03 */ + +#if __DARWIN_UNIX03 +#define _STRUCT_OPMASK_REG struct __darwin_opmask_reg +_STRUCT_OPMASK_REG +{ + char __opmask_reg[8]; +}; +#else /* !__DARWIN_UNIX03 */ +#define _STRUCT_OPMASK_REG struct opmask_reg +_STRUCT_OPMASK_REG +{ + char opmask_reg[8]; +}; +#endif /* !__DARWIN_UNIX03 */ + /* * Floating point state. */ @@ -311,6 +360,68 @@ _STRUCT_X86_AVX_STATE32 _STRUCT_XMM_REG __fpu_ymmh7; /* YMMH 7 */ }; +#define _STRUCT_X86_AVX512_STATE32 struct __darwin_i386_avx512_state +_STRUCT_X86_AVX512_STATE32 +{ + int __fpu_reserved[2]; + _STRUCT_FP_CONTROL __fpu_fcw; /* x87 FPU control word */ + _STRUCT_FP_STATUS __fpu_fsw; /* x87 FPU status word */ + __uint8_t __fpu_ftw; /* x87 FPU tag word */ + __uint8_t __fpu_rsrv1; /* reserved */ + __uint16_t __fpu_fop; /* x87 FPU Opcode */ + __uint32_t __fpu_ip; /* x87 FPU Instruction Pointer offset */ + __uint16_t __fpu_cs; /* x87 FPU Instruction Pointer Selector */ + __uint16_t __fpu_rsrv2; /* reserved */ + __uint32_t __fpu_dp; /* x87 FPU Instruction Operand(Data) Pointer offset */ + __uint16_t __fpu_ds; /* x87 FPU Instruction Operand(Data) Pointer Selector */ + __uint16_t __fpu_rsrv3; /* reserved */ + __uint32_t __fpu_mxcsr; /* MXCSR Register state */ + __uint32_t __fpu_mxcsrmask; /* MXCSR mask */ + _STRUCT_MMST_REG __fpu_stmm0; /* ST0/MM0 */ + _STRUCT_MMST_REG __fpu_stmm1; /* ST1/MM1 */ + _STRUCT_MMST_REG __fpu_stmm2; /* ST2/MM2 */ + _STRUCT_MMST_REG __fpu_stmm3; /* ST3/MM3 */ + _STRUCT_MMST_REG __fpu_stmm4; /* ST4/MM4 */ + _STRUCT_MMST_REG __fpu_stmm5; /* ST5/MM5 */ + _STRUCT_MMST_REG __fpu_stmm6; /* ST6/MM6 */ + _STRUCT_MMST_REG __fpu_stmm7; /* ST7/MM7 */ + _STRUCT_XMM_REG __fpu_xmm0; /* XMM 0 */ + _STRUCT_XMM_REG __fpu_xmm1; /* XMM 1 */ + _STRUCT_XMM_REG __fpu_xmm2; /* XMM 2 */ + _STRUCT_XMM_REG __fpu_xmm3; /* XMM 3 */ + _STRUCT_XMM_REG __fpu_xmm4; /* XMM 4 */ + _STRUCT_XMM_REG __fpu_xmm5; /* XMM 5 */ + _STRUCT_XMM_REG __fpu_xmm6; /* XMM 6 */ + _STRUCT_XMM_REG __fpu_xmm7; /* XMM 7 */ + char __fpu_rsrv4[14*16]; /* reserved */ + int __fpu_reserved1; + char __avx_reserved1[64]; + _STRUCT_XMM_REG __fpu_ymmh0; /* YMMH 0 */ + _STRUCT_XMM_REG __fpu_ymmh1; /* YMMH 1 */ + _STRUCT_XMM_REG __fpu_ymmh2; /* YMMH 2 */ + _STRUCT_XMM_REG __fpu_ymmh3; /* YMMH 3 */ + _STRUCT_XMM_REG __fpu_ymmh4; /* YMMH 4 */ + _STRUCT_XMM_REG __fpu_ymmh5; /* YMMH 5 */ + _STRUCT_XMM_REG __fpu_ymmh6; /* YMMH 6 */ + _STRUCT_XMM_REG __fpu_ymmh7; /* YMMH 7 */ + _STRUCT_OPMASK_REG __fpu_k0; /* K0 */ + _STRUCT_OPMASK_REG __fpu_k1; /* K1 */ + _STRUCT_OPMASK_REG __fpu_k2; /* K2 */ + _STRUCT_OPMASK_REG __fpu_k3; /* K3 */ + _STRUCT_OPMASK_REG __fpu_k4; /* K4 */ + _STRUCT_OPMASK_REG __fpu_k5; /* K5 */ + _STRUCT_OPMASK_REG __fpu_k6; /* K6 */ + _STRUCT_OPMASK_REG __fpu_k7; /* K7 */ + _STRUCT_YMM_REG __fpu_zmmh0; /* ZMMH 0 */ + _STRUCT_YMM_REG __fpu_zmmh1; /* ZMMH 1 */ + _STRUCT_YMM_REG __fpu_zmmh2; /* ZMMH 2 */ + _STRUCT_YMM_REG __fpu_zmmh3; /* ZMMH 3 */ + _STRUCT_YMM_REG __fpu_zmmh4; /* ZMMH 4 */ + _STRUCT_YMM_REG __fpu_zmmh5; /* ZMMH 5 */ + _STRUCT_YMM_REG __fpu_zmmh6; /* ZMMH 6 */ + _STRUCT_YMM_REG __fpu_zmmh7; /* ZMMH 7 */ +}; + #else /* !__DARWIN_UNIX03 */ #define _STRUCT_X86_FLOAT_STATE32 struct i386_float_state _STRUCT_X86_FLOAT_STATE32 @@ -384,15 +495,77 @@ _STRUCT_X86_AVX_STATE32 _STRUCT_XMM_REG fpu_xmm7; /* XMM 7 */ char fpu_rsrv4[14*16]; /* reserved */ int fpu_reserved1; - char __avx_reserved1[64]; - _STRUCT_XMM_REG __fpu_ymmh0; /* YMMH 0 */ - _STRUCT_XMM_REG __fpu_ymmh1; /* YMMH 1 */ - _STRUCT_XMM_REG __fpu_ymmh2; /* YMMH 2 */ - _STRUCT_XMM_REG __fpu_ymmh3; /* YMMH 3 */ - _STRUCT_XMM_REG __fpu_ymmh4; /* YMMH 4 */ - _STRUCT_XMM_REG __fpu_ymmh5; /* YMMH 5 */ - _STRUCT_XMM_REG __fpu_ymmh6; /* YMMH 6 */ - _STRUCT_XMM_REG __fpu_ymmh7; /* YMMH 7 */ + char avx_reserved1[64]; + _STRUCT_XMM_REG fpu_ymmh0; /* YMMH 0 */ + _STRUCT_XMM_REG fpu_ymmh1; /* YMMH 1 */ + _STRUCT_XMM_REG fpu_ymmh2; /* YMMH 2 */ + _STRUCT_XMM_REG fpu_ymmh3; /* YMMH 3 */ + _STRUCT_XMM_REG fpu_ymmh4; /* YMMH 4 */ + _STRUCT_XMM_REG fpu_ymmh5; /* YMMH 5 */ + _STRUCT_XMM_REG fpu_ymmh6; /* YMMH 6 */ + _STRUCT_XMM_REG fpu_ymmh7; /* YMMH 7 */ +}; + +#define _STRUCT_X86_AVX512_STATE32 struct i386_avx512_state +_STRUCT_X86_AVX512_STATE32 +{ + int fpu_reserved[2]; + _STRUCT_FP_CONTROL fpu_fcw; /* x87 FPU control word */ + _STRUCT_FP_STATUS fpu_fsw; /* x87 FPU status word */ + __uint8_t fpu_ftw; /* x87 FPU tag word */ + __uint8_t fpu_rsrv1; /* reserved */ + __uint16_t fpu_fop; /* x87 FPU Opcode */ + __uint32_t fpu_ip; /* x87 FPU Instruction Pointer offset */ + __uint16_t fpu_cs; /* x87 FPU Instruction Pointer Selector */ + __uint16_t fpu_rsrv2; /* reserved */ + __uint32_t fpu_dp; /* x87 FPU Instruction Operand(Data) Pointer offset */ + __uint16_t fpu_ds; /* x87 FPU Instruction Operand(Data) Pointer Selector */ + __uint16_t fpu_rsrv3; /* reserved */ + __uint32_t fpu_mxcsr; /* MXCSR Register state */ + __uint32_t fpu_mxcsrmask; /* MXCSR mask */ + _STRUCT_MMST_REG fpu_stmm0; /* ST0/MM0 */ + _STRUCT_MMST_REG fpu_stmm1; /* ST1/MM1 */ + _STRUCT_MMST_REG fpu_stmm2; /* ST2/MM2 */ + _STRUCT_MMST_REG fpu_stmm3; /* ST3/MM3 */ + _STRUCT_MMST_REG fpu_stmm4; /* ST4/MM4 */ + _STRUCT_MMST_REG fpu_stmm5; /* ST5/MM5 */ + _STRUCT_MMST_REG fpu_stmm6; /* ST6/MM6 */ + _STRUCT_MMST_REG fpu_stmm7; /* ST7/MM7 */ + _STRUCT_XMM_REG fpu_xmm0; /* XMM 0 */ + _STRUCT_XMM_REG fpu_xmm1; /* XMM 1 */ + _STRUCT_XMM_REG fpu_xmm2; /* XMM 2 */ + _STRUCT_XMM_REG fpu_xmm3; /* XMM 3 */ + _STRUCT_XMM_REG fpu_xmm4; /* XMM 4 */ + _STRUCT_XMM_REG fpu_xmm5; /* XMM 5 */ + _STRUCT_XMM_REG fpu_xmm6; /* XMM 6 */ + _STRUCT_XMM_REG fpu_xmm7; /* XMM 7 */ + char fpu_rsrv4[14*16]; /* reserved */ + int fpu_reserved1; + char avx_reserved1[64]; + _STRUCT_XMM_REG fpu_ymmh0; /* YMMH 0 */ + _STRUCT_XMM_REG fpu_ymmh1; /* YMMH 1 */ + _STRUCT_XMM_REG fpu_ymmh2; /* YMMH 2 */ + _STRUCT_XMM_REG fpu_ymmh3; /* YMMH 3 */ + _STRUCT_XMM_REG fpu_ymmh4; /* YMMH 4 */ + _STRUCT_XMM_REG fpu_ymmh5; /* YMMH 5 */ + _STRUCT_XMM_REG fpu_ymmh6; /* YMMH 6 */ + _STRUCT_XMM_REG fpu_ymmh7; /* YMMH 7 */ + _STRUCT_OPMASK_REG fpu_k0; /* K0 */ + _STRUCT_OPMASK_REG fpu_k1; /* K1 */ + _STRUCT_OPMASK_REG fpu_k2; /* K2 */ + _STRUCT_OPMASK_REG fpu_k3; /* K3 */ + _STRUCT_OPMASK_REG fpu_k4; /* K4 */ + _STRUCT_OPMASK_REG fpu_k5; /* K5 */ + _STRUCT_OPMASK_REG fpu_k6; /* K6 */ + _STRUCT_OPMASK_REG fpu_k7; /* K7 */ + _STRUCT_YMM_REG fpu_zmmh0; /* ZMMH 0 */ + _STRUCT_YMM_REG fpu_zmmh1; /* ZMMH 1 */ + _STRUCT_YMM_REG fpu_zmmh2; /* ZMMH 2 */ + _STRUCT_YMM_REG fpu_zmmh3; /* ZMMH 3 */ + _STRUCT_YMM_REG fpu_zmmh4; /* ZMMH 4 */ + _STRUCT_YMM_REG fpu_zmmh5; /* ZMMH 5 */ + _STRUCT_YMM_REG fpu_zmmh6; /* ZMMH 6 */ + _STRUCT_YMM_REG fpu_zmmh7; /* ZMMH 7 */ }; #endif /* !__DARWIN_UNIX03 */ @@ -445,6 +618,12 @@ _STRUCT_X86_DEBUG_STATE32 }; #endif /* !__DARWIN_UNIX03 */ +#define _STRUCT_X86_PAGEIN_STATE struct __x86_pagein_state +_STRUCT_X86_PAGEIN_STATE +{ + int __pagein_error; +}; + /* * 64 bit versions of the above */ @@ -503,6 +682,32 @@ _STRUCT_X86_THREAD_STATE64 }; #endif /* !__DARWIN_UNIX03 */ +/* + * 64 bit versions of the above (complete) + */ + +#if __DARWIN_UNIX03 +#define _STRUCT_X86_THREAD_FULL_STATE64 struct __darwin_x86_thread_full_state64 +_STRUCT_X86_THREAD_FULL_STATE64 +{ + _STRUCT_X86_THREAD_STATE64 ss64; + __uint64_t __ds; + __uint64_t __es; + __uint64_t __ss; + __uint64_t __gsbase; +}; +#else /* !__DARWIN_UNIX03 */ +#define _STRUCT_X86_THREAD_FULL_STATE64 struct x86_thread_full_state64 +_STRUCT_X86_THREAD_FULL_STATE64 +{ + _STRUCT_X86_THREAD_STATE64 ss64; + __uint64_t ds; + __uint64_t es; + __uint64_t ss; + __uint64_t gsbase; +}; +#endif /* !__DARWIN_UNIX03 */ + #if __DARWIN_UNIX03 #define _STRUCT_X86_FLOAT_STATE64 struct __darwin_x86_float_state64 @@ -624,6 +829,114 @@ _STRUCT_X86_AVX_STATE64 _STRUCT_XMM_REG __fpu_ymmh15; /* YMMH 15 */ }; +#define _STRUCT_X86_AVX512_STATE64 struct __darwin_x86_avx512_state64 +_STRUCT_X86_AVX512_STATE64 +{ + int __fpu_reserved[2]; + _STRUCT_FP_CONTROL __fpu_fcw; /* x87 FPU control word */ + _STRUCT_FP_STATUS __fpu_fsw; /* x87 FPU status word */ + __uint8_t __fpu_ftw; /* x87 FPU tag word */ + __uint8_t __fpu_rsrv1; /* reserved */ + __uint16_t __fpu_fop; /* x87 FPU Opcode */ + + /* x87 FPU Instruction Pointer */ + __uint32_t __fpu_ip; /* offset */ + __uint16_t __fpu_cs; /* Selector */ + + __uint16_t __fpu_rsrv2; /* reserved */ + + /* x87 FPU Instruction Operand(Data) Pointer */ + __uint32_t __fpu_dp; /* offset */ + __uint16_t __fpu_ds; /* Selector */ + + __uint16_t __fpu_rsrv3; /* reserved */ + __uint32_t __fpu_mxcsr; /* MXCSR Register state */ + __uint32_t __fpu_mxcsrmask; /* MXCSR mask */ + _STRUCT_MMST_REG __fpu_stmm0; /* ST0/MM0 */ + _STRUCT_MMST_REG __fpu_stmm1; /* ST1/MM1 */ + _STRUCT_MMST_REG __fpu_stmm2; /* ST2/MM2 */ + _STRUCT_MMST_REG __fpu_stmm3; /* ST3/MM3 */ + _STRUCT_MMST_REG __fpu_stmm4; /* ST4/MM4 */ + _STRUCT_MMST_REG __fpu_stmm5; /* ST5/MM5 */ + _STRUCT_MMST_REG __fpu_stmm6; /* ST6/MM6 */ + _STRUCT_MMST_REG __fpu_stmm7; /* ST7/MM7 */ + _STRUCT_XMM_REG __fpu_xmm0; /* XMM 0 */ + _STRUCT_XMM_REG __fpu_xmm1; /* XMM 1 */ + _STRUCT_XMM_REG __fpu_xmm2; /* XMM 2 */ + _STRUCT_XMM_REG __fpu_xmm3; /* XMM 3 */ + _STRUCT_XMM_REG __fpu_xmm4; /* XMM 4 */ + _STRUCT_XMM_REG __fpu_xmm5; /* XMM 5 */ + _STRUCT_XMM_REG __fpu_xmm6; /* XMM 6 */ + _STRUCT_XMM_REG __fpu_xmm7; /* XMM 7 */ + _STRUCT_XMM_REG __fpu_xmm8; /* XMM 8 */ + _STRUCT_XMM_REG __fpu_xmm9; /* XMM 9 */ + _STRUCT_XMM_REG __fpu_xmm10; /* XMM 10 */ + _STRUCT_XMM_REG __fpu_xmm11; /* XMM 11 */ + _STRUCT_XMM_REG __fpu_xmm12; /* XMM 12 */ + _STRUCT_XMM_REG __fpu_xmm13; /* XMM 13 */ + _STRUCT_XMM_REG __fpu_xmm14; /* XMM 14 */ + _STRUCT_XMM_REG __fpu_xmm15; /* XMM 15 */ + char __fpu_rsrv4[6*16]; /* reserved */ + int __fpu_reserved1; + char __avx_reserved1[64]; + _STRUCT_XMM_REG __fpu_ymmh0; /* YMMH 0 */ + _STRUCT_XMM_REG __fpu_ymmh1; /* YMMH 1 */ + _STRUCT_XMM_REG __fpu_ymmh2; /* YMMH 2 */ + _STRUCT_XMM_REG __fpu_ymmh3; /* YMMH 3 */ + _STRUCT_XMM_REG __fpu_ymmh4; /* YMMH 4 */ + _STRUCT_XMM_REG __fpu_ymmh5; /* YMMH 5 */ + _STRUCT_XMM_REG __fpu_ymmh6; /* YMMH 6 */ + _STRUCT_XMM_REG __fpu_ymmh7; /* YMMH 7 */ + _STRUCT_XMM_REG __fpu_ymmh8; /* YMMH 8 */ + _STRUCT_XMM_REG __fpu_ymmh9; /* YMMH 9 */ + _STRUCT_XMM_REG __fpu_ymmh10; /* YMMH 10 */ + _STRUCT_XMM_REG __fpu_ymmh11; /* YMMH 11 */ + _STRUCT_XMM_REG __fpu_ymmh12; /* YMMH 12 */ + _STRUCT_XMM_REG __fpu_ymmh13; /* YMMH 13 */ + _STRUCT_XMM_REG __fpu_ymmh14; /* YMMH 14 */ + _STRUCT_XMM_REG __fpu_ymmh15; /* YMMH 15 */ + _STRUCT_OPMASK_REG __fpu_k0; /* K0 */ + _STRUCT_OPMASK_REG __fpu_k1; /* K1 */ + _STRUCT_OPMASK_REG __fpu_k2; /* K2 */ + _STRUCT_OPMASK_REG __fpu_k3; /* K3 */ + _STRUCT_OPMASK_REG __fpu_k4; /* K4 */ + _STRUCT_OPMASK_REG __fpu_k5; /* K5 */ + _STRUCT_OPMASK_REG __fpu_k6; /* K6 */ + _STRUCT_OPMASK_REG __fpu_k7; /* K7 */ + _STRUCT_YMM_REG __fpu_zmmh0; /* ZMMH 0 */ + _STRUCT_YMM_REG __fpu_zmmh1; /* ZMMH 1 */ + _STRUCT_YMM_REG __fpu_zmmh2; /* ZMMH 2 */ + _STRUCT_YMM_REG __fpu_zmmh3; /* ZMMH 3 */ + _STRUCT_YMM_REG __fpu_zmmh4; /* ZMMH 4 */ + _STRUCT_YMM_REG __fpu_zmmh5; /* ZMMH 5 */ + _STRUCT_YMM_REG __fpu_zmmh6; /* ZMMH 6 */ + _STRUCT_YMM_REG __fpu_zmmh7; /* ZMMH 7 */ + _STRUCT_YMM_REG __fpu_zmmh8; /* ZMMH 8 */ + _STRUCT_YMM_REG __fpu_zmmh9; /* ZMMH 9 */ + _STRUCT_YMM_REG __fpu_zmmh10; /* ZMMH 10 */ + _STRUCT_YMM_REG __fpu_zmmh11; /* ZMMH 11 */ + _STRUCT_YMM_REG __fpu_zmmh12; /* ZMMH 12 */ + _STRUCT_YMM_REG __fpu_zmmh13; /* ZMMH 13 */ + _STRUCT_YMM_REG __fpu_zmmh14; /* ZMMH 14 */ + _STRUCT_YMM_REG __fpu_zmmh15; /* ZMMH 15 */ + _STRUCT_ZMM_REG __fpu_zmm16; /* ZMM 16 */ + _STRUCT_ZMM_REG __fpu_zmm17; /* ZMM 17 */ + _STRUCT_ZMM_REG __fpu_zmm18; /* ZMM 18 */ + _STRUCT_ZMM_REG __fpu_zmm19; /* ZMM 19 */ + _STRUCT_ZMM_REG __fpu_zmm20; /* ZMM 20 */ + _STRUCT_ZMM_REG __fpu_zmm21; /* ZMM 21 */ + _STRUCT_ZMM_REG __fpu_zmm22; /* ZMM 22 */ + _STRUCT_ZMM_REG __fpu_zmm23; /* ZMM 23 */ + _STRUCT_ZMM_REG __fpu_zmm24; /* ZMM 24 */ + _STRUCT_ZMM_REG __fpu_zmm25; /* ZMM 25 */ + _STRUCT_ZMM_REG __fpu_zmm26; /* ZMM 26 */ + _STRUCT_ZMM_REG __fpu_zmm27; /* ZMM 27 */ + _STRUCT_ZMM_REG __fpu_zmm28; /* ZMM 28 */ + _STRUCT_ZMM_REG __fpu_zmm29; /* ZMM 29 */ + _STRUCT_ZMM_REG __fpu_zmm30; /* ZMM 30 */ + _STRUCT_ZMM_REG __fpu_zmm31; /* ZMM 31 */ +}; + #else /* !__DARWIN_UNIX03 */ #define _STRUCT_X86_FLOAT_STATE64 struct x86_float_state64 _STRUCT_X86_FLOAT_STATE64 @@ -725,23 +1038,131 @@ _STRUCT_X86_AVX_STATE64 _STRUCT_XMM_REG fpu_xmm15; /* XMM 15 */ char fpu_rsrv4[6*16]; /* reserved */ int fpu_reserved1; - char __avx_reserved1[64]; - _STRUCT_XMM_REG __fpu_ymmh0; /* YMMH 0 */ - _STRUCT_XMM_REG __fpu_ymmh1; /* YMMH 1 */ - _STRUCT_XMM_REG __fpu_ymmh2; /* YMMH 2 */ - _STRUCT_XMM_REG __fpu_ymmh3; /* YMMH 3 */ - _STRUCT_XMM_REG __fpu_ymmh4; /* YMMH 4 */ - _STRUCT_XMM_REG __fpu_ymmh5; /* YMMH 5 */ - _STRUCT_XMM_REG __fpu_ymmh6; /* YMMH 6 */ - _STRUCT_XMM_REG __fpu_ymmh7; /* YMMH 7 */ - _STRUCT_XMM_REG __fpu_ymmh8; /* YMMH 8 */ - _STRUCT_XMM_REG __fpu_ymmh9; /* YMMH 9 */ - _STRUCT_XMM_REG __fpu_ymmh10; /* YMMH 10 */ - _STRUCT_XMM_REG __fpu_ymmh11; /* YMMH 11 */ - _STRUCT_XMM_REG __fpu_ymmh12; /* YMMH 12 */ - _STRUCT_XMM_REG __fpu_ymmh13; /* YMMH 13 */ - _STRUCT_XMM_REG __fpu_ymmh14; /* YMMH 14 */ - _STRUCT_XMM_REG __fpu_ymmh15; /* YMMH 15 */ + char avx_reserved1[64]; + _STRUCT_XMM_REG fpu_ymmh0; /* YMMH 0 */ + _STRUCT_XMM_REG fpu_ymmh1; /* YMMH 1 */ + _STRUCT_XMM_REG fpu_ymmh2; /* YMMH 2 */ + _STRUCT_XMM_REG fpu_ymmh3; /* YMMH 3 */ + _STRUCT_XMM_REG fpu_ymmh4; /* YMMH 4 */ + _STRUCT_XMM_REG fpu_ymmh5; /* YMMH 5 */ + _STRUCT_XMM_REG fpu_ymmh6; /* YMMH 6 */ + _STRUCT_XMM_REG fpu_ymmh7; /* YMMH 7 */ + _STRUCT_XMM_REG fpu_ymmh8; /* YMMH 8 */ + _STRUCT_XMM_REG fpu_ymmh9; /* YMMH 9 */ + _STRUCT_XMM_REG fpu_ymmh10; /* YMMH 10 */ + _STRUCT_XMM_REG fpu_ymmh11; /* YMMH 11 */ + _STRUCT_XMM_REG fpu_ymmh12; /* YMMH 12 */ + _STRUCT_XMM_REG fpu_ymmh13; /* YMMH 13 */ + _STRUCT_XMM_REG fpu_ymmh14; /* YMMH 14 */ + _STRUCT_XMM_REG fpu_ymmh15; /* YMMH 15 */ +}; + +#define _STRUCT_X86_AVX512_STATE64 struct x86_avx512_state64 +_STRUCT_X86_AVX512_STATE64 +{ + int fpu_reserved[2]; + _STRUCT_FP_CONTROL fpu_fcw; /* x87 FPU control word */ + _STRUCT_FP_STATUS fpu_fsw; /* x87 FPU status word */ + __uint8_t fpu_ftw; /* x87 FPU tag word */ + __uint8_t fpu_rsrv1; /* reserved */ + __uint16_t fpu_fop; /* x87 FPU Opcode */ + + /* x87 FPU Instruction Pointer */ + __uint32_t fpu_ip; /* offset */ + __uint16_t fpu_cs; /* Selector */ + + __uint16_t fpu_rsrv2; /* reserved */ + + /* x87 FPU Instruction Operand(Data) Pointer */ + __uint32_t fpu_dp; /* offset */ + __uint16_t fpu_ds; /* Selector */ + + __uint16_t fpu_rsrv3; /* reserved */ + __uint32_t fpu_mxcsr; /* MXCSR Register state */ + __uint32_t fpu_mxcsrmask; /* MXCSR mask */ + _STRUCT_MMST_REG fpu_stmm0; /* ST0/MM0 */ + _STRUCT_MMST_REG fpu_stmm1; /* ST1/MM1 */ + _STRUCT_MMST_REG fpu_stmm2; /* ST2/MM2 */ + _STRUCT_MMST_REG fpu_stmm3; /* ST3/MM3 */ + _STRUCT_MMST_REG fpu_stmm4; /* ST4/MM4 */ + _STRUCT_MMST_REG fpu_stmm5; /* ST5/MM5 */ + _STRUCT_MMST_REG fpu_stmm6; /* ST6/MM6 */ + _STRUCT_MMST_REG fpu_stmm7; /* ST7/MM7 */ + _STRUCT_XMM_REG fpu_xmm0; /* XMM 0 */ + _STRUCT_XMM_REG fpu_xmm1; /* XMM 1 */ + _STRUCT_XMM_REG fpu_xmm2; /* XMM 2 */ + _STRUCT_XMM_REG fpu_xmm3; /* XMM 3 */ + _STRUCT_XMM_REG fpu_xmm4; /* XMM 4 */ + _STRUCT_XMM_REG fpu_xmm5; /* XMM 5 */ + _STRUCT_XMM_REG fpu_xmm6; /* XMM 6 */ + _STRUCT_XMM_REG fpu_xmm7; /* XMM 7 */ + _STRUCT_XMM_REG fpu_xmm8; /* XMM 8 */ + _STRUCT_XMM_REG fpu_xmm9; /* XMM 9 */ + _STRUCT_XMM_REG fpu_xmm10; /* XMM 10 */ + _STRUCT_XMM_REG fpu_xmm11; /* XMM 11 */ + _STRUCT_XMM_REG fpu_xmm12; /* XMM 12 */ + _STRUCT_XMM_REG fpu_xmm13; /* XMM 13 */ + _STRUCT_XMM_REG fpu_xmm14; /* XMM 14 */ + _STRUCT_XMM_REG fpu_xmm15; /* XMM 15 */ + char fpu_rsrv4[6*16]; /* reserved */ + int fpu_reserved1; + char avx_reserved1[64]; + _STRUCT_XMM_REG fpu_ymmh0; /* YMMH 0 */ + _STRUCT_XMM_REG fpu_ymmh1; /* YMMH 1 */ + _STRUCT_XMM_REG fpu_ymmh2; /* YMMH 2 */ + _STRUCT_XMM_REG fpu_ymmh3; /* YMMH 3 */ + _STRUCT_XMM_REG fpu_ymmh4; /* YMMH 4 */ + _STRUCT_XMM_REG fpu_ymmh5; /* YMMH 5 */ + _STRUCT_XMM_REG fpu_ymmh6; /* YMMH 6 */ + _STRUCT_XMM_REG fpu_ymmh7; /* YMMH 7 */ + _STRUCT_XMM_REG fpu_ymmh8; /* YMMH 8 */ + _STRUCT_XMM_REG fpu_ymmh9; /* YMMH 9 */ + _STRUCT_XMM_REG fpu_ymmh10; /* YMMH 10 */ + _STRUCT_XMM_REG fpu_ymmh11; /* YMMH 11 */ + _STRUCT_XMM_REG fpu_ymmh12; /* YMMH 12 */ + _STRUCT_XMM_REG fpu_ymmh13; /* YMMH 13 */ + _STRUCT_XMM_REG fpu_ymmh14; /* YMMH 14 */ + _STRUCT_XMM_REG fpu_ymmh15; /* YMMH 15 */ + _STRUCT_OPMASK_REG fpu_k0; /* K0 */ + _STRUCT_OPMASK_REG fpu_k1; /* K1 */ + _STRUCT_OPMASK_REG fpu_k2; /* K2 */ + _STRUCT_OPMASK_REG fpu_k3; /* K3 */ + _STRUCT_OPMASK_REG fpu_k4; /* K4 */ + _STRUCT_OPMASK_REG fpu_k5; /* K5 */ + _STRUCT_OPMASK_REG fpu_k6; /* K6 */ + _STRUCT_OPMASK_REG fpu_k7; /* K7 */ + _STRUCT_YMM_REG fpu_zmmh0; /* ZMMH 0 */ + _STRUCT_YMM_REG fpu_zmmh1; /* ZMMH 1 */ + _STRUCT_YMM_REG fpu_zmmh2; /* ZMMH 2 */ + _STRUCT_YMM_REG fpu_zmmh3; /* ZMMH 3 */ + _STRUCT_YMM_REG fpu_zmmh4; /* ZMMH 4 */ + _STRUCT_YMM_REG fpu_zmmh5; /* ZMMH 5 */ + _STRUCT_YMM_REG fpu_zmmh6; /* ZMMH 6 */ + _STRUCT_YMM_REG fpu_zmmh7; /* ZMMH 7 */ + _STRUCT_YMM_REG fpu_zmmh8; /* ZMMH 8 */ + _STRUCT_YMM_REG fpu_zmmh9; /* ZMMH 9 */ + _STRUCT_YMM_REG fpu_zmmh10; /* ZMMH 10 */ + _STRUCT_YMM_REG fpu_zmmh11; /* ZMMH 11 */ + _STRUCT_YMM_REG fpu_zmmh12; /* ZMMH 12 */ + _STRUCT_YMM_REG fpu_zmmh13; /* ZMMH 13 */ + _STRUCT_YMM_REG fpu_zmmh14; /* ZMMH 14 */ + _STRUCT_YMM_REG fpu_zmmh15; /* ZMMH 15 */ + _STRUCT_ZMM_REG fpu_zmm16; /* ZMM 16 */ + _STRUCT_ZMM_REG fpu_zmm17; /* ZMM 17 */ + _STRUCT_ZMM_REG fpu_zmm18; /* ZMM 18 */ + _STRUCT_ZMM_REG fpu_zmm19; /* ZMM 19 */ + _STRUCT_ZMM_REG fpu_zmm20; /* ZMM 20 */ + _STRUCT_ZMM_REG fpu_zmm21; /* ZMM 21 */ + _STRUCT_ZMM_REG fpu_zmm22; /* ZMM 22 */ + _STRUCT_ZMM_REG fpu_zmm23; /* ZMM 23 */ + _STRUCT_ZMM_REG fpu_zmm24; /* ZMM 24 */ + _STRUCT_ZMM_REG fpu_zmm25; /* ZMM 25 */ + _STRUCT_ZMM_REG fpu_zmm26; /* ZMM 26 */ + _STRUCT_ZMM_REG fpu_zmm27; /* ZMM 27 */ + _STRUCT_ZMM_REG fpu_zmm28; /* ZMM 28 */ + _STRUCT_ZMM_REG fpu_zmm29; /* ZMM 29 */ + _STRUCT_ZMM_REG fpu_zmm30; /* ZMM 30 */ + _STRUCT_ZMM_REG fpu_zmm31; /* ZMM 31 */ }; #endif /* !__DARWIN_UNIX03 */ @@ -794,4 +1215,18 @@ _STRUCT_X86_DEBUG_STATE64 }; #endif /* !__DARWIN_UNIX03 */ +#if __DARWIN_UNIX03 +#define _STRUCT_X86_CPMU_STATE64 struct __darwin_x86_cpmu_state64 +_STRUCT_X86_CPMU_STATE64 +{ + __uint64_t __ctrs[16]; +}; +#else /* __DARWIN_UNIX03 */ +#define _STRUCT_X86_CPMU_STATE64 struct x86_cpmu_state64 +_STRUCT_X86_CPMU_STATE64 +{ + __uint64_t ctrs[16]; +}; +#endif /* !__DARWIN_UNIX03 */ + #endif /* _MACH_I386__STRUCTS_H_ */ diff --git a/cctools/include/mach/i386/fp_reg.h b/cctools/include/mach/i386/fp_reg.h index 09ec31c..6dbecce 100644 --- a/cctools/include/mach/i386/fp_reg.h +++ b/cctools/include/mach/i386/fp_reg.h @@ -59,6 +59,73 @@ #ifndef _I386_FP_SAVE_H_ #define _I386_FP_SAVE_H_ +#ifdef MACH_KERNEL_PRIVATE + + +struct x86_fx_thread_state { + unsigned short fx_control; /* control */ + unsigned short fx_status; /* status */ + unsigned char fx_tag; /* register tags */ + unsigned char fx_bbz1; /* better be zero when calling fxrtstor */ + unsigned short fx_opcode; + unsigned int fx_eip; /* eip instruction */ + unsigned short fx_cs; /* cs instruction */ + unsigned short fx_bbz2; /* better be zero when calling fxrtstor */ + unsigned int fx_dp; /* data address */ + unsigned short fx_ds; /* data segment */ + unsigned short fx_bbz3; /* better be zero when calling fxrtstor */ + unsigned int fx_MXCSR; + unsigned int fx_MXCSR_MASK; + unsigned short fx_reg_word[8][8]; /* STx/MMx registers */ + unsigned short fx_XMM_reg[8][16]; /* XMM0-XMM15 on 64 bit processors */ + /* XMM0-XMM7 on 32 bit processors... unused storage reserved */ + + unsigned char fx_reserved[16*5]; /* reserved by intel for future + * expansion */ + unsigned int fp_valid; + unsigned int fp_save_layout; + unsigned char fx_pad[8]; +}__attribute__ ((packed)); + +struct xsave_header { + uint64_t xstate_bv; + uint64_t xcomp_bv; + uint8_t xhrsvd[48]; +}; + +typedef struct { uint64_t lo64, hi64; }__attribute__ ((packed)) reg128_t; +typedef struct { reg128_t lo128, hi128; }__attribute__ ((packed)) reg256_t; +typedef struct { reg256_t lo256, hi256; }__attribute__ ((packed)) reg512_t; + +struct x86_avx_thread_state { + struct x86_fx_thread_state fp; + struct xsave_header _xh; /* Offset 512, xsave header */ + reg128_t x_YMM_Hi128[16]; /* Offset 576, high YMMs `*/ + /* Offset 832, end */ +}__attribute__ ((packed)); + +struct x86_avx512_thread_state { + struct x86_fx_thread_state fp; + struct xsave_header _xh; /* Offset 512, xsave header */ + reg128_t x_YMM_Hi128[16]; /* Offset 576, high YMMs */ + + uint64_t x_pad[16]; /* Offset 832, unused AMD LWP */ + uint64_t x_BNDREGS[8]; /* Offset 960, unused MPX */ + uint64_t x_BNDCTL[8]; /* Offset 1024, unused MPX */ + + uint64_t x_Opmask[8]; /* Offset 1088, K0-K7 */ + reg256_t x_ZMM_Hi256[16]; /* Offset 1152, ZMM0..15[511:256] */ + reg512_t x_Hi16_ZMM[16]; /* Offset 1664, ZMM16..31[511:0] */ + /* Offset 2688, end */ +}__attribute__ ((packed)); + +typedef union { + struct x86_fx_thread_state fx; + struct x86_avx_thread_state avx; + struct x86_avx512_thread_state avx512; +} x86_ext_thread_state_t; + +#endif /* MACH_KERNEL_PRIVATE */ /* * Control register */ @@ -115,4 +182,8 @@ #define FP_387 3 /* 80387 or 80486 */ #define FP_FXSR 4 /* Fast save/restore SIMD Extension */ +#define EVEX_PREFIX 0x62 /* AVX512's EVEX vector operation prefix */ +#define VEX2_PREFIX 0xC4 /* VEX 2-byte prefix for Opmask instructions */ +#define VEX3_PREFIX 0xC5 /* VEX 3-byte prefix for Opmask instructions */ + #endif /* _I386_FP_SAVE_H_ */ diff --git a/cctools/include/mach/i386/thread_state.h b/cctools/include/mach/i386/thread_state.h index 2d542d3..4eeaba3 100644 --- a/cctools/include/mach/i386/thread_state.h +++ b/cctools/include/mach/i386/thread_state.h @@ -33,7 +33,7 @@ #define _MACH_I386_THREAD_STATE_H_ /* Size of maximum exported thread state in words */ -#define I386_THREAD_STATE_MAX (224) /* Size of biggest state possible */ +#define I386_THREAD_STATE_MAX (614) /* Size of biggest state possible */ #if defined (__i386__) || defined(__x86_64__) #define THREAD_STATE_MAX I386_THREAD_STATE_MAX diff --git a/cctools/include/mach/i386/thread_status.h b/cctools/include/mach/i386/thread_status.h index 1945121..4c3b818 100644 --- a/cctools/include/mach/i386/thread_status.h +++ b/cctools/include/mach/i386/thread_status.h @@ -110,10 +110,14 @@ #define x86_DEBUG_STATE64 11 #define x86_DEBUG_STATE 12 #define THREAD_STATE_NONE 13 -/* 15 and 16 are used for the internal x86_SAVED_STATE flavours */ +/* 14 and 15 are used for the internal x86_SAVED_STATE flavours */ +/* Arrange for flavors to take sequential values, 32-bit, 64-bit, non-specific */ #define x86_AVX_STATE32 16 -#define x86_AVX_STATE64 17 - +#define x86_AVX_STATE64 (x86_AVX_STATE32 + 1) +#define x86_AVX_STATE (x86_AVX_STATE32 + 2) +#define x86_AVX512_STATE32 19 +#define x86_AVX512_STATE64 (x86_AVX512_STATE32 + 1) +#define x86_AVX512_STATE (x86_AVX512_STATE32 + 2) /* * Largest state on this machine: @@ -142,11 +146,15 @@ (x == x86_DEBUG_STATE) || \ (x == x86_AVX_STATE32) || \ (x == x86_AVX_STATE64) || \ + (x == x86_AVX_STATE) || \ + (x == x86_AVX512_STATE32) || \ + (x == x86_AVX512_STATE64) || \ + (x == x86_AVX512_STATE) || \ (x == THREAD_STATE_NONE)) struct x86_state_hdr { - int flavor; - int count; + uint32_t flavor; + uint32_t count; }; typedef struct x86_state_hdr x86_state_hdr_t; @@ -185,6 +193,10 @@ typedef _STRUCT_X86_AVX_STATE32 x86_avx_state32_t; #define x86_AVX_STATE32_COUNT ((mach_msg_type_number_t) \ (sizeof(x86_avx_state32_t)/sizeof(unsigned int))) +typedef _STRUCT_X86_AVX512_STATE32 x86_avx512_state32_t; +#define x86_AVX512_STATE32_COUNT ((mach_msg_type_number_t) \ + (sizeof(x86_avx512_state32_t)/sizeof(unsigned int))) + /* * to be deprecated in the future */ @@ -216,6 +228,10 @@ typedef _STRUCT_X86_AVX_STATE64 x86_avx_state64_t; #define x86_AVX_STATE64_COUNT ((mach_msg_type_number_t) \ (sizeof(x86_avx_state64_t)/sizeof(unsigned int))) +typedef _STRUCT_X86_AVX512_STATE64 x86_avx512_state64_t; +#define x86_AVX512_STATE64_COUNT ((mach_msg_type_number_t) \ + (sizeof(x86_avx512_state64_t)/sizeof(unsigned int))) + typedef _STRUCT_X86_EXCEPTION_STATE64 x86_exception_state64_t; #define x86_EXCEPTION_STATE64_COUNT ((mach_msg_type_number_t) \ ( sizeof (x86_exception_state64_t) / sizeof (int) )) @@ -263,6 +279,22 @@ struct x86_debug_state { } uds; }; +struct x86_avx_state { + x86_state_hdr_t ash; + union { + x86_avx_state32_t as32; + x86_avx_state64_t as64; + } ufs; +}; + +struct x86_avx512_state { + x86_state_hdr_t ash; + union { + x86_avx512_state32_t as32; + x86_avx512_state64_t as64; + } ufs; +}; + typedef struct x86_thread_state x86_thread_state_t; #define x86_THREAD_STATE_COUNT ((mach_msg_type_number_t) \ ( sizeof (x86_thread_state_t) / sizeof (int) )) @@ -279,6 +311,14 @@ typedef struct x86_debug_state x86_debug_state_t; #define x86_DEBUG_STATE_COUNT ((mach_msg_type_number_t) \ (sizeof(x86_debug_state_t)/sizeof(unsigned int))) +typedef struct x86_avx_state x86_avx_state_t; +#define x86_AVX_STATE_COUNT ((mach_msg_type_number_t) \ + (sizeof(x86_avx_state_t)/sizeof(unsigned int))) + +typedef struct x86_avx512_state x86_avx512_state_t; +#define x86_AVX512_STATE_COUNT ((mach_msg_type_number_t) \ + (sizeof(x86_avx512_state_t)/sizeof(unsigned int))) + /* * Machine-independent way for servers and Mach's exception mechanism to * choose the most efficient state flavor for exception RPC's: @@ -286,5 +326,142 @@ typedef struct x86_debug_state x86_debug_state_t; #define MACHINE_THREAD_STATE x86_THREAD_STATE #define MACHINE_THREAD_STATE_COUNT x86_THREAD_STATE_COUNT +#ifdef XNU_KERNEL_PRIVATE + +#define x86_SAVED_STATE32 THREAD_STATE_NONE + 1 +#define x86_SAVED_STATE64 THREAD_STATE_NONE + 2 + +/* + * The format in which thread state is saved by Mach on this machine. This + * state flavor is most efficient for exception RPC's to kernel-loaded + * servers, because copying can be avoided: + */ +struct x86_saved_state32 { + uint32_t gs; + uint32_t fs; + uint32_t es; + uint32_t ds; + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t cr2; /* kernel esp stored by pusha - we save cr2 here later */ + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; + uint16_t trapno; + uint16_t cpu; + uint32_t err; + uint32_t eip; + uint32_t cs; + uint32_t efl; + uint32_t uesp; + uint32_t ss; +}; +typedef struct x86_saved_state32 x86_saved_state32_t; + +#define x86_SAVED_STATE32_COUNT ((mach_msg_type_number_t) \ + (sizeof (x86_saved_state32_t)/sizeof(unsigned int))) + +#pragma pack(4) + +/* + * This is the state pushed onto the 64-bit interrupt stack + * on any exception/trap/interrupt. + */ +struct x86_64_intr_stack_frame { + uint16_t trapno; + uint16_t cpu; + uint32_t _pad; + uint64_t trapfn; + uint64_t err; + uint64_t rip; + uint64_t cs; + uint64_t rflags; + uint64_t rsp; + uint64_t ss; +}; +typedef struct x86_64_intr_stack_frame x86_64_intr_stack_frame_t; +_Static_assert((sizeof(x86_64_intr_stack_frame_t) % 16) == 0, + "interrupt stack frame size must be a multiple of 16 bytes"); + +/* + * thread state format for task running in 64bit long mode + * in long mode, the same hardware frame is always pushed regardless + * of whether there was a change in privilege level... therefore, there + * is no need for an x86_saved_state64_from_kernel variant + */ +struct x86_saved_state64 { + uint64_t rdi; /* arg0 for system call */ + uint64_t rsi; + uint64_t rdx; + uint64_t r10; /* R10 := RCX prior to syscall trap */ + uint64_t r8; + uint64_t r9; /* arg5 for system call */ + + uint64_t cr2; + uint64_t r15; + uint64_t r14; + uint64_t r13; + uint64_t r12; + uint64_t r11; + uint64_t rbp; + uint64_t rbx; + uint64_t rcx; + uint64_t rax; + + uint32_t gs; + uint32_t fs; + + uint64_t _pad; + + struct x86_64_intr_stack_frame isf; +}; +typedef struct x86_saved_state64 x86_saved_state64_t; +#define x86_SAVED_STATE64_COUNT ((mach_msg_type_number_t) \ + (sizeof (struct x86_saved_state64)/sizeof(unsigned int))) + +extern uint32_t get_eflags_exportmask(void); + +/* + * Unified, tagged saved state: + */ +typedef struct { + uint32_t flavor; + uint32_t _pad_for_16byte_alignment[3]; + union { + x86_saved_state32_t ss_32; + x86_saved_state64_t ss_64; + } uss; +} x86_saved_state_t; +#define ss_32 uss.ss_32 +#define ss_64 uss.ss_64 +#pragma pack() + +static inline boolean_t +is_saved_state64(x86_saved_state_t *iss) +{ + return (iss->flavor == x86_SAVED_STATE64); +} + +static inline boolean_t +is_saved_state32(x86_saved_state_t *iss) +{ + return (iss->flavor == x86_SAVED_STATE32); +} + +static inline x86_saved_state32_t * +saved_state32(x86_saved_state_t *iss) +{ + return &iss->ss_32; +} + +static inline x86_saved_state64_t * +saved_state64(x86_saved_state_t *iss) +{ + return &iss->ss_64; +} + +#endif /* XNU_KERNEL_PRIVATE */ #endif /* _MACH_I386_THREAD_STATUS_H_ */ diff --git a/cctools/include/mach/machine.h b/cctools/include/mach/machine.h index 28a5a1c..9217273 100644 --- a/cctools/include/mach/machine.h +++ b/cctools/include/mach/machine.h @@ -144,6 +144,7 @@ extern vm_offset_t interrupt_stack[]; #define CPU_TYPE_NS32332 ((cpu_type_t) 5) #define CPU_TYPE_MC680x0 ((cpu_type_t) 6) #define CPU_TYPE_I386 ((cpu_type_t) 7) +#define CPU_TYPE_X86 ((cpu_type_t) 7) #define CPU_TYPE_X86_64 ((cpu_type_t) (CPU_TYPE_I386 | CPU_ARCH_ABI64)) #define CPU_TYPE_MIPS ((cpu_type_t) 8) #define CPU_TYPE_NS32532 ((cpu_type_t) 9) @@ -157,9 +158,12 @@ extern vm_offset_t interrupt_stack[]; #define CPU_TYPE_MC98000 ((cpu_type_t) 18) #define CPU_TYPE_POWERPC ((cpu_type_t) 18) #define CPU_ARCH_ABI64 0x1000000 +#define CPU_ARCH_ABI64_32 0x2000000 +#define CPU_ARCH_MASK 0xff000000 /* cctools-port */ #define CPU_TYPE_POWERPC64 ((cpu_type_t)(CPU_TYPE_POWERPC | CPU_ARCH_ABI64)) #define CPU_TYPE_VEO ((cpu_type_t) 255) #define CPU_TYPE_ARM64 ((cpu_type_t)(CPU_TYPE_ARM | CPU_ARCH_ABI64)) +#define CPU_TYPE_ARM64_32 ((cpu_type_t)(CPU_TYPE_ARM | CPU_ARCH_ABI64_32)) /* @@ -171,8 +175,8 @@ extern vm_offset_t interrupt_stack[]; /* * Capability bits used in the definition of cpu_subtype. */ -#define CPU_SUBTYPE_MASK 0xff000000 /* mask for feature flags */ -#define CPU_SUBTYPE_LIB64 0x80000000 /* 64 bit libraries */ +#define CPU_SUBTYPE_MASK 0xff000000 /* mask for feature flags */ +#define CPU_SUBTYPE_LIB64 0x80000000 /* 64 bit libraries */ /* @@ -320,6 +324,10 @@ extern vm_offset_t interrupt_stack[]; #define CPU_SUBTYPE_ARM64_ALL ((cpu_subtype_t) 0) #define CPU_SUBTYPE_ARM64_V8 ((cpu_subtype_t) 1) +#define CPU_SUBTYPE_ARM64_32_V8 ((cpu_subtype_t) 1) +#define CPU_SUBTYPE_ARM64E ((cpu_subtype_t) 2) +#define CPU_SUBTYPE_ARM64_E CPU_SUBTYPE_ARM64E /* cctools-port */ + /* * MC88000 subtypes */ diff --git a/cctools/include/stuff/arch.h b/cctools/include/stuff/arch.h index 7b4b8c5..51e444f 100644 --- a/cctools/include/stuff/arch.h +++ b/cctools/include/stuff/arch.h @@ -97,6 +97,14 @@ __private_extern__ const char *get_arch_name_from_types( cpu_type_t cputype, cpu_subtype_t cpusubtype); +/* + * get_arch_name_if_known() returns the name of the architecture for the + * specified cputype and cpusubtype if known. If unknown it returns NULL. + */ +__private_extern__ const char *get_arch_name_if_known( + cpu_type_t cputype, + cpu_subtype_t cpusubtype); + /* * get_arch_family_from_cputype() returns the family architecture for the * specified cputype if known. If unknown it returns NULL. @@ -106,47 +114,28 @@ __private_extern__ const struct arch_flag *get_arch_family_from_cputype( /* * get_byte_sex_from_flag() returns the byte sex of the architecture for the - * specified cputype and cpusubtype if known. If unknown it returns - * UNKNOWN_BYTE_SEX. If the bytesex can be determined directly as in the case - * of reading a magic number from a file that should be done and this routine - * should not be used as it could be out of date. + * specified cputype and cpusubtype if known. If unknown it will abort(). + * If the bytesex can be determined directly as in the case of reading a magic + * number from a file that should be done and this routine should not be used + * as it could be out of date. */ __private_extern__ enum byte_sex get_byte_sex_from_flag( const struct arch_flag *flag); -/* - * get_stack_direction_from_flag() returns the direction the stack grows as - * either positive (+1) or negative (-1) of the architecture for the - * specified cputype and cpusubtype if known. If unknown it returns 0. - */ -__private_extern__ int get_stack_direction_from_flag( - const struct arch_flag *flag); - /* * get_stack_addr_from_flag() returns the default starting address of the user - * stack. + * stack. If unknown it will abort(). */ __private_extern__ uint64_t get_stack_addr_from_flag( const struct arch_flag *flag); -/* - * get_stack_size_from_flag() returns the default size of the userstack. - */ -__private_extern__ uint32_t get_stack_size_from_flag( - const struct arch_flag *flag); - /* * get_segalign_from_flag() returns the default segment alignment (page size). + * If unknown it will abort(). */ __private_extern__ uint32_t get_segalign_from_flag( const struct arch_flag *flag); -/* - * get_segprot_from_flag() returns the default segment protection. - */ -__private_extern__ vm_prot_t get_segprot_from_flag( - const struct arch_flag *flag); - /* * get_shared_region_size_from_flag() returns the size of the read only shared * region. diff --git a/cctools/include/stuff/args.h b/cctools/include/stuff/args.h new file mode 100644 index 0000000..2457306 --- /dev/null +++ b/cctools/include/stuff/args.h @@ -0,0 +1,45 @@ +// +// args.h +// cctools +// +// Created by Michael Trent on 5/31/19. +// + +#ifndef args_h +#define args_h + +/* + * args_expand_at() recursively expands "@file" options as they appear in the + * argc/argv options list. + * + * if "file" does not point to a valid file, the option "@file" will remain + * in the options list. + * + * if "file" does point to a valid file, that file will be parsed as a series + * of options separated by any amount of whitespace, and those options will + * replace "@file" where it appears in the options list. options files may + * themselves contain additional "@file" references, which will be recursively + * expanded. to prevent infinite recursion, args_expand_at() will fail if it + * attempts to load a "@file" path more than once. + * + * options are separated by any amount of whitespace. whitespace can be included + * in an option if it is wrapped in single or double quotes. individual + * characters can also be escaped with a single backslash character; including + * whitespace, quotes, and other backslashes. + * + * NB: args_expand_at() allows options to include quotes in the middle of the + * string; e.g., "one' 'option" will expand to "one option" rather than "one" + * and "option". This is consistent with unix shell behavior, but not consistent + * with some other implementations of the @file command-line option. + + * BUG: args_expand_at() will not return an error if an option contains an + * unterminated quote character. The string "'one more time" will yield a single + * option "'one more time". + * + * BUG: memory pointed to by argv_p is not freed if the pointer is replaced. + * Also, it is not clear how the argv array and its contents should be freed + * if the array is modified. + */ +int args_expand_at(int* argc_p, char** argv_p[]); + +#endif /* args_h */ diff --git a/cctools/include/stuff/best_arch.h b/cctools/include/stuff/best_arch.h index fdc3c27..627aa5f 100644 --- a/cctools/include/stuff/best_arch.h +++ b/cctools/include/stuff/best_arch.h @@ -27,6 +27,23 @@ #include #include +/* + * cpusubtype_findbestarch_64() is passed a cputype and cpusubtype and a set of + * fat_arch_64 structs and selects the best one that matches (if any) and + * returns a pointer to that fat_arch_64 struct (or NULL). The fat_arch_64 + * structs must be in the host byte sex and correct such that the fat_archs64 + * really points to enough memory for nfat_arch_64 structs. It is possible + * that this routine could fail if new cputypes or cpusubtypes are added and an + * old version of this routine is used. But if there is an exact match between + * the cputype and cpusubtype and one of the fat_arch_64 structs this routine + * will always succeed. + */ +__private_extern__ struct fat_arch_64 * cpusubtype_findbestarch_64( + cpu_type_t cputype, + cpu_subtype_t cpusubtype, + struct fat_arch_64 *fat_archs64, + uint32_t nfat_archs); + /* * cpusubtype_findbestarch() is passed a cputype and cpusubtype and a set of * fat_arch structs and selects the best one that matches (if any) and returns diff --git a/cctools/include/stuff/breakout.h b/cctools/include/stuff/breakout.h index dec6b38..211d792 100644 --- a/cctools/include/stuff/breakout.h +++ b/cctools/include/stuff/breakout.h @@ -36,7 +36,7 @@ */ struct toc_entry { char *symbol_name; - int32_t member_index; + int64_t member_index; }; /* @@ -50,9 +50,10 @@ struct arch { enum ofile_type type; /* The type of file for this architecture */ /* can be OFILE_ARCHIVE, OFILE_Mach_O, */ /* OFILE_LLVM_BITCODE or OFILE_UNKNOWN. */ - struct fat_arch *fat_arch; /* If this came from fat file this is valid */ - /* and not NULL (needed for the align value */ - /* and to output a fat file if only one arch)*/ + struct fat_arch *fat_arch; /* If this came from fat file one of these */ + struct fat_arch_64 /* is valid and not NULL (needed for the */ + *fat_arch64;/* align value and to output a fat file if */ + /* only one arch) */ char *fat_arch_name; /* If this came from fat file this is valid */ /* and is tthe name of this architecture */ /* (used for error messages). */ @@ -71,13 +72,15 @@ struct arch { enum bool toc_long_name;/* use the long name in the output */ char *toc_name; /* name of toc member */ uint32_t toc_name_size;/* size of name of toc member */ - uint32_t ntocs; /* number of table of contents entries */ + uint64_t ntocs; /* number of table of contents entries */ + enum bool using_64toc; /* TRUE if we are using a 64-bit toc */ struct toc_entry *toc_entries; /* the table of contents entries */ - struct ranlib *toc_ranlibs; /* the ranlib structs */ + struct ranlib *toc_ranlibs; /* the 32-bit ranlib structs */ + struct ranlib_64 *toc_ranlibs64; /* the 64-bit ranlib structs */ char *toc_strings; /* strings of symbol names for toc entries */ - uint32_t toc_strsize; /* number of bytes for the strings above */ - uint32_t library_size; /* current working size and final output size */ + uint64_t toc_strsize; /* number of bytes for the strings above */ + uint64_t library_size; /* current working size and final output size */ /* for this arch when it's a library (used */ /* for creating the toc entries). */ @@ -91,7 +94,7 @@ struct arch { /* if this is an unknown file: the addr and size of the file */ char *unknown_addr; - uint32_t unknown_size; + uint64_t unknown_size; /* don't update LC_ID_DYLIB timestamp */ enum bool dont_update_LC_ID_DYLIB_timestamp; @@ -101,7 +104,7 @@ struct member { enum ofile_type type; /* the type of this member can be OFILE_Mach_O*/ /* OFILE_LLVM_BITCODE or OFILE_UNKNOWN */ struct ar_hdr *ar_hdr; /* the archive header for this member */ - uint32_t offset; /* current working offset and final offset */ + uint64_t offset; /* current working offset and final offset */ /* use in creating the table of contents */ /* the name of the member in the output */ @@ -120,7 +123,7 @@ struct member { /* if this member is an unknown file: the addr and size of the member */ char *unknown_addr; - uint32_t unknown_size; + uint64_t unknown_size; /* * If this member was created from a file then input_file_name is set else @@ -173,6 +176,10 @@ struct object { struct section_64 **sections64; /* array of 64-bit section structs */ struct dyld_info_command *dyld_info; /* the LC_DYLD_INFO command,if any */ + struct linkedit_data_command + *dyld_exports_trie; /* the exports trie */ + struct linkedit_data_command + *dyld_chained_fixups; /* the fixups */ /* * This is only used for redo_prebinding and is calculated by breakout() @@ -207,6 +214,11 @@ struct object { uint32_t output_nsymbols; char *output_strings; uint32_t output_strings_size; + /* + * To get the code signature data on a page alignment and be compatible with + * existing tools we have to actually change the string table and pad it. + */ + uint32_t output_strings_size_pad; char *output_code_sig_data; uint32_t output_code_sig_data_size; char *output_split_info_data; @@ -219,6 +231,10 @@ struct object { uint32_t output_code_sign_drs_info_data_size; char *output_link_opt_hint_info_data; uint32_t output_link_opt_hint_info_data_size; + char *output_dyld_chained_fixups_data; + uint32_t output_dyld_chained_fixups_data_size; + char *output_dyld_exports_trie_data; + uint32_t output_dyld_exports_trie_data_size; uint32_t output_ilocalsym; uint32_t output_nlocalsym; @@ -275,6 +291,7 @@ __private_extern__ void writeout( unsigned short mode, enum bool sort_toc, enum bool commons_in_toc, + enum bool force_64bit_toc, enum bool library_warnings, uint32_t *throttle); @@ -283,9 +300,10 @@ __private_extern__ void writeout_to_mem( uint32_t narchs, char *filename, void **outputbuf, - uint32_t *length, + uint64_t *length, enum bool sort_toc, enum bool commons_in_toc, + enum bool force_64bit_toc, enum bool library_warning, enum bool *seen_archive); diff --git a/cctools/include/stuff/bytesex.h b/cctools/include/stuff/bytesex.h index e20228b..2ac451a 100644 --- a/cctools/include/stuff/bytesex.h +++ b/cctools/include/stuff/bytesex.h @@ -104,6 +104,11 @@ __private_extern__ void swap_fat_arch( uint32_t nfat_arch, enum byte_sex target_byte_sex); +__private_extern__ void swap_fat_arch_64( + struct fat_arch_64 *fat_archs64, + uint32_t nfat_arch, + enum byte_sex target_byte_sex); + __private_extern__ void swap_mach_header( struct mach_header *mh, enum byte_sex target_byte_sex); @@ -318,6 +323,10 @@ __private_extern__ void swap_arm_thread_state64_t( arm_thread_state64_t *cpu, enum byte_sex target_byte_sex); +__private_extern__ void swap_arm_exception_state64_t( + arm_exception_state64_t *except, + enum byte_sex target_byte_sex); + __private_extern__ void swap_ident_command( struct ident_command *id_cmd, enum byte_sex target_byte_sex); @@ -378,6 +387,19 @@ __private_extern__ void swap_source_version_command( struct source_version_command *sv, enum byte_sex target_byte_sex); +__private_extern__ void swap_note_command( + struct note_command *nc, + enum byte_sex target_byte_sex); + +__private_extern__ void swap_build_version_command( + struct build_version_command *bv, + enum byte_sex target_byte_sex); + +__private_extern__ void swap_build_tool_version( + struct build_tool_version *bt, + uint32_t ntools, + enum byte_sex target_byte_sex); + __private_extern__ void swap_nlist( struct nlist *symbols, uint32_t nsymbols, @@ -393,6 +415,11 @@ __private_extern__ void swap_ranlib( uint32_t nranlibs, enum byte_sex target_byte_sex); +__private_extern__ void swap_ranlib_64( + struct ranlib_64 *ranlibs, + uint64_t nranlibs, + enum byte_sex target_byte_sex); + __private_extern__ void swap_relocation_info( struct relocation_info *relocs, uint32_t nrelocs, @@ -455,6 +482,6 @@ __private_extern__ enum bool swap_object_headers( */ __private_extern__ enum byte_sex get_toc_byte_sex( char *addr, - uint32_t size); + uint64_t size); #endif /* _STUFF_BYTESEX_H_ */ diff --git a/cctools/include/stuff/lto.h b/cctools/include/stuff/lto.h index b64ff09..c58a0a4 100644 --- a/cctools/include/stuff/lto.h +++ b/cctools/include/stuff/lto.h @@ -24,7 +24,7 @@ __private_extern__ void lto_get_nlist_64( void *mod, uint32_t symbol_index); -__private_extern__ char * lto_symbol_name( +__private_extern__ const char * lto_symbol_name( void *mod, uint32_t symbol_index); diff --git a/cctools/include/stuff/ofile.h b/cctools/include/stuff/ofile.h index 04e4ead..44b3897 100644 --- a/cctools/include/stuff/ofile.h +++ b/cctools/include/stuff/ofile.h @@ -63,6 +63,7 @@ struct ofile { struct fat_header *fat_header; /* If a fat file these are filled in and */ struct fat_arch *fat_archs; /* if needed converted to host byte sex */ + struct fat_arch_64 *fat_archs64; /* If this is a fat file then these are valid and filled in */ uint32_t narch; /* the current architecture */ @@ -78,10 +79,12 @@ struct ofile { struct ar_hdr *toc_ar_hdr; /* the archive header for the toc */ char *toc_name; /* name of toc member */ uint32_t toc_name_size; /* size of name of toc member */ - struct ranlib *toc_ranlibs; /* ranlib structs */ - uint32_t toc_nranlibs; /* number of ranlib structs */ + enum bool toc_is_32bit; /* TRUE if toc is 32-bit */ + struct ranlib *toc_ranlibs; /* 32-bit ranlib structs */ + struct ranlib_64 *toc_ranlibs64; /* 64-bit ranlib_64 structs */ + uint64_t toc_nranlibs; /* number of ranlib structs */ char *toc_strings; /* strings of symbol names (for above) */ - uint32_t toc_strsize; /* number of bytes for the strings above */ + uint64_t toc_strsize; /* number of bytes for the strings above */ enum bool toc_bad; /* the toc needs to be rebuilt */ /* If this structure is currently referencing a System V archive and it has diff --git a/cctools/include/stuff/port.h b/cctools/include/stuff/port.h new file mode 100644 index 0000000..3c3eed2 --- /dev/null +++ b/cctools/include/stuff/port.h @@ -0,0 +1,20 @@ +#ifndef DISABLE_CLANG_AS +char *find_clang(); +#endif /* !DISABLE_CLANG_AS */ + +#ifndef HAVE_UTIMENS +#include +int utimens(const char *path, const struct timespec times[2]); +#endif /* !HAVE_UTIMENS */ + +#ifndef HAVE_STRMODE +void strmode(/* mode_t */ int mode, char *p); +#endif /* !__APPLE__ */ + +#ifndef HAVE_REALLOCF +void *reallocf(void *ptr, size_t size); +#elif defined(HAVE_BSD_STDLIB_H) +#include +#endif /* !HAVE_REALLOCF */ + +int asprintf(char **strp, const char *fmt, ...); diff --git a/cctools/include/stuff/rnd.h b/cctools/include/stuff/rnd.h index 1af3f97..b51fa7e 100644 --- a/cctools/include/stuff/rnd.h +++ b/cctools/include/stuff/rnd.h @@ -33,7 +33,9 @@ /* * rnd() rounds v to a multiple of r. + * + * r must be a non-zero power of 2. */ -__private_extern__ uint64_t rnd( - uint64_t v, - uint64_t r); +__private_extern__ uint64_t rnd(uint64_t v, uint64_t r); +__private_extern__ uint64_t rnd64(uint64_t v, uint64_t r); +__private_extern__ uint32_t rnd32(uint32_t v, uint32_t r); diff --git a/cctools/include/stuff/version_number.h b/cctools/include/stuff/version_number.h index 26ab0ff..2d28f81 100644 --- a/cctools/include/stuff/version_number.h +++ b/cctools/include/stuff/version_number.h @@ -21,6 +21,6 @@ * @APPLE_LICENSE_HEADER_END@ */ __private_extern__ enum bool get_version_number( - char *flag, - char *argument, + const char *flag, + const char *argument, uint32_t *value); diff --git a/cctools/include/stuff/write64.h b/cctools/include/stuff/write64.h new file mode 100644 index 0000000..b4a03b4 --- /dev/null +++ b/cctools/include/stuff/write64.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef HAVE_WRITE64 + +#include + +/* + * This is a drop-in write(2) replacement that does the right thing when trying + * to write out 31-bits or more of data. While the write(2) system call has + * 64-bit wide arguments, it only honors 31 bits for historical reasons. + * This restriction does not appear to be unique to Darwin. + */ +ssize_t write64(int fildes, const void *buf, size_t nbyte); + +#endif /* ! HAVE_WRITE64 */ diff --git a/cctools/include/sys/cdefs.h b/cctools/include/sys/cdefs.h index ca78da5..61e4e8b 100644 --- a/cctools/include/sys/cdefs.h +++ b/cctools/include/sys/cdefs.h @@ -1,12 +1,29 @@ +#if defined(__GLIBC__) || defined(__APPLE__) || defined(__FreeBSD__) || \ + defined(__OpenBSD__) || defined(__NetBSD__) || defined(__ANDROID__) + +#include_next + +#else + +#ifdef __cplusplus +#define __BEGIN_DECLS extern "C" { +#define __END_DECLS } +#else +#define __BEGIN_DECLS +#define __END_DECLS +#endif + +#define __P(x) x + +#endif /* __GLIBC__ || __APPLE__ */ + +#ifdef __GLIBC__ + /* * Workaround for a GLIBC bug. * https://sourceware.org/bugzilla/show_bug.cgi?id=14952 */ -#include_next - -#ifdef __GLIBC__ - #ifndef __extern_inline # define __extern_inline \ extern __inline __attribute__ ((__gnu_inline__)) diff --git a/cctools/install-sh b/cctools/install-sh new file mode 100755 index 0000000..8175c64 --- /dev/null +++ b/cctools/install-sh @@ -0,0 +1,518 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2018-03-11.20; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dstbase=`basename "$src"` + case $dst in + */) dst=$dst$dstbase;; + *) dst=$dst/$dstbase;; + esac + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + case $dstdir in + */) dstdirslash=$dstdir;; + *) dstdirslash=$dstdir/;; + esac + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + # Note that $RANDOM variable is not portable (e.g. dash); Use it + # here however when possible just to lower collision chance. + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + + trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 + + # Because "mkdir -p" follows existing symlinks and we likely work + # directly in world-writeable /tmp, make sure that the '$tmpdir' + # directory is successfully created first before we actually test + # 'mkdir -p' feature. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=${dstdirslash}_inst.$$_ + rmtmp=${dstdirslash}_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/cctools/ld64/Makefile.am b/cctools/ld64/Makefile.am index 0182df2..46ed3ef 100644 --- a/cctools/ld64/Makefile.am +++ b/cctools/ld64/Makefile.am @@ -1,2 +1,2 @@ -SUBDIRS = src +SUBDIRS = src doc/man ACLOCAL_AMFLAGS = -I m4 diff --git a/cctools/ld64/Makefile.in b/cctools/ld64/Makefile.in new file mode 100644 index 0000000..c2a817f --- /dev/null +++ b/cctools/ld64/Makefile.in @@ -0,0 +1,656 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = ld64 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +depcomp = +am__maybe_remake_depfiles = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = src doc/man +ACLOCAL_AMFLAGS = -I m4 +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps ld64/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps ld64/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/ld64/doc/man/Makefile.am b/cctools/ld64/doc/man/Makefile.am new file mode 100644 index 0000000..3cd1842 --- /dev/null +++ b/cctools/ld64/doc/man/Makefile.am @@ -0,0 +1,5 @@ +dist_man_MANS = +dist_man_MANS += man1/dyldinfo.1 +dist_man_MANS += man1/ld64.1 +dist_man_MANS += man1/ld.1 +dist_man_MANS += man1/unwinddump.1 diff --git a/cctools/ld64/doc/man/Makefile.in b/cctools/ld64/doc/man/Makefile.in new file mode 100644 index 0000000..a2d1aa9 --- /dev/null +++ b/cctools/ld64/doc/man/Makefile.in @@ -0,0 +1,556 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = ld64/doc/man +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +depcomp = +am__maybe_remake_depfiles = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man1dir = $(mandir)/man1 +am__installdirs = "$(DESTDIR)$(man1dir)" +NROFF = nroff +MANS = $(dist_man_MANS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +dist_man_MANS = man1/dyldinfo.1 man1/ld64.1 man1/ld.1 \ + man1/unwinddump.1 +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps ld64/doc/man/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps ld64/doc/man/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man1: $(dist_man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(dist_man_MANS)'; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.1[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.1[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(MANS) +installdirs: + for dir in "$(DESTDIR)$(man1dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man1 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man + +uninstall-man: uninstall-man1 + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-man1 install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags-am uninstall uninstall-am uninstall-man \ + uninstall-man1 + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/ld64/doc/man/man1/ld.1 b/cctools/ld64/doc/man/man1/ld.1 index 53fbaa5..5641efe 100644 --- a/cctools/ld64/doc/man/man1/ld.1 +++ b/cctools/ld64/doc/man/man1/ld.1 @@ -1,4 +1,4 @@ -.Dd March 7, 2011 +.Dd March 7, 2018 .Dt ld 1 .Os Darwin .Sh NAME @@ -6,14 +6,14 @@ .Nd "linker" .Sh SYNOPSIS .Nm -files... -.Op options -.Op Fl o Ar outputfile +files... +.Op options +.Op Fl o Ar outputfile .Sh DESCRIPTION The .Nm ld command combines several object files and libraries, resolves references, and -produces an ouput file. +produces an ouput file. .Nm ld can produce a final linked image (executable, dylib, or bundle), or with the -r option, produce another object file. If the -o option is not used, the output @@ -21,7 +21,7 @@ file produced is named "a.out". .Ss Universal The linker accepts universal (multiple-architecture) input files, but always creates a "thin" (single-architecture), standard Mach-O output file. -The architecture for the output file is specified using the -arch option. +The architecture for the output file is specified using the -arch option. If this option is not used, .Nm ld attempts to determine the output architecture by examining the object @@ -29,76 +29,74 @@ files in command line order. The first "thin" architecture determines that of the output file. If no input object file is a "thin" file, the native 32-bit architecture for the host is used. .Pp -Usually, +Usually, .Nm ld -is not used directly. Instead the -.Xr gcc(1) -compiler driver invokes +is not used directly. Instead the compiler driver invokes .Nm ld. -The compiler driver can be passed multiple -arch options and it will create a -universal final linked image by invoking +The compiler driver can be passed multiple -arch options and it will create a +universal final linked image by invoking .Nm ld multiple times and then running .Xr lipo(1) merge the outputs into a universal file. .Ss Layout The object files are loaded in the order in which they are specified on the -command line. The segments and the sections in those segments will appear in -the output file in the order they are encountered in the object files being linked. +command line. The segments and the sections in those segments will appear in +the output file in the order they are encountered in the object files being linked. All zero fill sections will appear after all non-zero fill sections in their segments. -Sections created from files with the -sectcreate option will be laid out at after -sections from .o files. The use of the -order_file option will alter the layout +Sections created from files with the -sectcreate option will be laid out at after +sections from .o files. The use of the -order_file option will alter the layout rules above, and move the symbols specified to start of their section. .Ss Libraries A static library (aka static archive) is a collection of .o files with a table of contents -that lists the global symbols in the .o files. +that lists the global symbols in the .o files. .Nm ld will only pull .o files out of a static library if needed to resolve some symbol reference. -Unlike traditional linkers, +Unlike traditional linkers, .Nm ld will continually search a static library while linking. There is no need to specify a static -library multiple times on the command line. +library multiple times on the command line. .Pp A dynamic library (aka dylib or framework) is a final linked image. Putting a dynamic -library on the command line causes two things: 1) The generated final linked image +library on the command line causes two things: 1) The generated final linked image will have encoded that it depends on that dynamic library. 2) Exported symbols from the -dynamic library are used to resolve references. +dynamic library are used to resolve references. .Pp -Both dynamic and static libraries are searched as they appear on the command line. +Both dynamic and static libraries are searched as they appear on the command line. .Ss Search paths .Nm ld maintains a list of directories to search for a library or framework to use. The default library search path is /usr/lib then /usr/local/lib. The -L option will add a new library search path. The default framework search path is /Library/Frameworks then /System/Library/Frameworks. (Note: previously, /Network/Library/Frameworks was at the end of the default path. If you need -that functionality, you need to explicitly add -F/Network/Library/Frameworks). +that functionality, you need to explicitly add -F/Network/Library/Frameworks). The -F option will add a new framework search path. The -Z option will remove the standard search paths. The -syslibroot option will prepend a prefix to all search paths. .Ss Two-level namespace -By default all references resolved to a dynamic library record the library to which +By default all references resolved to a dynamic library record the library to which they were resolved. At runtime, dyld uses that information to directly resolve symbols. The alternative is to use the -flat_namespace option. With flat namespace, the library is not recorded. At runtime, dyld will search each dynamic library in load -order when resolving symbols. This is slower, but more like how other operating systems -resolve symbols. +order when resolving symbols. This is slower, but more like how other operating systems +resolve symbols. .Ss Indirect dynamic libraries If the command line specifies to link against dylib A, and when dylib A was built it linked -against dylib B, then B is considered an indirect dylib. -When linking for two-level namespace, ld does not look at indirect dylibs, except when -re-exported by a direct dylibs. On the other hand when linking for flat namespace, +against dylib B, then B is considered an indirect dylib. +When linking for two-level namespace, ld does not look at indirect dylibs, except when +re-exported by a direct dylibs. On the other hand when linking for flat namespace, ld does load all indirect dylibs and uses them to resolve references. -Even though indirect dylibs are specified via a full path, +Even though indirect dylibs are specified via a full path, .Nm ld first uses the specified search paths to locate each indirect dylib. If one cannot be found using the search paths, the full path is used. .Ss Dynamic libraries undefines -When linking for two-level namespace, -.Nm ld -does not verify that undefines in dylibs actually -exist. But when linking for flat namespace, +When linking for two-level namespace, .Nm ld -does check that all undefines from all loaded dylibs have a matching definition. +does not verify that undefines in dylibs actually +exist. But when linking for flat namespace, +.Nm ld +does check that all undefines from all loaded dylibs have a matching definition. This is sometimes used to force selected functions to be loaded from a static library. .Sh OPTIONS .Ss Options that control the kind of output @@ -110,13 +108,13 @@ Produce a mach-o shared library that has file type MH_DYLIB. .It Fl bundle Produce a mach-o bundle that has file type MH_BUNDLE. .It Fl r -Merges object files to produce another mach-o object file with file type MH_OBJECT. +Merges object files to produce another mach-o object file with file type MH_OBJECT. .It Fl dylinker Produce a mach-o dylinker that has file type MH_DYLINKER. Only used when building dyld. .It Fl dynamic The default. Implied by -dylib, -bundle, or -execute .It Fl static -Produces a mach-o file that does not use the dyld. Only used building the kernel. +Produces a mach-o file that does not use the dyld. Only used building the kernel. .It Fl preload Produces a mach-o file in which the mach_header, load commands, and symbol table are not in any segment. This output type is used for firmware or embedded development @@ -137,44 +135,36 @@ This is the same as the -lx but forces the library and all references to it to b That is, the library is allowed to be missing at runtime. .It Fl weak_library Ar path_to_library This is the same as listing a file name path to a library on the link line except that it forces the -library and all references to it to be marked as weak imports. +library and all references to it to be marked as weak imports. .It Fl reexport-l Ns Ar x -This is the same as the -lx but specifies that the all symbols in library x should be available to +This is the same as the -lx but specifies that the all symbols in library x should be available to clients linking to the library being created. This was previously done with a separate -sub_library option. .It Fl reexport_library Ar path_to_library -This is the same as listing a file name path to a library on the link line and it specifies that the +This is the same as listing a file name path to a library on the link line and it specifies that the all symbols in library path should be available to clients linking to the library being created. This was previously done with a separate -sub_library option. -.It Fl lazy-l Ns Ar x -This is the same as the -lx but it is only for shared libraries and the linker -will construct glue code so that the shared library is not loaded until -the first function in it is called. -.It Fl lazy_library Ar path_to_library -This is the same as listing a file name path to a shared library on the link line -except that the linker will construct glue code so that the shared library is not -loaded until the first function in it is called. .It Fl upward-l Ns Ar x -This is the same as the -lx but specifies that the dylib is an upward dependency. +This is the same as the -lx but specifies that the dylib is an upward dependency. .It Fl upward_library Ar path_to_library -This is the same as listing a file name path to a library on the link line but also marks +This is the same as listing a file name path to a library on the link line but also marks the dylib as an upward dependency. .It Fl L Ns dir -Add -.Ar dir -to the list of directories in which to search for libraries. +Add +.Ar dir +to the list of directories in which to search for libraries. Directories specified with -L are searched in the order they appear on the command line and before the default search path. In Xcode4 and later, there can be a space between the -L and directory. .It Fl Z Do not search the standard directories when searching for libraries and frameworks. .It Fl syslibroot Ar rootdir -Prepend -.Ar rootdir +Prepend +.Ar rootdir to all search paths when searching for libraries or frameworks. .It Fl search_paths_first -This is now the default (in Xcode4 tools). When processing -lx the linker now searches each directory -in its library search paths for `libx.dylib' then `libx.a' before the moving on to the next path -in the library search path. +This is now the default (in Xcode4 tools). When processing -lx the linker now searches each directory +in its library search paths for `libx.dylib' then `libx.a' before the moving on to the next path +in the library search path. .It Fl search_dylibs_first Changes the searching behavior for libraries. The default is that when processing -lx the linker searches each directory in its library search paths for `libx.dylib' then `libx.a'. @@ -186,24 +176,19 @@ This option tells the linker to search for `name.framework/name' the framework s If the optional suffix is specified the framework is first searched for the name with the suffix and then without (e.g. look for `name.framework/name_suffix' first, if not there try `name.framework/name'). .It Fl weak_framework Ar name[,suffix] -This is the same as the -framework name[,suffix] but forces the framework and all -references to it to be marked as weak imports. +This is the same as the -framework name[,suffix] but forces the framework and all +references to it to be marked as weak imports. .It Fl reexport_framework Ar name[,suffix] -This is the same as the -framework name[,suffix] but also specifies that the +This is the same as the -framework name[,suffix] but also specifies that the all symbols in that framework should be available to clients linking to the library being created. This was previously done with a separate -sub_umbrella option. -.It Fl lazy_framework Ar name[,suffix] -This is the same as the -framework name[,suffix] except that the linker will -construct glue code so that the framework is not -loaded until the first function in it is called. You cannot directly access -data or Objective-C classes in a framework linked this way. .It Fl upward_framework Ar name[,suffix] -This is the same as the -framework name[,suffix] but also specifies that the -framework is an upward dependency. +This is the same as the -framework name[,suffix] but also specifies that the +framework is an upward dependency. .It Fl F Ns dir -Add +Add .Ar dir -to the list of directories in which to search for frameworks. +to the list of directories in which to search for frameworks. Directories specified with -F are searched in the order they appear on the command line and before the default search path. In Xcode4 and later, there can be a space between the -F and directory. @@ -218,42 +203,42 @@ archives to be loaded. This option allows you to target a specific archive. .Ss Options that control additional content .Bl -tag .It Fl sectcreate Ar segname sectname file -The section -.Ar sectname -in the segment -.Ar segname -is created from the contents of file -.Ar file. -The combination of segname and sectname must be unique Ð there cannot already be a section (segname,sectname) +The section +.Ar sectname +in the segment +.Ar segname +is created from the contents of file +.Ar file. +The combination of segname and sectname must be unique Ð there cannot already be a section (segname,sectname) from any other input. .It Fl filelist Ar file[,dirname] -Specifies that the linker should link the files listed in -.Ar file . -This is an alternative to listing the files on the command line. +Specifies that the linker should link the files listed in +.Ar file . +This is an alternative to listing the files on the command line. The file names are listed one per line separated only by newlines. (Spaces and tabs are assumed to be part of the file name.) -If the optional directory name, -.Ar dirname +If the optional directory name, +.Ar dirname is specified, it is prepended to each name in the list file. .It Fl dtrace Ar file -Enables dtrace static probes when producing a final linked image. The file +Enables dtrace static probes when producing a final linked image. The file .Ar file must be a DTrace script which declares the static probes. .El -.Ss Options that control optimizations +.Ss Options that control optimizations .Bl -tag .It Fl dead_strip -Remove functions and data that are unreachable by the entry point or exported symbols. +Remove functions and data that are unreachable by the entry point or exported symbols. .It Fl order_file Ar file Alters the order in which functions and data are laid out. For each section in the output file, -any symbol in that section that are specified in the order file +any symbol in that section that are specified in the order file .Ar file -is moved to the start of its section and laid out in the same order as in the order file +is moved to the start of its section and laid out in the same order as in the order file .Ar file . Order files are text files with one symbol name per line. Lines starting with a # are comments. -A symbol name may be optionally preceded with its object file leaf name and a colon (e.g. foo.o:_foo). -This is useful for static functions/data that occur in multiple files. +A symbol name may be optionally preceded with its object file leaf name and a colon (e.g. foo.o:_foo). +This is useful for static functions/data that occur in multiple files. A symbol name may also be optionally preceded with the architecture (e.g. ppc:_foo or ppc:foo.o:_foo). -This enables you to have one order file that works for multiple architectures. +This enables you to have one order file that works for multiple architectures. Literal c-strings may be ordered by by quoting the string (e.g. "Hello, world\\n") in the order file. .It Fl no_order_inits When the -order_file option is not used, the linker lays out functions in object file order and @@ -263,38 +248,61 @@ to the end. Use this option to disable the automatic rearrangement of initialize By default the linker reorders global data in the __DATA segment so that all global variables that dyld will need to adjust at launch time will early in the __DATA segment. This reduces the number of dirty pages at launch time. This option disables that optimization. -.It Fl macosx_version_min Ar version -This is set to indicate the oldest Mac OS X version that that the output is to be used on. Specifying +.It Fl platform_version Ar platform Ar min_version Ar sdk_version +This is set to indicate the platform, oldest supported version of that platform that output is to be +used on, and the SDK that the output was built against. +.Ar platform +is a numeric value as defined in , or it may be one of the following strings: +.Bl -tag -compact +.It \(bu macos +.It \(bu ios +.It \(bu tvos +.It \(bu watchos +.It \(bu bridgeos +.It \(bu mac-catalyst +.It \(bu ios-sim +.It \(bu tvos-sim +.It \(bu watchos-sim +.It \(bu driverkit +.El +Specifying a newer min or SDK version enables the linker to assume features of that OS or SDK in the +output file. The format of +.Ar min_version +and +.Ar sdk_version +is a version number such as 10.13 or 10.14 +.It Fl macos_version_min Ar version +This is set to indicate the oldest macOS version that that the output is to be used on. Specifying a later version enables the linker to assumes features of that OS in the output file. The format of .Ar version -is a Mac OS X version number such as 10.4 or 10.5 +is a macOS version number such as 10.9 or 10.14 .It Fl ios_version_min Ar version This is set to indicate the oldest iOS version that that the output is to be used on. Specifying a later version enables the linker to assumes features of that OS in the output file. The format of .Ar version is an iOS version number such as 3.1 or 4.0 .It Fl image_base Ar address -Specifies the perferred load address for a dylib or bundle. The argument +Specifies the preferred load address for a dylib or bundle. The argument .Ar address is a hexadecimal number with an optional leading 0x. By choosing non-overlapping address for all dylibs and bundles that a program loads, launch time can be improved because dyld will not need to "rebase" the image (that is, adjust pointers within the image to work at the loaded address). -It is often easier to not use this option, but instead use the rebase(1) tool, and give it a list of dylibs. +It is often easier to not use this option, but instead use the rebase(1) tool, and give it a list of dylibs. It will then choose non-overlapping addresses for the list and rebase them all. This option is also called -seg1addr for compatibility. .It Fl no_implicit_dylibs -When creating a two-level namespace final linked image, normally the linker will hoist up public dylibs +When creating a two-level namespace final linked image, normally the linker will hoist up public dylibs that are implicitly linked to make the two-level namespace -encoding more efficient for dyld. For example, Cocoa re-exports AppKit and AppKit re-exports Foundation. +encoding more efficient for dyld. For example, Cocoa re-exports AppKit and AppKit re-exports Foundation. If you link with -framework Cocoa and use a symbol from Foundation, the linker will implicitly add a load -command to load Foundation and encode the symbol as coming from Foundation. If you use this option, +command to load Foundation and encode the symbol as coming from Foundation. If you use this option, the linker will not add a load command for Foundation and encode the symbol as coming from Cocoa. Then at runtime dyld will have to search Cocoa and AppKit before finding the symbol in Foundation. .It Fl exported_symbols_order Ar file When targeting Mac OS X 10.6 or later, the format of the exported symbol information can be optimized to make lookups of popular symbols faster. This option is used to pass a file containing a list of the symbols most frequently used by clients of the dynamic library being built. Not all exported symbols -need to be listed. +need to be listed. .It Fl no_zero_fill_sections By default the linker moves all zero fill sections to the end of the __DATA segment and configures them to use no space on disk. This option suppresses that optimization, so zero-filled data occupies @@ -306,32 +314,32 @@ Disables linker creation of branch islands which allows images to be created tha maximum branch distance. Useful with -preload when code is in multiple sections but all are within the branch range. .El -.Ss Options when creating a dynamic library (dylib) +.Ss Options when creating a dynamic library (dylib) .Bl -tag .It Fl install_name Ar name -Sets an internal "install path" (LC_ID_DYLIB) in a dynamic library. Any clients linked against the library -will record that path as the way dyld should locate this library. If this option is not specified, then +Sets an internal "install path" (LC_ID_DYLIB) in a dynamic library. Any clients linked against the library +will record that path as the way dyld should locate this library. If this option is not specified, then the -o path will be used. This option is also called -dylib_install_name for compatibility. .It Fl mark_dead_strippable_dylib -Specifies that the dylib being built can be dead strip by any client. That is, the dylib has +Specifies that the dylib being built can be dead strip by any client. That is, the dylib has no initialization side effects. So if a client links against the dylib, but never uses any symbol from it, the linker can optimize away the use of the dylib. .It Fl compatibility_version Ar number -Specifies the compatibility version number of the library. When a library is loaded by dyld, the +Specifies the compatibility version number of the library. When a library is loaded by dyld, the compatibility version is checked and if the program's version is greater that the library's version, it is an error. -The format of -.Ar number -is X[.Y[.Z]] where X must be a positive non-zero number less than or equal to 65535, -and .Y and .Z are optional and if present must be non-negative numbers less than or equal to 255. -If the compatibility version number is not specified, it has a value of 0 and no checking is done when the library is used. +The format of +.Ar number +is X[.Y[.Z]] where X must be a positive non-zero number less than or equal to 65535, +and .Y and .Z are optional and if present must be non-negative numbers less than or equal to 255. +If the compatibility version number is not specified, it has a value of 0 and no checking is done when the library is used. This option is also called -dylib_compatibility_version for compatibility. .It Fl current_version Ar number -Specifies the current version number of the library. The current version of the library can be obtained -programmatically by the user of the library so it can determine exactly which version of the library it is using. -The format of -.Ar number -is X[.Y[.Z]] where X must be a positive non-zero number less than or equal to 65535, -and .Y and .Z are optional and if present must be non-negative numbers less than or equal to 255. +Specifies the current version number of the library. The current version of the library can be obtained +programmatically by the user of the library so it can determine exactly which version of the library it is using. +The format of +.Ar number +is X[.Y[.Z]] where X must be a positive non-zero number less than or equal to 65535, +and .Y and .Z are optional and if present must be non-negative numbers less than or equal to 255. If the version number is not specified, it has a value of 0. This option is also called -dylib_current_version for compatibility. .El @@ -339,8 +347,8 @@ This option is also called -dylib_current_version for compatibility. .Bl -tag .It Fl pie This makes a special kind of main executable that is position independent (PIE). On Mac OS X 10.5 and later, the OS -the OS will load a PIE at a random address each time it is executed. You cannot create a PIE from .o files compiled -with -mdynamic-no-pic. That means the codegen is less optimal, but the address randomization adds some +the OS will load a PIE at a random address each time it is executed. You cannot create a PIE from .o files compiled +with -mdynamic-no-pic. That means the codegen is less optimal, but the address randomization adds some security. When targeting Mac OS X 10.7 or later PIE is the default for main executables. .It Fl no_pie Do not make a position independent executable (PIE). This is the default, when targeting 10.6 and earlier. @@ -348,43 +356,39 @@ Do not make a position independent executable (PIE). This is the default, when By default the linker creates an unreadable segment starting at address zero named __PAGEZERO. Its existence will cause a bus error if a NULL pointer is dereferenced. The argument .Ar size -is a hexadecimal number with an optional leading 0x. If +is a hexadecimal number with an optional leading 0x. If .Ar size -is zero, the linker will not generate a page zero segment. By default on 32-bit architectures the page zero size -is 4KB. On 64-bit architectures, the default size is 4GB. The ppc64 architecture has some special cases. Since Mac -OS X 10.4 did not support 4GB page zero programs, the default page zero size for ppc64 will be 4KB unless --macosx_version_min is 10.5 or later. Also, the -mdynamic-no-pic codegen model for ppc64 will only work if the -code is placed in the lower 2GB of the address space, so the if the linker detects any such code, the page zero -size is set to 4KB and then a new unreadable trailing segment is created after the code, filling up the lower 4GB. +is zero, the linker will not generate a page zero segment. By default on 32-bit architectures the page zero size +is 4KB. On 64-bit architectures, the default size is 4GB. .It Fl stack_size Ar size Specifies the maximum stack size for the main thread in a program. Without this option a program has a 8MB stack. The argument .Ar size -is a hexadecimal number with an optional leading 0x. The +is a hexadecimal number with an optional leading 0x. The .Ar size should be a multiple of the architecture's page size (4KB or 16KB). -.It Fl allow_stack_execute +.It Fl allow_stack_execute Marks executable so that all stacks in the task will be given stack execution privilege. This includes pthread stacks. .It Fl export_dynamic Preserves all global symbols in main executables during LTO. Without this option, Link Time Optimization is allowed to inline and remove global functions. This option is used when a main executable may load -a plug-in which requires certain symbols from the main executable. +a plug-in which requires certain symbols from the main executable. .El .Ss Options when creating a bundle .Bl -tag .It Fl bundle_loader Ar executable -This specifies the -.Ar executable -that will be loading the bundle output file being linked. -Undefined symbols from the bundle are checked against the specified -.Ar executable -like it was one of the +This specifies the +.Ar executable +that will be loading the bundle output file being linked. +Undefined symbols from the bundle are checked against the specified +.Ar executable +like it was one of the dynamic libraries the bundle was linked with. .El .Ss Options when creating an object file .Bl -tag .It Fl keep_private_externs -Don't turn private external (aka visibility=hidden) symbols into static symbols, +Don't turn private external (aka visibility=hidden) symbols into static symbols, but rather leave them as private external in the resulting object file. .It Fl d Force definition of common symbols. That is, transform tentative definitions into real definitions. @@ -392,85 +396,85 @@ Force definition of common symbols. That is, transform tentative definitions in .Ss Options that control symbol resolution .Bl -tag .It Fl exported_symbols_list Ar filename -The specified -.Ar filename -contains a list of global symbol names that will remain as global symbols in the output file. -All other global symbols will be treated as if they were marked as __private_extern__ (aka visibility=hidden) +The specified +.Ar filename +contains a list of global symbol names that will remain as global symbols in the output file. +All other global symbols will be treated as if they were marked as __private_extern__ (aka visibility=hidden) and will not be global in the output file. The symbol names listed in filename must be one per line. -Leading and trailing white space are not part of the symbol name. +Leading and trailing white space are not part of the symbol name. Lines starting with # are ignored, as are lines with only white space. Some wildcards (similar to shell file matching) are supported. The * matches zero or more characters. The ? matches one character. [abc] matches one character which must be an 'a', 'b', or 'c'. [a-z] matches -any single lower case letter from 'a' to 'z'. +any single lower case letter from 'a' to 'z'. .It Fl exported_symbol Ar symbol -The specified +The specified .Ar symbol -is added to the list of global symbols names that will remain as global symbols in the output file. This -option can be used multiple times. For short lists, this can be more convenient than creating a file and using +is added to the list of global symbols names that will remain as global symbols in the output file. This +option can be used multiple times. For short lists, this can be more convenient than creating a file and using -exported_symbols_list. .It Fl unexported_symbols_list Ar file -The specified -.Ar filename -contains a list of global symbol names that will not remain as global symbols in the output file. +The specified +.Ar filename +contains a list of global symbol names that will not remain as global symbols in the output file. The symbols will be treated as if they were marked as __private_extern__ (aka visibility=hidden) and will not be global -in the output file. The symbol names listed in filename must be one per line. -Leading and trailing white space are not part of the symbol name. +in the output file. The symbol names listed in filename must be one per line. +Leading and trailing white space are not part of the symbol name. Lines starting with # are ignored, as are lines with only white space. Some wildcards (similar to shell file matching) are supported. The * matches zero or more characters. The ? matches one character. [abc] matches one character which must be an 'a', 'b', or 'c'. [a-z] matches -any single lower case letter from 'a' to 'z'. +any single lower case letter from 'a' to 'z'. .It Fl unexported_symbol Ar symbol -The specified +The specified .Ar symbol -is added to the list of global symbols names that will not remain as global symbols in the output file. This -option can be used multiple times. For short lists, this can be more convenient than creating a file and using +is added to the list of global symbols names that will not remain as global symbols in the output file. This +option can be used multiple times. For short lists, this can be more convenient than creating a file and using -unexported_symbols_list. .It Fl reexported_symbols_list Ar file -The specified -.Ar filename +The specified +.Ar filename contains a list of symbol names that are implemented in a dependent dylib and should be re-exported -through the dylib being created. +through the dylib being created. .It Fl alias Ar symbol_name Ar alternate_symbol_name -Create an alias named +Create an alias named .Ar alternate_symbol_name for the symbol .Ar symbol_name . By default the alias symbol has global visibility. This option was previous the -idef:indir option. .It Fl alias_list Ar filename -The specified +The specified .Ar filename contains a list of aliases. The symbol name and its alias are on one line, separated by whitespace. Lines starting with # are ignored. -.It Fl flat_namespace +.It Fl flat_namespace Alters how symbols are resolved at build time and runtime. With -two_levelnamespace (the default), the linker -only searches dylibs on the command line for symbols, and records in which dylib they were found. With -flat_namespace, +only searches dylibs on the command line for symbols, and records in which dylib they were found. With -flat_namespace, the linker searches all dylibs on the command line and all dylibs those original dylibs depend on. The linker does not record which dylib an external symbol came from, so at runtime dyld again searches all images and uses the first definition it finds. In addition, any undefines in loaded flat_namespace dylibs must be resolvable -at build time. +at build time. .It Fl u Ar symbol_name -Specified that symbol +Specified that symbol .Ar symbol_name must be defined for the link to succeed. This is useful to force selected functions to be loaded from a static library. .It Fl U Ar symbol_name -Specified that it is ok for +Specified that it is ok for .Ar symbol_name to have no definition. With -two_levelnamespace, the resulting symbol will be marked dynamic_lookup which means dyld will search all loaded images. .It Fl undefined Ar treatment Specifies how undefined symbols are to be treated. Options are: error, warning, suppress, or dynamic_lookup. The -default is error. +default is error. .It Fl rpath Ar path -Add +Add .Ar path to the runpath search path list for image being created. At runtime, dyld uses the runpath when searching for dylibs whose load path begins with @rpath/. .It Fl commons Ar treatment -Specifies how commons (aka tentative definitions) are resolved with respect to dylibs. Options are: +Specifies how commons (aka tentative definitions) are resolved with respect to dylibs. Options are: ignore_dylibs, use_dylibs, error. The default is ignore_dylibs which means the linker will turn a tentative definition in an object file into a real definition and not even check dylibs for conflicts. The dylibs -option means the linker should check linked dylibs for definitions and use them to replace tentative definitions +option means the linker should check linked dylibs for definitions and use them to replace tentative definitions from object files. The error option means the linker should issue an error whenever a tentative definition in an object file conflicts with an external symbol in a linked dylib. See also -warn_commons. .El @@ -480,7 +484,7 @@ object file conflicts with an external symbol in a linked dylib. See also -warn Log why each object file in a static library is loaded. That is, what symbol was needed. Also called -whyload for compatibility. .It Fl why_live Ar symbol_name -Logs a chain of references to +Logs a chain of references to .Ar symbol_name . Only applicable with -dead_strip . It can help debug why something that you think should be dead strip removed is not removed. @@ -508,17 +512,21 @@ that will be automatically removed when linked into a final linked image. This allows dead code stripping, which uses symbols to break up code and data, to work properly and provides the security of having source symbol names removed. .It Fl non_global_symbols_strip_list Ar filename -The specified -.Ar filename -contains a list of non-global symbol names that should be removed from the output file's symbol table. All other +The specified +.Ar filename +contains a list of non-global symbol names that should be removed from the output file's symbol table. All other non-global symbol names will remain in the output files symbol table. See -exported_symbols_list for syntax and use of wildcards. .It Fl non_global_symbols_no_strip_list Ar filename -The specified -.Ar filename -contains a list of non-global symbol names that should be remain in the output file's symbol table. All other +The specified +.Ar filename +contains a list of non-global symbol names that should be remain in the output file's symbol table. All other symbol names will be removed from the output file's symbol table. See -exported_symbols_list for syntax and use of wildcards. +.It Fl oso_prefix Ar prefix-path +When generating the debug map, the linker will remove the specified +.Ar prefix-path +from the path in OSO symbols. This can be used so to help build servers generate identical binaries. .El .Ss Options for Bitcode build flow .Bl -tag @@ -526,7 +534,7 @@ of wildcards. Generates an embedded bitcode bundle in the output binary. The bitcode bundle is embedded in __LLVM, __bundle section. This option requires all the object files, static libraries and user frameworks/dylibs contain bitcode. Note: not all the linker options are supported to use together with -bitcode_bundle. -.It Fl bitcode_hide_symbol +.It Fl bitcode_hide_symbols Specifies this option together with -bitcode_bundle to hide all non-exported symbols from output bitcode bundle. The hide symbol process might not be reversible. To obtain a reverse mapping file to recover all the symbols, use -bitcode_symbol_map option. @@ -541,10 +549,24 @@ Otherwise, the reverse map will be written to a file at .Bl -tag .It Fl v Prints the version of the linker. +.It Fl version_details +Prints the version info about the linker in JSON +.It Fl no_weak_imports +Error if any symbols are weak imports (i.e. allowed to be unresolved (NULL) at runtime). Useful for config based +projects that assume they are built and run on the same OS version. .It Fl no_deduplicate Don't run deduplication pass in linker .It Fl verbose_deduplicate Prints names of functions that are eliminated by deduplication and total code savings size. +.It Fl no_inits +Error if the output contains any static initializers +.It Fl no_warn_inits +Do not warn if the output contains any static initializers +.It Fl debug_variant +Do not warn about issues that are only problems for binaries shipping to customers. +.It Fl unaligned_pointers Ar treatment +Specifies how unaligned pointers in __DATA segments should be handled. Options are: 'warning', 'error', or 'suppress'. +The default for arm64e is 'error' and for all other architectures it is 'suppress'. .It Fl dirty_data_list Ar filename Specifies a file containing the names of data symbols likely to be dirtied. If the linker is creating a __DATA_DIRTY segment, those symbols will be moved @@ -561,34 +583,33 @@ Moves data symbols to another segment. The command line option specifies the target segment name and a path to a file containing a list of symbols to move. Comments can be added to the symbol file by starting a line with a #. If there are multiple instances of a symbol name (for instance a "static int foo=5;" in multiple files) -the symbol name in the symbol list file can be prefixed with the object file name +the symbol name in the symbol list file can be prefixed with the object file name (e.g. "init.o:_foo") to move a specific instance. -.It Fl move_to_ro_section Ar segment_name Ar section_name Ar filename +.It Fl move_to_ro_segment Ar segment_name Ar filename Moves code symbols to another segment. The command line option specifies the target segment name and a path to a file containing a list of symbols to move. Comments can be added to the symbol file by starting a line with a #. If there are multiple instances of a symbol name (for instance a "static int foo() {}" in multiple files) -the symbol name in the symbol list file can be prefixed with the object file name +the symbol name in the symbol list file can be prefixed with the object file name (e.g. "init.o:_foo") to move a specific instance. .It Fl rename_section Ar orgSegment orgSection newSegment newSection Renames section orgSegment/orgSection to newSegment/newSection. -.It Fl rename_segment Ar orgSegment newSegment +.It Fl rename_segment Ar orgSegment newSegment Renames all sections with orgSegment segment name to have newSegment segment name. .It Fl trace_symbol_layout For using in debugging -rename_section, -rename_segment, -move_to_ro_segment, and -move_to_rw_segment. This option prints out a line show where and why each symbol was moved. -Note: These options do not chain. For each symbol, the linker first checks --move_to_ro_segment and -move_to_rw_segment. If the symbol is not moved, -it checks for an applicable -rename_section. Only if the symbol still has -not been moved, does the linker look for an applicable -rename_segment option. +Note: These options do chain. For each symbol, the linker first checks +-move_to_ro_segment and -move_to_rw_segment. Next it applies any -rename_section options, +and lastly and -rename_segment options. .It Fl section_order Ar segname Ar colon_separated_section_list Only for use with -preload. Specifies the order that sections with the specified segment should be layout out. -For example: "-section_order __ROM __text:__const:__cstring". +For example: "-section_order __ROM __text:__const:__cstring". .It Fl segment_order Ar colon_separated_segment_list Only for use with -preload. Specifies the order segments should be layout out. -For example: "-segment_order __ROM:__ROM2:__RAM". +For example: "-segment_order __ROM:__ROM2:__RAM". .It Fl allow_heap_execute -Normally i386 main executables will be marked so that the Mac OS X 10.7 and later kernel +Normally i386 main executables will be marked so that the Mac OS X 10.7 and later kernel will only allow pages with the x-bit to execute instructions. This option overrides that behavior and allows instructions on any page to be executed. .It Fl application_extension @@ -596,7 +617,7 @@ Specifies that the code is being linked for use in an application extension. Th will then validiate that any dynamic libraries linked against are safe for use in application extensions. .It Fl no_application_extension -Specifies that the code is being linked is not safe for use in an application extension. +Specifies that the code is being linked is not safe for use in an application extension. For instance, can be used when creating a framework that should not be used in an application extension. .It Fl fatal_warnings @@ -608,22 +629,25 @@ linker but are needed by earlier linker tools. .It Fl warn_compact_unwind When producing a final linked image, the linker processes the __eh_frame section and produces an __unwind_info section. Most FDE entries in the __eh_frame can be represented -by a 32-bit value in the __unwind_info section. The option issues a warning for +by a 32-bit value in the __unwind_info section. The option issues a warning for any function whose FDE cannot be expressed in the compact unwind format. .It Fl warn_weak_exports Issue a warning if the resulting final linked image contains weak external symbols. Such symbols require dyld to do extra work at launch time to coalesce those symbols. +.It Fl no_weak_exports +Issue an erro if the resulting final linked image contains weak external symbols. Such +symbols require dyld to do extra work at launch time to coalesce those symbols. .It Fl objc_gc_compaction -Marks the Objective-C image info in the final linked image with the bit that says that the +Marks the Objective-C image info in the final linked image with the bit that says that the code was built to work the compacting garbage collection. .It Fl objc_gc Verifies all code was compiled with -fobjc-gc or -fobjc-gc-only. .It Fl objc_gc_only Verifies all code was compiled with -fobjc-gc-only. .It Fl dead_strip_dylibs -Remove dylibs that are unreachable by the entry point or exported symbols. That is, +Remove dylibs that are unreachable by the entry point or exported symbols. That is, suppresses the generation of load command commands for dylibs which supplied no -symbols during the link. This option should not be used when linking against a dylib which +symbols during the link. This option should not be used when linking against a dylib which is required at runtime for some indirect reason such as the dylib has an important initializer. .It Fl allow_sub_type_mismatches Normally the linker considers different cpu-subtype for ARM (e.g. armv4t and armv6) to be different @@ -636,32 +660,32 @@ Sets the MH_ROOT_SAFE bit in the mach header of the output file. .It Fl setuid_safe Sets the MH_SETUID_SAFE bit in the mach header of the output file. .It Fl interposable -Indirects access to all to exported symbols when creating a dynamic library. +Indirects access to all to exported symbols when creating a dynamic library. .It Fl init Ar symbol_name -The specified symbol_name will be run as the first initializer. Only used when creating a dynamic library. +The specified symbol_name will be run as the first initializer. Only used when creating a dynamic library. .It Fl sub_library Ar library_name -The specified dylib will be re-exported. For example the library_name for /usr/lib/libobjc_profile.A.dylib would be libobjc. -Only used when creating a dynamic library. +The specified dylib will be re-exported. For example the library_name for /usr/lib/libobjc_profile.A.dylib would be libobjc. +Only used when creating a dynamic library. .It Fl sub_umbrella Ar framework_name -The specified framework will be re-exported. Only used when creating a dynamic library. +The specified framework will be re-exported. Only used when creating a dynamic library. .It Fl allowable_client Ar name -Restricts what can link against the dynamic library being created. By default any code +Restricts what can link against the dynamic library being created. By default any code can link against any dylib. But if a dylib is supposed to be private to a small set of clients, you can formalize that by adding a -allowable_client for each client. If a client is libfoo.1.dylib its -allowable_client name would be "foo". If a client is Foo.framework its -allowable_client name would be "Foo". For the degenerate -case where you want no one to ever link against a dylib, you can set the --allowable_client to "!". +case where you want no one to ever link against a dylib, you can set the +-allowable_client to "!". .It Fl client_name Ar name -Enables a bundle to link against a dylib that was built with -allowable_client. +Enables a bundle to link against a dylib that was built with -allowable_client. The name specified must match one of the -allowable_client names specified when the dylib was created. .It Fl umbrella Ar framework_name Specifies that the dylib being linked is re-exported through an umbrella framework of the specified name. .It Fl headerpad Ar size -Specifies the minimum space for future expansion of the load commands. Only useful if intend to run +Specifies the minimum space for future expansion of the load commands. Only useful if intend to run install_name_tool to alter the load commands later. Size is a hexadecimal number. .It Fl headerpad_max_install_names -Automatically adds space for future expansion of load commands such that all paths could expand to MAXPATHLEN. +Automatically adds space for future expansion of load commands such that all paths could expand to MAXPATHLEN. Only useful if intend to run install_name_tool to alter the load commands later. .It Fl bind_at_load Sets a bit in the mach header of the resulting binary which tells dyld to bind all symbols when the binary is loaded, rather than lazily. @@ -669,43 +693,43 @@ Sets a bit in the mach header of the resulting binary which tells dyld to bind a Sets a bit in the mach header of the resulting binary which tells dyld to not only use flat namespace for the binary, but force flat namespace binding on all dylibs and bundles loaded in the process. Can only be used when linking main executables. .It Fl sectalign Ar segname Ar sectname Ar value -The section named sectname in the segment segname will have its alignment set to value, where value is a hexadecimal -number that must be an integral power of 2. +The section named sectname in the segment segname will have its alignment set to value, where value is a hexadecimal +number that must be an integral power of 2. .It Fl stack_addr Ar address Specifies the initial address of the stack pointer value, where value is a hexadecimal number rounded to a page boundary. .It Fl segprot Ar segname Ar max_prot Ar init_prot -Specifies the maximum and initial virtual memory protection of the named segment, name, to be max and init ,respectively. +Specifies the maximum and initial virtual memory protection of the named segment, name, to be max and init ,respectively. The values for max and init are any combination of the characters `r' (for read), `w' (for write), `x' (for execute) and `-' (no access). .It Fl seg_addr_table Ar filename -Specifies a file containing base addresses for dynamic libraries. Each line of the file is a hexadecimal base address +Specifies a file containing base addresses for dynamic libraries. Each line of the file is a hexadecimal base address followed by whitespace then the install name of the corresponding dylib. The # character denotes a comment. .It Fl segs_read_write_addr Ar address -Allows a dynamic library to be built where the read-only and read-write segments are not contiguous. The address +Allows a dynamic library to be built where the read-only and read-write segments are not contiguous. The address specified is a hexadecimal number that indicates the base address for the read-write segments. .It Fl segs_read_only_addr Ar address -Allows a dynamic library to be built where the read-only and read-write segments are not contiguous. The address +Allows a dynamic library to be built where the read-only and read-write segments are not contiguous. The address specified is a hexadecimal number that indicates the base address for the read-only segments. .It Fl segaddr Ar name Ar address -Specifies the starting address of the segment named name to be address. The address must be a hexadecimal number +Specifies the starting address of the segment named name to be address. The address must be a hexadecimal number that is a multiple of 4K page size. .It Fl seg_page_size Ar name Ar size -Specifies the page size used by the specified segment. By default the page size is 4096 for all segments. +Specifies the page size used by the specified segment. By default the page size is 4096 for all segments. The linker will lay out segments such that size of a segment is always an even multiple of its page size. .It Fl dylib_file Ar install_name:file_name -Specifies that a dynamic shared library is in a different location than its standard location. Use this option -when you link with a library that is dependent on a dynamic library, and the dynamic library is in a location other -than its default location. install_name specifies the path where the library normally resides. file_name specifies -the path of the library you want to use instead. For example, if you link to a library that depends upon the dynamic -library libsys and you have libsys installed in a nondefault location, you would use this option: +Specifies that a dynamic shared library is in a different location than its standard location. Use this option +when you link with a library that is dependent on a dynamic library, and the dynamic library is in a location other +than its default location. install_name specifies the path where the library normally resides. file_name specifies +the path of the library you want to use instead. For example, if you link to a library that depends upon the dynamic +library libsys and you have libsys installed in a nondefault location, you would use this option: -dylib_file /lib/libsys_s.A.dylib:/me/lib/libsys_s.A.dylib. .It Fl prebind -The created output file will be in the prebound format. This was used in Mac OS X 10.3 and earlier to improve launch performance. +The created output file will be in the prebound format. This was used in Mac OS X 10.3 and earlier to improve launch performance. .It Fl weak_reference_mismatches Ar treatment -Specifies what to do if a symbol is weak-imported in one object file but not weak-imported in another. The valid +Specifies what to do if a symbol is weak-imported in one object file but not weak-imported in another. The valid treatments are: error, weak, or non-weak. The default is non-weak. .It Fl read_only_relocs Ar treatment -Enables the use of relocations which will cause dyld to modify (copy-on-write) read-only pages. The compiler will -normally never generate such code. +Enables the use of relocations which will cause dyld to modify (copy-on-write) read-only pages. The compiler will +normally never generate such code. .It Fl force_cpusubtype_ALL The is only applicable with -arch ppc. It tells the linker to ignore the PowerPC cpu requirements (e.g. G3, G4 or G5) encoded in the object files and mark the resulting binary as runnable on any PowerPC cpu. @@ -714,20 +738,20 @@ Only used when building dyld. .It Fl no_arch_warnings Suppresses warning messages about files that have the wrong architecture for the -arch flag .It Fl arch_errors_fatal -Turns into errors, warnings about files that have the wrong architecture for the -arch flag. +Turns into errors, warnings about files that have the wrong architecture for the -arch flag. .It Fl e Ar symbol_name Specifies the entry point of a main executable. By default the entry name is "start" which is found in crt1.o which contains the glue code need to set up and call main(). .It Fl w Suppress all warning messages .It Fl final_output Ar name -Specifies the install name of a dylib if -install_name is not used. This option is used by gcc driver when it is invoked -with multiple -arch arguments. +Specifies the install name of a dylib if -install_name is not used. This option is used by compiler driver when it is invoked +with multiple -arch arguments. .It Fl arch_multiple -Specifes that the linker should augment error and warning messages with the architecture name. This option is used by gcc -driver when it is invoked with multiple -arch arguments. +Specifes that the linker should augment error and warning messages with the architecture name. This option is used by compiler +driver when it is invoked with multiple -arch arguments. .It Fl twolevel_namespace_hints -Specifies that hints should be added to the resulting binary that can help speed up runtime binding by dyld as long as the +Specifies that hints should be added to the resulting binary that can help speed up runtime binding by dyld as long as the libraries being linked against have not changed. .It Fl dot Ar path Create a file at the specified path containing a graph of symbol dependencies. The .dot file can be viewed in GraphViz. @@ -743,24 +767,21 @@ in a header file. .It Fl read_only_stubs [i386 only] Makes the __IMPORT segment of a final linked images read-only. This option makes a program slightly more secure in that the JMP instructions in the i386 fast stubs cannot be easily overwritten by malicious code. The downside -is the dyld must use mprotect() to temporarily make the segment writable while it is binding the stubs. +is the dyld must use mprotect() to temporarily make the segment writable while it is binding the stubs. .It Fl slow_stubs -[i386 only] Instead of using single JMP instruction stubs, the linker creates code in the __TEXT segment which -calls through a lazy pointer in the __DATA segment. +[i386 only] Instead of using single JMP instruction stubs, the linker creates code in the __TEXT segment which +calls through a lazy pointer in the __DATA segment. .It Fl interposable_list Ar filename -The specified -.Ar filename +The specified +.Ar filename contains a list of global symbol names that should always be accessed indirectly. For instance, if libSystem.dylib is linked such that _malloc is interposable, then calls to malloc() from within libSystem will go through a dyld -stub and could potentially indirected to an alternate malloc. If libSystem.dylib were built without making _malloc -interposable then if _malloc was interposed at runtime, calls to malloc from with libSystem would be missed +stub and could potentially indirected to an alternate malloc. If libSystem.dylib were built without making _malloc +interposable then if _malloc was interposed at runtime, calls to malloc from with libSystem would be missed (not interposed) because they would be direct calls. .It Fl no_function_starts By default the linker creates a compress table of function start addresses in the LINKEDIT of final linked image. This option disables that behavior. -.It Fl no_version_load_command -By default the linker creates a load command in final linked images that contains the -macosx_version_min. -This option disables that behavior. .It Fl no_objc_category_merging By default when producing final linked image, the linker will optimize Objective-C classes by merging any categories on a class into the class. Both the class and its categories must be defined in the image @@ -768,16 +789,28 @@ being linked for the optimization to occur. Using this option disables that beh .It Fl object_path_lto Ar filename When performing Link Time Optimization (LTO) and a temporary mach-o object file is needed, if this option is used, the temporary file will be stored at the specified path and remain after the link -is complete. Without the option, the linker picks a path and deletes the object file before the linker +is complete. Without the option, the linker picks a path and deletes the object file before the linker tool completes, thus tools such as the debugger or dsymutil will not be able to access the DWARF debug info in the temporary object file. .It Fl lto_library Ar path When performing Link Time Optimization (LTO), the linker normally loads libLTO.dylib relative to the linker binary (../lib/libLTO.dylib). This option allows the user to specify the path to a specific libLTO.dylib to load instead. +.It Fl cache_path_lto Ar path +When performing Incremental Link Time Optimization (LTO), use this directory as a cache for incremental rebuild. +.It Fl prune_interval_lto Ar seconds +When performing Incremental Link Time Optimization (LTO), the cache will pruned after the specified interval. A value 0 +will force pruning to occur and a value of -1 will disable pruning. +.It Fl prune_after_lto Ar seconds +When pruning the cache for Incremental Link Time Optimization (LTO), the cache entries are removed after the +specificied interval. +.It Fl max_relative_cache_size_lto Ar percent +When performing Incremental Link Time Optimization (LTO), the cache will be pruned to not go over this percentage +of the free space. I.e. a value of 100 would indicate that the cache may fill the disk, and a value of 50 would +indicate that the cache size will be kept under the free disk space. .It Fl page_align_data_atoms -During development, this option can be used to space out all global variables so each is on a separate page. -This is useful when analyzing dirty and resident pages. The information can then be used to create an +During development, this option can be used to space out all global variables so each is on a separate page. +This is useful when analyzing dirty and resident pages. The information can then be used to create an order file to cluster commonly used/dirty globals onto the same page(s). .It Fl not_for_dyld_shared_cache Normally, the linker will add extra info to dylibs with -install_name starting with /usr/lib or @@ -787,7 +820,7 @@ tells the linker to not add that extra info. .Ss Obsolete Options .Bl -tag .It Fl segalign Ar value -All segments must be page aligned. +All segments must be page aligned. .It Fl seglinkedit Object files (MH_OBJECT) with a LINKEDIT segment are no longer supported. This option is obsolete. .It Fl noseglinkedit @@ -808,13 +841,13 @@ When using -prebind, the linker allows overlapping by default, so this option is LD_PREBIND is no longer supported as a way to force on prebinding, so there no longer needs to be a command line way to override LD_PREBIND. This option is obsolete. .It Fl sect_diff_relocs Ar treatment -This option was an attempt to warn about linking .o files compiled without -mdynamic-no-pic into +This option was an attempt to warn about linking .o files compiled without -mdynamic-no-pic into a main executable, but the false positive rate generated too much noise to make the option useful. This option is obsolete. .It Fl run_init_lazily This option was removed in Mac OS X 10.2. .It Fl single_module -This is now the default so does not need to be specified. +This is now the default so does not need to be specified. .It Fl multi_module Multi-modules in dynamic libraries have been ignored at runtime since Mac OS X 10.4.0. This option is obsolete. .It Fl no_dead_strip_inits_and_terms @@ -824,7 +857,7 @@ Obsolete incremental load format. This option is obsolete. .It Fl b Used with -A option to strip base file's symbols. This option is obsolete. ..It Fl M -Obsolete option to produce a load map. Use -map option instead. +Obsolete option to produce a load map. Use -map option instead. .It Fl Sn Don't strip any symbols. This is the default. This option is obsolete. .It Fl Si @@ -835,15 +868,15 @@ This style of debugging is obsolete in Mac OS X 10.5. This option is obsolete. .It Fl X Strip local symbols that begin with 'L'. This is the default. This option is obsolete. .It Fl s -Completely strip the output, including removing the symbol table. This file format variant is no longer supported. +Completely strip the output, including removing the symbol table. This file format variant is no longer supported. This option is obsolete. .It Fl m Don't treat multiple definitions as an error. This is no longer supported. This option is obsolete. .It Fl y Ns symbol -Display each file in which +Display each file in which .Ar symbol is used. This was previously used to debug where an undefined symbol was used, but the linker now -automatically prints out all usages. The -why_live option can also be used to display what kept +automatically prints out all usages. The -why_live option can also be used to display what kept a symbol from being dead striped. This option is obsolete. .It Fl Y Ar number Used to control how many occurrences of each symbol specified with -y would be shown. This option is obsolete. @@ -854,23 +887,37 @@ bit has been obsolete since Mac OS X 10.4. This option is obsolete. Previously provided a way to warn or error if any of the symbol definitions in the output file matched any definitions in dynamic library being linked. This option is obsolete. .It Fl multiply_defined Ar treatment -Previously provided a way to warn or error if any of the symbols used from a dynamic library were also +Previously provided a way to warn or error if any of the symbols used from a dynamic library were also available in another linked dynamic library. This option is obsolete. .It Fl private_bundle -Previously prevented errors when -flat_namespace, -bundle, and -bundle_loader were used and the bundle +Previously prevented errors when -flat_namespace, -bundle, and -bundle_loader were used and the bundle contained a definition that conflicted with a symbol in the main executable. The linker no longer errors on such conflicts. This option is obsolete. .It Fl noall_load This is the default. This option is obsolete. .It Fl seg_addr_table_filename Ar path -Use +Use .Ar path instead of the install name of the library for matching an entry in the seg_addr_table. This option is obsolete. .It Fl sectorder Ar segname sectname orderfile Replaced by more general -order_file option. .It Fl sectorder_detail -Produced extra logging about which entries from a sectorder entries were used. Replaced by -order_file_statistics. -This option is obsolete. +Produced extra logging about which entries from a sectorder entries were used. Replaced by -order_file_statistics. +This option is obsolete. +.It Fl lazy_framework Ar name[,suffix] +This is the same as the -framework name[,suffix] except that the linker will +construct glue code so that the framework is not +loaded until the first function in it is called. You cannot directly access +data or Objective-C classes in a framework linked this way. This option +is deprecated. +.It Fl lazy-l Ns Ar x +This is the same as the -lx but it is only for shared libraries and the linker +will construct glue code so that the shared library is not loaded until +the first function in it is called. This option is deprecated. +.It Fl lazy_library Ar path_to_library +This is the same as listing a file name path to a shared library on the link line +except that the linker will construct glue code so that the shared library is not +loaded until the first function in it is called. This option is deprecated. .El .Sh SEE ALSO as(1), ar(1), cc(1), nm(1), otool(1) lipo(1), diff --git a/cctools/ld64/doc/man/man1/rebase.1 b/cctools/ld64/doc/man/man1/rebase.1 deleted file mode 100644 index 6743a96..0000000 --- a/cctools/ld64/doc/man/man1/rebase.1 +++ /dev/null @@ -1,39 +0,0 @@ -.Dd June 6, 2006 -.Dt rebase 1 -.Os Darwin -.Sh NAME -.Nm rebase -.Nd "Changes base address of dylibs and bundles" -.Sh SYNOPSIS -.Nm -.Op Fl low_address Ar addr -.Op Fl high_address Ar addr -.Op Fl arch Ar arch -.Op Fl v -.Ar file(s) -.Sh DESCRIPTION -The base address of an image (dylib or bundle) is the preferred address for it to be loaded. By -default all images are built with a base address of zero. At runtime, if the -preferred memory range is already occupied, dyld will "slide" the image to a new address range. -There is a small cost to the slide, as dyld must do some fix ups. -The rebase tool takes a list of images and adjust their base address to be non-overlapping. If no -low or high address is specified, the a suitable address range is choosen for the architecture. -.Pp -The options are as follows: -.Bl -tag -width indent -.It Fl low_address Ar addr -Force the base address for the first image to be -.Ar addr -(specified in hex). Each subsequent file gets the next available base address. -.It Fl high_address Ar addr -Force the base address for the last image to be such that when that image is loaded it occupies -memory up to -.Ar addr -(specified in hex). Each preceeding file gets the previous available base address. -.It Fl arch Ar arch -Only rebase the specified architecture. Other architectures in a universal image are left as is. -.It Fl v -Verbose. Print information about rebasing done. -.El -.Sh SEE ALSO -.Xr ld 1 diff --git a/cctools/ld64/src/3rd/BlocksRuntime/Makefile.in b/cctools/ld64/src/3rd/BlocksRuntime/Makefile.in new file mode 100644 index 0000000..3c95689 --- /dev/null +++ b/cctools/ld64/src/3rd/BlocksRuntime/Makefile.in @@ -0,0 +1,614 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = ld64/src/3rd/BlocksRuntime +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libBlocksRuntime_la_LIBADD = +am_libBlocksRuntime_la_OBJECTS = data.lo runtime.lo +libBlocksRuntime_la_OBJECTS = $(am_libBlocksRuntime_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libBlocksRuntime_la_SOURCES) +DIST_SOURCES = $(libBlocksRuntime_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libBlocksRuntime.la +noinst_HEADERS = \ + Block.h \ + Block_private.h \ + config.h + +libBlocksRuntime_la_SOURCES = \ + data.c \ + runtime.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps ld64/src/3rd/BlocksRuntime/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps ld64/src/3rd/BlocksRuntime/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libBlocksRuntime.la: $(libBlocksRuntime_la_OBJECTS) $(libBlocksRuntime_la_DEPENDENCIES) $(EXTRA_libBlocksRuntime_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libBlocksRuntime_la_OBJECTS) $(libBlocksRuntime_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/ld64/src/3rd/Makefile.am b/cctools/ld64/src/3rd/Makefile.am index 3c7993f..046e038 100644 --- a/cctools/ld64/src/3rd/Makefile.am +++ b/cctools/ld64/src/3rd/Makefile.am @@ -1,7 +1,7 @@ SUBDIRS = BlocksRuntime noinst_LTLIBRARIES = libhelper.la -noinst_HEADERS = helper.h strlcat.h strlcpy.h qsort_r.h -libhelper_la_CFLAGS=-I$(top_srcdir)/include -I$(top_srcdir)/include/foreign $(ENDIAN_FLAG) $(WARNINGS) +noinst_HEADERS = helper.h strlcat.h strlcpy.h qsort_r.h md5.h mkpath_np.h +libhelper_la_CFLAGS=-I$(top_srcdir)/include -I$(top_srcdir)/include/foreign $(ENDIAN_FLAG) $(WARNINGS) -D__DARWIN_UNIX03 libhelper_la_SOURCES = \ helper.c \ @@ -9,4 +9,5 @@ libhelper_la_SOURCES = \ strlcat.c \ strlcpy.c \ eprintf.c \ - md5.c + md5.c \ + mkpath_np.c diff --git a/cctools/ld64/src/3rd/Makefile.in b/cctools/ld64/src/3rd/Makefile.in new file mode 100644 index 0000000..8f1f080 --- /dev/null +++ b/cctools/ld64/src/3rd/Makefile.in @@ -0,0 +1,760 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = ld64/src/3rd +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libhelper_la_LIBADD = +am_libhelper_la_OBJECTS = libhelper_la-helper.lo \ + libhelper_la-qsort_r.lo libhelper_la-strlcat.lo \ + libhelper_la-strlcpy.lo libhelper_la-eprintf.lo \ + libhelper_la-md5.lo libhelper_la-mkpath_np.lo +libhelper_la_OBJECTS = $(am_libhelper_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libhelper_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libhelper_la_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libhelper_la_SOURCES) +DIST_SOURCES = $(libhelper_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = BlocksRuntime +noinst_LTLIBRARIES = libhelper.la +noinst_HEADERS = helper.h strlcat.h strlcpy.h qsort_r.h md5.h mkpath_np.h +libhelper_la_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign $(ENDIAN_FLAG) $(WARNINGS) -D__DARWIN_UNIX03 +libhelper_la_SOURCES = \ + helper.c \ + qsort_r.c \ + strlcat.c \ + strlcpy.c \ + eprintf.c \ + md5.c \ + mkpath_np.c + +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps ld64/src/3rd/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps ld64/src/3rd/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libhelper.la: $(libhelper_la_OBJECTS) $(libhelper_la_DEPENDENCIES) $(EXTRA_libhelper_la_DEPENDENCIES) + $(AM_V_CCLD)$(libhelper_la_LINK) $(libhelper_la_OBJECTS) $(libhelper_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +libhelper_la-helper.lo: helper.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-helper.lo `test -f 'helper.c' || echo '$(srcdir)/'`helper.c + +libhelper_la-qsort_r.lo: qsort_r.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-qsort_r.lo `test -f 'qsort_r.c' || echo '$(srcdir)/'`qsort_r.c + +libhelper_la-strlcat.lo: strlcat.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-strlcat.lo `test -f 'strlcat.c' || echo '$(srcdir)/'`strlcat.c + +libhelper_la-strlcpy.lo: strlcpy.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-strlcpy.lo `test -f 'strlcpy.c' || echo '$(srcdir)/'`strlcpy.c + +libhelper_la-eprintf.lo: eprintf.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-eprintf.lo `test -f 'eprintf.c' || echo '$(srcdir)/'`eprintf.c + +libhelper_la-md5.lo: md5.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-md5.lo `test -f 'md5.c' || echo '$(srcdir)/'`md5.c + +libhelper_la-mkpath_np.lo: mkpath_np.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-mkpath_np.lo `test -f 'mkpath_np.c' || echo '$(srcdir)/'`mkpath_np.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool \ + clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/ld64/src/3rd/helper.c b/cctools/ld64/src/3rd/helper.c index 4eb1fc3..f3a8437 100644 --- a/cctools/ld64/src/3rd/helper.c +++ b/cctools/ld64/src/3rd/helper.c @@ -1,4 +1,7 @@ -const char ldVersionString[] = "264.3.102\n"; +#define VAL(x) #x +#define STRINGIFY(x) VAL(x) + +const char ldVersionString[] = "@(#)PROGRAM:ld PROJECT:ld64-" STRINGIFY(LD64_VERSION_NUM) "\n"; #ifndef __APPLE__ @@ -36,8 +39,12 @@ void __assert_rtn(const char *func, const char *file, int line, const char *msg) __assert(msg, file, line, func); #elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) __assert(msg, line, file); -#else +#elif defined(__GLIBC__) || defined(__MINGW32__) __assert(msg, file, line); +#else + fprintf(stderr, "Assertion failed: %s (%s: %s: %d)\n", msg, file, func, line); + fflush(NULL); + abort(); #endif /* __FreeBSD__ */ } diff --git a/cctools/ld64/src/3rd/helper.h b/cctools/ld64/src/3rd/helper.h index a705ac3..4fac2e1 100644 --- a/cctools/ld64/src/3rd/helper.h +++ b/cctools/ld64/src/3rd/helper.h @@ -1,40 +1,18 @@ #ifndef _HELPER_H #define _HELPER_H +#ifndef __USE_GNU +#define __USE_GNU +#endif + #ifdef __cplusplus extern "C" { #endif -#ifndef __has_extension -#define __has_extension(x) 0 -#endif - -#ifndef __has_include -#define __has_include(x) 0 -#endif - -#ifndef __has_include_next -#define __has_include_next(x) 0 -#endif - #include #include #include #include - -#ifndef __USE_GNU -#define __USE_GNU -#endif - -#ifndef __APPLE__ -typedef char uuid_string_t__[37]; -#define uuid_string_t uuid_string_t__ -#endif - -#ifdef __NetBSD__ -#define stoi(a,b) atoi(a.c_str()); do { if (!b) break; const char *p = a.c_str(); *b = 0; while (isdigit(*p++)) (*b)++; } while (0) -#endif - #include struct dyld_unwind_sections @@ -48,6 +26,11 @@ struct dyld_unwind_sections typedef Dl_info dl_info; +#ifndef __APPLE__ +typedef char uuid_string_t__[37]; +#define uuid_string_t uuid_string_t__ +#endif + int _NSGetExecutablePath(char *path, unsigned int *size); int _dyld_find_unwind_sections(void* i, struct dyld_unwind_sections* sec); mach_port_t mach_host_self(void); diff --git a/cctools/ld64/src/3rd/mkpath_np.c b/cctools/ld64/src/3rd/mkpath_np.c new file mode 100644 index 0000000..72b4563 --- /dev/null +++ b/cctools/ld64/src/3rd/mkpath_np.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2011 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef __APPLE__ + +#include "mkpath_np.h" + +#include +#include +#include +#include + +/* This extended version of mkpath_np is provided to help NSFileManager + * maintain binary compatibility. If firstdir is not NULL, *firstdir will be + * set to the path of the first created directory, and it is the caller's + * responsibility to free the returned string. This SPI is subject to removal + * once NSFileManager no longer has a need for it, and use in new code is + * highly discouraged. + * + * See: + */ + +int +_mkpath_np(const char *path, mode_t omode, const char ** firstdir) +{ + char *apath = NULL; + unsigned int depth = 0; + mode_t chmod_mode = 0; + int retval = 0; + int old_errno = errno; + struct stat sbuf; + + /* Try the trivial case first. */ + if (0 == mkdir(path, omode)) { + if (firstdir) { + *firstdir = strdup(path); + } + goto mkpath_exit; + } + + /* Anything other than an ENOENT, EEXIST, or EISDIR indicates an + * error that we need to send back to the caller. ENOENT indicates + * that we need to try a lower level. + */ + switch (errno) { + case ENOENT: + break; + case EEXIST: + if (stat(path, &sbuf) == 0) { + if (S_ISDIR(sbuf.st_mode)) { + retval = EEXIST; + } else { + retval = ENOTDIR; + } + } else { + retval = EIO; + } + goto mkpath_exit; + case EISDIR: /* */ + retval = EEXIST; + goto mkpath_exit; + default: + retval = errno; + goto mkpath_exit; + } + + apath = strdup(path); + if (apath == NULL) { + retval = ENOMEM; + goto mkpath_exit; + } + + while (1) { + /* Increase our depth and try making that directory */ + char *s = strrchr(apath, '/'); + if (!s) { + /* We should never hit this under normal circumstances, + * but it can occur due to really unfortunate timing + */ + retval = ENOENT; + goto mkpath_exit; + } + *s = '\0'; + depth++; + + if (0 == mkdir(apath, S_IRWXU | S_IRWXG | S_IRWXO)) { + /* Found our starting point */ + + /* POSIX 1003.2: + * For each dir operand that does not name an existing + * directory, effects equivalent to those cased by the + * following command shall occcur: + * + * mkdir -p -m $(umask -S),u+wx $(dirname dir) && + * mkdir [-m mode] dir + */ + + struct stat dirstat; + if (-1 == stat(apath, &dirstat)) { + /* Really unfortunate timing ... */ + retval = ENOENT; + goto mkpath_exit; + } + + if ((dirstat.st_mode & (S_IWUSR | S_IXUSR)) != (S_IWUSR | S_IXUSR)) { + chmod_mode = dirstat.st_mode | S_IWUSR | S_IXUSR; + if (-1 == chmod(apath, chmod_mode)) { + /* Really unfortunate timing ... */ + retval = ENOENT; + goto mkpath_exit; + } + } + + if (firstdir) { + *firstdir = strdup(apath); + } + break; + } else if (errno == EEXIST) { + /* Some other process won the race in creating this directory + * before we did. We will use this as our starting point. + * See: + */ + if (stat(apath, &sbuf) == 0 && + S_ISDIR(sbuf.st_mode)) { + + if (firstdir) { + *firstdir = strdup(apath); + } + break; + } + + retval = ENOTDIR; + goto mkpath_exit; + } else if (errno != ENOENT) { + retval = errno; + goto mkpath_exit; + } + } + + while (depth > 1) { + /* Decrease our depth and make that directory */ + char *s = strrchr(apath, '\0'); + *s = '/'; + depth--; + + if (-1 == mkdir(apath, S_IRWXU | S_IRWXG | S_IRWXO)) { + /* This handles "." and ".." added to the new section of path */ + if (errno == EEXIST) + continue; + retval = errno; + goto mkpath_exit; + } + + if (chmod_mode) { + if (-1 == chmod(apath, chmod_mode)) { + /* Really unfortunate timing ... */ + retval = ENOENT; + goto mkpath_exit; + } + } + } + + if (-1 == mkdir(path, omode)) { + retval = errno; + if (errno == EEXIST && + stat(path, &sbuf) == 0 && + !S_ISDIR(sbuf.st_mode)) { + retval = ENOTDIR; + } + } + +mkpath_exit: + free(apath); + + errno = old_errno; + return retval; +} + +int mkpath_np(const char *path, mode_t omode) { + return _mkpath_np(path, omode, NULL); +} + +#endif /* ! __APPLE__ */ \ No newline at end of file diff --git a/cctools/ld64/src/3rd/mkpath_np.h b/cctools/ld64/src/3rd/mkpath_np.h new file mode 100644 index 0000000..4821c30 --- /dev/null +++ b/cctools/ld64/src/3rd/mkpath_np.h @@ -0,0 +1,12 @@ +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +int mkpath_np(const char *path, mode_t omode); + +#ifdef __cplusplus +} +#endif diff --git a/cctools/ld64/src/Makefile.in b/cctools/ld64/src/Makefile.in new file mode 100644 index 0000000..bada8f7 --- /dev/null +++ b/cctools/ld64/src/Makefile.in @@ -0,0 +1,655 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = ld64/src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +depcomp = +am__maybe_remake_depfiles = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = 3rd ld other +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps ld64/src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps ld64/src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/ld64/src/abstraction/MachOFileAbstraction.hpp b/cctools/ld64/src/abstraction/MachOFileAbstraction.hpp index cfedc81..5c9994e 100644 --- a/cctools/ld64/src/abstraction/MachOFileAbstraction.hpp +++ b/cctools/ld64/src/abstraction/MachOFileAbstraction.hpp @@ -40,244 +40,272 @@ #include "configure.h" -// stuff that will eventually go away once newer cctools headers are widespread -#ifndef LC_LOAD_UPWARD_DYLIB - #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */ + + +//#if SUPPORT_ARCH_arm64 || SUPPORT_ARCH_arm64e || SUPPORT_ARCH_arm64_32 + #include +///#endif + +#ifndef BIND_SPECIAL_DYLIB_WEAK_LOOKUP +#define BIND_SPECIAL_DYLIB_WEAK_LOOKUP -3 #endif -#ifndef CPU_SUBTYPE_ARM_V5TEJ - #define CPU_SUBTYPE_ARM_V5TEJ ((cpu_subtype_t) 7) -#endif -#ifndef CPU_SUBTYPE_ARM_XSCALE - #define CPU_SUBTYPE_ARM_XSCALE ((cpu_subtype_t) 8) -#endif -#ifndef CPU_SUBTYPE_ARM_V7 - #define CPU_SUBTYPE_ARM_V7 ((cpu_subtype_t) 9) +#ifndef BIND_OPCODE_THREADED +#define BIND_OPCODE_THREADED 0xD0 #endif -#ifndef N_ARM_THUMB_DEF - #define N_ARM_THUMB_DEF 0x0008 +#ifndef BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB +#define BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB 0x00 #endif -#ifndef MH_DEAD_STRIPPABLE_DYLIB - #define MH_DEAD_STRIPPABLE_DYLIB 0x400000 -#endif -#ifndef MH_KEXT_BUNDLE - #define MH_KEXT_BUNDLE 11 -#endif -#ifndef LC_DYLD_INFO - #define LC_DYLD_INFO 0x22 /* compressed dyld information */ - #define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD) /* compressed dyld information only */ - struct dyld_info_command { - uint32_t cmd; /* LC_DYLD_INFO or LC_DYLD_INFO_ONLY */ - uint32_t cmdsize; /* sizeof(struct dyld_info_command) */ - uint32_t rebase_off; /* file offset to rebase info */ - uint32_t rebase_size; /* size of rebase info */ - uint32_t bind_off; /* file offset to binding info */ - uint32_t bind_size; /* size of binding info */ - uint32_t weak_bind_off; /* file offset to weak binding info */ - uint32_t weak_bind_size; /* size of weak binding info */ - uint32_t lazy_bind_off; /* file offset to lazy binding info */ - uint32_t lazy_bind_size; /* size of lazy binding infs */ - uint32_t export_off; /* file offset to lazy binding info */ - uint32_t export_size; /* size of lazy binding infs */ +#ifndef BIND_SUBOPCODE_THREADED_APPLY +#define BIND_SUBOPCODE_THREADED_APPLY 0x01 +#endif + +#ifndef EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE + #define EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE 0x02 +#endif +#ifndef MH_SIM_SUPPORT + #define MH_SIM_SUPPORT 0x08000000 +#endif +#ifndef PLATFORM_IOSMAC + #define PLATFORM_IOSMAC 6 +#endif +#ifndef SG_READ_ONLY + #define SG_READ_ONLY 0x10 +#endif + +#ifndef N_COLD_FUNC + #define N_COLD_FUNC 0x0400 +#endif + +#if __has_include() + #include +#else + // header of the LC_DYLD_CHAINED_FIXUPS payload + struct dyld_chained_fixups_header + { + uint32_t fixups_version; // 0 + uint32_t starts_offset; // offset of dyld_chained_starts_in_image in chain_data + uint32_t imports_offset; // offset of imports table in chain_data + uint32_t symbols_offset; // offset of symbol strings in chain_data + uint32_t imports_count; // number of imported symbol names + uint32_t imports_format; // DYLD_CHAINED_IMPORT* + uint32_t symbols_format; // 0 => uncompressed, 1 => zlib compressed }; - #define REBASE_TYPE_POINTER 1 - #define REBASE_TYPE_TEXT_ABSOLUTE32 2 - #define REBASE_TYPE_TEXT_PCREL32 3 + // This struct is embedded in LC_DYLD_CHAINED_FIXUPS payload + struct dyld_chained_starts_in_image + { + uint32_t seg_count; + uint32_t seg_info_offset[1]; // each entry is offset into this struct for that segment + // followed by pool of dyld_chain_starts_in_segment data + }; - #define REBASE_OPCODE_MASK 0xF0 - #define REBASE_IMMEDIATE_MASK 0x0F - #define REBASE_OPCODE_DONE 0x00 - #define REBASE_OPCODE_SET_TYPE_IMM 0x10 - #define REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x20 - #define REBASE_OPCODE_ADD_ADDR_ULEB 0x30 - #define REBASE_OPCODE_ADD_ADDR_IMM_SCALED 0x40 - #define REBASE_OPCODE_DO_REBASE_IMM_TIMES 0x50 - #define REBASE_OPCODE_DO_REBASE_ULEB_TIMES 0x60 - #define REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB 0x70 - #define REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB 0x80 + // This struct is embedded in dyld_chain_starts_in_image + // and passed down to the kernel for page-in linking + struct dyld_chained_starts_in_segment + { + uint32_t size; // size of this (amount kernel needs to copy) + uint16_t page_size; // 0x1000 or 0x4000 + uint16_t pointer_format; // DYLD_CHAINED_PTR_* + uint64_t segment_offset; // offset in memory to start of segment + uint32_t max_valid_pointer; // for 32-bit OS, any value beyond this is not a pointer + uint16_t page_count; // how many pages are in array + uint16_t page_start[1]; // each entry is offset in each page of first element in chain + // or DYLD_CHAINED_PTR_START_NONE if no fixups on page + // uint16_t chain_starts[1]; // some 32-bit formats may require multiple starts per page. + // for those, if high bit is set in page_starts[], then it + // is index into chain_starts[] which is a list of starts + // the last of which has the high bit set + }; - #define BIND_TYPE_POINTER 1 - #define BIND_TYPE_TEXT_ABSOLUTE32 2 - #define BIND_TYPE_TEXT_PCREL32 3 + enum { + DYLD_CHAINED_PTR_START_NONE = 0xFFFF, // used in page_start[] to denote a page with no fixups + DYLD_CHAINED_PTR_START_MULTI = 0x8000, // used in page_start[] to denote a page which has multiple starts + DYLD_CHAINED_PTR_START_LAST = 0x8000, // used in chain_starts[] to denote last start in list for page + }; - #define BIND_SPECIAL_DYLIB_SELF 0 - #define BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE -1 - #define BIND_SPECIAL_DYLIB_FLAT_LOOKUP -2 - #define BIND_SYMBOL_FLAGS_WEAK_IMPORT 0x1 - #define BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION 0x8 + // This struct is embedded in __TEXT,__chain_starts section in firmware + struct dyld_chained_starts_offsets + { + uint32_t pointer_format; // DYLD_CHAINED_PTR_32_FIRMWARE + uint32_t starts_count; // number of starts in array + uint32_t chain_starts[1]; // array chain start offsets + }; - #define BIND_OPCODE_MASK 0xF0 - #define BIND_IMMEDIATE_MASK 0x0F - #define BIND_OPCODE_DONE 0x00 - #define BIND_OPCODE_SET_DYLIB_ORDINAL_IMM 0x10 - #define BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB 0x20 - #define BIND_OPCODE_SET_DYLIB_SPECIAL_IMM 0x30 - #define BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM 0x40 - #define BIND_OPCODE_SET_TYPE_IMM 0x50 - #define BIND_OPCODE_SET_ADDEND_SLEB 0x60 - #define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70 - #define BIND_OPCODE_ADD_ADDR_ULEB 0x80 - #define BIND_OPCODE_DO_BIND 0x90 - #define BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB 0xA0 - #define BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED 0xB0 - #define BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0xC0 - #define EXPORT_SYMBOL_FLAGS_KIND_MASK 0x03 - #define EXPORT_SYMBOL_FLAGS_KIND_REGULAR 0x00 - #define EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL 0x01 - #define EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION 0x04 - #define EXPORT_SYMBOL_FLAGS_INDIRECT_DEFINITION 0x08 - #define EXPORT_SYMBOL_FLAGS_HAS_SPECIALIZATIONS 0x10 + // values for dyld_chained_starts_in_segment.pointer_format + enum { + DYLD_CHAINED_PTR_ARM64E = 1, + DYLD_CHAINED_PTR_64 = 2, + DYLD_CHAINED_PTR_32 = 3, + DYLD_CHAINED_PTR_32_CACHE = 4, + DYLD_CHAINED_PTR_32_FIRMWARE = 5, + }; -#endif + // DYLD_CHAINED_PTR_ARM64E + struct dyld_chained_ptr_arm64e_rebase + { + uint64_t target : 43, + high8 : 8, + next : 11, // 8-byte stide + bind : 1, // == 0 + auth : 1; // == 0 + }; -#ifndef S_THREAD_LOCAL_REGULAR - #define S_THREAD_LOCAL_REGULAR 0x11 -#endif + // DYLD_CHAINED_PTR_ARM64E + struct dyld_chained_ptr_arm64e_bind + { + uint64_t ordinal : 16, + zero : 16, + addend : 19, + next : 11, // 8-byte stide + bind : 1, // == 1 + auth : 1; // == 0 + }; -#ifndef S_THREAD_LOCAL_ZEROFILL - #define S_THREAD_LOCAL_ZEROFILL 0x12 -#endif + // DYLD_CHAINED_PTR_ARM64E + struct dyld_chained_ptr_arm64e_auth_rebase + { + uint64_t target : 32, + diversity : 16, + addrDiv : 1, + key : 2, + next : 11, // 8-byte stide + bind : 1, // == 0 + auth : 1; // == 1 + }; -#ifndef S_THREAD_LOCAL_VARIABLES - #define S_THREAD_LOCAL_VARIABLES 0x13 -#endif + // DYLD_CHAINED_PTR_ARM64E + struct dyld_chained_ptr_arm64e_auth_bind + { + uint64_t ordinal : 16, + zero : 16, + diversity : 16, + addrDiv : 1, + key : 2, + next : 11, // 8-byte stide + bind : 1, // == 1 + auth : 1; // == 1 + }; -#ifndef S_THREAD_LOCAL_VARIABLE_POINTERS - #define S_THREAD_LOCAL_VARIABLE_POINTERS 0x14 -#endif + // DYLD_CHAINED_PTR_64 + struct dyld_chained_ptr_64_rebase + { + uint64_t target : 36, // 64GB max image size + high8 : 8, // top 8 bits set to this after slide added + reserved : 7, // all zeros + next : 12, // 4-byte stride + bind : 1; // == 0 + }; -#ifndef S_THREAD_LOCAL_INIT_FUNCTION_POINTERS - #define S_THREAD_LOCAL_INIT_FUNCTION_POINTERS 0x15 -#endif + // DYLD_CHAINED_PTR_64 + struct dyld_chained_ptr_64_bind + { + uint64_t ordinal : 24, + addend : 8, // 0 thru 255 + reserved : 19, // all zeros + next : 12, // 4-byte stride + bind : 1; // == 1 + }; -#ifndef MH_HAS_TLV_DESCRIPTORS - #define MH_HAS_TLV_DESCRIPTORS 0x800000 -#endif + // DYLD_CHAINED_PTR_32 + struct dyld_chained_ptr_32_rebase + { + uint32_t target : 26, // 64MB max image size + next : 5, // 4-byte stride + bind : 1; // == 0 + }; + + // DYLD_CHAINED_PTR_32 + struct dyld_chained_ptr_32_bind + { + uint32_t ordinal : 20, + addend : 6, // 0 thru 63 + next : 5, // 4-byte stride + bind : 1; // == 1 + }; + + // DYLD_CHAINED_PTR_32_CACHE + struct dyld_chained_ptr_32_cache_rebase + { + uint32_t target : 30, // 1GB max dyld cache TEXT and DATA + next : 2; // 4-byte stride + }; + + + // DYLD_CHAINED_PTR_32_FIRMWARE + struct dyld_chained_ptr_32_firmware_rebase + { + uint32_t target : 26, // 64MB max firmware TEXT and DATA + next : 6; // 4-byte stride + }; + + + + // values for dyld_chained_fixups_header.imports_format + enum { + DYLD_CHAINED_IMPORT = 1, + DYLD_CHAINED_IMPORT_ADDEND = 2, + DYLD_CHAINED_IMPORT_ADDEND64 = 3, + }; + + // DYLD_CHAINED_IMPORT + struct dyld_chained_import + { + uint32_t lib_ordinal : 8, + weak_import : 1, + name_offset : 23; + }; + + // DYLD_CHAINED_IMPORT_ADDEND + struct dyld_chained_import_addend + { + uint32_t lib_ordinal : 8, + weak_import : 1, + name_offset : 23; + int32_t addend; + }; + + // DYLD_CHAINED_IMPORT_ADDEND64 + struct dyld_chained_import_addend64 + { + uint64_t lib_ordinal : 16, + weak_import : 1, + reserved : 15, + name_offset : 32; + uint64_t addend; + }; + +#endif // __has_include() + + +#define LC_DYLD_EXPORTS_TRIE (0x33 | LC_REQ_DYLD) +#define LC_DYLD_CHAINED_FIXUPS (0x34 | LC_REQ_DYLD) -#ifndef X86_64_RELOC_TLV - #define X86_64_RELOC_TLV 9 -#endif #define GENERIC_RLEOC_TLV 5 -#ifndef EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER - #define EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER 0x10 -#endif - -#ifndef EXPORT_SYMBOL_FLAGS_REEXPORT - #define EXPORT_SYMBOL_FLAGS_REEXPORT 0x08 -#endif - // type internal to linker #define BIND_TYPE_OVERRIDE_OF_WEAKDEF_IN_DYLIB 0 -#ifndef LC_VERSION_MIN_MACOSX - #define LC_VERSION_MIN_MACOSX 0x24 - #define LC_VERSION_MIN_IPHONEOS 0x25 - struct version_min_command { - uint32_t cmd; /* LC_VERSION_MIN_MACOSX or LC_VERSION_MIN_IPHONEOS */ - uint32_t cmdsize; /* sizeof(struct min_version_command) */ - uint32_t version; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ - uint32_t reserved; /* zero */ - }; +#ifndef CPU_TYPE_ARM64_32 + #ifndef CPU_ARCH_ABI64_32 + #define CPU_ARCH_ABI64_32 0x02000000 + #endif + #define CPU_TYPE_ARM64_32 (CPU_TYPE_ARM | CPU_ARCH_ABI64_32) #endif - -#ifndef N_SYMBOL_RESOLVER - #define N_SYMBOL_RESOLVER 0x100 +#ifndef CPU_SUBTYPE_ARM64_32_V8 + #define CPU_SUBTYPE_ARM64_32_V8 1 #endif - -#ifndef N_AST - #define N_AST 0x32 +#ifndef CPU_SUBTYPE_ARM64E + #define CPU_SUBTYPE_ARM64E 2 + #define ARM64_RELOC_AUTHENTICATED_POINTER 11 #endif -#ifndef LC_FUNCTION_STARTS - #define LC_FUNCTION_STARTS 0x26 -#endif - -#ifndef MH_NO_HEAP_EXECUTION - #define MH_NO_HEAP_EXECUTION 0x1000000 -#endif - -#ifndef LC_DYLD_ENVIRONMENT - #define LC_DYLD_ENVIRONMENT 0x27 -#endif - -#ifndef LC_DATA_IN_CODE - #define LC_DATA_IN_CODE 0x29 /* table of non-instructions in __text */ - struct data_in_code_entry { - uint32_t offset; - uint16_t length; - uint16_t kind; - }; -#endif - -#ifndef LC_DYLIB_CODE_SIGN_DRS - #define LC_DYLIB_CODE_SIGN_DRS 0x2B -#endif - -#ifndef LC_ENCRYPTION_INFO_64 - #define LC_ENCRYPTION_INFO_64 0x2C - struct encryption_info_command_64 { - uint32_t cmd; - uint32_t cmdsize; - uint32_t cryptoff; - uint32_t cryptsize; - uint32_t cryptid; - uint32_t pad; - }; -#endif - -#ifndef MH_APP_EXTENSION_SAFE - #define MH_APP_EXTENSION_SAFE 0x02000000 -#endif - -#ifndef N_ALT_ENTRY - #define N_ALT_ENTRY 0x0200 -#endif - -#ifndef CPU_SUBTYPE_ARM_V7F - #define CPU_SUBTYPE_ARM_V7F ((cpu_subtype_t) 10) -#endif -#ifndef CPU_SUBTYPE_ARM_V7K - #define CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t) 12) -#endif -#ifndef CPU_SUBTYPE_ARM_V7S - #define CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t) 11) -#endif - - - -// hack until arm64 headers are worked out -#ifndef CPU_TYPE_ARM64 - #define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64) -#endif -#ifndef CPU_SUBTYPE_ARM64_ALL - #define CPU_SUBTYPE_ARM64_ALL 0 -#endif -#ifndef CPU_SUBTYPE_ARM64_V8 - #define CPU_SUBTYPE_ARM64_V8 1 -#endif - - -#define ARM64_RELOC_UNSIGNED 0 // for pointers -#define ARM64_RELOC_SUBTRACTOR 1 // must be followed by a ARM64_RELOC_UNSIGNED -#define ARM64_RELOC_BRANCH26 2 // a B/BL instruction with 26-bit displacement -#define ARM64_RELOC_PAGE21 3 // pc-rel distance to page of target -#define ARM64_RELOC_PAGEOFF12 4 // offset within page, scaled by r_length -#define ARM64_RELOC_GOT_LOAD_PAGE21 5 // pc-rel distance to page of GOT slot -#define ARM64_RELOC_GOT_LOAD_PAGEOFF12 6 // offset within page of GOT slot, scaled by r_length -#define ARM64_RELOC_POINTER_TO_GOT 7 // for pointers to GOT slots -#define ARM64_RELOC_TLVP_LOAD_PAGE21 8 // pc-rel distance to page of TLVP slot -#define ARM64_RELOC_TLVP_LOAD_PAGEOFF12 9 // offset within page of TLVP slot, scaled by r_length -#define ARM64_RELOC_ADDEND 10 // r_symbolnum is addend for next reloc - - #define UNW_ARM64_X0 0 #define UNW_ARM64_X1 1 @@ -379,85 +407,18 @@ #define UNW_ARM_D31 287 - -#ifndef LC_SOURCE_VERSION - #define LC_SOURCE_VERSION 0x2A - struct source_version_command { - uint32_t cmd; /* LC_SOURCE_VERSION */ - uint32_t cmdsize; /* 16 */ - uint64_t version; /* A.B.C.D.E packed as a24.b10.c10.d10.e10 */ - }; +#ifndef LC_LINKER_OPTIMIZATION_HINTS + #define LC_LINKER_OPTIMIZATION_HINTS 0x2E + #define LOH_ARM64_ADRP_ADRP 1 + #define LOH_ARM64_ADRP_LDR 2 + #define LOH_ARM64_ADRP_ADD_LDR 3 + #define LOH_ARM64_ADRP_LDR_GOT_LDR 4 + #define LOH_ARM64_ADRP_ADD_STR 5 + #define LOH_ARM64_ADRP_LDR_GOT_STR 6 + #define LOH_ARM64_ADRP_ADD 7 + #define LOH_ARM64_ADRP_LDR_GOT 8 #endif -#ifndef LC_MAIN - #define LC_MAIN (0x28|LC_REQ_DYLD) /* replacement for LC_UNIXTHREAD */ - struct entry_point_command { - uint32_t cmd; /* LC_MAIN only used in MH_EXECUTE filetypes */ - uint32_t cmdsize; /* 24 */ - uint64_t entryoff; /* file (__TEXT) offset of main() */ - uint64_t stacksize;/* if not zero, initial stack size */ - }; -#endif - -#ifndef LC_DYLIB_CODE_SIGN_DRS - #define LC_DYLIB_CODE_SIGN_DRS 0x2B -#endif - -#ifndef LC_LINKER_OPTION - #define LC_LINKER_OPTION 0x2D - - struct linker_option_command { - uint32_t cmd; /*LC_LINKER_OPTION only used in MH_OBJECT filetypes */ - uint32_t cmdsize; - uint32_t count; /* number of strings */ - /* concatenation of zero terminated UTF8 strings. Zero filled at end to align */ - }; -#endif - -#ifndef LC_LINKER_OPTIMIZATION_HINTS - #define LC_LINKER_OPTIMIZATION_HINTS 0x2E - #define LOH_ARM64_ADRP_ADRP 1 - #define LOH_ARM64_ADRP_LDR 2 - #define LOH_ARM64_ADRP_ADD_LDR 3 - #define LOH_ARM64_ADRP_LDR_GOT_LDR 4 - #define LOH_ARM64_ADRP_ADD_STR 5 - #define LOH_ARM64_ADRP_LDR_GOT_STR 6 - #define LOH_ARM64_ADRP_ADD 7 - #define LOH_ARM64_ADRP_LDR_GOT 8 -#endif - -#ifndef LC_VERSION_MIN_TVOS - #define LC_VERSION_MIN_TVOS 0x2F -#endif - -#ifndef LC_VERSION_MIN_WATCHOS - #define LC_VERSION_MIN_WATCHOS 0x30 -#endif - -#ifndef EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE - #define EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE 0x02 -#endif - -#ifndef CPU_SUBTYPE_ARM_V8 - #define CPU_SUBTYPE_ARM_V8 ((cpu_subtype_t) 13) -#endif - -#ifndef CPU_SUBTYPE_ARM_V6M - #define CPU_SUBTYPE_ARM_V6M ((cpu_subtype_t) 14) -#endif - -#ifndef CPU_SUBTYPE_ARM_V7M - #define CPU_SUBTYPE_ARM_V7M ((cpu_subtype_t) 15) -#endif - -#ifndef CPU_SUBTYPE_ARM_V7EM - #define CPU_SUBTYPE_ARM_V7EM ((cpu_subtype_t) 16) -#endif - -#ifndef CPU_SUBTYPE_X86_64_H - #define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t) 8) -#endif - #define UNWIND_ARM_MODE_MASK 0x0F000000 #define UNWIND_ARM_MODE_FRAME 0x01000000 #define UNWIND_ARM_MODE_FRAME_D 0x02000000 @@ -506,6 +467,11 @@ #define DYLD_CACHE_ADJ_V2_THUMB_MOVW_MOVT 0x0A #define DYLD_CACHE_ADJ_V2_THUMB_BR22 0x0B #define DYLD_CACHE_ADJ_V2_IMAGE_OFF_32 0x0C +#define DYLD_CACHE_ADJ_V2_THREADED_POINTER_64 0x0D + +#ifndef S_INIT_FUNC_OFFSETS + #define S_INIT_FUNC_OFFSETS 0x16 +#endif @@ -578,15 +544,19 @@ static const ArchInfo archInfoArray[] = { #define SUPPORT_ARCH_arm_any 1 #endif #if SUPPORT_ARCH_arm64 - { "arm64", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL, "arm64-", "aarch64-", false, false }, + { "arm64", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL, "arm64-", "aarch64-", true, false }, #endif #if SUPPORT_ARCH_arm64v8 { "arm64v8", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_V8, "arm64v8-", "aarch64-", true, false }, +#endif +#if SUPPORT_ARCH_arm64e + { "arm64e", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_E, "arm64e-", "aarch64-", true, false }, #endif { NULL, 0, 0, NULL, NULL, false, false } }; - + + // weird, but this include must wait until after SUPPORT_ARCH_arm_any is set up #if SUPPORT_ARCH_arm_any #include @@ -1649,13 +1619,8 @@ public: uint32_t version() const INLINE { return fields.version; } void set_version(uint32_t value) INLINE { E::set32(fields.version, value); } -#ifdef DICE_KIND_DATA uint32_t sdk() const INLINE { return fields.sdk; } void set_sdk(uint32_t value) INLINE { E::set32(fields.sdk, value); } -#else - uint32_t sdk() const INLINE { return fields.reserved; } - void set_sdk(uint32_t value) INLINE { E::set32(fields.reserved, value); } -#endif typedef typename P::E E; private: @@ -1663,6 +1628,58 @@ private: }; + +// +// mach-o build version load command +// +template +class macho_build_version_command { +public: + uint32_t cmd() const INLINE { return E::get32(fields.cmd); } + void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } + + uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } + void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } + + uint32_t platform() const INLINE { return fields.platform; } + void set_platform(uint32_t value) INLINE { E::set32(fields.platform, value); } + + uint32_t minos() const INLINE { return fields.minos; } + void set_minos(uint32_t value) INLINE { E::set32(fields.minos, value); } + + uint32_t sdk() const INLINE { return fields.sdk; } + void set_sdk(uint32_t value) INLINE { E::set32(fields.sdk, value); } + + uint32_t ntools() const INLINE { return fields.ntools; } + void set_ntools(uint32_t value) INLINE { E::set32(fields.ntools, value); } + + + typedef typename P::E E; +private: + build_version_command fields; +}; + + +// +// mach-o build version load command +// +template +class macho_build_tool_version { +public: + uint32_t tool() const INLINE { return E::get32(fields.tool); } + void set_tool(uint32_t value) INLINE { E::set32(fields.tool, value); } + + uint32_t version() const INLINE { return E::get32(fields.version); } + void set_version(uint32_t value) INLINE { E::set32(fields.version, value); } + + typedef typename P::E E; +private: + build_tool_version fields; +}; + + + + // // mach-o __LD, __compact_unwind section in object files // @@ -1763,14 +1780,6 @@ private: data_in_code_entry fields; }; -#ifndef DICE_KIND_DATA - #define DICE_KIND_DATA 0x0001 - #define DICE_KIND_JUMP_TABLE8 0x0002 - #define DICE_KIND_JUMP_TABLE16 0x0003 - #define DICE_KIND_JUMP_TABLE32 0x0004 - #define DICE_KIND_ABS_JUMP_TABLE32 0x0005 -#endif - template class macho_linker_option_command { public: @@ -1793,8 +1802,6 @@ private: - - #endif // __MACH_O_FILE_ABSTRACTION__ diff --git a/cctools/ld64/src/configure.h b/cctools/ld64/src/configure.h index 70f3b94..972eda0 100644 --- a/cctools/ld64/src/configure.h +++ b/cctools/ld64/src/configure.h @@ -18,28 +18,26 @@ #include #endif +#define LD_PAGE_SIZE 0x1000 #define CPU_SUBTYPE_X86_ALL ((cpu_subtype_t)3) -#define SUPPORT_ARCH_armv4t 1 -#define SUPPORT_ARCH_armv5 1 #define SUPPORT_ARCH_armv6 1 #define SUPPORT_ARCH_armv7 1 -#define SUPPORT_ARCH_armv7f 1 -#define SUPPORT_ARCH_armv7k 1 #define SUPPORT_ARCH_armv7s 1 -#define SUPPORT_ARCH_armv6m 1 -#define SUPPORT_ARCH_armv7m 1 -#define SUPPORT_ARCH_armv7em 1 -#define SUPPORT_ARCH_armv8 1 #define SUPPORT_ARCH_arm64 1 -#define SUPPORT_ARCH_arm64v8 1 +#define SUPPORT_ARCH_arm64e 1 +#define SUPPORT_ARCH_arm64_32 1 #define SUPPORT_ARCH_i386 1 #define SUPPORT_ARCH_x86_64 1 #define SUPPORT_ARCH_x86_64h 1 +#define SUPPORT_ARCH_armv6m 1 +#define SUPPORT_ARCH_armv7k 1 +#define SUPPORT_ARCH_armv7m 1 +#define SUPPORT_ARCH_armv7em 1 #define SUPPORT_APPLE_TV 1 -#define ALL_SUPPORTED_ARCHS "armv4t armv5 armv6 armv7 armv7f armv7k armv7s armv6m armv7m armv7em armv8 arm64 arm64v8 i386 x86_64 x86_64h (tvOS)" +#define ALL_SUPPORTED_ARCHS "armv6 armv7 armv7s arm64 arm64e arm64_32 i386 x86_64 x86_64h armv6m armv7k armv7m armv7em (tvOS)" #define BITCODE_XAR_VERSION "1.0" diff --git a/cctools/ld64/src/create_configure b/cctools/ld64/src/create_configure index 9ce654d..b2b7017 100755 --- a/cctools/ld64/src/create_configure +++ b/cctools/ld64/src/create_configure @@ -11,13 +11,13 @@ else fi if [ -z "${RC_SUPPORTED_ARCHS}" ]; then - RC_SUPPORTED_ARCHS="i386 x86_64 x86_64h armv6 armv7 armv7s armv7m armv7k arm64" + RC_SUPPORTED_ARCHS="i386 x86_64 x86_64h armv6 armv7 armv7s armv7m armv7k arm64 arm64e" fi for ANARCH in ${RC_SUPPORTED_ARCHS} do - KNOWN_ARCHS=",armv4t,armv5,armv6,armv7,armv7f,armv7k,armv7s,armv6m,armv7m,armv7em,armv8,arm64,arm64v8,i386,x86_64,x86_64h," - FOUND=`echo "$KNOWN_ARCHS" | grep ",$ANARCH,"` + KNOWN_ARCHS=",armv4t,armv5,armv6,armv7,armv7f,armv7k,armv7s,armv6m,armv7m,armv7em,armv8,arm64,arm64v8,arm64e,i386,x86_64,x86_64h," + FOUND=`echo "$KNOWN_ARCHS" | grep ",$ANARCH,"` if [ $FOUND ]; then echo "#define SUPPORT_ARCH_$ANARCH 1" >> ${DERIVED_FILE_DIR}/configure.h else @@ -25,24 +25,25 @@ do fi done -if [ -n "${RC_HIDE_TIDE}" ]; then - echo "#define ALL_SUPPORTED_ARCHS \"${RC_SUPPORTED_ARCHS}\"" >> ${DERIVED_FILE_DIR}/configure.h - echo "#define SUPPORT_APPLE_TV 0" >> ${DERIVED_FILE_DIR}/configure.h -else - if [ -n "${DT_VARIANT}" -a "${DT_VARIANT}" != "PONDEROSA" ]; then - echo "#define ALL_SUPPORTED_ARCHS \"${RC_SUPPORTED_ARCHS}\"" >> ${DERIVED_FILE_DIR}/configure.h - echo "#define SUPPORT_APPLE_TV 0" >> ${DERIVED_FILE_DIR}/configure.h - else - echo "#define ALL_SUPPORTED_ARCHS \"${RC_SUPPORTED_ARCHS} (tvOS)\"" >> ${DERIVED_FILE_DIR}/configure.h - echo "#define SUPPORT_APPLE_TV 1" >> ${DERIVED_FILE_DIR}/configure.h - fi -fi +echo "#define ALL_SUPPORTED_ARCHS \"${RC_SUPPORTED_ARCHS}\"" >> ${DERIVED_FILE_DIR}/configure.h if [ -f "${DT_TOOLCHAIN_DIR}/usr/lib/libswiftDemangle.dylib" ]; then - echo "-Wl,-lazy_library,${DT_TOOLCHAIN_DIR}/usr/lib/libswiftDemangle.dylib" > ${DERIVED_FILE_DIR}/linkExtras + echo "${DT_TOOLCHAIN_DIR}/usr/lib/libswiftDemangle.dylib" > ${DERIVED_FILE_DIR}/linkExtras echo "#define DEMANGLE_SWIFT 1" >> ${DERIVED_FILE_DIR}/configure.h else echo "" > ${DERIVED_FILE_DIR}/linkExtras fi echo "#define BITCODE_XAR_VERSION \"1.0\"" >> ${DERIVED_FILE_DIR}/configure.h + +if [ -n "${RC_ProjectSourceVersion}" ]; then + echo "#define LD64_VERSION_NUM ${RC_ProjectSourceVersion}" >> ${DERIVED_FILE_DIR}/configure.h +else + echo "#define LD64_VERSION_NUM 0" >> ${DERIVED_FILE_DIR}/configure.h +fi + +if [ -n "${LD_FORCE_16KB_PAGES}" ]; then + echo "#define LD_PAGE_SIZE 0x4000" >> ${DERIVED_FILE_DIR}/configure.h +else + echo "#define LD_PAGE_SIZE 0x1000" >> ${DERIVED_FILE_DIR}/configure.h +fi diff --git a/cctools/ld64/src/ld/Architectures.hpp b/cctools/ld64/src/ld/Architectures.hpp index fdf795b..76a4d7c 100644 --- a/cctools/ld64/src/ld/Architectures.hpp +++ b/cctools/ld64/src/ld/Architectures.hpp @@ -61,6 +61,18 @@ struct arm64 typedef Pointer64 P; }; +// ld64-port: I am not sure if this is correct. +struct arm64e +{ + typedef Pointer64 P; +}; + +// ld64-port: Nor am I sure if this is correct either... +struct arm64_32 +{ + typedef Pointer32 P; +}; + #endif // __ARCHITECTURES__ diff --git a/cctools/ld64/src/ld/Bitcode.hpp b/cctools/ld64/src/ld/Bitcode.hpp index 68822d2..f44efc0 100644 --- a/cctools/ld64/src/ld/Bitcode.hpp +++ b/cctools/ld64/src/ld/Bitcode.hpp @@ -32,6 +32,7 @@ namespace ld { class Bitcode { public: Bitcode(const uint8_t* content, uint32_t size) : _content(content), _size(size) { } + virtual ~Bitcode() { } virtual bool isMarker() const { return _size <= 1 ; } virtual const uint8_t* getContent() const { return _content; } diff --git a/cctools/ld64/src/ld/HeaderAndLoadCommands.hpp b/cctools/ld64/src/ld/HeaderAndLoadCommands.hpp index cbcee62..b385403 100644 --- a/cctools/ld64/src/ld/HeaderAndLoadCommands.hpp +++ b/cctools/ld64/src/ld/HeaderAndLoadCommands.hpp @@ -28,6 +28,7 @@ #include #include #include +#include // ld64-port #include #include @@ -63,6 +64,9 @@ public: virtual const uint8_t* getUUID() const = 0; virtual bool bitcodeBundleCommand(uint64_t& cmdOffset, uint64_t& cmdEnd, uint64_t& sectOffset, uint64_t& sectEnd) const = 0; + virtual void linkeditCmdInfo(uint64_t& offset, uint64_t& size) const = 0; + virtual void symbolTableCmdInfo(uint64_t& offset, uint64_t& size) const = 0; + }; template @@ -77,6 +81,7 @@ public: virtual const char* name() const { return "mach-o header and load commands"; } virtual uint64_t size() const; virtual uint64_t objectAddress() const { return _address; } + virtual void copyRawContent(uint8_t buffer[]) const; // overrides of HeaderAndLoadCommandsAbtract @@ -85,7 +90,10 @@ public: virtual const uint8_t* getUUID() const { return &_uuid[0]; } virtual bool bitcodeBundleCommand(uint64_t& cmdOffset, uint64_t& cmdEnd, uint64_t& sectOffset, uint64_t& sectEnd) const; - + virtual void linkeditCmdInfo(uint64_t& offset, uint64_t& size) const; + virtual void symbolTableCmdInfo(uint64_t& offset, uint64_t& size) const; + + private: typedef typename A::P P; typedef typename A::P::E E; @@ -102,15 +110,18 @@ private: uint32_t commandsCount() const; uint32_t threadLoadCommandSize() const; uint8_t* copySingleSegmentLoadCommand(uint8_t* p) const; - uint8_t* copySegmentLoadCommands(uint8_t* p) const; + uint8_t* copySegmentLoadCommands(uint8_t* p, uint8_t* base) const; uint8_t* copyDyldInfoLoadCommand(uint8_t* p) const; - uint8_t* copySymbolTableLoadCommand(uint8_t* p) const; + uint8_t* copyExportsTrieLoadCommand(uint8_t* p) const; + uint8_t* copyChainedFixupsLoadCommand(uint8_t* p) const; + uint8_t* copySymbolTableLoadCommand(uint8_t* p, uint8_t* base) const; uint8_t* copyDynamicSymbolTableLoadCommand(uint8_t* p) const; uint8_t* copyDyldLoadCommand(uint8_t* p) const; uint8_t* copyDylibIDLoadCommand(uint8_t* p) const; uint8_t* copyRoutinesLoadCommand(uint8_t* p) const; uint8_t* copyUUIDLoadCommand(uint8_t* p) const; - uint8_t* copyVersionLoadCommand(uint8_t* p) const; + uint8_t* copyVersionLoadCommand(uint8_t* p, ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion) const; + uint8_t* copyBuildVersionLoadCommand(uint8_t* p, ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion) const; uint8_t* copySourceVersionLoadCommand(uint8_t* p) const; uint8_t* copyThreadsLoadCommand(uint8_t* p) const; uint8_t* copyEntryPointLoadCommand(uint8_t* p) const; @@ -154,6 +165,10 @@ private: bool _hasDataInCodeLoadCommand; bool _hasSourceVersionLoadCommand; bool _hasOptimizationHints; + bool _hasExportsTrieLoadCommand; + bool _hasChainedFixupsLoadCommand; + bool _simulatorSupportDylib; + ld::VersionSet _platforms; uint32_t _dylibLoadCommmandsCount; uint32_t _allowableClientLoadCommmandsCount; uint32_t _dyldEnvironExrasCount; @@ -161,7 +176,10 @@ private: std::vector _subUmbrellaNames; uint8_t _uuid[16]; mutable macho_uuid_command

* _uuidCmdInOutputBuffer; + mutable uint32_t _linkeditCmdOffset; + mutable uint32_t _symboltableCmdOffset; std::vector< std::vector > _linkerOptions; + std::unordered_set& _toolsVersions; static ld::Section _s_section; static ld::Section _s_preload_section; @@ -179,8 +197,9 @@ HeaderAndLoadCommandsAtom::HeaderAndLoadCommandsAtom(const Options& opts, ld: ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified, ld::Atom::symbolTableNotIn, false, false, false, - (opts.outputKind() == Options::kPreload) ? ld::Atom::Alignment(0) : ld::Atom::Alignment(12) ), - _options(opts), _state(state), _writer(writer), _address(0), _uuidCmdInOutputBuffer(NULL) + (opts.outputKind() == Options::kPreload) ? ld::Atom::Alignment(0) : ld::Atom::Alignment(log2(opts.segmentAlignment())) ), + _options(opts), _state(state), _writer(writer), _address(0), _uuidCmdInOutputBuffer(NULL), _linkeditCmdOffset(0), _symboltableCmdOffset(0), + _toolsVersions(state.toolsVersions) { bzero(_uuid, 16); _hasDyldInfoLoadCommand = opts.makeCompressedDyldInfo(); @@ -190,10 +209,13 @@ HeaderAndLoadCommandsAtom::HeaderAndLoadCommandsAtom(const Options& opts, ld: _hasEntryPointLoadCommand = _options.needsEntryPointLoadCommand(); _hasEncryptionLoadCommand = opts.makeEncryptable(); _hasSplitSegInfoLoadCommand = opts.sharedRegionEligible(); - _hasRoutinesLoadCommand = (opts.initFunctionName() != NULL); + _hasRoutinesLoadCommand = (opts.initFunctionName() != NULL) && (state.entryPoint != NULL); _hasSymbolTableLoadCommand = true; _hasUUIDLoadCommand = (opts.UUIDMode() != Options::kUUIDNone); _hasOptimizationHints = (_state.someObjectHasOptimizationHints && (opts.outputKind() == Options::kObjectFile)); + _hasExportsTrieLoadCommand = opts.makeChainedFixups() && opts.dyldLoadsOutput(); + _hasChainedFixupsLoadCommand = opts.makeChainedFixups() && opts.dyldLoadsOutput(); + switch ( opts.outputKind() ) { case Options::kDynamicExecutable: case Options::kDynamicLibrary: @@ -212,15 +234,13 @@ HeaderAndLoadCommandsAtom::HeaderAndLoadCommandsAtom(const Options& opts, ld: break; } } - for (CStringSet::const_iterator it = _state.linkerOptionFrameworks.begin(); it != _state.linkerOptionFrameworks.end(); ++it) { - const char* frameWorkName = *it; + for (const char* frameworkName : _state.unprocessedLinkerOptionFrameworks) { std::vector* lo = new std::vector(); lo->push_back("-framework"); - lo->push_back(frameWorkName); + lo->push_back(frameworkName); _linkerOptions.push_back(*lo); }; - for (CStringSet::const_iterator it = _state.linkerOptionLibraries.begin(); it != _state.linkerOptionLibraries.end(); ++it) { - const char* libName = *it; + for (const char* libName : _state.unprocessedLinkerOptionLibraries) { std::vector* lo = new std::vector(); char * s = new char[strlen(libName)+3]; strcpy(s, "-l"); @@ -238,9 +258,11 @@ HeaderAndLoadCommandsAtom::HeaderAndLoadCommandsAtom(const Options& opts, ld: } _hasRPathLoadCommands = (_options.rpaths().size() != 0); _hasSubFrameworkLoadCommand = (_options.umbrellaName() != NULL); - _hasVersionLoadCommand = _options.addVersionLoadCommand() || - (!state.objectFileFoundWithNoVersion && (_options.outputKind() == Options::kObjectFile) - && ((_options.platform() != Options::kPlatformUnknown) || (state.derivedPlatformLoadCommand != 0)) ); + _platforms = _options.platforms(); + _hasVersionLoadCommand = _options.addVersionLoadCommand(); + // in ld -r mode, only if all input .o files have load command, then add one to output + if ( !_hasVersionLoadCommand && (_options.outputKind() == Options::kObjectFile) && !state.objectFileFoundWithNoVersion ) + _hasVersionLoadCommand = true; _hasFunctionStartsLoadCommand = _options.addFunctionStarts(); _hasDataInCodeLoadCommand = _options.addDataInCodeInfo(); _hasSourceVersionLoadCommand = _options.needsSourceVersionLoadCommand(); @@ -368,10 +390,25 @@ bool HeaderAndLoadCommandsAtom::bitcodeBundleCommand(uint64_t &cmdOffset, uin return false; } +template +void HeaderAndLoadCommandsAtom::linkeditCmdInfo(uint64_t &offset, uint64_t &size) const +{ + offset = _linkeditCmdOffset; + size = sizeof(macho_segment_command

); +} + +template +void HeaderAndLoadCommandsAtom::symbolTableCmdInfo(uint64_t &offset, uint64_t &size) const +{ + offset = _symboltableCmdOffset; + size = sizeof(macho_symtab_command

); +} + + template uint64_t HeaderAndLoadCommandsAtom::size() const { - uint32_t sz = sizeof(macho_header

); + __block uint32_t sz = sizeof(macho_header

); sz += sizeof(macho_segment_command

) * this->segmentCount(); sz += sizeof(macho_section

) * this->nonHiddenSectionCount(); @@ -381,7 +418,13 @@ uint64_t HeaderAndLoadCommandsAtom::size() const if ( _hasDyldInfoLoadCommand ) sz += sizeof(macho_dyld_info_command

); - + + if ( _hasChainedFixupsLoadCommand ) + sz += sizeof(linkedit_data_command); + + if ( _hasExportsTrieLoadCommand ) + sz += sizeof(linkedit_data_command); + if ( _hasSymbolTableLoadCommand ) sz += sizeof(macho_symtab_command

); @@ -397,9 +440,18 @@ uint64_t HeaderAndLoadCommandsAtom::size() const if ( _hasUUIDLoadCommand ) sz += sizeof(macho_uuid_command

); - if ( _hasVersionLoadCommand ) - sz += sizeof(macho_version_min_command

); - + if ( _hasVersionLoadCommand ) { + if ( _hasVersionLoadCommand ) { + _options.platforms().forEach(^(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop) { + if (_options.shouldUseBuildVersion(platform, minVersion)) { + sz += alignedSize(sizeof(macho_build_version_command

) + sizeof(macho_build_tool_version

)*_toolsVersions.size()); + } else { + sz += sizeof(macho_version_min_command

); + } + }); + } + } + if ( _hasSourceVersionLoadCommand ) sz += sizeof(macho_source_version_command

); @@ -485,6 +537,12 @@ uint32_t HeaderAndLoadCommandsAtom::commandsCount() const if ( _hasDyldInfoLoadCommand ) ++count; + if ( _hasChainedFixupsLoadCommand ) + ++count; + + if ( _hasExportsTrieLoadCommand ) + ++count; + if ( _hasSymbolTableLoadCommand ) ++count; @@ -499,9 +557,10 @@ uint32_t HeaderAndLoadCommandsAtom::commandsCount() const if ( _hasUUIDLoadCommand ) ++count; - - if ( _hasVersionLoadCommand ) - ++count; + + if ( _hasVersionLoadCommand ) { + count += _options.platforms().count(); + } if ( _hasSourceVersionLoadCommand ) ++count; @@ -609,10 +668,6 @@ uint32_t HeaderAndLoadCommandsAtom::flags() const bits |= MH_WEAK_DEFINES; if ( _writer.usesWeakExternalSymbols || _state.hasWeakExternalSymbols ) bits |= MH_BINDS_TO_WEAK; - if ( _options.prebind() ) - bits |= MH_PREBOUND; - if ( _options.splitSeg() ) - bits |= MH_SPLIT_SEGS; if ( (_options.outputKind() == Options::kDynamicLibrary) && _writer._noReExportedDylibs && _options.useSimplifiedDylibReExports() ) { @@ -628,6 +683,8 @@ uint32_t HeaderAndLoadCommandsAtom::flags() const bits |= MH_NO_HEAP_EXECUTION; if ( _options.markAppExtensionSafe() && (_options.outputKind() == Options::kDynamicLibrary) ) bits |= MH_APP_EXTENSION_SAFE; + if (_options.isSimulatorSupportDylib()) + bits |= MH_SIM_SUPPORT; } if ( _options.hasExecutableStack() ) bits |= MH_ALLOW_STACK_EXECUTION; @@ -646,7 +703,6 @@ template <> uint32_t HeaderAndLoadCommandsAtom::cpuType() const { return CP template <> uint32_t HeaderAndLoadCommandsAtom::cpuType() const { return CPU_TYPE_ARM64; } - template <> uint32_t HeaderAndLoadCommandsAtom::cpuSubType() const { @@ -656,7 +712,7 @@ uint32_t HeaderAndLoadCommandsAtom::cpuSubType() const template <> uint32_t HeaderAndLoadCommandsAtom::cpuSubType() const { - if ( (_options.outputKind() == Options::kDynamicExecutable) && (_state.cpuSubType == CPU_SUBTYPE_X86_64_ALL) && (_options.macosxVersionMin() >= ld::mac10_5) ) + if ( (_options.outputKind() == Options::kDynamicExecutable) && (_state.cpuSubType == CPU_SUBTYPE_X86_64_ALL) && _options.platforms().minOS(ld::mac10_5) ) return (_state.cpuSubType | 0x80000000); else return _state.cpuSubType; @@ -671,7 +727,7 @@ uint32_t HeaderAndLoadCommandsAtom::cpuSubType() const template <> uint32_t HeaderAndLoadCommandsAtom::cpuSubType() const { - return CPU_SUBTYPE_ARM64_ALL; + return _state.cpuSubType; } @@ -715,7 +771,7 @@ uint8_t* HeaderAndLoadCommandsAtom::copySingleSegmentLoadCommand(uint8_t* p) if ( cmd->fileoff() == 0 ) cmd->set_fileoff(fsect->fileOffset); cmd->set_vmsize(fsect->address + fsect->size - cmd->vmaddr()); - if ( (fsect->type() != ld::Section::typeZeroFill) && (fsect->type() != ld::Section::typeTentativeDefs) ) + if ( !sectionTakesNoDiskSpace(fsect) ) cmd->set_filesize(fsect->fileOffset + fsect->size - cmd->fileoff()); ++msect; } @@ -730,13 +786,16 @@ struct SegInfo { uint32_t nonSectCreateSections; uint32_t maxProt; uint32_t initProt; + uint32_t flags; std::vector sections; }; SegInfo::SegInfo(const char* n, const Options& opts) - : segName(n), nonHiddenSectionCount(0), nonSectCreateSections(0), maxProt(opts.maxSegProtection(n)), initProt(opts.initialSegProtection(n)) -{ + : segName(n), nonHiddenSectionCount(0), nonSectCreateSections(0), maxProt(opts.maxSegProtection(n)), initProt(opts.initialSegProtection(n)), flags(0) +{ + if ( opts.readOnlyDataSegment(n) ) + flags = SG_READ_ONLY; } @@ -815,6 +874,9 @@ uint32_t HeaderAndLoadCommandsAtom::sectionFlags(ld::Internal::FinalSection* return S_DTRACE_DOF; case ld::Section::typeUnwindInfo: return S_REGULAR; + case ld::Section::typeThreadStarts: + case ld::Section::typeChainStarts: + return S_REGULAR; case ld::Section::typeObjCClassRefs: case ld::Section::typeObjC2CategoryList: return S_REGULAR | S_ATTR_NO_DEAD_STRIP; @@ -881,6 +943,8 @@ uint32_t HeaderAndLoadCommandsAtom::sectionFlags(ld::Internal::FinalSection* return S_REGULAR | S_ATTR_DEBUG; case ld::Section::typeSectCreate: return S_REGULAR; + case ld::Section::typeInitOffsets: + return S_INIT_FUNC_OFFSETS; } return S_REGULAR; } @@ -905,7 +969,7 @@ bool HeaderAndLoadCommandsAtom::sectionTakesNoDiskSpace(ld::Internal::FinalSe template -uint8_t* HeaderAndLoadCommandsAtom::copySegmentLoadCommands(uint8_t* p) const +uint8_t* HeaderAndLoadCommandsAtom::copySegmentLoadCommands(uint8_t* p, uint8_t* base) const { // group sections into segments std::vector segs; @@ -964,8 +1028,9 @@ uint8_t* HeaderAndLoadCommandsAtom::copySegmentLoadCommands(uint8_t* p) const segCmd->set_maxprot(si.maxProt); segCmd->set_initprot(si.initProt); segCmd->set_nsects(si.nonHiddenSectionCount); - segCmd->set_flags(si.nonSectCreateSections ? 0 : SG_NORELOC); // FIXME, really should check all References - + segCmd->set_flags(si.flags | (si.nonSectCreateSections ? 0 : SG_NORELOC)); // FIXME, really should check all References + if ( strcmp(segCmd->segname(), "__LINKEDIT") == 0 ) + _linkeditCmdOffset = p - base; p += sizeof(macho_segment_command

); macho_section

* msect = (macho_section

*)p; for (std::vector::iterator sit = si.sections.begin(); sit != si.sections.end(); ++sit) { @@ -993,8 +1058,9 @@ uint8_t* HeaderAndLoadCommandsAtom::copySegmentLoadCommands(uint8_t* p) const template -uint8_t* HeaderAndLoadCommandsAtom::copySymbolTableLoadCommand(uint8_t* p) const +uint8_t* HeaderAndLoadCommandsAtom::copySymbolTableLoadCommand(uint8_t* p, uint8_t* base) const { + _symboltableCmdOffset = p - base; // build LC_SYMTAB command macho_symtab_command

* symbolTableCmd = (macho_symtab_command

*)p; symbolTableCmd->set_cmd(LC_SYMTAB); @@ -1078,6 +1144,34 @@ uint8_t* HeaderAndLoadCommandsAtom::copyDyldInfoLoadCommand(uint8_t* p) const return p + sizeof(macho_dyld_info_command

); } +template +uint8_t* HeaderAndLoadCommandsAtom::copyExportsTrieLoadCommand(uint8_t* p) const +{ + // build LC_DYLD_EXPORTS_TRIE command + linkedit_data_command* cmd = (linkedit_data_command*)p; + + cmd->cmd = LC_DYLD_EXPORTS_TRIE; + cmd->cmdsize = sizeof(linkedit_data_command); + cmd->dataoff = _writer.exportSection->fileOffset; + cmd->datasize = _writer.exportSection->size; + + return p + sizeof(linkedit_data_command); +} + +template +uint8_t* HeaderAndLoadCommandsAtom::copyChainedFixupsLoadCommand(uint8_t* p) const +{ + // build LC_DYLD_CHAINED_FIXUPS command + linkedit_data_command* cmd = (linkedit_data_command*)p; + + cmd->cmd = LC_DYLD_CHAINED_FIXUPS; + cmd->cmdsize = sizeof(linkedit_data_command); + cmd->dataoff = _writer.chainInfoSection->fileOffset; + cmd->datasize = _writer.chainInfoSection->size; + + return p + sizeof(linkedit_data_command); +} + template uint8_t* HeaderAndLoadCommandsAtom::copyDyldLoadCommand(uint8_t* p) const @@ -1145,47 +1239,46 @@ uint8_t* HeaderAndLoadCommandsAtom::copyUUIDLoadCommand(uint8_t* p) const template -uint8_t* HeaderAndLoadCommandsAtom::copyVersionLoadCommand(uint8_t* p) const +uint8_t* HeaderAndLoadCommandsAtom::copyVersionLoadCommand(uint8_t* p, ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion) const { macho_version_min_command

* cmd = (macho_version_min_command

*)p; - switch (_options.platform()) { - case Options::kPlatformUnknown: - assert(_state.derivedPlatformLoadCommand != 0 && "unknown platform"); - cmd->set_cmd(_state.derivedPlatformLoadCommand); - cmd->set_cmdsize(sizeof(macho_version_min_command

)); - cmd->set_version(_state.minOSVersion); - cmd->set_sdk(0); - break; - case Options::kPlatformOSX: - cmd->set_cmd(LC_VERSION_MIN_MACOSX); - cmd->set_cmdsize(sizeof(macho_version_min_command

)); - cmd->set_version(_state.minOSVersion); - cmd->set_sdk(_options.sdkVersion()); - break; - case Options::kPlatformiOS: - cmd->set_cmd(LC_VERSION_MIN_IPHONEOS); - cmd->set_cmdsize(sizeof(macho_version_min_command

)); - cmd->set_version(_state.minOSVersion); - cmd->set_sdk(_options.sdkVersion()); - break; - case Options::kPlatformWatchOS: - cmd->set_cmd(LC_VERSION_MIN_WATCHOS); - cmd->set_cmdsize(sizeof(macho_version_min_command

)); - cmd->set_version(_state.minOSVersion); - cmd->set_sdk(_options.sdkVersion()); - break; -#if SUPPORT_APPLE_TV - case Options::kPlatform_tvOS: - cmd->set_cmd(LC_VERSION_MIN_TVOS); - cmd->set_cmdsize(sizeof(macho_version_min_command

)); - cmd->set_version(_state.minOSVersion); - cmd->set_sdk(_options.sdkVersion()); - break; -#endif - } + const PlatformInfo& info = platformInfo(platform); + assert(info.loadCommandIfNotUsingBuildVersionLC != 0 && "platform requires LC_BUILD_VERSION"); + cmd->set_cmd(info.loadCommandIfNotUsingBuildVersionLC); + cmd->set_cmdsize(sizeof(macho_version_min_command

)); + cmd->set_version(minVersion); + cmd->set_sdk(sdkVersion); return p + sizeof(macho_version_min_command

); } + + +template + uint8_t* HeaderAndLoadCommandsAtom::copyBuildVersionLoadCommand(uint8_t* p, ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion) const +{ + macho_build_version_command

* cmd = (macho_build_version_command

*)p; + + // temp hack until iOSMac SDK version plumbed through + if (platform == ld::Platform::iOSMac) + sdkVersion = 0x000D0000; + + cmd->set_cmd(LC_BUILD_VERSION); + cmd->set_cmdsize(alignedSize(sizeof(macho_build_version_command

) + sizeof(macho_build_tool_version

)*_toolsVersions.size())); + cmd->set_platform((uint32_t)platform); + cmd->set_minos(minVersion); + cmd->set_sdk(sdkVersion); + cmd->set_ntools(_toolsVersions.size()); + macho_build_tool_version

* tools = (macho_build_tool_version

*)(p + sizeof(macho_build_version_command

)); + for (uint64_t tool : _toolsVersions) { + tools->set_tool((uint64_t)tool >> 32); + tools->set_version(tool & 0xFFFFFFFF); + ++tools; + } + + return p + cmd->cmdsize(); +} + + template uint8_t* HeaderAndLoadCommandsAtom::copySourceVersionLoadCommand(uint8_t* p) const { @@ -1337,14 +1430,21 @@ uint8_t* HeaderAndLoadCommandsAtom::copyDylibLoadCommand(uint8_t* p, const ld { uint32_t sz = alignedSize(sizeof(macho_dylib_command

) + strlen(dylib->installPath()) + 1); macho_dylib_command

* cmd = (macho_dylib_command

*)p; + bool weakLink = dylib->forcedWeakLinked() || dylib->allSymbolsAreWeakImported(); + bool upward = dylib->willBeUpwardDylib() && _options.useUpwardDylibs(); + bool reExport = dylib->willBeReExported() && _options.useSimplifiedDylibReExports(); + if ( weakLink && upward ) + warning("cannot weak upward link. Dropping weak for %s", dylib->installPath()); + if ( weakLink && reExport ) + warning("cannot weak re-export a dylib. Dropping weak for %s", dylib->installPath()); if ( dylib->willBeLazyLoadedDylib() ) cmd->set_cmd(LC_LAZY_LOAD_DYLIB); - else if ( dylib->forcedWeakLinked() || dylib->allSymbolsAreWeakImported() ) - cmd->set_cmd(LC_LOAD_WEAK_DYLIB); - else if ( dylib->willBeReExported() && _options.useSimplifiedDylibReExports() ) + else if ( reExport ) cmd->set_cmd(LC_REEXPORT_DYLIB); - else if ( dylib->willBeUpwardDylib() && _options.useUpwardDylibs() ) + else if ( upward ) cmd->set_cmd(LC_LOAD_UPWARD_DYLIB); + else if ( weakLink ) + cmd->set_cmd(LC_LOAD_WEAK_DYLIB); else cmd->set_cmd(LC_LOAD_DYLIB); cmd->set_cmdsize(sz); @@ -1487,7 +1587,6 @@ uint8_t* HeaderAndLoadCommandsAtom::copyOptimizationHintsLoadCommand(uint8_t* return p + sizeof(macho_linkedit_data_command

); } - template void HeaderAndLoadCommandsAtom::copyRawContent(uint8_t buffer[]) const { @@ -1504,12 +1603,12 @@ void HeaderAndLoadCommandsAtom::copyRawContent(uint8_t buffer[]) const mh->set_flags(this->flags()); // copy load commands - uint8_t* p = &buffer[sizeof(macho_header

)]; + __block uint8_t* p = &buffer[sizeof(macho_header

)]; if ( _options.outputKind() == Options::kObjectFile ) p = this->copySingleSegmentLoadCommand(p); else - p = this->copySegmentLoadCommands(p); + p = this->copySegmentLoadCommands(p, buffer); if ( _hasDylibIDLoadCommand ) p = this->copyDylibIDLoadCommand(p); @@ -1517,8 +1616,14 @@ void HeaderAndLoadCommandsAtom::copyRawContent(uint8_t buffer[]) const if ( _hasDyldInfoLoadCommand ) p = this->copyDyldInfoLoadCommand(p); + if ( _hasChainedFixupsLoadCommand ) + p = this->copyChainedFixupsLoadCommand(p); + + if ( _hasExportsTrieLoadCommand ) + p = this->copyExportsTrieLoadCommand(p); + if ( _hasSymbolTableLoadCommand ) - p = this->copySymbolTableLoadCommand(p); + p = this->copySymbolTableLoadCommand(p, buffer); if ( _hasDynamicSymbolTableLoadCommand ) p = this->copyDynamicSymbolTableLoadCommand(p); @@ -1531,9 +1636,16 @@ void HeaderAndLoadCommandsAtom::copyRawContent(uint8_t buffer[]) const if ( _hasUUIDLoadCommand ) p = this->copyUUIDLoadCommand(p); - - if ( _hasVersionLoadCommand ) - p = this->copyVersionLoadCommand(p); + + if ( _hasVersionLoadCommand ) { + _options.platforms().forEach(^(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop) { + if (_options.shouldUseBuildVersion(platform, minVersion)) { + p = this->copyBuildVersionLoadCommand(p, platform, minVersion, sdkVersion); + } else { + p = this->copyVersionLoadCommand(p, platform, minVersion, sdkVersion); + } + }); + } if ( _hasSourceVersionLoadCommand ) p = this->copySourceVersionLoadCommand(p); diff --git a/cctools/ld64/src/ld/InputFiles.cpp b/cctools/ld64/src/ld/InputFiles.cpp index d810506..f74000e 100644 --- a/cctools/ld64/src/ld/InputFiles.cpp +++ b/cctools/ld64/src/ld/InputFiles.cpp @@ -28,7 +28,11 @@ #include #include #include +#ifdef __APPLE__ #include +#else // ld64-port +#include // for std::thread +#endif #include #include #include @@ -40,18 +44,8 @@ #include #include #include -#include #include -// ld64-port -#ifdef __linux__ -#ifndef __USE_GNU -#define __USE_GNU -#endif -#include -#endif -// ld64-port end - #include #include #include @@ -186,26 +180,49 @@ private: ld::Section CustomStackAtom::_s_section("__UNIXSTACK", "__stack", ld::Section::typeStack, true); +static bool isCompilerSupportLib(const char* path) { + const char* libName = strrchr(path, '/'); + return ( (libName != NULL) && (strncmp(libName, "/libclang_rt", 12) == 0) ); +} -const char* InputFiles::fileArch(const uint8_t* p, unsigned len) + +const char* InputFiles::extractFileInfo(const uint8_t* p, unsigned len, const char* path, ld::Platform& platform) { + platform = ld::Platform::unknown; + const char* result = mach_o::relocatable::archName(p); - if ( result != NULL ) - return result; + if ( result != NULL ) { + cpu_type_t type; + cpu_subtype_t subtype; + uint32_t ignore; + mach_o::relocatable::isObjectFile(p, len, &type, &subtype, &platform, &ignore); + return result; + } result = mach_o::dylib::archName(p); - if ( result != NULL ) + if ( result != NULL ) { + cpu_type_t type; + cpu_subtype_t subtype; + uint32_t ignore; + mach_o::dylib::isDylibFile(p, len, &type, &subtype, &platform, &ignore); return result; + } #ifdef LTO_SUPPORT result = lto::archName(p, len); if ( result != NULL ) return result; #endif /* LTO_SUPPORT */ - - if ( strncmp((const char*)p, "!\n", 8) == 0 ) - return "archive"; - + + const char* archiveArchName; + if ( ::archive::isArchiveFile(p, len, &platform, &archiveArchName) ) + return archiveArchName; + +#ifdef TAPI_SUPPORT + if ( textstub::dylib::isTextStubFile(p, len, path) ) + return "text-stub"; +#endif + char *unsupported = (char *)malloc(128); strcpy(unsupported, "unsupported file format ("); for (unsigned i=0; igetInstallName().c_str(), info.path); + return file; + } +#endif /* TAPI_SUPPORT */ // map in whole file - uint64_t len = info.fileLen; + struct stat stat_buf; int fd = ::open(info.path, O_RDONLY, 0); if ( fd == -1 ) throwf("can't open file, errno=%d", errno); - if ( info.fileLen < 20 ) - throwf("file too small (length=%llu)", info.fileLen); - - uint8_t* p = (uint8_t*)::mmap(NULL, info.fileLen, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0); + if ( ::fstat(fd, &stat_buf) != 0 ) + throwf("fstat(%s) failed, errno=%d\n", info.path, errno); + if ( stat_buf.st_size < 20 ) + throwf("file too small (length=%llu)", stat_buf.st_size); + int64_t len = stat_buf.st_size; + uint8_t* p = (uint8_t*)::mmap(NULL, stat_buf.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0); if ( p == (uint8_t*)(-1) ) throwf("can't map file, errno=%d", errno); @@ -243,18 +274,16 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib const struct fat_arch* archs = (struct fat_arch*)(p + sizeof(struct fat_header)); bool sliceFound = false; sliceCount = OSSwapBigToHostInt32(fh->nfat_arch); - if ( _options.preferSubArchitecture() ) { - // first try to find a slice that match cpu-type and cpu-sub-type - for (uint32_t i=0; i < sliceCount; ++i) { - if ( (OSSwapBigToHostInt32(archs[i].cputype) == (uint32_t)_options.architecture()) - && (OSSwapBigToHostInt32(archs[i].cpusubtype) == (uint32_t)_options.subArchitecture()) ) { - sliceToUse = i; - sliceFound = true; - break; - } + // first try to find a slice that match cpu-type and cpu-sub-type + for (uint32_t i=0; i < sliceCount; ++i) { + if ( (OSSwapBigToHostInt32(archs[i].cputype) == (uint32_t)_options.architecture()) + && ((OSSwapBigToHostInt32(archs[i].cpusubtype) & ~CPU_SUBTYPE_MASK) == (uint32_t)_options.subArchitecture()) ) { + sliceToUse = i; + sliceFound = true; + break; } } - if ( !sliceFound ) { + if ( !sliceFound && _options.allowSubArchitectureMismatches() ) { // look for any slice that matches just cpu-type for (uint32_t i=0; i < sliceCount; ++i) { if ( OSSwapBigToHostInt32(archs[i].cputype) == (uint32_t)_options.architecture() ) { @@ -264,28 +293,39 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib } } } + if ( !sliceFound ) { + // Look for a fallback slice. + for (uint32_t i = 0; i < sliceCount; ++i) { + if ( OSSwapBigToHostInt32(archs[i].cputype) == (uint32_t)_options.fallbackArchitecture() && + OSSwapBigToHostInt32(archs[i].cpusubtype) == (uint32_t)_options.fallbackSubArchitecture() ) { + sliceToUse = i; + sliceFound = true; + break; + } + } + } if ( sliceFound ) { uint32_t fileOffset = OSSwapBigToHostInt32(archs[sliceToUse].offset); len = OSSwapBigToHostInt32(archs[sliceToUse].size); - if ( fileOffset+len > info.fileLen ) { + if ( fileOffset+len > stat_buf.st_size ) { // file size was read awhile ago. If file is being written, wait a second to see if big enough now sleep(1); - uint64_t newFileLen = info.fileLen; + int64_t newFileLen = stat_buf.st_size; struct stat statBuffer; if ( stat(info.path, &statBuffer) == 0 ) { newFileLen = statBuffer.st_size; } if ( fileOffset+len > newFileLen ) { throwf("truncated fat file. Slice from %u to %llu is past end of file with length %llu", - fileOffset, fileOffset+len, info.fileLen); + fileOffset, fileOffset+len, stat_buf.st_size); } } // if requested architecture is page aligned within fat file, then remap just that portion of file // ld64-port: remapping the file on Cygwin fails for an unknown reason, so always go the alternative way there #ifndef __CYGWIN__ - if ( (fileOffset & 0x00000FFF) == 0 ) { + if ( (fileOffset & PAGE_MASK) == 0 ) { // unmap whole file - munmap((caddr_t)p, info.fileLen); + munmap((caddr_t)p, stat_buf.st_size); // re-map just part we need p = (uint8_t*)::mmap(NULL, len, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, fileOffset); if ( p == (uint8_t*)(-1) ) @@ -308,19 +348,20 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib objOpts.logAllFiles = _options.logAllFiles(); objOpts.warnUnwindConversionProblems = _options.needsUnwindInfoSection(); objOpts.keepDwarfUnwind = _options.keepDwarfUnwind(); - objOpts.forceDwarfConversion= (_options.outputKind() == Options::kDyld); + objOpts.forceDwarfConversion= false; objOpts.neverConvertDwarf = !_options.needsUnwindInfoSection(); objOpts.verboseOptimizationHints = _options.verboseOptimizationHints(); objOpts.armUsesZeroCostExceptions = _options.armUsesZeroCostExceptions(); - objOpts.simulator = _options.targetIOSSimulator(); - objOpts.ignoreMismatchPlatform = ((_options.outputKind() == Options::kPreload) || (_options.outputKind() == Options::kStaticExecutable)); +#if SUPPORT_ARCH_arm64e + objOpts.supportsAuthenticatedPointers = _options.supportsAuthenticatedPointers(); +#endif objOpts.subType = _options.subArchitecture(); - objOpts.platform = _options.platform(); - objOpts.minOSVersion = _options.minOSversion(); + objOpts.platforms = _options.platforms(); objOpts.srcKind = ld::relocatable::File::kSourceObj; objOpts.treateBitcodeAsData = _options.bitcodeKind() == Options::kBitcodeAsData; objOpts.usingBitcode = _options.bundleBitcode(); objOpts.maxDefaultCommonAlignment = _options.maxDefaultCommonAlign(); + objOpts.internalSDK = _options.internalSDK(); ld::relocatable::File* objResult = mach_o::relocatable::parse(p, len, info.path, info.modTime, info.ordinal, objOpts); if ( objResult != NULL ) { @@ -350,10 +391,12 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib if ( dylibResult != NULL ) { return dylibResult; } +#ifdef TAPI_SUPPORT dylibResult = textstub::dylib::parse(p, len, info.path, info.modTime, _options, info.ordinal, info.options.fBundleLoader, indirectDylib); if ( dylibResult != NULL ) { return dylibResult; } +#endif /* TAPI_SUPPORT */ break; case Options::kStaticExecutable: case Options::kDyld: @@ -374,8 +417,7 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib archOpts.verboseLoad = _options.whyLoad(); archOpts.logAllFiles = _options.logAllFiles(); // Set ObjSource Kind, libclang_rt is compiler static library - const char* libName = strrchr(info.path, '/'); - if ( (libName != NULL) && (strncmp(libName, "/libclang_rt", 12) == 0) ) + if ( isCompilerSupportLib(info.path) ) archOpts.objOpts.srcKind = ld::relocatable::File::kSourceCompilerArchive; else archOpts.objOpts.srcKind = ld::relocatable::File::kSourceArchive; @@ -384,6 +426,7 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib ld::archive::File* archiveResult = ::archive::parse(p, len, info.path, info.modTime, info.ordinal, archOpts); if ( archiveResult != NULL ) { + OSAtomicAdd64(len, &_totalArchiveSize); OSAtomicIncrement32(&_totalArchivesLoaded); return archiveResult; @@ -393,7 +436,9 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib // does not seem to be any valid linker input file, check LTO misconfiguration problems if ( lto::archName((uint8_t*)p, len) != NULL ) { if ( lto::libLTOisLoaded() ) { - throwf("lto file was built for %s which is not the architecture being linked (%s): %s", fileArch(p, len), _options.architectureName(), info.path); + ld::Platform filePlatform; + const char* fileArchName = extractFileInfo(p, len, info.path, filePlatform); + throwf("lto file was built for %s which is not the architecture being linked (%s): %s", fileArchName, _options.architectureName(), info.path); } else { #ifdef __APPLE__ // ld64-port @@ -427,8 +472,14 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib if ( dylibsNotAllowed ) { cpu_type_t dummy1; cpu_type_t dummy2; - if ( mach_o::dylib::isDylibFile(p, &dummy1, &dummy2) ) + ld::Platform ignorePlatform; + uint32_t ignoreOSVers; + if ( mach_o::dylib::isDylibFile(p, len, &dummy1, &dummy2, &ignorePlatform, &ignoreOSVers) ) throw "ignoring unexpected dylib file"; +#ifdef TAPI_SUPPORT + if ( textstub::dylib::isTextStubFile(p, len, info.path) ) + throw "ignoring unexpected dylib text stub file"; +#endif } // error handling @@ -437,13 +488,18 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib } else { if ( isFatFile ) - throwf("file is universal (%u slices) but does not contain a(n) %s slice: %s", sliceCount, _options.architectureName(), info.path); - else - throwf("file was built for %s which is not the architecture being linked (%s): %s", fileArch(p, len), _options.architectureName(), info.path); + throwf("file is universal (%u slices) but does not contain the %s architecture: %s", sliceCount, _options.architectureName(), info.path); + else { + ld::Platform filePlatform; + const char* fileArchName = extractFileInfo(p, len, info.path, filePlatform); + throwf("building for %s-%s but attempting to link with file built for %s-%s", + _options.platforms().to_str().c_str(), _options.architectureName(), + ld::platformInfo(filePlatform).printName, fileArchName); + } } } -void InputFiles::logDylib(ld::File* file, bool indirect) +void InputFiles::logDylib(ld::File* file, bool indirect, bool speculative) { if ( _options.traceDylibs() ) { const char* fullPath = file->path(); @@ -455,37 +511,45 @@ void InputFiles::logDylib(ld::File* file, bool indirect) // don't log upward dylibs when XBS is computing dependencies logTraceInfo("[Logging for XBS] Used upward dynamic library: %s\n", fullPath); } + else if ( (dylib != NULL ) && dylib->speculativelyLoaded() ) { + logTraceInfo("[Logging for XBS] Speculatively loaded dynamic library: %s\n", fullPath); + } else { - if ( indirect ) - logTraceInfo("[Logging for XBS] Used indirect dynamic library: %s\n", fullPath); - else + if ( indirect ) { + if ( speculative ) + logTraceInfo("[Logging for XBS] Speculatively loaded indirect dynamic library: %s\n", fullPath); + else + logTraceInfo("[Logging for XBS] Used indirect dynamic library: %s\n", fullPath); + } + else { logTraceInfo("[Logging for XBS] Used dynamic library: %s\n", fullPath); + } } } if ( _options.dumpDependencyInfo() ) { const ld::dylib::File* dylib = dynamic_cast(file); if ( file == _bundleLoader ) { - _options.dumpDependency(Options::depBundleLoader, file->path()); + _options.addDependency(Options::depBundleLoader, file->path()); } else if ( (dylib != NULL ) && dylib->willBeUpwardDylib() ) { if ( indirect ) - _options.dumpDependency(Options::depUpwardIndirectDylib, file->path()); + _options.addDependency(Options::depUpwardIndirectDylib, file->path()); else - _options.dumpDependency(Options::depUpwardDirectDylib, file->path()); + _options.addDependency(Options::depUpwardDirectDylib, file->path()); } else { if ( indirect ) - _options.dumpDependency(Options::depIndirectDylib, file->path()); + _options.addDependency(Options::depIndirectDylib, file->path()); else - _options.dumpDependency(Options::depDirectDylib, file->path()); + _options.addDependency(Options::depDirectDylib, file->path()); } } } void InputFiles::logArchive(ld::File* file) const { - if ( _options.traceArchives() && (_archiveFilesLogged.count(file) == 0) ) { + if ( (_options.traceArchives() || _options.traceEmitJSON()) && (_archiveFilesLogged.count(file) == 0) ) { // LD_TRACE_ARCHIVES should only print out when a .o is actually used from an archive _archiveFilesLogged.insert(file); const char* fullPath = file->path(); @@ -493,45 +557,25 @@ void InputFiles::logArchive(ld::File* file) const if ( realpath(fullPath, realName) != NULL ) fullPath = realName; logTraceInfo("[Logging for XBS] Used static archive: %s\n", fullPath); + + std::string archivePath(fullPath); + _archiveFilePaths.push_back(archivePath); } } void InputFiles::logTraceInfo(const char* format, ...) const { - // one time open() of custom LD_TRACE_FILE - static int trace_file = -1; - if ( trace_file == -1 ) { - const char *trace_file_path = _options.traceOutputFile(); - if ( trace_file_path != NULL ) { - trace_file = open(trace_file_path, O_WRONLY | O_APPEND | O_CREAT, 0666); - if ( trace_file == -1 ) - throwf("Could not open or create trace file (errno=%d): %s", errno, trace_file_path); - } - else { - trace_file = fileno(stderr); - } - } - char trace_buffer[MAXPATHLEN * 2]; va_list ap; va_start(ap, format); int length = vsnprintf(trace_buffer, sizeof(trace_buffer), format, ap); va_end(ap); - char* buffer_ptr = trace_buffer; - - while (length > 0) { - ssize_t amount_written = write(trace_file, buffer_ptr, length); - if(amount_written == -1) - /* Failure to write shouldn't fail the build. */ - return; - buffer_ptr += amount_written; - length -= amount_written; - } + _options.writeToTraceFile(trace_buffer, length); } -ld::dylib::File* InputFiles::findDylib(const char* installPath, const char* fromPath) +ld::dylib::File* InputFiles::findDylib(const char* installPath, const ld::dylib::File* fromDylib, bool speculative) { //fprintf(stderr, "findDylib(%s, %s)\n", installPath, fromPath); InstallNameToDylib::iterator pos = _installPathToDylibs.find(installPath); @@ -552,7 +596,7 @@ ld::dylib::File* InputFiles::findDylib(const char* installPath, const char* from if ( dylibReader != NULL ) { addDylib(dylibReader, info); //_installPathToDylibs[strdup(installPath)] = dylibReader; - this->logDylib(dylibReader, true); + this->logDylib(dylibReader, true, speculative); return dylibReader; } else @@ -563,20 +607,9 @@ ld::dylib::File* InputFiles::findDylib(const char* installPath, const char* from } } } - char newPath[MAXPATHLEN]; - // handle @loader_path - if ( strncmp(installPath, "@loader_path/", 13) == 0 ) { - strcpy(newPath, fromPath); - char* addPoint = strrchr(newPath,'/'); - if ( addPoint != NULL ) - strcpy(&addPoint[1], &installPath[13]); - else - strcpy(newPath, &installPath[13]); - installPath = newPath; - } - // note: @executable_path case is handled inside findFileUsingPaths() - // search for dylib using -F and -L paths - Options::FileInfo info = _options.findFileUsingPaths(installPath); + + // search for dylib using -F and -L paths and expanding @ paths + Options::FileInfo info = _options.findIndirectDylib(installPath, fromDylib); _indirectDylibOrdinal = _indirectDylibOrdinal.nextIndirectDylibOrdinal(); info.ordinal = _indirectDylibOrdinal; info.options.fIndirectDylib = true; @@ -587,7 +620,7 @@ ld::dylib::File* InputFiles::findDylib(const char* installPath, const char* from //assert(_installPathToDylibs.find(installPath) != _installPathToDylibs.end()); //_installPathToDylibs[strdup(installPath)] = dylibReader; addDylib(dylibReader, info); - this->logDylib(dylibReader, true); + this->logDylib(dylibReader, true, speculative); return dylibReader; } else @@ -640,80 +673,112 @@ bool InputFiles::libraryAlreadyLoaded(const char* path) return true; } + char realDylibPath[PATH_MAX]; + if ( (realpath(path, realDylibPath) != NULL) && (strcmp(path, realDylibPath) != 0) ) { + return libraryAlreadyLoaded(realDylibPath); + } + return false; } void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHandler& handler) { - if ( _options.outputKind() == Options::kObjectFile ) - return; + if ( _options.outputKind() == Options::kObjectFile ) + return; + + while (! state.unprocessedLinkerOptionLibraries.empty() || ! state.unprocessedLinkerOptionFrameworks.empty()) { - // process frameworks specified in .o linker options - for (CStringSet::const_iterator it = state.linkerOptionFrameworks.begin(); it != state.linkerOptionFrameworks.end(); ++it) { - const char* frameworkName = *it; - if ( state.linkerOptionFrameworksProcessed.count(frameworkName) ) - continue; - Options::FileInfo info = _options.findFramework(frameworkName); - if ( ! this->frameworkAlreadyLoaded(info.path, frameworkName) ) { - info.ordinal = _linkerOptionOrdinal.nextLinkerOptionOrdinal(); + // process frameworks specified in .o linker options + CStringSet newFrameworks = std::move(state.unprocessedLinkerOptionFrameworks); + state.unprocessedLinkerOptionFrameworks.clear(); + for (const char* frameworkName : newFrameworks) { + if ( state.linkerOptionFrameworks.count(frameworkName) ) + continue; try { - ld::File* reader = this->makeFile(info, true); - ld::dylib::File* dylibReader = dynamic_cast(reader); - if ( dylibReader != NULL ) { - if ( ! dylibReader->installPathVersionSpecific() ) { + Options::FileInfo info = _options.findFramework(frameworkName); + if ( ! this->frameworkAlreadyLoaded(info.path, frameworkName) ) { + _linkerOptionOrdinal = _linkerOptionOrdinal.nextLinkerOptionOrdinal(); + info.ordinal = _linkerOptionOrdinal; + ld::File* reader = this->makeFile(info, true); + ld::dylib::File* dylibReader = dynamic_cast(reader); + ld::archive::File* archiveReader = dynamic_cast(reader); + if ( dylibReader != NULL ) { + if ( ! dylibReader->installPathVersionSpecific() ) { + checkDylibClientRestrictions(dylibReader); + dylibReader->forEachAtom(handler); + dylibReader->setImplicitlyLinked(); + dylibReader->setSpeculativelyLoaded(); + this->addDylib(dylibReader, info); + } + } + else if ( archiveReader != NULL ) { + _searchLibraries.push_back(LibraryInfo(archiveReader)); + _options.addDependency(Options::depArchive, archiveReader->path()); + // -force_load_swift_libs + if (info.options.fForceLoad) { + archiveReader->forEachAtom(handler); + } + } + else { + throwf("framework linker option at %s is not a dylib and not an archive", info.path); + } + } + } + catch (const char* msg) { + if ( strstr(msg, "but linking") != nullptr ) + warning("%s '%s.framework'", msg, frameworkName); + // only warn about missing auto-linked framework if some missing symbol error happens later + state.missingLinkerOptionFrameworks.insert(frameworkName); + } + state.linkerOptionFrameworks.insert(frameworkName); + } + + // process libraries specified in .o linker options + // fixme optimize with std::move? + CStringSet newLibraries = std::move(state.unprocessedLinkerOptionLibraries); + state.unprocessedLinkerOptionLibraries.clear(); + for (const char* libName : newLibraries) { + if ( state.linkerOptionLibraries.count(libName) ) + continue; + try { + Options::FileInfo info = _options.findLibrary(libName); + if ( ! this->libraryAlreadyLoaded(info.path) ) { + _linkerOptionOrdinal = _linkerOptionOrdinal.nextLinkerOptionOrdinal(); + info.ordinal = _linkerOptionOrdinal; + // -force_load_swift_libs + info.options.fForceLoad = _options.forceLoadSwiftLibs() && (strncmp(libName, "swift", 5) == 0); + ld::File* reader = this->makeFile(info, true); + ld::dylib::File* dylibReader = dynamic_cast(reader); + ld::archive::File* archiveReader = dynamic_cast(reader); + if ( dylibReader != NULL ) { + checkDylibClientRestrictions(dylibReader); dylibReader->forEachAtom(handler); dylibReader->setImplicitlyLinked(); + dylibReader->setSpeculativelyLoaded(); this->addDylib(dylibReader, info); } - } - else { - throwf("framework linker option at %s is not a dylib", info.path); - } - } - catch (const char* msg) { - warning("Auto-Linking supplied '%s', %s", info.path, msg); - } - } - state.linkerOptionFrameworksProcessed.insert(frameworkName); - } - // process libraries specified in .o linker options - for (CStringSet::const_iterator it = state.linkerOptionLibraries.begin(); it != state.linkerOptionLibraries.end(); ++it) { - const char* libName = *it; - if ( state.linkerOptionLibrariesProcessed.count(libName) ) - continue; - Options::FileInfo info = _options.findLibrary(libName); - if ( ! this->libraryAlreadyLoaded(info.path) ) { - info.ordinal = _linkerOptionOrdinal.nextLinkerOptionOrdinal(); - try { - // -force_load_swift_libs - info.options.fForceLoad = _options.forceLoadSwiftLibs() && (strncmp(libName, "swift", 5) == 0); - ld::File* reader = this->makeFile(info, true); - ld::dylib::File* dylibReader = dynamic_cast(reader); - ld::archive::File* archiveReader = dynamic_cast(reader); - if ( dylibReader != NULL ) { - dylibReader->forEachAtom(handler); - dylibReader->setImplicitlyLinked(); - this->addDylib(dylibReader, info); - } - else if ( archiveReader != NULL ) { - _searchLibraries.push_back(LibraryInfo(archiveReader)); - if ( _options.dumpDependencyInfo() ) - _options.dumpDependency(Options::depArchive, archiveReader->path()); - // -force_load_swift_libs - if (info.options.fForceLoad) { - archiveReader->forEachAtom(handler); + else if ( archiveReader != NULL ) { + _searchLibraries.push_back(LibraryInfo(archiveReader)); + _options.addDependency(Options::depArchive, archiveReader->path()); + // -force_load_swift_libs + if (info.options.fForceLoad) { + archiveReader->forEachAtom(handler); + } } - } - else { - throwf("linker option dylib at %s is not a dylib", info.path); - } - } + else { + throwf("linker option dylib at %s is not a dylib", info.path); + } + } + } catch (const char* msg) { - warning("Auto-Linking supplied '%s', %s", info.path, msg); + if ( strstr(msg, "but linking") != nullptr ) + warning("%s '%s'", msg, libName); + // only warn about missing auto-linked library if some missing symbol error happens later + state.missingLinkerOptionLibraries.insert(libName); } + state.linkerOptionLibraries.insert(libName); } - state.linkerOptionLibrariesProcessed.insert(libName); } } @@ -730,12 +795,16 @@ void InputFiles::createIndirectDylibs() if ( dylibsProcessed.count(*it) == 0 ) unprocessedDylibs.push_back(*it); } + // ld64 output is not deterministic due to dylib processing order + std::sort(unprocessedDylibs.begin(), unprocessedDylibs.end(), [](const ld::dylib::File* lhs, const ld::dylib::File* rhs) { + return strcmp(lhs->path(), rhs->path()) < 0; + }); for (std::vector::iterator it=unprocessedDylibs.begin(); it != unprocessedDylibs.end(); it++) { dylibsProcessed.insert(*it); (*it)->processIndirectLibraries(this, _options.implicitlyLinkIndirectPublicDylibs()); } } - + // go back over original dylibs and mark sub frameworks as re-exported if ( _options.outputKind() == Options::kDynamicLibrary ) { const char* myLeaf = strrchr(_options.installPath(), '/'); @@ -762,13 +831,24 @@ void InputFiles::createOpaqueFileSections() // extra command line sections always at end for (Options::ExtraSection::const_iterator it=_options.extraSectionsBegin(); it != _options.extraSectionsEnd(); ++it) { _inputFiles.push_back(opaque_section::parse(it->segmentName, it->sectionName, it->path, it->data, it->dataLen)); - if ( _options.dumpDependencyInfo() ) - _options.dumpDependency(Options::depSection, it->path); + _options.addDependency(Options::depSection, it->path); } } +const char* sGrandfatheredLooseAllow[] = { + "/CloudKitCode.framework", + "/CloudKitCodeProtobuf.framework", + "/Helix.framework", + "/NewsCore.framework", + "/NewsServicesInternal.framework", + "/NewsTransport.framework", + "/NewsUI.framework", + "/Silex.framework" +}; + + void InputFiles::checkDylibClientRestrictions(ld::dylib::File* dylib) { // Check for any restrictions on who can link with this dylib @@ -836,6 +916,17 @@ void InputFiles::checkDylibClientRestrictions(ld::dylib::File* dylib) if ( strncmp(*it, clientName, clientNameLen) == 0 ) isAllowableClient = true; } + // temp fix until projects update allowable clients + if ( !isAllowableClient ) { + for (const char* frameworkName : sGrandfatheredLooseAllow) { + if ( strstr(dylib->installPath(), frameworkName) != NULL ) { + warning("%s did not mark %s as an allowable client", dylib->installPath(), clientName); + isAllowableClient = true; + break; + } + } + } + } if ( !isParent && !isSibling && !isAllowableClient ) { @@ -844,83 +935,27 @@ void InputFiles::checkDylibClientRestrictions(ld::dylib::File* dylib) dylib->path(), dylibParentName); } else { - throwf("cannot link directly with %s", dylib->path()); + throwf("cannot link directly with dylib/framework, your binary is not an allowed client of %s", dylib->path()); } } } } -void InputFiles::inferArchitecture(Options& opts, const char** archName) -{ - _inferredArch = true; - // scan all input files, looking for a thin .o file. - // the first one found is presumably the architecture to link - uint8_t buffer[4096]; - const std::vector& files = opts.getInputFiles(); - for (std::vector::const_iterator it = files.begin(); it != files.end(); ++it) { - int fd = ::open(it->path, O_RDONLY, 0); - if ( fd != -1 ) { - struct stat stat_buf; - if ( fstat(fd, &stat_buf) != -1) { - ssize_t readAmount = stat_buf.st_size; - if ( 4096 < readAmount ) - readAmount = 4096; - ssize_t amount = read(fd, buffer, readAmount); - ::close(fd); - if ( amount >= readAmount ) { - cpu_type_t type; - cpu_subtype_t subtype; - Options::Platform platform; - if ( mach_o::relocatable::isObjectFile(buffer, &type, &subtype, &platform) ) { - opts.setArchitecture(type, subtype, platform); - *archName = opts.architectureName(); - return; - } - } - } - } - } - - // no thin .o files found, so default to same architecture this tool was built as - warning("-arch not specified"); -#if __i386__ - opts.setArchitecture(CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL, Options::kPlatformOSX); -#elif __x86_64__ - opts.setArchitecture(CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL, Options::kPlatformOSX); -#elif __ppc__ // ld64-port - opts.setArchitecture(CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL, Options::kPlatformOSX); -#elif __ppc64__ // ld64-port - opts.setArchitecture(CPU_TYPE_POWERPC64, CPU_SUBTYPE_POWERPC_ALL, Options::kPlatformOSX); -#elif __arm__ - opts.setArchitecture(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6, Options::kPlatformiOS); // ld64-port: Options::kPlatformOSX -> Options::kPlatformiOS -#elif __arm64__ // ld64-port - opts.setArchitecture(CPU_TYPE_ARM, CPU_SUBTYPE_ARM64_ALL, Options::kPlatformiOS); -#else - #error unknown default architecture -#endif - *archName = opts.architectureName(); -} - - -InputFiles::InputFiles(Options& opts, const char** archName) +InputFiles::InputFiles(Options& opts) : _totalObjectSize(0), _totalArchiveSize(0), _totalObjectLoaded(0), _totalArchivesLoaded(0), _totalDylibsLoaded(0), _options(opts), _bundleLoader(NULL), - _inferredArch(false), _exception(NULL), _indirectDylibOrdinal(ld::File::Ordinal::indirectDylibBase()), _linkerOptionOrdinal(ld::File::Ordinal::linkeOptionBase()) { // fStartCreateReadersTime = mach_absolute_time(); - if ( opts.architecture() == 0 ) { - // command line missing -arch, so guess arch - inferArchitecture(opts, archName); - } #if HAVE_PTHREADS pthread_mutex_init(&_parseLock, NULL); pthread_cond_init(&_parseWorkReady, NULL); pthread_cond_init(&_newFileAvailable, NULL); + _neededFileSlot = -1; #endif const std::vector& files = _options.getInputFiles(); if ( files.size() == 0 ) @@ -955,20 +990,7 @@ InputFiles::InputFiles(Options& opts, const char** archName) // initialize info for parsing input files on worker threads unsigned int ncpus; -#ifdef __linux__ // ld64-port - cpu_set_t cs; - CPU_ZERO(&cs); - - if (!sched_getaffinity(0, sizeof(cs), &cs)) { - ncpus = 0; - - for (int i = 0; i < CPU_SETSIZE; i++) - if (CPU_ISSET(i, &cs)) - ncpus++; - } else { - ncpus = 1; - } -#else +#ifdef __APPLE__ int mib[2]; size_t len = sizeof(ncpus); mib[0] = CTL_HW; @@ -976,6 +998,10 @@ InputFiles::InputFiles(Options& opts, const char** archName) if (sysctl(mib, 2, &ncpus, &len, NULL, 0) != 0) { ncpus = 1; } +#else // ld64-port + ncpus = std::thread::hardware_concurrency(); + if (ncpus <= 0) + ncpus = 1; #endif _availableWorkers = MIN(ncpus, files.size()); // max # workers we permit _idleWorkers = 0; @@ -1033,9 +1059,9 @@ void InputFiles::parseWorkerThread() { if (_s_logPThreads) printf("parsing index %u\n", slot); try { file = makeFile(entry, false); - } + } catch (const char *msg) { - if ( (strstr(msg, "architecture") != NULL) && !_options.errorOnOtherArchFiles() ) { + if ( ((strstr(msg, "architecture") != NULL) || (strstr(msg, "attempting to link") != NULL)) && !_options.errorOnOtherArchFiles() ) { if ( _options.ignoreOtherArchInputFiles() ) { // ignore, because this is about an architecture not in use } @@ -1133,7 +1159,7 @@ ld::File* InputFiles::addDylib(ld::dylib::File* reader, const Options::FileInfo& // log direct readers if ( ! info.options.fIndirectDylib ) - this->logDylib(reader, false); + this->logDylib(reader, false, false); // update stats _totalDylibsLoaded++; @@ -1229,8 +1255,11 @@ void InputFiles::forEachInitialAtom(ld::File::AtomHandler& handler, ld::Internal pthread_cond_wait(&_newFileAvailable, &_parseLock); } - if (_exception) + if (_exception) { + // the tool is erroring out. wait for other threads to finish so we don't destruct global objects out from under them + sleep(1); throw _exception; + } // The input file is parsed. Assimilate it and call its atom iterator. if (_s_logPThreads) printf("consuming slot %lu\n", fileIndex); @@ -1245,8 +1274,7 @@ void InputFiles::forEachInitialAtom(ld::File::AtomHandler& handler, ld::Internal { ld::relocatable::File* reloc = (ld::relocatable::File*)file; _options.snapshot().recordObjectFile(reloc->path()); - if ( _options.dumpDependencyInfo() ) - _options.dumpDependency(Options::depObjectFile, reloc->path()); + _options.addDependency(Options::depObjectFile, reloc->path()); } break; case ld::File::Dylib: @@ -1259,11 +1287,14 @@ void InputFiles::forEachInitialAtom(ld::File::AtomHandler& handler, ld::Internal { ld::archive::File* archive = (ld::archive::File*)file; // force loaded archives should be in LD_TRACE - if ( (info.options.fForceLoad || _options.fullyLoadArchives()) && _options.traceArchives() ) + if ( (info.options.fForceLoad || _options.fullyLoadArchives()) && (_options.traceArchives() || _options.traceEmitJSON()) ) logArchive(archive); + + if ( isCompilerSupportLib(info.path) && (info.options.fForceLoad || _options.fullyLoadArchives()) ) + state.forceLoadCompilerRT = true; + _searchLibraries.push_back(LibraryInfo(archive)); - if ( _options.dumpDependencyInfo() ) - _options.dumpDependency(Options::depArchive, archive->path()); + _options.addDependency(Options::depArchive, archive->path()); } break; case ld::File::Other: @@ -1274,7 +1305,17 @@ void InputFiles::forEachInitialAtom(ld::File::AtomHandler& handler, ld::Internal } break; } - file->forEachAtom(handler); + try { + file->forEachAtom(handler); + } + catch (const char* msg) { + asprintf((char**)&_exception, "%s file '%s'", msg, file->path()); + } + } + if (_exception) { + // the tool is erroring out. wait for other threads to finish so we don't destruct global objects out from under them + sleep(1); + throw _exception; } markExplicitlyLinkedDylibs(); @@ -1356,16 +1397,17 @@ bool InputFiles::searchLibraries(const char* name, bool searchDylibs, bool searc ld::archive::File *archiveFile = lib.archive(); if ( dataSymbolOnly ) { if ( archiveFile->justInTimeDataOnlyforEachAtom(name, handler) ) { - if ( _options.traceArchives() ) + if ( _options.traceArchives() || _options.traceEmitJSON()) logArchive(archiveFile); _options.snapshot().recordArchive(archiveFile->path()); + // DALLAS _state.archives.push_back(archiveFile); // found data definition in static library, done return true; } } else { if ( archiveFile->justInTimeforEachAtom(name, handler) ) { - if ( _options.traceArchives() ) + if ( _options.traceArchives() || _options.traceEmitJSON()) logArchive(archiveFile); _options.snapshot().recordArchive(archiveFile->path()); // found definition in static library, done @@ -1473,13 +1515,25 @@ void InputFiles::dylibs(ld::Internal& state) for (InstallNameToDylib::const_iterator it=_installPathToDylibs.begin(); it != _installPathToDylibs.end(); ++it) { ld::dylib::File* dylibFile = it->second; if ( dylibFile->implicitlyLinked() && dylibsOK ) { - if ( ! vectorContains(implicitDylibs, dylibFile) ) { + if ( !vectorContains(implicitDylibs, dylibFile) && !vectorContains(state.dylibs, dylibFile) ) { implicitDylibs.push_back(dylibFile); } } } // make implicit dylib order be deterministic by sorting by install_name std::sort(implicitDylibs.begin(), implicitDylibs.end(), DylibByInstallNameSorter()); + + if ( _options.traceDylibs() ) { + for (ld::dylib::File* dylib : implicitDylibs) { + if ( dylib->speculativelyLoaded() && !dylib->explicitlyLinked() && dylib->providedExportAtom() ) { + const char* fullPath = dylib->path(); + char realName[MAXPATHLEN]; + if ( realpath(fullPath, realName) != NULL ) + fullPath = realName; + logTraceInfo("[Logging for XBS] Used dynamic library: %s\n", fullPath); + } + } + } state.dylibs.insert(state.dylibs.end(), implicitDylibs.begin(), implicitDylibs.end()); } @@ -1493,8 +1547,24 @@ void InputFiles::dylibs(ld::Internal& state) state.bundleLoader = _bundleLoader; // give an error when -nostdlib is used and libSystem is missing - if ( (state.dylibs.size() == 0) && _options.needsEntryPointLoadCommand() ) - throw "dynamic main executables must link with libSystem.dylib"; + if ( (state.dylibs.size() == 0) && _options.needsEntryPointLoadCommand() && !_options.platforms().contains(ld::Platform::driverKit)) { + // HACK until 39514191 is fixed + bool grandfather = false; + for (const File* inFile : _inputFiles) { + if ( strstr(inFile->path(), "exit-asm.o") != NULL ) + grandfather = true; + } + if ( !grandfather ) + throw "dynamic main executables must link with libSystem.dylib"; + } +} + +void InputFiles::archives(ld::Internal& state) +{ + for (const std::string& path : _archiveFilePaths) { + + state.archivePaths.push_back(path); + } } diff --git a/cctools/ld64/src/ld/InputFiles.h b/cctools/ld64/src/ld/InputFiles.h index e9927cd..ef9c756 100644 --- a/cctools/ld64/src/ld/InputFiles.h +++ b/cctools/ld64/src/ld/InputFiles.h @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -57,10 +56,10 @@ namespace tool { class InputFiles : public ld::dylib::File::DylibHandler { public: - InputFiles(Options& opts, const char** archName); + InputFiles(Options& opts); // implementation from ld::dylib::File::DylibHandler - virtual ld::dylib::File* findDylib(const char* installPath, const char* fromPath); + virtual ld::dylib::File* findDylib(const char* installPath, const ld::dylib::File* fromDylib, bool speculative); // iterates all atoms in initial files void forEachInitialAtom(ld::File::AtomHandler&, ld::Internal& state); @@ -72,8 +71,8 @@ public: // copy dylibs to link with in command line order void dylibs(ld::Internal& state); - bool inferredArch() const { return _inferredArch; } - + void archives(ld::Internal& state); + void addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHandler& handler); void createIndirectDylibs(); @@ -87,11 +86,11 @@ public: private: void inferArchitecture(Options& opts, const char** archName); - const char* fileArch(const uint8_t* p, unsigned len); + const char* extractFileInfo(const uint8_t* p, unsigned len, const char* path, ld::Platform& platform); ld::File* makeFile(const Options::FileInfo& info, bool indirectDylib); ld::File* addDylib(ld::dylib::File* f, const Options::FileInfo& info); void logTraceInfo (const char* format, ...) const; - void logDylib(ld::File*, bool indirect); + void logDylib(ld::File*, bool indirect, bool speculative); void logArchive(ld::File*) const; void markExplicitlyLinkedDylibs(); void checkDylibClientRestrictions(ld::dylib::File*); @@ -108,15 +107,15 @@ private: static void parseWorkerThread(InputFiles *inputFiles); void startThread(void (*threadFunc)(InputFiles *)) const; - typedef std::unordered_map InstallNameToDylib; + typedef std::map InstallNameToDylib; const Options& _options; std::vector _inputFiles; mutable std::set _archiveFilesLogged; + mutable std::vector _archiveFilePaths; InstallNameToDylib _installPathToDylibs; std::set _allDylibs; ld::dylib::File* _bundleLoader; - bool _inferredArch; struct strcompclass { bool operator() (const char *a, const char *b) const { return ::strcmp(a, b) < 0; } }; diff --git a/cctools/ld64/src/ld/LinkEdit.hpp b/cctools/ld64/src/ld/LinkEdit.hpp index c4421ef..effc10e 100644 --- a/cctools/ld64/src/ld/LinkEdit.hpp +++ b/cctools/ld64/src/ld/LinkEdit.hpp @@ -103,6 +103,10 @@ public: _data.push_back(byte); } + void append_mem(const void* mem, size_t len) { + _data.insert(_data.end(), (uint8_t*)mem, (uint8_t*)mem + len); + } + static unsigned int uleb128_size(uint64_t value) { uint32_t result = 0; do { @@ -130,7 +134,9 @@ public: virtual void copyRawContent(uint8_t buffer[]) const; virtual void encode() const = 0; - + + const uint8_t* rawContent() const { return this->_encodedData.start(); } + LinkEditAtom(const Options& opts, ld::Internal& state, OutputFile& writer, const ld::Section& sect, unsigned int pointerSize) @@ -176,6 +182,8 @@ public: virtual void encode() const; private: + void encodeV1() const; + struct rebase_tmp { rebase_tmp(uint8_t op, uint64_t p1, uint64_t p2=0) : opcode(op), operand1(p1), operand2(p2) {} @@ -204,8 +212,28 @@ void RebaseInfoAtom::encode() const // sort rebase info by type, then address std::vector& info = this->_writer._rebaseInfo; + if (info.empty()) + return; + std::sort(info.begin(), info.end()); + // use encoding based on target minOS + if ( _options.useLinkedListBinding() && !this->_writer._hasUnalignedFixup ) { + if ( info.back()._type != REBASE_TYPE_POINTER ) + throw "unsupported rebase type with linked list opcodes"; + // As the binding and rebasing are both linked lists, just use the binds + // to do everything. + } else { + encodeV1(); + } +} + + +template +void RebaseInfoAtom::encodeV1() const +{ + std::vector& info = this->_writer._rebaseInfo; + // convert to temp encoding that can be more easily optimized std::vector mid; uint64_t curSegStart = 0; @@ -388,6 +416,9 @@ public: private: + void encodeV1() const; + void encodeV2() const; + typedef typename A::P P; typedef typename A::P::E E; typedef typename A::P::uint_t pint_t; @@ -411,11 +442,23 @@ ld::Section BindingInfoAtom::_s_section("__LINKEDIT", "__binding", ld::Sectio template void BindingInfoAtom::encode() const +{ + // use encoding based on target minOS + if ( _options.useLinkedListBinding() && !this->_writer._hasUnalignedFixup ) { + encodeV2(); + } else { + encodeV1(); + } +} + + +template +void BindingInfoAtom::encodeV1() const { // sort by library, symbol, type, then address std::vector& info = this->_writer._bindingInfo; std::sort(info.begin(), info.end()); - + // convert to temp encoding that can be more easily optimized std::vector mid; uint64_t curSegStart = 0; @@ -600,6 +643,229 @@ void BindingInfoAtom::encode() const if (log) fprintf(stderr, "total binding info size = %ld\n", this->_encodedData.size()); } +template +void BindingInfoAtom::encodeV2() const +{ + std::vector& bindInfo = this->_writer._bindingInfo; + std::vector& rebaseInfo = this->_writer._rebaseInfo; + const static bool log = false; + + std::sort(bindInfo.begin(), bindInfo.end()); + + // convert to temp encoding that can be more easily optimized + std::vector mid; + uint64_t curSegStart = 0; + uint64_t curSegEnd = 0; + uint32_t curSegIndex = 0; + int ordinal = 0x80000000; + const char* symbolName = NULL; + uint8_t type = 0; + uint64_t address = (uint64_t)(-1); + int64_t addend = 0; + uint64_t numBinds = (uint64_t)(-1); + for (std::vector::iterator it = bindInfo.begin(); it != bindInfo.end(); ++it) { + bool madeChange = false; + if ( ordinal != it->_libraryOrdinal ) { + if ( it->_libraryOrdinal <= 0 ) { + // special lookups are encoded as negative numbers in BindingInfo + mid.push_back(binding_tmp(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM, it->_libraryOrdinal)); + } + else if ( it->_libraryOrdinal <= 15 ) { + mid.push_back(binding_tmp(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM, it->_libraryOrdinal)); + } + else { + mid.push_back(binding_tmp(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB, it->_libraryOrdinal)); + } + ordinal = it->_libraryOrdinal; + madeChange = true; + } + if ( symbolName != it->_symbolName ) { + mid.push_back(binding_tmp(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM, it->_flags, 0, it->_symbolName)); + symbolName = it->_symbolName; + madeChange = true; + } + if ( type != it->_type ) { + if ( it->_type != BIND_TYPE_POINTER ) + throw "unsupported bind type with linked list opcodes"; + mid.push_back(binding_tmp(BIND_OPCODE_SET_TYPE_IMM, it->_type)); + type = it->_type; + madeChange = true; + } + if ( address != it->_address ) { + // Note, we don't push the addresses here. That is all done later with the threaded chains + if ( (it->_address < curSegStart) || ( it->_address >= curSegEnd) ) { + if ( ! this->_writer.findSegment(this->_state, it->_address, &curSegStart, &curSegEnd, &curSegIndex) ) + throw "binding address outside range of any segment"; + } + address = it->_address; + } + if ( addend != it->_addend ) { + mid.push_back(binding_tmp(BIND_OPCODE_SET_ADDEND_SLEB, it->_addend)); + addend = it->_addend; + madeChange = true; + } + + if (madeChange) { + ++numBinds; + mid.push_back(binding_tmp(BIND_OPCODE_DO_BIND, 0)); + } + it->_threadedBindOrdinal = numBinds; + } + + // We can only support 2^16 bind ordinals. + if ( (numBinds > 0x10000) && (numBinds != (uint64_t)(-1)) ) + throwf("too many binds (%llu). The limit is 65536", numBinds); + + // Now that we have the bind ordinal table populate, set the page starts. + + std::vector& threadedRebaseBindIndices = this->_writer._threadedRebaseBindIndices; + threadedRebaseBindIndices.reserve(bindInfo.size() + rebaseInfo.size()); + + for (int64_t i = 0, e = rebaseInfo.size(); i != e; ++i) + threadedRebaseBindIndices.push_back(-i); + + for (int64_t i = 0, e = bindInfo.size(); i != e; ++i) + threadedRebaseBindIndices.push_back(i + 1); + + // Now sort the entries by address. + std::sort(threadedRebaseBindIndices.begin(), threadedRebaseBindIndices.end(), + [&rebaseInfo, &bindInfo](int64_t indexA, int64_t indexB) { + if (indexA == indexB) + return false; + uint64_t addressA = indexA <= 0 ? rebaseInfo[-indexA]._address : bindInfo[indexA - 1]._address; + uint64_t addressB = indexB <= 0 ? rebaseInfo[-indexB]._address : bindInfo[indexB - 1]._address; + assert(addressA != addressB); + return addressA < addressB; + }); + + curSegStart = 0; + curSegEnd = 0; + curSegIndex = 0; + uint64_t prevPageIndex = 0; + for (int64_t entryIndex : threadedRebaseBindIndices) { + OutputFile::RebaseInfo* rebase = nullptr; + OutputFile::BindingInfo* bind = nullptr; + uint64_t address = 0; + if (entryIndex <= 0) { + rebase = &rebaseInfo[-entryIndex]; + address = rebase->_address; + } else { + bind = &bindInfo[entryIndex - 1]; + address = bind->_address; + } + assert((address & 7) == 0); + + bool newSegment = false; + if ( (address < curSegStart) || ( address >= curSegEnd) ) { + // Start of a new segment. + if ( ! this->_writer.findSegment(this->_state, address, &curSegStart, &curSegEnd, &curSegIndex) ) + throw "binding address outside range of any segment"; + newSegment = true; + } + + // At this point we know we have the page starts array space reserved + // so set the page start for this entry if we haven't got one already. + uint64_t pageIndex = ( address - curSegStart ) / 4096; + if ( newSegment || (pageIndex != prevPageIndex) ) { + mid.push_back(binding_tmp(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, curSegIndex, address - curSegStart)); + mid.push_back(binding_tmp(BIND_OPCODE_THREADED | BIND_SUBOPCODE_THREADED_APPLY, 0)); + } + prevPageIndex = pageIndex; + } + mid.push_back(binding_tmp(BIND_OPCODE_DONE, 0)); + + // convert to compressed encoding + this->_encodedData.reserve(bindInfo.size()*2); + + // First push the total number of binds so that we can allocate space for this in dyld. + if ( log ) fprintf(stderr, "BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB(%lld)\n", numBinds + 1); + this->_encodedData.append_byte(BIND_OPCODE_THREADED | BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB); + this->_encodedData.append_uleb128(numBinds + 1); + + bool done = false; + for (typename std::vector::iterator it = mid.begin(); !done && it != mid.end() ; ++it) { + switch ( it->opcode ) { + case BIND_OPCODE_DONE: + if ( log ) fprintf(stderr, "BIND_OPCODE_DONE()\n"); + done = true; + break; + case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: + if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM(%lld)\n", it->operand1); + this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | it->operand1); + break; + case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: + if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB(%lld)\n", it->operand1); + this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB); + this->_encodedData.append_uleb128(it->operand1); + break; + case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: + if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM(%lld)\n", it->operand1); + this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | (it->operand1 & BIND_IMMEDIATE_MASK)); + break; + case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: + if ( log ) fprintf(stderr, "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM(0x%0llX, %s)\n", it->operand1, it->name); + this->_encodedData.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | it->operand1); + this->_encodedData.append_string(it->name); + break; + case BIND_OPCODE_SET_TYPE_IMM: + if ( log ) fprintf(stderr, "BIND_OPCODE_SET_TYPE_IMM(%lld)\n", it->operand1); + this->_encodedData.append_byte(BIND_OPCODE_SET_TYPE_IMM | it->operand1); + break; + case BIND_OPCODE_SET_ADDEND_SLEB: + if ( log ) fprintf(stderr, "BIND_OPCODE_SET_ADDEND_SLEB(%lld)\n", it->operand1); + this->_encodedData.append_byte(BIND_OPCODE_SET_ADDEND_SLEB); + this->_encodedData.append_sleb128(it->operand1); + break; + case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: + if ( log ) fprintf(stderr, "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(%lld, 0x%llX)\n", it->operand1, it->operand2); + this->_encodedData.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | it->operand1); + this->_encodedData.append_uleb128(it->operand2); + break; + case BIND_OPCODE_ADD_ADDR_ULEB: + if ( log ) fprintf(stderr, "BIND_OPCODE_ADD_ADDR_ULEB(0x%llX)\n", it->operand1); + this->_encodedData.append_byte(BIND_OPCODE_ADD_ADDR_ULEB); + this->_encodedData.append_uleb128(it->operand1); + break; + case BIND_OPCODE_DO_BIND: + if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND()\n"); + this->_encodedData.append_byte(BIND_OPCODE_DO_BIND); + break; + case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: + if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB(0x%llX)\n", it->operand1); + this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB); + this->_encodedData.append_uleb128(it->operand1); + break; + case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: + if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED(%lld=0x%llX)\n", it->operand1, it->operand1*sizeof(pint_t)); + this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED | it->operand1 ); + break; + case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: + if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB(%lld, %lld)\n", it->operand1, it->operand2); + this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB); + this->_encodedData.append_uleb128(it->operand1); + this->_encodedData.append_uleb128(it->operand2); + break; + case BIND_OPCODE_THREADED | BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB: + if ( log ) fprintf(stderr, "BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB(%lld)\n", it->operand1); + this->_encodedData.append_byte(BIND_OPCODE_THREADED | BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB); + this->_encodedData.append_uleb128(it->operand1); + break; + case BIND_OPCODE_THREADED | BIND_SUBOPCODE_THREADED_APPLY: + this->_encodedData.append_byte(BIND_OPCODE_THREADED | BIND_SUBOPCODE_THREADED_APPLY); + if ( log ) fprintf(stderr, "BIND_SUBOPCODE_THREADED_APPLY()\n"); + break; + } + } + + // align to pointer size + this->_encodedData.append_byte(BIND_OPCODE_DONE); + this->_encodedData.pad_to_size(sizeof(pint_t)); + + this->_encoded = true; + + if (log) fprintf(stderr, "total binding info size = %ld\n", this->_encodedData.size()); +} + template @@ -914,6 +1180,172 @@ void LazyBindingInfoAtom::encode() const + +template +class ChainedInfoAtom : public LinkEditAtom +{ +public: + ChainedInfoAtom(const Options& opts, ld::Internal& state, OutputFile& writer) + : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { _encoded = true; } + + // overrides of ld::Atom + virtual const char* name() const { return "fixup chain info"; } + // overrides of LinkEditAtom + virtual void encode() const; + +private: + typedef typename A::P P; + typedef typename A::P::E E; + typedef typename A::P::uint_t pint_t; + + + static ld::Section _s_section; +}; + +template +ld::Section ChainedInfoAtom::_s_section("__LINKEDIT", "__chainfixups", ld::Section::typeLinkEdit, true); + + + +template +void ChainedInfoAtom::encode() const +{ + this->_encodedData.bytes().reserve(1024); + + uint16_t format = DYLD_CHAINED_IMPORT; + if ( _writer._chainedFixupBinds.hasHugeAddends() ) + format = DYLD_CHAINED_IMPORT_ADDEND64; + else if ( _writer._chainedFixupBinds.hasLargeAddends() ) + format = DYLD_CHAINED_IMPORT_ADDEND; + dyld_chained_fixups_header header; + header.fixups_version = 0; + header.starts_offset = sizeof(dyld_chained_fixups_header); + header.imports_offset = 0; // fixed up later + header.symbols_offset = 0; // fixed up later + header.imports_count = _writer._chainedFixupBinds.count(); + header.imports_format = format; + header.symbols_format = 0; + this->_encodedData.append_mem(&header, sizeof(dyld_chained_fixups_header)); + const unsigned segsHeaderOffset = this->_encodedData.size(); + + // write starts table + dyld_chained_starts_in_image segs; + segs.seg_count = _writer._chainedFixupSegments.size(); + segs.seg_info_offset[0] = 0; + this->_encodedData.append_mem(&segs, sizeof(dyld_chained_starts_in_image)); + uint32_t emptyOffset = 0; + for (unsigned i=1; i < _writer._chainedFixupSegments.size(); ++i) + this->_encodedData.append_mem(&emptyOffset, sizeof(uint32_t)); // fixed up later if segment used + unsigned segIndex = 0; + uint64_t baseAddress = 0; + uint64_t maxRebaseAddress = 0; + for (OutputFile::ChainedFixupSegInfo& segInfo : _writer._chainedFixupSegments) { + if ( strcmp(segInfo.name, "__TEXT") == 0 ) + baseAddress = segInfo.startAddr; + else if ( strcmp(segInfo.name, "__LINKEDIT") == 0 ) + maxRebaseAddress = (segInfo.startAddr - baseAddress + 0x00100000-1) & -0x00100000; // align to 1MB + } + _writer._chainedFixupBinds.setMaxRebase(maxRebaseAddress); + for (OutputFile::ChainedFixupSegInfo& segInfo : _writer._chainedFixupSegments) { + if ( !segInfo.pages.empty() ) { + uint32_t startBytesPerPage = sizeof(uint16_t); + if ( segInfo.pointerFormat == DYLD_CHAINED_PTR_32 ) + startBytesPerPage = 32; // guesstimate 32-bit chains go ~0.5K before needing a new start + dyld_chained_starts_in_segment aSeg; + aSeg.size = sizeof(dyld_chained_starts_in_segment) + segInfo.pages.size()*startBytesPerPage; + aSeg.page_size = segInfo.pageSize; + aSeg.pointer_format = segInfo.pointerFormat; + aSeg.segment_offset = segInfo.startAddr - baseAddress; + aSeg.max_valid_pointer = maxRebaseAddress; + aSeg.page_count = segInfo.pages.size(); + dyld_chained_starts_in_image* segHeader = (dyld_chained_starts_in_image*)(this->_encodedData.start()+segsHeaderOffset); + segHeader->seg_info_offset[segIndex] = this->_encodedData.size() - segsHeaderOffset; + this->_encodedData.append_mem(&aSeg, sizeof(dyld_chained_starts_in_segment)-sizeof(uint16_t)); + std::vector segChainOverflows; + for (OutputFile::ChainedFixupPageInfo& pageInfo : segInfo.pages) { + uint16_t startOffset = pageInfo.fixupOffsets.empty() ? DYLD_CHAINED_PTR_START_NONE : pageInfo.fixupOffsets.front(); + this->_encodedData.append_mem(&startOffset, sizeof(startOffset)); + } + if ( segInfo.pointerFormat == DYLD_CHAINED_PTR_32 ) { + // zero out chain overflow area + long padBytes = (startBytesPerPage-2) * segInfo.pages.size(); + for (long i=0; i < padBytes; ++i) + this->_encodedData.append_byte(0); + } + } + ++segIndex; + } + + // build imports and symbol table + __block std::vector imports; + __block std::vector importsAddend; + __block std::vector importsAddend64; + __block std::vector stringPool; + stringPool.push_back('\0'); + _writer._chainedFixupBinds.forEachBind(^(unsigned int bindOrdinal, const ld::Atom* importAtom, uint64_t addend) { + uint32_t libOrdinal; + bool isBind = _writer.needsBind(importAtom, nullptr, nullptr, nullptr, &libOrdinal); + assert(isBind); + const char* symName = importAtom->name(); + if ( header.imports_format == DYLD_CHAINED_IMPORT ) { + dyld_chained_import anImport; + anImport.lib_ordinal = libOrdinal; + anImport.weak_import = importAtom->weakImported(); + anImport.name_offset = stringPool.size(); + imports.push_back(anImport); + } + else if ( header.imports_format == DYLD_CHAINED_IMPORT_ADDEND ) { + dyld_chained_import_addend anImportA; + anImportA.lib_ordinal = libOrdinal; + anImportA.weak_import = importAtom->weakImported(); + anImportA.name_offset = stringPool.size(); + anImportA.addend = addend; + importsAddend.push_back(anImportA); + } + else { + dyld_chained_import_addend64 anImportA64; + anImportA64.lib_ordinal = libOrdinal; + anImportA64.weak_import = importAtom->weakImported(); + anImportA64.name_offset = stringPool.size(); + anImportA64.addend = addend; + importsAddend64.push_back(anImportA64); + } + stringPool.insert(stringPool.end(), symName, &symName[strlen(symName)+1]); + }); + + // write imports and symbol table + dyld_chained_fixups_header* chainHeader = (dyld_chained_fixups_header*)(this->_encodedData.start()); + switch ( header.imports_format ) { + case DYLD_CHAINED_IMPORT: + this->_encodedData.pad_to_size(4); + chainHeader = (dyld_chained_fixups_header*)(this->_encodedData.start()); + chainHeader->imports_offset = this->_encodedData.size(); + this->_encodedData.append_mem(&imports[0], sizeof(dyld_chained_import)*imports.size()); + break; + case DYLD_CHAINED_IMPORT_ADDEND: + this->_encodedData.pad_to_size(4); + chainHeader = (dyld_chained_fixups_header*)(this->_encodedData.start()); + chainHeader->imports_offset = this->_encodedData.size(); + this->_encodedData.append_mem(&importsAddend[0], sizeof(dyld_chained_import_addend)*importsAddend.size()); + break; + case DYLD_CHAINED_IMPORT_ADDEND64: + this->_encodedData.pad_to_size(8); + chainHeader = (dyld_chained_fixups_header*)(this->_encodedData.start()); + chainHeader->imports_offset = this->_encodedData.size(); + this->_encodedData.append_mem(&importsAddend64[0], sizeof(dyld_chained_import_addend64)*importsAddend64.size()); + break; + } + chainHeader = (dyld_chained_fixups_header*)(this->_encodedData.start()); + chainHeader->symbols_offset = this->_encodedData.size(); + this->_encodedData.append_mem(&stringPool[0], stringPool.size()); + + // align to pointer size + this->_encodedData.pad_to_size(sizeof(pint_t)); + + this->_encoded = true; +} + + template class ExportInfoAtom : public LinkEditAtom { @@ -998,7 +1430,7 @@ void ExportInfoAtom::encode() const entry.flags |= EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION; entry.other = this->_writer.compressedOrdinalForAtom(atom); if ( entry.other == BIND_SPECIAL_DYLIB_SELF ) { - warning("not adding explict export for symbol %s because it is already re-exported from dylib %s", entry.name, atom->file()->path()); + warning("not adding explict export for symbol %s because it is already re-exported from dylib %s", entry.name, atom->safeFilePath()); continue; } if ( atom->isAlias() ) { @@ -1135,6 +1567,12 @@ void SplitSegInfoV1Atom::addSplitSegInfo(uint64_t address, ld::Fixup::Ki case ld::Fixup::kindStoreTargetAddressLittleEndian64: _64bitPointerLocations.push_back(address); break; +#if SUPPORT_ARCH_arm64e + case ld::Fixup::kindStoreLittleEndianAuth64: + case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64: + assert(false); + break; +#endif default: warning("codegen at address 0x%08llX prevents image from working in dyld shared cache", address); break; @@ -1206,6 +1644,12 @@ void SplitSegInfoV1Atom::addSplitSegInfo(uint64_t address, ld::Fixup::Kin case ld::Fixup::kindStoreTargetAddressLittleEndian64: _64bitPointerLocations.push_back(address); break; +#if SUPPORT_ARCH_arm64e + case ld::Fixup::kindStoreLittleEndianAuth64: + case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64: + warning("authenticated pointer at address 0x%08llX prevents image from working in dyld shared cache", address); + break; +#endif default: warning("codegen at address 0x%08llX prevents image from working in dyld shared cache", address); break; diff --git a/cctools/ld64/src/ld/LinkEditClassic.hpp b/cctools/ld64/src/ld/LinkEditClassic.hpp index 2eab13b..e897a3c 100644 --- a/cctools/ld64/src/ld/LinkEditClassic.hpp +++ b/cctools/ld64/src/ld/LinkEditClassic.hpp @@ -303,7 +303,8 @@ bool SymbolTableAtom::addLocal(const ld::Atom* atom, StringPoolAtom* pool) symbolName = anonName; } } - entry.set_n_strx(pool->add(symbolName)); + // ER: Coalesce the string pools for the symbol table when linking objects together + entry.set_n_strx(pool->addUnique(symbolName)); // set n_type uint8_t type = N_SECT; @@ -414,6 +415,8 @@ void SymbolTableAtom::addGlobal(const ld::Atom* atom, StringPoolAtom* pool) desc |= N_NO_DEAD_STRIP; if ( (this->_options.outputKind() == Options::kObjectFile) && this->_state.allObjectFilesScatterable && isAltEntry(atom) ) desc |= N_ALT_ENTRY; + if ( (this->_options.outputKind() == Options::kObjectFile) && atom->cold() ) + desc |= N_COLD_FUNC; if ( (atom->definition() == ld::Atom::definitionRegular) && (atom->combine() == ld::Atom::combineByName) ) { desc |= N_WEAK_DEF; // support auto hidden weak symbols: .weak_def_can_be_hidden @@ -491,10 +494,7 @@ void SymbolTableAtom::addImport(const ld::Atom* atom, StringPoolAtom* pool) entry.set_n_type(N_UNDF | N_EXT); } else { - if ( this->_options.prebind() ) - entry.set_n_type(N_PBUD | N_EXT); - else - entry.set_n_type(N_UNDF | N_EXT); + entry.set_n_type(N_UNDF | N_EXT); } // set n_sect @@ -669,39 +669,18 @@ bool SymbolTableAtom::hasStabs(uint32_t& ssos, uint32_t& ssoe, uint32_t& sos, template void SymbolTableAtom::encode() { - uint32_t symbolIndex = 0; + // Note: We lay out the symbol table so that the strings for the stabs (local) symbols are at the + // end of the string pool. The stabs strings are not used when calculated the UUID for the image. + // If the stabs strings were not last, the string offsets for all other symbols may very which would alter the UUID. - // make nlist entries for all local symbols - std::vector& localAtoms = this->_writer._localAtoms; - std::vector& globalAtoms = this->_writer._exportedAtoms; - _locals.reserve(localAtoms.size()+this->_state.stabs.size()); - this->_writer._localSymbolsStartIndex = 0; - // make nlist entries for all debug notes - _stabsIndexStart = symbolIndex; - _stabsStringsOffsetStart = this->_writer._stringPoolAtom->currentOffset(); - for (std::vector::const_iterator sit=this->_state.stabs.begin(); sit != this->_state.stabs.end(); ++sit) { - macho_nlist

entry; - entry.set_n_type(sit->type); - entry.set_n_sect(sectionIndexForStab(*sit)); - entry.set_n_desc(sit->desc); - entry.set_n_value(valueForStab(*sit)); - entry.set_n_strx(stringOffsetForStab(*sit, this->_writer._stringPoolAtom)); - _locals.push_back(entry); - ++symbolIndex; - } - _stabsIndexEnd = symbolIndex; - _stabsStringsOffsetEnd = this->_writer._stringPoolAtom->currentOffset(); - for (std::vector::const_iterator it=localAtoms.begin(); it != localAtoms.end(); ++it) { - const ld::Atom* atom = *it; - if ( this->addLocal(atom, this->_writer._stringPoolAtom) ) - this->_writer._atomToSymbolIndex[atom] = symbolIndex++; - } - this->_writer._localSymbolsCount = symbolIndex; - + // reserve space for local symbols + uint32_t localsCount = _state.stabs.size() + this->_writer._localAtoms.size(); // make nlist entries for all global symbols + std::vector& globalAtoms = this->_writer._exportedAtoms; _globals.reserve(globalAtoms.size()); - this->_writer._globalSymbolsStartIndex = symbolIndex; + uint32_t symbolIndex = localsCount; + this->_writer._globalSymbolsStartIndex = localsCount; for (std::vector::const_iterator it=globalAtoms.begin(); it != globalAtoms.end(); ++it) { const ld::Atom* atom = *it; this->addGlobal(atom, this->_writer._stringPoolAtom); @@ -718,6 +697,31 @@ void SymbolTableAtom::encode() this->_writer._atomToSymbolIndex[*it] = symbolIndex++; } this->_writer._importSymbolsCount = symbolIndex - this->_writer._importSymbolsStartIndex; + + // go back to start and make nlist entries for all local symbols + std::vector& localAtoms = this->_writer._localAtoms; + _locals.reserve(localsCount); + symbolIndex = 0; + this->_writer._localSymbolsStartIndex = 0; + _stabsIndexStart = 0; + _stabsStringsOffsetStart = this->_writer._stringPoolAtom->currentOffset(); + for (const ld::relocatable::File::Stab& stab : _state.stabs) { + macho_nlist

entry; + entry.set_n_type(stab.type); + entry.set_n_sect(sectionIndexForStab(stab)); + entry.set_n_desc(stab.desc); + entry.set_n_value(valueForStab(stab)); + entry.set_n_strx(stringOffsetForStab(stab, this->_writer._stringPoolAtom)); + _locals.push_back(entry); + ++symbolIndex; + } + _stabsIndexEnd = symbolIndex; + _stabsStringsOffsetEnd = this->_writer._stringPoolAtom->currentOffset(); + for (const ld::Atom* atom : localAtoms) { + if ( this->addLocal(atom, this->_writer._stringPoolAtom) ) + this->_writer._atomToSymbolIndex[atom] = symbolIndex++; + } + this->_writer._localSymbolsCount = symbolIndex; } template @@ -756,6 +760,9 @@ public: virtual void addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind, const ld::Atom* inAtom, uint32_t offsetInAtom, bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc, +#if SUPPORT_ARCH_arm64e + ld::Fixup* fixupWithAuthData, +#endif const ld::Atom* toTarget, uint64_t toAddend, const ld::Atom* fromTarget, uint64_t fromAddend) = 0; protected: @@ -800,6 +807,9 @@ public: virtual void addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind, const ld::Atom* inAtom, uint32_t offsetInAtom, bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc, +#if SUPPORT_ARCH_arm64e + ld::Fixup* fixupWithAuthData, +#endif const ld::Atom* toTarget, uint64_t toAddend, const ld::Atom* fromTarget, uint64_t fromAddend) { } @@ -897,6 +907,9 @@ public: virtual void addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind, const ld::Atom* inAtom, uint32_t offsetInAtom, bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc, +#if SUPPORT_ARCH_arm64e + ld::Fixup* fixupWithAuthData, +#endif const ld::Atom* toTarget, uint64_t toAddend, const ld::Atom* fromTarget, uint64_t fromAddend) { } @@ -1056,6 +1069,9 @@ public: virtual void addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind, const ld::Atom* inAtom, uint32_t offsetInAtom, bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc, +#if SUPPORT_ARCH_arm64e + ld::Fixup* fixupWithAuthData, +#endif const ld::Atom* toTarget, uint64_t toAddend, const ld::Atom* fromTarget, uint64_t fromAddend); @@ -1075,6 +1091,10 @@ private: uint64_t toAddend; const ld::Atom* fromTarget; uint64_t fromAddend; +#if SUPPORT_ARCH_arm64e + bool hasAuthData; + ld::Fixup::AuthData authData; +#endif }; uint32_t sectSymNum(bool external, const ld::Atom* target); void encodeSectionReloc(ld::Internal::FinalSection* sect, @@ -1820,6 +1840,27 @@ void SectionRelocationsAtom::encodeSectionReloc(ld::Internal::FinalSectio relocs.push_back(reloc1); break; + case ld::Fixup::kindStoreARM64TLVPLoadPageOff12: + case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12: + reloc1.set_r_address(address); + reloc1.set_r_symbolnum(symbolNum); + reloc1.set_r_pcrel(false); + reloc1.set_r_length(2); + reloc1.set_r_extern(external); + reloc1.set_r_type(ARM64_RELOC_TLVP_LOAD_PAGEOFF12); + relocs.push_back(reloc1); + break; + + case ld::Fixup::kindStoreARM64TLVPLoadPage21: + case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21: + reloc1.set_r_address(address); + reloc1.set_r_symbolnum(symbolNum); + reloc1.set_r_pcrel(true); + reloc1.set_r_length(2); + reloc1.set_r_extern(external); + reloc1.set_r_type(ARM64_RELOC_TLVP_LOAD_PAGE21); + relocs.push_back(reloc1); + break; case ld::Fixup::kindStoreLittleEndian64: case ld::Fixup::kindStoreTargetAddressLittleEndian64: @@ -1903,6 +1944,33 @@ void SectionRelocationsAtom::encodeSectionReloc(ld::Internal::FinalSectio relocs.push_back(reloc1); break; +#if SUPPORT_ARCH_arm64e + case ld::Fixup::kindStoreLittleEndianAuth64: + case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64: { + assert(entry.fromTarget == NULL); + assert(entry.hasAuthData); + + // An authenticated pointer is: + // { + // int32_t addend; + // uint16_t diversityData; + // uint16_t hasAddressDiversity : 1; + // uint16_t key : 2; + // uint16_t zeroes : 11; + // uint16_t zero : 1; + // uint16_t authenticated : 1; + // } + reloc1.set_r_address(address); + reloc1.set_r_symbolnum(symbolNum); + reloc1.set_r_pcrel(false); + reloc1.set_r_length(3); + reloc1.set_r_extern(external); + reloc1.set_r_type(ARM64_RELOC_AUTHENTICATED_POINTER); + relocs.push_back(reloc1); + } + break; +#endif + default: assert(0 && "need to handle arm64 -r reloc"); @@ -1916,6 +1984,9 @@ template void SectionRelocationsAtom::addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind kind, const ld::Atom* inAtom, uint32_t offsetInAtom, bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc, +#if SUPPORT_ARCH_arm64e + ld::Fixup* fixupWithAuthData, +#endif const ld::Atom* toTarget, uint64_t toAddend, const ld::Atom* fromTarget, uint64_t fromAddend) { @@ -1929,6 +2000,14 @@ void SectionRelocationsAtom::addSectionReloc(ld::Internal::FinalSection* sect entry.toAddend = toAddend; entry.fromTarget = fromTarget; entry.fromAddend = fromAddend; +#if SUPPORT_ARCH_arm64e + if (fixupWithAuthData) { + entry.hasAuthData = true; + entry.authData = fixupWithAuthData->u.authData; + } else { + entry.hasAuthData = false; + } +#endif static ld::Internal::FinalSection* lastSection = NULL; static SectionAndEntries* lastSectionAndEntries = NULL; @@ -1998,6 +2077,7 @@ private: void encodeStubSection(ld::Internal::FinalSection* sect); void encodeLazyPointerSection(ld::Internal::FinalSection* sect); void encodeNonLazyPointerSection(ld::Internal::FinalSection* sect); + void encodeTLVPointerSection(ld::Internal::FinalSection* sect); uint32_t symIndexOfStubAtom(const ld::Atom*); uint32_t symIndexOfLazyPointerAtom(const ld::Atom*); uint32_t symIndexOfNonLazyPointerAtom(const ld::Atom*); @@ -2047,10 +2127,20 @@ uint32_t IndirectSymbolTableAtom::symIndexOfStubAtom(const ld::Atom* stubAtom template uint32_t IndirectSymbolTableAtom::symIndexOfLazyPointerAtom(const ld::Atom* lpAtom) { - for (ld::Fixup::iterator fit = lpAtom->fixupsBegin(); fit != lpAtom->fixupsEnd(); ++fit) { - if ( fit->kind == ld::Fixup::kindLazyTarget ) { - assert(fit->binding == ld::Fixup::bindingDirectlyBound); - return symbolIndex(fit->u.target); + if ( lpAtom->contentType() == ld::Atom::typeLazyPointer || lpAtom->contentType() == ld::Atom::typeLazyDylibPointer ) { + for (ld::Fixup::iterator fit = lpAtom->fixupsBegin(); fit != lpAtom->fixupsEnd(); ++fit) { + if ( fit->kind == ld::Fixup::kindLazyTarget ) { + assert(fit->binding == ld::Fixup::bindingDirectlyBound); + return symbolIndex(fit->u.target); + } + } + } + else if ( lpAtom->contentType() == ld::Atom::typeNonLazyPointer ) { + for (ld::Fixup::iterator fit = lpAtom->fixupsBegin(); fit != lpAtom->fixupsEnd(); ++fit) { + if ( (fit->kind == ld::Fixup::kindStoreTargetAddressLittleEndian32) || (fit->kind == ld::Fixup::kindStoreTargetAddressLittleEndian64) ) { + assert(fit->binding == ld::Fixup::bindingDirectlyBound); + return symbolIndex(fit->u.target); + } } } throw "internal error: lazy pointer missing fixupLazyTarget fixup"; @@ -2061,9 +2151,18 @@ uint32_t IndirectSymbolTableAtom::symIndexOfNonLazyPointerAtom(const ld::Atom { //fprintf(stderr, "symIndexOfNonLazyPointerAtom(%p) %s\n", nlpAtom, nlpAtom->name()); for (ld::Fixup::iterator fit = nlpAtom->fixupsBegin(); fit != nlpAtom->fixupsEnd(); ++fit) { - // non-lazy-pointer to a stripped symbol => no symbol index - if ( fit->clusterSize != ld::Fixup::k1of1 ) - return INDIRECT_SYMBOL_LOCAL; +#if SUPPORT_ARCH_arm64e + // Skip authentication fixups + if ( fit->clusterSize == ld::Fixup::k1of2 ) { + if ( fit->kind != ld::Fixup::kindSetAuthData ) + break; + ++fit; + } else +#endif + { + if ( fit->clusterSize != ld::Fixup::k1of1 ) + return INDIRECT_SYMBOL_LOCAL; + } const ld::Atom* target; switch ( fit->binding ) { case ld::Fixup::bindingDirectlyBound: @@ -2153,6 +2252,16 @@ void IndirectSymbolTableAtom::encodeNonLazyPointerSection(ld::Internal::Final } } +template +void IndirectSymbolTableAtom::encodeTLVPointerSection(ld::Internal::FinalSection* sect) +{ + sect->indirectSymTabStartIndex = _entries.size(); + for (std::vector::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) { + _entries.push_back(symIndexOfNonLazyPointerAtom(*ait)); + } +} + + template void IndirectSymbolTableAtom::encode() { @@ -2184,6 +2293,9 @@ void IndirectSymbolTableAtom::encode() case ld::Section::typeNonLazyPointer: this->encodeNonLazyPointerSection(sect); break; + case ld::Section::typeTLVPointers: + this->encodeTLVPointerSection(sect); + break; default: break; } diff --git a/cctools/ld64/src/ld/Makefile.am b/cctools/ld64/src/ld/Makefile.am index 98b93df..0ce1d31 100644 --- a/cctools/ld64/src/ld/Makefile.am +++ b/cctools/ld64/src/ld/Makefile.am @@ -7,9 +7,10 @@ ld_LDADD = \ $(top_builddir)/ld64/src/ld/parsers/libParsers.la \ $(top_builddir)/ld64/src/ld/passes/libPasses.la \ $(UUID_LIB) \ - $(LTO_LIB) \ + $(LTO_RPATH) \ $(XAR_LIB) \ - $(DL_LIB) + $(DL_LIB) \ + $(TAPI_LIB) ld_LDFLAGS = $(PTHREAD_FLAGS) $(EXECINFO_LIB) @@ -17,6 +18,7 @@ ld_CXXFLAGS = \ -D__DARWIN_UNIX03 \ $(WARNINGS) \ $(LTO_DEF) \ + $(TAPI_DEF) \ $(ENDIAN_FLAG) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/include/foreign \ @@ -34,6 +36,7 @@ ld_CFLAGS = \ -D__DARWIN_UNIX03 \ $(WARNINGS) \ $(LTO_DEF) \ + $(TAPI_DEF) \ $(ENDIAN_FLAG) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/include/foreign \ @@ -55,4 +58,5 @@ ld_SOURCES = \ Resolver.cpp \ Snapshot.cpp \ SymbolTable.cpp \ + PlatformSupport.cpp \ code-sign-blobs/blob.cpp diff --git a/cctools/ld64/src/ld/Makefile.in b/cctools/ld64/src/ld/Makefile.in new file mode 100644 index 0000000..15dd347 --- /dev/null +++ b/cctools/ld64/src/ld/Makefile.in @@ -0,0 +1,928 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = ld$(EXEEXT) +subdir = ld64/src/ld +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am__dirstamp = $(am__leading_dot)dirstamp +am_ld_OBJECTS = ld-debugline.$(OBJEXT) ld-InputFiles.$(OBJEXT) \ + ld-ld.$(OBJEXT) ld-Options.$(OBJEXT) ld-OutputFile.$(OBJEXT) \ + ld-Resolver.$(OBJEXT) ld-Snapshot.$(OBJEXT) \ + ld-SymbolTable.$(OBJEXT) ld-PlatformSupport.$(OBJEXT) \ + code-sign-blobs/ld-blob.$(OBJEXT) +ld_OBJECTS = $(am_ld_OBJECTS) +am__DEPENDENCIES_1 = +ld_DEPENDENCIES = $(top_builddir)/ld64/src/3rd/libhelper.la \ + $(top_builddir)/ld64/src/3rd/BlocksRuntime/libBlocksRuntime.la \ + $(top_builddir)/ld64/src/ld/parsers/libParsers.la \ + $(top_builddir)/ld64/src/ld/passes/libPasses.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +ld_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(ld_CXXFLAGS) \ + $(CXXFLAGS) $(ld_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(ld_SOURCES) +DIST_SOURCES = $(ld_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = parsers passes +ld_LDADD = \ + $(top_builddir)/ld64/src/3rd/libhelper.la \ + $(top_builddir)/ld64/src/3rd/BlocksRuntime/libBlocksRuntime.la \ + $(top_builddir)/ld64/src/ld/parsers/libParsers.la \ + $(top_builddir)/ld64/src/ld/passes/libPasses.la \ + $(UUID_LIB) \ + $(LTO_RPATH) \ + $(XAR_LIB) \ + $(DL_LIB) \ + $(TAPI_LIB) + +ld_LDFLAGS = $(PTHREAD_FLAGS) $(EXECINFO_LIB) +ld_CXXFLAGS = \ + -D__DARWIN_UNIX03 \ + $(WARNINGS) \ + $(LTO_DEF) \ + $(TAPI_DEF) \ + $(ENDIAN_FLAG) \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/include/foreign \ + -I$(top_srcdir)/ld64/src \ + -I$(top_srcdir)/ld64/src/abstraction \ + -I$(top_srcdir)/ld64/src/3rd \ + -I$(top_srcdir)/ld64/src/3rd/BlocksRuntime \ + -I$(top_srcdir)/ld64/src/3rd/include \ + -I$(top_srcdir)/ld64/src/ld \ + -I$(top_srcdir)/ld64/src/ld/parsers \ + -I$(top_srcdir)/ld64/src/ld/passes \ + -DPROGRAM_PREFIX="\"$(PROGRAM_PREFIX)\"" + +ld_CFLAGS = \ + -D__DARWIN_UNIX03 \ + $(WARNINGS) \ + $(LTO_DEF) \ + $(TAPI_DEF) \ + $(ENDIAN_FLAG) \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/include/foreign \ + -I$(top_srcdir)/ld64/src \ + -I$(top_srcdir)/ld64/src/abstraction \ + -I$(top_srcdir)/ld64/src/3rd \ + -I$(top_srcdir)/ld64/src/3rd/BlocksRuntime \ + -I$(top_srcdir)/ld64/src/ld \ + -I$(top_srcdir)/ld64/src/ld/parsers \ + -I$(top_srcdir)/ld64/src/ld/passes \ + -DPROGRAM_PREFIX="\"$(PROGRAM_PREFIX)\"" + +ld_SOURCES = \ + debugline.c \ + InputFiles.cpp \ + ld.cpp \ + Options.cpp \ + OutputFile.cpp \ + Resolver.cpp \ + Snapshot.cpp \ + SymbolTable.cpp \ + PlatformSupport.cpp \ + code-sign-blobs/blob.cpp + +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .cpp .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps ld64/src/ld/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps ld64/src/ld/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +code-sign-blobs/$(am__dirstamp): + @$(MKDIR_P) code-sign-blobs + @: > code-sign-blobs/$(am__dirstamp) +code-sign-blobs/ld-blob.$(OBJEXT): code-sign-blobs/$(am__dirstamp) + +ld$(EXEEXT): $(ld_OBJECTS) $(ld_DEPENDENCIES) $(EXTRA_ld_DEPENDENCIES) + @rm -f ld$(EXEEXT) + $(AM_V_CXXLD)$(ld_LINK) $(ld_OBJECTS) $(ld_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f code-sign-blobs/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +ld-debugline.o: debugline.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CFLAGS) $(CFLAGS) -c -o ld-debugline.o `test -f 'debugline.c' || echo '$(srcdir)/'`debugline.c + +ld-debugline.obj: debugline.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CFLAGS) $(CFLAGS) -c -o ld-debugline.obj `if test -f 'debugline.c'; then $(CYGPATH_W) 'debugline.c'; else $(CYGPATH_W) '$(srcdir)/debugline.c'; fi` + +.cpp.o: + $(AM_V_CXX)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(AM_V_CXX)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: + $(AM_V_CXX)$(LTCXXCOMPILE) -c -o $@ $< + +ld-InputFiles.o: InputFiles.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o ld-InputFiles.o `test -f 'InputFiles.cpp' || echo '$(srcdir)/'`InputFiles.cpp + +ld-InputFiles.obj: InputFiles.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o ld-InputFiles.obj `if test -f 'InputFiles.cpp'; then $(CYGPATH_W) 'InputFiles.cpp'; else $(CYGPATH_W) '$(srcdir)/InputFiles.cpp'; fi` + +ld-ld.o: ld.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o ld-ld.o `test -f 'ld.cpp' || echo '$(srcdir)/'`ld.cpp + +ld-ld.obj: ld.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o ld-ld.obj `if test -f 'ld.cpp'; then $(CYGPATH_W) 'ld.cpp'; else $(CYGPATH_W) '$(srcdir)/ld.cpp'; fi` + +ld-Options.o: Options.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o ld-Options.o `test -f 'Options.cpp' || echo '$(srcdir)/'`Options.cpp + +ld-Options.obj: Options.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o ld-Options.obj `if test -f 'Options.cpp'; then $(CYGPATH_W) 'Options.cpp'; else $(CYGPATH_W) '$(srcdir)/Options.cpp'; fi` + +ld-OutputFile.o: OutputFile.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o ld-OutputFile.o `test -f 'OutputFile.cpp' || echo '$(srcdir)/'`OutputFile.cpp + +ld-OutputFile.obj: OutputFile.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o ld-OutputFile.obj `if test -f 'OutputFile.cpp'; then $(CYGPATH_W) 'OutputFile.cpp'; else $(CYGPATH_W) '$(srcdir)/OutputFile.cpp'; fi` + +ld-Resolver.o: Resolver.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o ld-Resolver.o `test -f 'Resolver.cpp' || echo '$(srcdir)/'`Resolver.cpp + +ld-Resolver.obj: Resolver.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o ld-Resolver.obj `if test -f 'Resolver.cpp'; then $(CYGPATH_W) 'Resolver.cpp'; else $(CYGPATH_W) '$(srcdir)/Resolver.cpp'; fi` + +ld-Snapshot.o: Snapshot.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o ld-Snapshot.o `test -f 'Snapshot.cpp' || echo '$(srcdir)/'`Snapshot.cpp + +ld-Snapshot.obj: Snapshot.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o ld-Snapshot.obj `if test -f 'Snapshot.cpp'; then $(CYGPATH_W) 'Snapshot.cpp'; else $(CYGPATH_W) '$(srcdir)/Snapshot.cpp'; fi` + +ld-SymbolTable.o: SymbolTable.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o ld-SymbolTable.o `test -f 'SymbolTable.cpp' || echo '$(srcdir)/'`SymbolTable.cpp + +ld-SymbolTable.obj: SymbolTable.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o ld-SymbolTable.obj `if test -f 'SymbolTable.cpp'; then $(CYGPATH_W) 'SymbolTable.cpp'; else $(CYGPATH_W) '$(srcdir)/SymbolTable.cpp'; fi` + +ld-PlatformSupport.o: PlatformSupport.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o ld-PlatformSupport.o `test -f 'PlatformSupport.cpp' || echo '$(srcdir)/'`PlatformSupport.cpp + +ld-PlatformSupport.obj: PlatformSupport.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o ld-PlatformSupport.obj `if test -f 'PlatformSupport.cpp'; then $(CYGPATH_W) 'PlatformSupport.cpp'; else $(CYGPATH_W) '$(srcdir)/PlatformSupport.cpp'; fi` + +code-sign-blobs/ld-blob.o: code-sign-blobs/blob.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o code-sign-blobs/ld-blob.o `test -f 'code-sign-blobs/blob.cpp' || echo '$(srcdir)/'`code-sign-blobs/blob.cpp + +code-sign-blobs/ld-blob.obj: code-sign-blobs/blob.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ld_CXXFLAGS) $(CXXFLAGS) -c -o code-sign-blobs/ld-blob.obj `if test -f 'code-sign-blobs/blob.cpp'; then $(CYGPATH_W) 'code-sign-blobs/blob.cpp'; else $(CYGPATH_W) '$(srcdir)/code-sign-blobs/blob.cpp'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(PROGRAMS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f code-sign-blobs/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-binPROGRAMS clean-generic clean-libtool \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-binPROGRAMS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/ld64/src/ld/Options.cpp b/cctools/ld64/src/ld/Options.cpp index c07958b..0d14849 100644 --- a/cctools/ld64/src/ld/Options.cpp +++ b/cctools/ld64/src/ld/Options.cpp @@ -27,31 +27,45 @@ #include #include #include +#ifdef __APPLE__ // ld64-port #include +#endif #include #include #include #include +#ifndef __ANDROID__ // ld64-port #include +#endif #include #include +#ifdef TAPI_SUPPORT +#include +#endif /* TAPI_SUPPORT */ #include #include #include +#include "ld.hpp" #include "Options.h" #include "Architectures.hpp" #include "MachOFileAbstraction.hpp" #include "Snapshot.h" +#include "macho_relocatable_file.h" // from FunctionNameDemangle.h extern "C" size_t fnd_get_demangled_name(const char *mangledName, char *outputBuffer, size_t length); +#define VAL(x) #x +#define STRINGIFY(x) VAL(x) + // upward dependency on lto::version() namespace lto { extern const char* version(); + extern unsigned static_api_version(); + extern unsigned runtime_api_version(); } // magic to place command line in crash reports @@ -116,42 +130,83 @@ void throwf(const char* format, ...) throw t; } +std::vector Options::FileInfo::lib_cli_argument() const +{ + // fIndirectDylib unused + bool special = options.fReExport || options.fLazyLoad || options.fUpward; + + if (options.fBundleLoader) { + if (special) throw "internal error; bundle loader cannot have these extra attributes"; + return {"-bundle-loader", path}; + } else { + std::vector args = {}; + if (options.fReExport) { + args.push_back("-reexport_library"); + args.push_back(path); + } + else if (options.fLazyLoad) { + args.push_back("-lazy_library"); + args.push_back(path); + } + else if (options.fUpward) { + args.push_back("-upward_library"); + args.push_back(path); + } + else { + // bare path + args.push_back(path); + } + + // This one alone can be combined with the others + if (options.fWeakImport) { + args.push_back("-weak_library"); + args.push_back(path); + } + + return args; + } +} bool Options::FileInfo::checkFileExists(const Options& options, const char *p) { + if (isInlined) { + modTime = 0; + return true; + } struct stat statBuffer; if (p == NULL) p = path; if ( stat(p, &statBuffer) == 0 ) { if (p != path) path = strdup(p); - fileLen = statBuffer.st_size; modTime = statBuffer.st_mtime; return true; } - if ( options.dumpDependencyInfo() ) - options.dumpDependency(Options::depNotFound, p); + options.addDependency(Options::depNotFound, p); +// fprintf(stderr, "not found: %s\n", p); return false; } Options::Options(int argc, const char* argv[]) - : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable), - fHasPreferredSubType(false), fArchSupportsThumb2(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false), - fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false), + : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), + fFallbackArchitecture(0), fFallbackSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable), + fHasPreferredSubType(false), fArchSupportsThumb2(false), fBindAtLoad(false), fKeepPrivateExterns(false), + fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false), fInterposeMode(kInterposeNone), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace), - fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName(NULL), - fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL), - fBaseWritableAddress(0), fSplitSegs(false), + fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName(NULL), + fBaseAddress(0), fMaxAddress(0xFFFFFFFFFFFFFFFFULL), + fBaseWritableAddress(0), fExportMode(kExportDefault), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir), fUndefinedTreatment(kUndefinedError), fMessagesPrefixedWithArchitecture(true), fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak), fClientName(NULL), fUmbrellaName(NULL), fInitFunctionName(NULL), fDotOutputFile(NULL), fExecutablePath(NULL), - fBundleLoader(NULL), fDtraceScriptName(NULL), fSegAddrTablePath(NULL), fMapPath(NULL), - fDyldInstallPath("/usr/lib/dyld"), fTempLtoObjectPath(NULL), fOverridePathlibLTO(NULL), fLtoCpu(NULL), + fBundleLoader(NULL), fDtraceScriptName(NULL), fMapPath(NULL), + fDyldInstallPath("/usr/lib/dyld"), fLtoCachePath(NULL), fTempLtoObjectPath(NULL), fOverridePathlibLTO(NULL), fLtoCpu(NULL), + fKextObjectsEnable(-1),fKextObjectsDirPath(NULL),fToolchainPath(NULL),fOrderFilePath(NULL), fZeroPageSize(ULLONG_MAX), fStackSize(0), fStackAddr(0), fSourceVersion(0), fSDKVersion(0), fExecutableStack(false), fNonExecutableHeap(false), fDisableNonExecutableHeap(false), - fMinimumHeaderPad(32), fSegmentAlignment(4096), + fMinimumHeaderPad(32), fSegmentAlignment(LD_PAGE_SIZE), fCommonsMode(kCommonsIgnoreDylibs), fUUIDMode(kUUIDContent), fLocalSymbolHandling(kLocalSymbolsAll), fWarnCommons(false), fVerbose(false), fKeepRelocations(false), fWarnStabs(false), fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false), @@ -161,8 +216,10 @@ Options::Options(int argc, const char* argv[]) fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false), fUsingLazyDylibLinking(false), fEncryptable(true), fEncryptableForceOn(false), fEncryptableForceOff(false), fOrderData(true), fMarkDeadStrippableDylib(false), - fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false), - fAllowCpuSubtypeMismatches(false), fEnforceDylibSubtypesMatch(false), fUseSimplifiedDylibReExports(false), + fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), + fMakeThreadedStartsSection(false), fNoEHLabels(false), + fAllowCpuSubtypeMismatches(false), fEnforceDylibSubtypesMatch(false), + fWarnOnSwiftABIVersionMismatches(false), fUseSimplifiedDylibReExports(false), fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false), fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false), fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false), @@ -170,36 +227,40 @@ Options::Options(int argc, const char* argv[]) fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true), fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false), fAutoOrderInitializers(true), fOptimizeZeroFill(true), fMergeZeroFill(false), fLogObjectFiles(false), - fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false), - fOutputSlidable(false), fWarnWeakExports(false), + fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false), fTraceEmitJSON(false), + fOutputSlidable(false), fWarnWeakExports(false), fNoWeakExports(false), fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false), fDemangle(false), fTLVSupport(false), fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false), - fVersionLoadCommandForcedOff(false), fFunctionStartsLoadCommand(false), + fVersionLoadCommandForcedOff(false), fForceLegacyVersionLoadCommands(false), fFunctionStartsLoadCommand(false), fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false), fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false), fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false), fNeedsThreadLoadCommand(false), fEntryPointLoadCommand(false), - fEntryPointLoadCommandForceOn(false), fEntryPointLoadCommandForceOff(false), - fSourceVersionLoadCommand(false), + fSourceVersionLoadCommand(false), fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false), - fTargetIOSSimulator(false), fExportDynamic(false), fAbsoluteSymbols(false), - fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true), + fExportDynamic(false), fAbsoluteSymbols(false), + fAllowSimulatorToLinkWithMacOSX(false), fSimulatorSupportDylib(false), fKeepDwarfUnwind(true), fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false), fVerboseOptimizationHints(false), fIgnoreOptimizationHints(false), fGenerateDtraceDOF(true), fAllowBranchIslands(true), fTraceSymbolLayout(false), fMarkAppExtensionSafe(false), fCheckAppExtensionSafe(false), fForceLoadSwiftLibs(false), fSharedRegionEncodingV2(false), fUseDataConstSegment(false), - fUseDataConstSegmentForceOn(false), fUseDataConstSegmentForceOff(false), + fUseDataConstSegmentForceOn(false), fUseDataConstSegmentForceOff(false), fUseTextExecSegment(false), fBundleBitcode(false), fHideSymbols(false), fVerifyBitcode(false), - fReverseMapUUIDRename(false), fDeDupe(true), fVerboseDeDupe(false), + fReverseMapUUIDRename(false), fDeDupe(true), fVerboseDeDupe(false), fMakeInitializersIntoOffsets(false), + fUseLinkedListBinding(false), fMakeChainedFixups(false), fMakeChainedFixupsSection(false), fNoLazyBinding(false), fDebugVariant(false), fReverseMapPath(NULL), fLTOCodegenOnly(false), - fIgnoreAutoLink(false), fAllowDeadDups(false), fBitcodeKind(kBitcodeProcess), - fPlatform(kPlatformUnknown), fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL), - fMacVersionMin(ld::macVersionUnset), fIOSVersionMin(ld::iOSVersionUnset), fWatchOSVersionMin(ld::wOSVersionUnset), // ld64-port: added fWatchOSVersionMin(ld::wOSVersionUnset) - https://gist.github.com/tpoechtrager/6537a058dfb4d587fff4 - fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL), - fDependencyInfoPath(NULL), fDependencyFileDescriptor(-1), fMaxDefaultCommonAlign(0), fFilePreference(kModTime), - fForceTextBasedStub(false) + fIgnoreAutoLink(false), fAllowDeadDups(false), fAllowWeakImports(true), fInitializersTreatment(Options::kInvalid), + fZeroModTimeInDebugMap(false), fBitcodeKind(kBitcodeProcess), + fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL), fPlatfromVersionCmdFound(false), fInternalSDK(false), + fSaveTempFiles(false), fLinkSnapshot(this), fSnapshotRequested(false), fPipelineFifo(NULL), + fDependencyInfoPath(NULL), fBuildContextName(NULL), fTraceFileDescriptor(-1), fMaxDefaultCommonAlign(0), + fUnalignedPointerTreatment(kUnalignedPointerIgnore), +#ifdef TAPI_SUPPORT + fPreferTAPIFile(false), +#endif + fOSOPrefixPath(NULL) { this->checkForClassic(argc, argv); this->parsePreCommandLineEnvironmentSettings(); @@ -208,17 +269,15 @@ Options::Options(int argc, const char* argv[]) this->reconfigureDefaults(); this->checkIllegalOptionCombinations(); - if ( this->dumpDependencyInfo() ) { - this->dumpDependency(depOutputFile, fOutputFile); - if ( fMapPath != NULL ) - this->dumpDependency(depOutputFile, fMapPath); - } + this->addDependency(depOutputFile, fOutputFile); + if ( fMapPath != NULL ) + this->addDependency(depOutputFile, fMapPath); } Options::~Options() { - if ( fDependencyFileDescriptor != -1 ) - ::close(fDependencyFileDescriptor); + if ( fTraceFileDescriptor != -1 ) + ::close(fTraceFileDescriptor); } bool Options::errorBecauseOfWarnings() const @@ -302,6 +361,22 @@ bool Options::allGlobalsAreDeadStripRoots() const return false; } +bool Options::dyldLoadsOutput() const +{ + switch ( fOutputKind ) { + case Options::kStaticExecutable: + case Options::kPreload: + case Options::kObjectFile: + case Options::kKextBundle: + return false; + case Options::kDynamicExecutable: + case Options::kDynamicLibrary: + case Options::kDynamicBundle: + case Options::kDyld: + return true; + } + +} bool Options::keepRelocations() { @@ -325,25 +400,34 @@ uint32_t Options::initialSegProtection(const char* segName) const return it->init; } } - if ( strcmp(segName, "__PAGEZERO") == 0 ) { - return 0; + if ( strcmp(segName, "__TEXT") == 0 ) { + return ( fUseTextExecSegment ? VM_PROT_READ : (VM_PROT_READ | VM_PROT_EXECUTE) ); } - else if ( strcmp(segName, "__TEXT") == 0 ) { + else if ( strcmp(segName, "__TEXT_EXEC") == 0 ) { return VM_PROT_READ | VM_PROT_EXECUTE; } + else if ( strcmp(segName, "__PAGEZERO") == 0 ) { + return 0; + } else if ( strcmp(segName, "__LINKEDIT") == 0 ) { return VM_PROT_READ; } - + // all others default to read-write return VM_PROT_READ | VM_PROT_WRITE; } +bool Options::readOnlyDataSegment(const char* name) const +{ + // set SG_READ_ONLY on segment + // but not for shared cache dylibs (because __objc_const is not read-only) + return ( fUseDataConstSegment && (strcmp(name, "__DATA_CONST") == 0) && (!fSharedRegionEligible || (fOutputKind == Options::kDyld)) ); +} + uint32_t Options::maxSegProtection(const char* segName) const { - // iPhoneOS always uses same protection for max and initial - // simulator apps need to use MacOSX max-prot - if ( (fPlatform != kPlatformOSX) && !fTargetIOSSimulator ) + // i386 uses text-relocations so, need max prot to be rwx. All others have max==init + if ( fArchitecture != CPU_TYPE_I386 ) return initialSegProtection(segName); for(std::vector::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) { @@ -397,6 +481,9 @@ bool Options::hasCustomSectionAlignment(const char* segName, const char* sectNam if ( (strcmp(it->segmentName, segName) == 0) && (strcmp(it->sectionName, sectName) == 0) ) return true; } + if ( fEncryptable && (strcmp(sectName, "__oslogstring") == 0) && (strcmp(segName, "__TEXT") == 0) ) + return true; + return false; } @@ -406,6 +493,9 @@ uint8_t Options::customSectionAlignment(const char* segName, const char* sectNam if ( (strcmp(it->segmentName, segName) == 0) && (strcmp(it->sectionName, sectName) == 0) ) return it->alignment; } + if ( fEncryptable && (strcmp(sectName, "__oslogstring") == 0) && (strcmp(segName, "__TEXT") == 0) ) + return __builtin_ctz(fSegmentAlignment); + return 0; } @@ -510,6 +600,74 @@ void Options::loadSymbolOrderFile(const char* fileOfExports, NameToOrder& orderM // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table } +void Options::loadImplictZipperFile(const char *path, std::vector& paths) +{ + // read in whole file + int fd = ::open(path, O_RDONLY, 0); + if ( fd == -1 ) return; // Early exist if the file is not present + struct stat stat_buf; + ::fstat(fd, &stat_buf); + char* p = (char*)malloc(stat_buf.st_size); + if ( p == NULL ) + throwf("can't process auto zipper file: %s", path); + + if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size ) + throwf("can't process auto zipper file: %s", path); + + ::close(fd); + + // parse into paths and add to a vector + char * const end = &p[stat_buf.st_size]; + enum { lineStart, inInstallname, inComment } state = lineStart; + char* installnameStart = NULL; + for (char* s = p; s < end; ++s ) { + switch ( state ) { + case lineStart: + if ( *s =='#' ) { + state = inComment; + } + else if ( !isspace(*s) ) { + state = inInstallname; + installnameStart = s; + } + break; + case inInstallname: + if ( (*s == '\n') || (*s == '\r') ) { + *s = '\0'; + // removing any trailing spaces + char* last = s-1; + while ( isspace(*last) ) { + *last = '\0'; + --last; + } + paths.push_back(installnameStart); + state = lineStart; + } + break; + case inComment: + if ( (*s == '\n') || (*s == '\r') ) + state = lineStart; + break; + } + } + if ( state == inInstallname ) { + warning("missing line-end at end of file \"%s\"", path); + int len = end-installnameStart+1; + char* temp = new char[len]; + strlcpy(temp, installnameStart, len); + + // remove any trailing spaces + char* last = &temp[len-2]; + while ( isspace(*last) ) { + *last = '\0'; + --last; + } + paths.push_back(installnameStart); + } + + // Note: we do not free() the malloc buffer, because the strings are returned out via paths +} + bool Options::forceWeak(const char* symbolName) const { return fForceWeakSymbols.contains(symbolName); @@ -578,74 +736,47 @@ const std::vector* Options::sectionOrder(const char* segName) const return NULL; } -uint32_t Options::minOSversion() const -{ - switch (fPlatform) { - case kPlatformiOS: - return iOSVersionMin(); - case kPlatformOSX: - return macosxVersionMin(); - case kPlatformWatchOS: - return watchOSVersionMin(); -#if SUPPORT_APPLE_TV - case Options::kPlatform_tvOS: - return iOSVersionMin(); -#endif - default: - break; - } - return 0; -} - -void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype, Options::Platform platform) +void Options::setInferredArch(cpu_type_t type, cpu_subtype_t subtype) { + assert(fArchitecture == 0); for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) { if ( (type == t->cpuType) && (subtype == t->cpuSubType) ) { - fArchitecture = type; - fSubArchitecture = subtype; - fArchitectureName = t->archName; + fArchitecture = type; + fSubArchitecture = subtype; + fArchitectureName = t->archName; fHasPreferredSubType = t->isSubType; - fArchSupportsThumb2 = t->supportsThumb2; - fPlatform = platform; - switch ( type ) { - case CPU_TYPE_I386: - case CPU_TYPE_X86_64: - if ( (fPlatform == kPlatformOSX) && (fOutputKind != Options::kObjectFile) ) { - #ifdef DEFAULT_MACOSX_MIN_VERSION - warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION); - setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION); - #else - warning("-macosx_version_min not specified, assuming 10.6"); - fMacVersionMin = ld::mac10_6; - #endif - } - break; - case CPU_TYPE_ARM: - case CPU_TYPE_ARM64: - if ( (fPlatform == kPlatformiOS) && (fOutputKind != Options::kObjectFile) ) { - #if defined(DEFAULT_IPHONEOS_MIN_VERSION) - warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION); - setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION); - #else - warning("-ios_version_min not specified, assuming 6.0"); - setIOSVersionMin("6.0"); - #endif - } - break; + fArchSupportsThumb2 = t->supportsThumb2; +#if SUPPORT_ARCH_arm64e + if ( (fArchitecture == CPU_TYPE_ARM64) && (fSubArchitecture == CPU_SUBTYPE_ARM64E) ) { + fSupportsAuthenticatedPointers = true; } - fLinkSnapshot.recordArch(fArchitectureName); - // only use compressed LINKEDIT for: - // Mac OS X 10.6 or later - // iOS 3.1 or later - if ( !fMakeCompressedDyldInfo && minOS(ld::mac10_6, ld::iOS_3_1) && !fMakeCompressedDyldInfoForceOff ) - fMakeCompressedDyldInfo = true; - // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB - if ( minOS(ld::mac10_5, ld::iOS_2_0) ) - fUseSimplifiedDylibReExports = true; - return; +#endif + break; } } - fArchitectureName = "unknown architecture"; + if ( fArchitecture == 0 ) { + // some arch not in our table + fArchitecture = type; + fSubArchitecture = subtype; + fArchitectureName = "unknown"; + } + + fLinkSnapshot.recordArch(fArchitectureName); +} + +void Options::setInferredPlatform(ld::Platform platform, uint32_t minOsVers) +{ + assert(platforms().empty()); + fPlatforms.insert(ld::PlatformVersion(platform, minOsVers)); + + // only use compressed LINKEDIT for: + // Mac OS X 10.6 or later + // iOS 3.1 or later + if ( !fMakeCompressedDyldInfo && platforms().minOS(ld::version2009) && !fMakeCompressedDyldInfoForceOff ) + fMakeCompressedDyldInfo = true; + // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB + if ( platforms().minOS(ld::version2008) ) + fUseSimplifiedDylibReExports = true; } bool Options::armUsesZeroCostExceptions() const @@ -653,6 +784,35 @@ bool Options::armUsesZeroCostExceptions() const return ( (fArchitecture == CPU_TYPE_ARM) && (fSubArchitecture == CPU_SUBTYPE_ARM_V7K) ); } +void Options::selectFallbackArch(const char *arch) +{ + // Should have the format "desired_arch:fallback_arch", for example "arm64_32:armv7k" to allow an armv7k + // slice to substitute for arm64_32 if the latter isn't present. + if (const char* fallbackEnv = getenv("LD_DYLIB_ARCH_FALLBACK") ) { + std::string fallback(fallbackEnv); + auto delimPos = fallback.find(':'); + + // Check we've got a potentially valid fallback string and that it's this architecture we're falling back from. + if ( delimPos == std::string::npos || fallback.substr(0, delimPos) != arch ) + return; + + std::string fallbackTo = fallback.substr(delimPos + 1); + for (const ArchInfo *t = archInfoArray; t->archName != nullptr; ++t) { + if ( fallbackTo == t->archName ) { + fFallbackArchitecture = t->cpuType; + fFallbackSubArchitecture = t->cpuSubType; + } + } + } + else { + // let x86_64h fallback and use x86_64 slice + if ( (fArchitecture == CPU_TYPE_X86_64) && (fSubArchitecture == CPU_SUBTYPE_X86_64_H) ) { + fFallbackArchitecture = CPU_TYPE_X86_64; + fFallbackSubArchitecture = CPU_SUBTYPE_X86_ALL; + } + } +} + void Options::parseArch(const char* arch) { if ( arch == NULL ) @@ -664,6 +824,7 @@ void Options::parseArch(const char* arch) fSubArchitecture = t->cpuSubType; fHasPreferredSubType = t->isSubType; fArchSupportsThumb2 = t->supportsThumb2; + selectFallbackArch(arch); return; } } @@ -814,60 +975,98 @@ static std::string replace_extension(const std::string &path, const std::string return result; } +#ifdef TAPI_SUPPORT + +void Options::addTAPIInterface(tapi::LinkerInterfaceFile* interface, const char *path) const { +#if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 3) || (TAPI_API_VERSION_MAJOR > 1)) + if (tapi::APIVersion::isAtLeast(1, 3)) { + for (auto &name : interface->inlinedFrameworkNames()) { + fTAPIFiles.emplace_back(interface, path, name.c_str()); + } + } +#endif +} + +#endif /* TAPI_SUPPORT */ + bool Options::findFile(const std::string &path, const std::vector &tbdExtensions, FileInfo& result) const { +#ifdef TAPI_SUPPORT FileInfo tbdInfo; for ( const auto &ext : tbdExtensions ) { auto newPath = replace_extension(path, ext); bool found = tbdInfo.checkFileExists(*this, newPath.c_str()); if ( fTraceDylibSearching ) printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), newPath.c_str()); - if ( found ) { - if ( (fFilePreference == kTextBasedStub) || fForceTextBasedStub ) { - result = tbdInfo; - return true; - } else { - break; - } - } + if ( found ) + break; } +#endif FileInfo dylibInfo; { bool found = dylibInfo.checkFileExists(*this, path.c_str()); if ( fTraceDylibSearching ) printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), path.c_str()); - if ( found && (fFilePreference == kMachO) ) { + // ld64-port +#ifndef TAPI_SUPPORT + if ( found ) result = dylibInfo; - return true; - } + return found; +#endif } - if ( !dylibInfo.missing() && tbdInfo.missing() ) { - result = dylibInfo; - return true; +#ifdef TAPI_SUPPORT + // There is only a text-based stub file or a dynamic library file. + if ( tbdInfo.missing() != dylibInfo.missing() ) { + result = tbdInfo.missing() ? dylibInfo : tbdInfo; } - else if ( dylibInfo.missing() && !tbdInfo.missing() ) { - result = tbdInfo; - return true; - } - else if ( !dylibInfo.missing() && !tbdInfo.missing() ) { - if ( dylibInfo.modTime == tbdInfo.modTime ) { + // There are both - a text-based stub file and a dynamic library file. + else if ( !tbdInfo.missing() && !dylibInfo.missing() ) { + // Check if we should prefer the text-based stub file (env var). + if (fPreferTAPIFile) { result = tbdInfo; - return true; } + // Check if we should prefer the text-based stub file (installapi). + else if (tapi::LinkerInterfaceFile::shouldPreferTextBasedStubFile(tbdInfo.path)) { + result = tbdInfo; + } + // If the files are still in sync we can use and should use the text-based stub file. + else if (tapi::LinkerInterfaceFile::areEquivalent(tbdInfo.path, dylibInfo.path)) { + result = tbdInfo; + } + // Otherwise issue a warning and fall-back to the dynamic library file. else { - // Disable false warning about out-of-sync .tbd files. - //warning("text-based stub file %s and library file %s are out of sync. Falling back to library file for linking.", tbdInfo.path, dylibInfo.path); + // Suppress warnings about iOSHostAdditions until mastering is fixed (rdar://46486148) + if ( strstr(tbdInfo.path, "/SDKs/iOSHostAdditions") == NULL ) + warning("text-based stub file %s and library file %s are out of sync. Falling back to library file for linking.", tbdInfo.path, dylibInfo.path); result = dylibInfo; - return true; } + } else { + return false; } - + return true; +#else return false; +#endif } -Options::FileInfo Options::findFile(const std::string &path) const + +static bool startsWith(const std::string& str, const std::string& prefix) +{ + return (str.compare(0, prefix.length(), prefix) == 0); +} + +static std::string getDirPath(const std::string& path) +{ + std::string::size_type lastSlashPos = path.find_last_of('/'); + if ( lastSlashPos == std::string::npos ) + return "./"; + else + return path.substr(0, lastSlashPos+1); +} + +Options::FileInfo Options::findFile(const std::string &path, const ld::dylib::File* fromDylib) const { FileInfo result; @@ -879,35 +1078,138 @@ Options::FileInfo Options::findFile(const std::string &path) const return result; } } + + // expand @ variables + if ( path[0] == '@' ) { + if ( startsWith(path, "@executable_path/") && (fExecutablePath != nullptr) ) { + std::string exeBasedPath = getDirPath(fExecutablePath) + &path[17]; + if ( findFile(exeBasedPath, {".tbd"}, result) ) + return result; + } + else if ( startsWith(path, "@loader_path/") && (fromDylib != nullptr) ) { + char absPath[PATH_MAX]; + if ( realpath(fromDylib->path(), absPath) != NULL ) { + std::string loaderBasedPath = getDirPath(fromDylib->path()) + &path[13]; + if ( findFile(loaderBasedPath, {".tbd"}, result) ) + return result; + } + } + else if ( startsWith(path, "@rpath/") ) { + // first search any LC_RPATH supplied by dyld that re-exports dylib to be found + if ( fromDylib != nullptr ) { + for (const char* rp : fromDylib->rpaths() ) { + std::string rpath = rp; + // handle dylib that has LC_RPATH = @loader_path/blah + if ( startsWith(rpath, "@loader_path/") ) { + char absPath[PATH_MAX]; + if ( realpath(fromDylib->path(), absPath) != NULL ) + rpath = getDirPath(absPath) + &rpath[13]; + else + rpath = getDirPath(fromDylib->path()) + &rpath[13]; + } + std::string rpathBasedPath = rpath + "/" + &path[6]; + if ( findFile(rpathBasedPath, {".tbd"}, result) ) + return result; + } + } + } + } + +#ifdef TAPI_SUPPORT + // find inlined TBD file before raw path. + // rdar://problem/35864452 + if (hasInlinedTAPIFile(path)) { + FileInfo inlinedFile(path.c_str()); + inlinedFile.isInlined = true; + return inlinedFile; + } +#endif /* TAPI_SUPPORT */ + // try raw path if ( findFile(path, {".tbd"}, result) ) return result; - // try @executable_path substitution - if ( (path.find("@executable_path/") == 0) && (fExecutablePath != nullptr) ) { - char newPath[strlen(fExecutablePath) + path.size()]; - strcpy(newPath, fExecutablePath); - char* addPoint = strrchr(newPath,'/'); - if ( addPoint != nullptr ) - strcpy(&addPoint[1], &path[17]); - else - strcpy(newPath, &path[17]); - - if ( findFile(newPath, {".tbd"}, result) ) - return result; - } - // not found throwf("file not found: %s", path.c_str()); } -Options::FileInfo Options::findFileUsingPaths(const std::string &path) const +#ifdef TAPI_SUPPORT + +bool Options::hasInlinedTAPIFile(const std::string &path) const { + for (const auto &dylib : fTAPIFiles) { + if (dylib.getInstallName() == path) + return true; + } + return false; +} + +tapi::LinkerInterfaceFile* Options::findTAPIFile(const std::string &path) const +{ +#if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 3) || (TAPI_API_VERSION_MAJOR > 1)) + tapi::LinkerInterfaceFile* interface = nullptr; + std::string TBDPath; + + // create parsing options. + tapi::ParsingFlags flags = tapi::ParsingFlags::None; + if (enforceDylibSubtypesMatch()) + flags |= tapi::ParsingFlags::ExactCpuSubType; + + if (!allowWeakImports()) + flags |= tapi::ParsingFlags::DisallowWeakImports; + + __block uint32_t linkMinOSVersion = 0; + //FIXME handle this correctly once we have multi-platform TAPI. + platforms().forEach(^(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop) { + if (linkMinOSVersion == 0) + linkMinOSVersion = minVersion; + if (platform == ld::Platform::macOS) + linkMinOSVersion = minVersion; + }); + + // Search through all the inlined framework. + for (const auto &dylib : fTAPIFiles) { + if (dylib.getInstallName() == path) { + // If the install name matches, parse the framework. + std::string errorMessage; + auto file = dylib.getInterfaceFile()->getInlinedFramework(path.c_str(), architecture(), subArchitecture(), + flags, tapi::PackedVersion32(linkMinOSVersion), errorMessage); + if (!file) + throw strdup(errorMessage.c_str()); + + if (!interface) { + // If this is the first inlined framework found, record the information. + interface = file; + TBDPath = dylib.getTAPIFilePath(); + } else { + // If we found other inlined framework already, check to see if their versions are the same. + // If not the same, emit an warning and record the newer one. Otherwise, just use the current one. + if (interface->getCurrentVersion() == file->getCurrentVersion()) + continue; + warning("Inlined framework/dylib mismatch: %s (%s and %s)", path.c_str(), + TBDPath.c_str(), dylib.getTAPIFilePath().c_str()); + if (interface->getCurrentVersion() < file->getCurrentVersion()) { + interface = file; + TBDPath = dylib.getTAPIFilePath(); + } + } + } + } + return interface; +#else + return nullptr; +#endif +} + +#endif /* TAPI_SUPPORT */ + +// search for indirect dylib first using -F and -L paths first +Options::FileInfo Options::findIndirectDylib(const std::string& installName, const ld::dylib::File* fromDylib) const { FileInfo result; - auto lastSlashPos = path.find_last_of('/'); + auto lastSlashPos = installName.find_last_of('/'); auto pos = ( lastSlashPos != std::string::npos ) ? lastSlashPos + 1 : 0; - auto leafName = path.substr(pos); + auto leafName = installName.substr(pos); // Is this in a framework? // /path/Foo.framework/Foo ==> true (Foo) @@ -916,7 +1218,7 @@ Options::FileInfo Options::findFileUsingPaths(const std::string &path) const bool isFramework = false; if ( lastSlashPos != std::string::npos ) { auto frameworkDir = std::string("/").append(leafName).append(".framework/"); - if ( path.rfind(frameworkDir) != std::string::npos ) + if ( installName.rfind(frameworkDir) != std::string::npos ) isFramework = true; } @@ -925,9 +1227,9 @@ Options::FileInfo Options::findFileUsingPaths(const std::string &path) const // don't need to try variations, just paths. We do need to add the additional bits // onto the framework path though. if ( isFramework ) { - auto endPos = path.rfind(".framework"); - auto beginPos = path.find_last_of('/', endPos); - auto leafPath = path.substr(beginPos); + auto endPos = installName.rfind(".framework"); + auto beginPos = installName.find_last_of('/', endPos); + auto leafPath = installName.substr(beginPos); for (const auto* dir : fFrameworkSearchPaths) { auto possiblePath = dir + leafPath; if ( findFile(possiblePath, {".tbd"}, result) ) @@ -938,7 +1240,7 @@ Options::FileInfo Options::findFileUsingPaths(const std::string &path) const // ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard bool embeddedDylib = ( (leafName.size() > 6) && (leafName.find(".dylib", leafName.size()-6) != std::string::npos) - && (path.find(".framework/") != std::string::npos) ); + && (installName.find(".framework/") != std::string::npos) ); if ( !embeddedDylib ) { for (const auto* dir : fLibrarySearchPaths) { //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName); @@ -950,61 +1252,7 @@ Options::FileInfo Options::findFileUsingPaths(const std::string &path) const } // If we didn't find it fall back to findFile. - return findFile(path); -} - - - -void Options::parseSegAddrTable(const char* segAddrPath, const char* installPth) -{ - FILE* file = fopen(segAddrPath, "r"); - if ( file == NULL ) { - warning("-seg_addr_table file cannot be read: %s", segAddrPath); - return; - } - - char path[PATH_MAX]; - uint64_t firstColumAddress = 0; - uint64_t secondColumAddress = 0; - bool hasSecondColumn = false; - while ( fgets(path, PATH_MAX, file) != NULL ) { - path[PATH_MAX-1] = '\0'; - char* eol = strchr(path, '\n'); - if ( eol != NULL ) - *eol = '\0'; - // ignore lines not starting with 0x number - if ( (path[0] == '0') && (path[1] == 'x') ) { - char* p; - firstColumAddress = strtoull(path, &p, 16); - while ( isspace(*p) ) - ++p; - // see if second column is a number - if ( (p[0] == '0') && (p[1] == 'x') ) { - secondColumAddress = strtoull(p, &p, 16); - hasSecondColumn = true; - while ( isspace(*p) ) - ++p; - } - while ( isspace(*p) ) - ++p; - if ( p[0] == '/' ) { - // remove any trailing whitespace - for(char* end = eol-1; (end > p) && isspace(*end); --end) - *end = '\0'; - // see if this line is for the dylib being linked - if ( strcmp(p, installPth) == 0 ) { - fBaseAddress = firstColumAddress; - if ( hasSecondColumn ) { - fBaseWritableAddress = secondColumAddress; - fSplitSegs = true; - } - break; // out of while loop - } - } - } - } - - fclose(file); + return findFile(installName, fromDylib); } void Options::loadFileList(const char* fileOfPaths, ld::File::Ordinal baseOrdinal) @@ -1024,16 +1272,14 @@ void Options::loadFileList(const char* fileOfPaths, ld::File::Ordinal baseOrdina file = fopen(realFileOfPaths, "r"); if ( file == NULL ) throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths, errno, strerror(errno)); - if ( this->dumpDependencyInfo() ) - this->dumpDependency(Options::depFileList, realFileOfPaths); + this->addDependency(Options::depFileList, realFileOfPaths); } } else { file = fopen(fileOfPaths, "r"); if ( file == NULL ) throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths, errno, strerror(errno)); - if ( this->dumpDependencyInfo() ) - this->dumpDependency(Options::depFileList, fileOfPaths); + this->addDependency(Options::depFileList, fileOfPaths); } char path[PATH_MAX]; @@ -1244,8 +1490,7 @@ void Options::loadExportFile(const char* fileOfExports, const char* option, SetW if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size ) throwf("can't read %s file: %s", option, fileOfExports); - if ( this->dumpDependencyInfo() ) - this->dumpDependency(Options::depMisc, fileOfExports); + this->addDependency(Options::depMisc, fileOfExports); ::close(fd); @@ -1318,8 +1563,7 @@ void Options::parseAliasFile(const char* fileOfAliases) throwf("can't read alias file: %s", fileOfAliases); p[stat_buf.st_size] = '\n'; ::close(fd); - if ( this->dumpDependencyInfo() ) - this->dumpDependency(Options::depMisc, fileOfAliases); + this->addDependency(Options::depMisc, fileOfAliases); // parse into symbols and add to fAliases AliasPair pair; @@ -1427,63 +1671,6 @@ Options::Treatment Options::parseTreatment(const char* treatment) return kInvalid; } -void Options::setMacOSXVersionMin(const char* version) -{ - uint32_t value; - if ( !parsePackedVersion32(version, value) ) { - throwf("-macosx_version_min value malformed: '%s'", version); - } - fMacVersionMin = (ld::MacVersionMin)value; - fPlatform = kPlatformOSX; -} - -void Options::setIOSVersionMin(const char* version) -{ - uint32_t value; - if ( !parsePackedVersion32(version, value) ) { - throwf("-ios_version_min value malformed: '%s'", version); - } - fIOSVersionMin = (ld::IOSVersionMin)value; - fPlatform = kPlatformiOS; -} - - -void Options::setWatchOSVersionMin(const char* version) -{ - uint32_t value; - if ( !parsePackedVersion32(version, value) ) { - throwf("-watchos_version_min value malformed: '%s'", version); - } - fWatchOSVersionMin = (ld::WatchOSVersionMin)value; - fPlatform = kPlatformWatchOS; -} - - -bool Options::minOS(ld::MacVersionMin requiredMacMin, ld::IOSVersionMin requirediPhoneOSMin) -{ - if ( fMacVersionMin != ld::macVersionUnset ) { - return ( fMacVersionMin >= requiredMacMin ); - } - else if ( fWatchOSVersionMin != ld::wOSVersionUnset ) { - // Hack until we fully track watch and ios versions seperately - return ( (fWatchOSVersionMin + 0x00070000) >= requirediPhoneOSMin); - } - else { - return ( fIOSVersionMin >= requirediPhoneOSMin ); - } -} - -bool Options::min_iOS(ld::IOSVersionMin requirediOSMin) -{ - if ( fWatchOSVersionMin != ld::wOSVersionUnset ) { - // Hack until we fully track watch and ios versions seperately - return ( (fWatchOSVersionMin + 0x00070000) >= requirediOSMin); - } - else { - return ( fIOSVersionMin >= requirediOSMin ); - } -} - void Options::setWeakReferenceMismatchTreatment(const char* treatment) { if ( treatment == NULL ) @@ -1721,6 +1908,19 @@ void Options::parseOrderFile(const char* path, bool cstring) // order files override auto-ordering fAutoOrderInitializers = false; + // ld64 should prefer OrderFiles from the SDK over the ones in / + for (const char* sdkPath : fSDKPaths) { + char fullPath[PATH_MAX]; + strlcpy(fullPath, sdkPath, PATH_MAX); + strlcat(fullPath, "/", PATH_MAX); + strlcat(fullPath, path, PATH_MAX); + struct stat statBuffer; + if ( stat(fullPath, &statBuffer) == 0 ) { + path = strdup(fullPath); + break; + } + } + // read in whole file int fd = ::open(path, O_RDONLY, 0); if ( fd == -1 ) @@ -1734,8 +1934,8 @@ void Options::parseOrderFile(const char* path, bool cstring) throwf("can't read order file: %s", path); ::close(fd); p[stat_buf.st_size] = '\n'; - if ( this->dumpDependencyInfo() ) - this->dumpDependency(Options::depMisc, path); + this->addDependency(Options::depMisc, path); + fOrderFilePath = strdup(path); // parse into vector of pairs char * const end = &p[stat_buf.st_size+1]; @@ -1941,6 +2141,16 @@ bool Options::moveRwSymbol(const char* symName, const char* filePath, const char return false; } +bool Options::moveAXMethodList(const char* className) const +{ + for (const SymbolsMove& sm : fSymbolsMovesAXMethodLists) { + bool wildcard; + if ( sm.symbols.containsWithPrefix(className, NULL, wildcard) ) + return true; + } + return false; +} + bool Options::moveRoSymbol(const char* symName, const char* filePath, const char*& seg, bool& wildCardMatch) const { for (std::vector::const_iterator it=fSymbolsMovesCode.begin(); it != fSymbolsMovesCode.end(); ++it) { @@ -2092,7 +2302,7 @@ bool Options::parsePackedVersion32(const std::string& versionStr, uint32_t &resu return false; } - result = (majorValue << 16) | (minorValue << 8) | microValue; + result = (uint32_t)((majorValue << 16) | (minorValue << 8) | microValue); return true; } @@ -2104,42 +2314,26 @@ bool Options::parsePackedVersion32(const std::string& versionStr, uint32_t &resu std::string Options::getSDKVersionStr() const { - return getVersionString32(fSDKVersion); -} + std::string retval; + auto appendString = [&](const std::string& string) { + if (retval.empty()) { + retval = string; + } else { + retval += "/"; + retval += string; + } + }; -std::string Options::getPlatformStr() const -{ - switch (fPlatform) { - case Options::kPlatformOSX: - return "MacOSX"; - case Options::kPlatformiOS: - if (targetIOSSimulator()) - return "iPhoneSimulator"; - else - return "iPhoneOS"; - case Options::kPlatformWatchOS: - if (targetIOSSimulator()) - return "watchOS Simulator"; - else - return "watchOS"; -#if SUPPORT_APPLE_TV - case Options::kPlatform_tvOS: - if (targetIOSSimulator()) - return "AppleTVSimulator"; - else - return "AppleTVOS"; - break; -#endif - case Options::kPlatformUnknown: - return "Unknown"; - default: // ld64-port - __builtin_unreachable(); - } + platforms().forEach(^(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop) { + appendString(getVersionString32(sdkVersion)); + }); + + return retval; } std::vector Options::writeBitcodeLinkOptions() const { - std::vector linkCommand; + __block std::vector linkCommand; switch ( fOutputKind ) { case Options::kDynamicLibrary: linkCommand.push_back("-dylib"); @@ -2171,41 +2365,18 @@ std::vector Options::writeBitcodeLinkOptions() const // Add deployment target. // Platform is allowed to be unknown for "ld -r". - switch (fPlatform) { - case Options::kPlatformOSX: - linkCommand.push_back("-macosx_version_min"); - linkCommand.push_back(getVersionString32((unsigned)fMacVersionMin)); - break; - case Options::kPlatformiOS: - if (targetIOSSimulator()) - linkCommand.push_back("-ios_simulator_version_min"); - else - linkCommand.push_back("-ios_version_min"); - linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin)); - break; - case Options::kPlatformWatchOS: - if (targetIOSSimulator()) - linkCommand.push_back("-watchos_simulator_version_min"); - else - linkCommand.push_back("-watchos_version_min"); - linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin)); - break; -#if SUPPORT_APPLE_TV - case Options::kPlatform_tvOS: - if (targetIOSSimulator()) - linkCommand.push_back("-tvos_simulator_version_min"); - else - linkCommand.push_back("-tvos_version_min"); - linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin)); - break; -#endif - case Options::kPlatformUnknown: - if ( fOutputKind != Options::kObjectFile ) { - throwf("platform is unknown for final bitcode bundle," - "deployment target and min version is required for -bitcode_bundle"); - } - break; - } + + platforms().forEach(^(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop) { + std::string printName = platformInfo(platform).printName; + std::transform(printName.begin(), printName.end(), printName.begin(), [](unsigned char c) -> unsigned char { + if (c == ' ') return '-'; + return std::tolower(c); + }); + linkCommand.push_back("-platform_version"); + linkCommand.push_back(platformInfo(platform).printName); + linkCommand.push_back(getVersionString32(minVersion)); + linkCommand.push_back(getVersionString32(sdkVersion)); + }); // entry name @@ -2256,6 +2427,56 @@ std::vector Options::writeBitcodeLinkOptions() const return linkCommand; } +const char* Options::checkForNullArgument(const char* argument_name, const char* arg) const +{ + if ( arg == NULL ) + throwf("missing argument for %s", argument_name); + return arg; +} + +const char* Options::checkForNullVersionArgument(const char* argument_name, const char* arg) const +{ + if ( arg == NULL ) + throwf("%s missing version argument", argument_name); + return arg; +} + +static const ld::PlatformInfo* isPlatformOption(const char* arg) +{ + __block const ld::PlatformInfo* result = nullptr; + forEachSupportedPlatform(^(const ld::PlatformInfo& info, bool& stop) { + if ( strcmp(arg, info.commandLineArg) == 0 ) { + result = &info; + stop = true; + } + }); + return result; +} + +static const ld::PlatformInfo* isPlatformName(const char* arg) +{ + __block const ld::PlatformInfo* result = nullptr; + char *end = nullptr; + ld::Platform platformNumber = (ld::Platform)strtol(arg, &end, 10); + forEachSupportedPlatform(^(const ld::PlatformInfo& info, bool& stop) { + if (*end == 0 && platformNumber == info.platform) { + result = &info; + stop = true; + return; + } + auto normalizedStringComp = [](char c1, char c2){ + return (c1 == c2 || std::toupper(c1) == std::toupper(c2) + || (c1 == ' ' && c2 == '-') || (c1 == '-' && c2 == ' ')); + }; + if (strlen(arg) != strlen(info.printName)) return; + if (!std::equal(&arg[0], &arg[strlen(arg)], &info.printName[0], normalizedStringComp)) return; + result = &info; + stop = true; + }); + return result; +} + + // // Process all command line arguments. // @@ -2292,6 +2513,16 @@ void Options::parse(int argc, const char* argv[]) if (fPrintOptions) fprintf (stderr, "[Logging ld64 options]\t%s\n", arg); + // grandfather in old arg name + if ( strcmp(arg, "-iphoneos_version_min") == 0 ) + arg = "-ios_version_min"; + + if ( strcmp(arg, "-macosx_version_min") == 0 ) + arg = "-macos_version_min"; + + if ( (strcmp(arg, "-iosmac_version_min") == 0) || (strcmp(arg, "-uikitformac_version_min") == 0) ) + arg = "-maccatalyst_version_min"; + if ( (arg[1] == 'L') || (arg[1] == 'F') ) { snapshotArgCount = 0; // stripped out of link snapshot if (arg[2] == '\0') @@ -2305,8 +2536,13 @@ void Options::parse(int argc, const char* argv[]) fprintf (stdout, "ld64: For information on command line options please use 'man ld'.\n"); exit (0); } + else if ( strcmp(arg, "--dump-normalized-lib-args") == 0 ) { + fDumpNormalizedLibArgs = true; + } else if ( strcmp(arg, "-arch") == 0 ) { - parseArch(argv[++i]); + const char* arch = argv[++i]; + parseArch(arch); + fLinkSnapshot.recordArch(arch); } else if ( strcmp(arg, "-dynamic") == 0 ) { // default @@ -2344,19 +2580,29 @@ void Options::parse(int argc, const char* argv[]) fOutputKind = kKextBundle; cannotBeUsedWithBitcode(arg); } + else if ( strcmp(arg, "-kext_objects_dir") == 0 ) { + fKextObjectsDirPath = argv[++i]; + if ( fKextObjectsDirPath == NULL ) + throw "missing argument to -kext_objects_dir"; + fKextObjectsEnable = 1; + } + else if ( strcmp(arg, "-no_kext_objects") == 0 ) { + fKextObjectsEnable = 0; + } else if ( strcmp(arg, "-o") == 0 ) { - snapshotArgCount = 0; - fOutputFile = argv[++i]; - fLinkSnapshot.setSnapshotName(fOutputFile); + snapshotArgCount = 0; + fOutputFile = checkForNullArgument(arg, argv[++i]); + fLinkSnapshot.setOutputPath(fOutputFile); } else if ( strncmp(arg, "-lazy-l", 7) == 0 ) { snapshotArgCount = 0; FileInfo info = findLibrary(&arg[7], true); - info.options.fLazyLoad = true; + info.options.fLazyLoad = false; info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i); addLibrary(info); - fUsingLazyDylibLinking = true; + fUsingLazyDylibLinking = false; cannotBeUsedWithBitcode(arg); + warning("-lazy-l is deprecated, changing to regular link"); } else if ( strcmp(arg, "-lto_library") == 0 ) { snapshotFileArgIndex = 1; @@ -2364,6 +2610,41 @@ void Options::parse(int argc, const char* argv[]) if ( fOverridePathlibLTO == NULL ) throw "missing argument to -lto_library"; } + else if ( strcmp(arg, "-cache_path_lto") == 0 ) { + fLtoCachePath = argv[++i]; + if ( fLtoCachePath == NULL ) + throw "missing argument to -cache_path_lto"; + } + else if ( strcmp(arg, "-prune_interval_lto") == 0 ) { + const char* value = argv[++i]; + if ( value == NULL ) + throw "missing argument to -prune_interval_lto"; + char* endptr; + fLtoPruneIntervalOverwrite = true; + fLtoPruneInterval = strtoul(value, &endptr, 10); + if ( *endptr != '\0') + throw "invalid argument for -prune_interval_lto"; + } + else if ( strcmp(arg, "-prune_after_lto") == 0 ) { + const char* value = argv[++i]; + if ( value == NULL ) + throw "missing argument to -prune_after_lto"; + char* endptr; + fLtoPruneAfter = strtoul(value, &endptr, 10); + if ( *endptr != '\0') + throw "invalid argument for -prune_after_lto"; + } + else if ( strcmp(arg, "-max_relative_cache_size_lto") == 0 ) { + const char* value = argv[++i]; + if ( value == NULL ) + throw "missing argument to -max_relative_cache_size_lto"; + char* endptr; + fLtoMaxCacheSize = strtoul(value, &endptr, 10); + if ( *endptr != '\0') + throw "invalid argument for -max_relative_cache_size_lto"; + if (fLtoMaxCacheSize > 100) + throw "Expect a value between 0 and 100 for -max_relative_cache_size_lto"; + } else if ( (arg[1] == 'l') && (strncmp(arg,"-lazy_",6) !=0) ) { snapshotArgCount = 0; FileInfo info = findLibrary(&arg[2]); @@ -2412,7 +2693,8 @@ void Options::parse(int argc, const char* argv[]) } // Similar to -all_load, but for the following archive only. else if ( strcmp(arg, "-force_load") == 0 ) { - FileInfo info = findFile(argv[++i]); + const char* path = checkForNullArgument(arg, argv[++i]); + FileInfo info = findFile(path); info.options.fForceLoad = true; info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i); addLibrary(info); @@ -2496,6 +2778,25 @@ void Options::parse(int argc, const char* argv[]) } else if ( strcmp(arg, "-final_output") == 0 ) { fFinalName = argv[++i]; + // some projects end up with double slash in -final_output path + if ( strstr(fFinalName, "//") != NULL ) { + char fixedPath[strlen(fFinalName)+1]; + char* t = fixedPath; + bool lastWasSlash = false; + for (const char* s=fFinalName; *s != '\0'; ++s) { + if ( *s == '/' ) { + if ( !lastWasSlash ) + *t++ = *s; + lastWasSlash = true; + } + else { + *t++ = *s; + lastWasSlash = false; + } + } + *t = '\0'; + fFinalName = strdup(fixedPath); + } } // Ensure that all calls to exported symbols go through lazy pointers. Multi-module // just ensures that this happens for cross object file boundaries. @@ -2539,13 +2840,15 @@ void Options::parse(int argc, const char* argv[]) if ( fExportMode == kDontExportSome ) throw "can't use -exported_symbol and -unexported_symbols"; fExportMode = kExportSome; - fExportSymbols.insert(argv[++i]); + const char* symbol = checkForNullArgument(arg, argv[++i]); + fExportSymbols.insert(symbol); } else if ( strcmp(arg, "-unexported_symbol") == 0 ) { if ( fExportMode == kExportSome ) throw "can't use -unexported_symbol and -exported_symbol"; fExportMode = kDontExportSome; - fDontExportSymbols.insert(argv[++i]); + const char* symbol = checkForNullArgument(arg, argv[++i]); + fDontExportSymbols.insert(symbol); } else if ( strcmp(arg, "-non_global_symbols_no_strip_list") == 0 ) { snapshotFileArgIndex = 1; @@ -2576,7 +2879,8 @@ void Options::parse(int argc, const char* argv[]) else if ( strcmp(arg, "-weak_library") == 0 ) { // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now) snapshotArgCount = 0; - FileInfo info = findFile(argv[++i]); + const char* path = checkForNullArgument(arg, argv[++i]); + FileInfo info = findFile(path); info.options.fWeakImport = true; info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i); addLibrary(info); @@ -2585,12 +2889,14 @@ void Options::parse(int argc, const char* argv[]) else if ( strcmp(arg, "-lazy_library") == 0 ) { // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now) snapshotArgCount = 0; - FileInfo info = findFile(argv[++i]); - info.options.fLazyLoad = true; + const char* path = checkForNullArgument(arg, argv[++i]); + FileInfo info = findFile(path); + info.options.fLazyLoad = false; info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i); addLibrary(info); - fUsingLazyDylibLinking = true; + fUsingLazyDylibLinking = false; cannotBeUsedWithBitcode(arg); + warning("-lazy_library is deprecated, changing to regular link"); } else if ( strcmp(arg, "-framework") == 0 ) { snapshotArgCount = 0; @@ -2610,11 +2916,12 @@ void Options::parse(int argc, const char* argv[]) // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now) snapshotArgCount = 0; FileInfo info = findFramework(argv[++i]); - info.options.fLazyLoad = true; + info.options.fLazyLoad = false; info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i); addLibrary(info); - fUsingLazyDylibLinking = true; + fUsingLazyDylibLinking = false; cannotBeUsedWithBitcode(arg); + warning("-lazy_framework is deprecated, changing to regular link"); } else if ( strcmp(arg, "-search_paths_first") == 0 ) { // previously handled by buildSearchPaths() @@ -2655,6 +2962,24 @@ void Options::parse(int argc, const char* argv[]) break; } } + else if ( strcmp(arg, "-unaligned_pointers") == 0 ) { + switch ( parseTreatment(argv[++i]) ) { + case kNULL: + case kInvalid: + throw "-unaligned_pointers missing [ warning | error | suppress ]"; + case kWarning: + fUnalignedPointerTreatment = Options::kUnalignedPointerWarning; + cannotBeUsedWithBitcode(arg); + break; + case kSuppress: + fUnalignedPointerTreatment = Options::kUnalignedPointerIgnore; + cannotBeUsedWithBitcode(arg); + break; + case kError: + fUnalignedPointerTreatment = Options::kUnalignedPointerError; + break; + } + } else if ( strcmp(arg, "-sect_diff_relocs") == 0 ) { warnObsolete(arg); ++i; @@ -2669,12 +2994,11 @@ void Options::parse(int argc, const char* argv[]) // are prebound. This can then be fixed up by update_prebinding // later. Prebinding is less useful on 10.4 and greater. else if ( strcmp(arg, "-prebind") == 0 ) { - fPrebind = true; + warnObsolete(arg); cannotBeUsedWithBitcode(arg); } else if ( strcmp(arg, "-noprebind") == 0 ) { warnObsolete(arg); - fPrebind = false; } else if ( strcmp(arg, "-prebind_allow_overlap") == 0 ) { warnObsolete(arg); @@ -2743,22 +3067,23 @@ void Options::parse(int argc, const char* argv[]) } // ??? Deprecate when we deprecate split-seg. else if ( strcmp(arg, "-segs_read_only_addr") == 0 ) { - fBaseAddress = parseAddress(argv[++i]); + warnObsolete(arg); + ++i; cannotBeUsedWithBitcode(arg); } // ??? Deprecate when we deprecate split-seg. else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) { - fBaseWritableAddress = parseAddress(argv[++i]); - fSplitSegs = true; + warnObsolete(arg); + ++i; cannotBeUsedWithBitcode(arg); } // ??? Deprecate when we get rid of basing at build time. else if ( strcmp(arg, "-seg_addr_table") == 0 ) { + warnObsolete(arg); snapshotFileArgIndex = 1; const char* name = argv[++i]; if ( name == NULL ) throw "-seg_addr_table missing argument"; - fSegAddrTablePath = name; cannotBeUsedWithBitcode(arg); } else if ( strcmp(arg, "-seg_addr_table_filename") == 0 ) { @@ -2838,81 +3163,60 @@ void Options::parse(int argc, const char* argv[]) warnObsolete(arg); } else if ( strcmp(arg, "-twolevel_namespace_hints") == 0 ) { - // FIX FIX + warnObsolete(arg); } - // Use this flag to set default behavior for deployement targets. - else if ( strcmp(arg, "-macosx_version_min") == 0 ) { - const char* macVers = argv[++i]; - if ( macVers == NULL ) - throw "-macosx_version_min missing version argument"; - const char* envMacVers = getenv("MACOSX_DEPLOYMENT_TARGET"); - const char* enviPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET"); - if ( (envMacVers != NULL) && (enviPhoneVers != NULL) ) { - // when conflicting deployments set, break tie by looking at syslibroot - warning("both MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET are set"); - if ( !fSDKPaths.empty() ) { - const char* sysrootPath = fSDKPaths.back(); - const char* lastSlash = strrchr(sysrootPath, '/'); - if ( strstr(lastSlash, "Simulator") != NULL ) - setIOSVersionMin(enviPhoneVers); - else - setMacOSXVersionMin(macVers); - } - else { - setMacOSXVersionMin(macVers); - } + else if ( strcmp(arg, "-platform_version") == 0 ) { + const char* platform = argv[++i]; + const ld::PlatformInfo* info = isPlatformName(platform); + if (info == nullptr) { + throwf("unknown platform string \"%s\"", arg); } - else { - setMacOSXVersionMin(macVers); + const char* versStr = checkForNullVersionArgument(arg, argv[++i]); + if ( versStr == NULL ) + throwf("%s missing min version argument", arg); + uint32_t minVersValue; + if ( !parsePackedVersion32(versStr, minVersValue) ) { + throwf("%s min version malformed: '%s'", arg, versStr); + } + const char* SDKVersStr = checkForNullVersionArgument(arg, argv[++i]); + if ( SDKVersStr == NULL ) + throwf("%s missing sdk version argument", arg); + uint32_t SDKValue; + if ( !parsePackedVersion32(SDKVersStr, SDKValue) ) { + throwf("%s sdk version malformed: '%s'", arg, SDKVersStr); + } + if (fPlatforms.contains(info->platform)) { + std::string existingVersionStr = getVersionString32(fPlatforms.minOS(info->platform)); + warning("passed two min versions (%s, %s) for platform %s. Using %s.", + existingVersionStr.c_str(), versStr, info->printName, versStr); + fPlatforms.updateMinVersion(info->platform, minVersValue); + fPlatforms.updateSDKVersion(info->platform, SDKValue); + } else { + fPlatforms.insert(ld::PlatformVersion(info->platform, minVersValue, SDKValue)); + } + fPlatfromVersionCmdFound = true; + } + else if ( const ld::PlatformInfo* info = isPlatformOption(arg) ) { + const char* versStr = checkForNullVersionArgument(arg, argv[++i]); + if ( versStr == NULL ) + throwf("%s missing version argument", arg); + uint32_t value; + if ( !parsePackedVersion32(versStr, value) ) { + throwf("%s value malformed: '%s'", arg, versStr); + } + if ( value < info->minimumOsVersion ) { + value = info->minimumOsVersion; + warning("OS version (%s) too small, changing to %s", versStr, getVersionString32(info->minimumOsVersion).c_str()); + } + if (fPlatforms.contains(info->platform)) { + std::string existingVersionStr = getVersionString32(fPlatforms.minOS(info->platform)); + warning("passed two min versions (%s, %s) for platform %s. Using %s.", + existingVersionStr.c_str(), versStr, info->printName, versStr); + fPlatforms.updateMinVersion(info->platform, value); + } else { + fPlatforms.insert(ld::PlatformVersion(info->platform, value)); } } - else if ( (strcmp(arg, "-ios_version_min") == 0) || (strcmp(arg, "-iphoneos_version_min") == 0) ) { - const char* vers = argv[++i]; - if ( vers == NULL ) - throw "-ios_version_min missing version argument"; - setIOSVersionMin(vers); - } - else if ( (strcmp(arg, "-aspen_version_min") == 0) ) { // ld64-port - // for backward compatibility with llvm-gcc. - ++i; - } - else if ( strcmp(arg, "-ios_simulator_version_min") == 0 ) { - const char* vers = argv[++i]; - if ( vers == NULL ) - throw "-ios_simulator_version_min missing version argument"; - setIOSVersionMin(vers); - fTargetIOSSimulator = true; - } - else if ( strcmp(arg, "-watchos_version_min") == 0 ) { - const char* vers = argv[++i]; - if ( vers == NULL ) - throw "-watchos_version_min missing version argument"; - setWatchOSVersionMin(vers); - } - else if ( strcmp(arg, "-watchos_simulator_version_min") == 0 ) { - const char* vers = argv[++i]; - if ( vers == NULL ) - throw "-watchos_simulator_version_min missing version argument"; - setWatchOSVersionMin(vers); - fTargetIOSSimulator = true; - } - #if SUPPORT_APPLE_TV - else if ( strcmp(arg, "-tvos_version_min") == 0 ) { - const char* vers = argv[++i]; - if ( vers == NULL ) - throw "-tvos_version_min missing version argument"; - setIOSVersionMin(vers); - fPlatform = kPlatform_tvOS; - } - else if ( strcmp(arg, "-tvos_simulator_version_min") == 0 ) { - const char* vers = argv[++i]; - if ( vers == NULL ) - throw "-tvos_simulator_version_min missing version argument"; - setIOSVersionMin(vers); - fPlatform = kPlatform_tvOS; - fTargetIOSSimulator = true; - } - #endif else if ( strcmp(arg, "-multiply_defined") == 0 ) { //warnObsolete(arg); ++i; @@ -3146,12 +3450,8 @@ void Options::parse(int argc, const char* argv[]) } else if ( strcmp(arg, "-alias") == 0 ) { Options::AliasPair pair; - pair.realName = argv[++i]; - if ( pair.realName == NULL ) - throw "missing argument to -alias"; - pair.alias = argv[++i]; - if ( pair.alias == NULL ) - throw "missing argument to -alias"; + pair.realName = checkForNullArgument(arg, argv[++i]); + pair.alias = checkForNullArgument(arg, argv[++i]); fAliases.push_back(pair); cannotBeUsedWithBitcode(arg); } @@ -3170,12 +3470,10 @@ void Options::parse(int argc, const char* argv[]) fVerifyBitcode = true; } else if ( strcmp(arg, "-bitcode_symbol_map") == 0) { - fReverseMapPath = argv[++i]; - if ( fReverseMapPath == NULL ) - throw "missing argument to -bitcode_symbol_map"; + fReverseMapPath = checkForNullArgument(arg, argv[++i]); struct stat statbuf; - ::stat(fReverseMapPath, &statbuf); - if (S_ISDIR(statbuf.st_mode)) { + int ret = ::stat(fReverseMapPath, &statbuf); + if ( ret == 0 && S_ISDIR(statbuf.st_mode)) { char tempPath[PATH_MAX]; sprintf(tempPath, "%s/XXXXXX", fReverseMapPath); int tempFile = ::mkstemp(tempPath); @@ -3187,20 +3485,18 @@ void Options::parse(int argc, const char* argv[]) } else fReverseMapTempPath = std::string(fReverseMapPath); } - else if ( strcmp(argv[i], "-flto-codegen-only") == 0) { + else if ( strcmp(arg, "-flto-codegen-only") == 0) { fLTOCodegenOnly = true; } - else if ( strcmp(argv[i], "-ignore_auto_link") == 0) { + else if ( strcmp(arg, "-ignore_auto_link") == 0) { fIgnoreAutoLink = true; } - else if ( strcmp(argv[i], "-allow_dead_duplicates") == 0) { + else if ( strcmp(arg, "-allow_dead_duplicates") == 0) { fAllowDeadDups = true; } - else if ( strcmp(argv[i], "-bitcode_process_mode") == 0 ) { - const char* bitcode_type = argv[++i]; - if ( bitcode_type == NULL ) - throw "missing argument to -bitcode_process_mode"; - else if ( strcmp(bitcode_type, "strip") == 0 ) + else if ( strcmp(arg, "-bitcode_process_mode") == 0 ) { + const char* bitcode_type = checkForNullArgument(arg, argv[++i]); + if ( strcmp(bitcode_type, "strip") == 0 ) fBitcodeKind = kBitcodeStrip; else if ( strcmp(bitcode_type, "marker") == 0 ) fBitcodeKind = kBitcodeMarker; @@ -3212,9 +3508,7 @@ void Options::parse(int argc, const char* argv[]) throw "unknown argument to -bitcode_process_mode {strip,marker,data,bitcode}"; } else if ( strcmp(arg, "-rpath") == 0 ) { - const char* path = argv[++i]; - if ( path == NULL ) - throw "missing argument to -rpath"; + const char* path = checkForNullArgument(arg, argv[++i]); fRPaths.push_back(path); } else if ( strcmp(arg, "-read_only_stubs") == 0 ) { @@ -3224,9 +3518,7 @@ void Options::parse(int argc, const char* argv[]) warnObsolete(arg); } else if ( strcmp(arg, "-map") == 0 ) { - fMapPath = argv[++i]; - if ( fMapPath == NULL ) - throw "missing argument to -map"; + fMapPath = checkForNullArgument(arg, argv[++i]); } else if ( strcmp(arg, "-pie") == 0 ) { fPositionIndependentExecutable = true; @@ -3248,7 +3540,8 @@ void Options::parse(int argc, const char* argv[]) else if ( strcmp(arg, "-reexport_library") == 0 ) { // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now) snapshotArgCount = 0; - FileInfo info = findFile(argv[++i]); + const char* path = checkForNullArgument(arg, argv[++i]); + FileInfo info = findFile(path); info.options.fReExport = true; info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i); addLibrary(info); @@ -3275,7 +3568,8 @@ void Options::parse(int argc, const char* argv[]) else if ( strcmp(arg, "-upward_library") == 0 ) { // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now) snapshotArgCount = 0; - FileInfo info = findFile(argv[++i]); + const char* path = checkForNullArgument(arg, argv[++i]); + FileInfo info = findFile(path); info.options.fUpward = true; info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i); addLibrary(info); @@ -3313,16 +3607,12 @@ void Options::parse(int argc, const char* argv[]) cannotBeUsedWithBitcode(arg); } else if ( strcmp(arg, "-mllvm") == 0 ) { - const char* opts = argv[++i]; - if ( opts == NULL ) - throw "missing argument to -mllvm"; + const char* opts = checkForNullArgument(arg, argv[++i]); fLLVMOptions.push_back(opts); cannotBeUsedWithBitcode(arg); } else if ( strcmp(arg, "-mcpu") == 0 ) { - const char* cpu = argv[++i]; - if ( cpu == NULL ) - throw "missing argument to -mcpu"; + const char* cpu = checkForNullArgument(arg, argv[++i]); fLtoCpu = cpu; cannotBeUsedWithBitcode(arg); } @@ -3378,9 +3668,7 @@ void Options::parse(int argc, const char* argv[]) cannotBeUsedWithBitcode(arg); } else if ( strcmp(arg, "-objc_abi_version") == 0 ) { - const char* version = argv[++i]; - if ( version == NULL ) - throw "-objc_abi_version missing version number"; + const char* version = checkForNullVersionArgument(arg, argv[++i]); if ( strcmp(version, "2") == 0 ) { fObjCABIVersion1Override = false; fObjCABIVersion2Override = true; @@ -3395,23 +3683,26 @@ void Options::parse(int argc, const char* argv[]) else if ( strcmp(arg, "-warn_weak_exports") == 0 ) { fWarnWeakExports = true; } + else if ( strcmp(arg, "-no_weak_exports") == 0 ) { + fNoWeakExports = true; + } else if ( strcmp(arg, "-objc_gc_compaction") == 0 ) { fObjcGcCompaction = true; cannotBeUsedWithBitcode(arg); } else if ( strcmp(arg, "-objc_gc") == 0 ) { fObjCGc = true; - if ( fObjCGcOnly ) { + if ( fObjCGcOnly ) { warning("-objc_gc overriding -objc_gc_only"); - fObjCGcOnly = false; + fObjCGcOnly = false; } cannotBeUsedWithBitcode(arg); } else if ( strcmp(arg, "-objc_gc_only") == 0 ) { fObjCGcOnly = true; - if ( fObjCGc ) { + if ( fObjCGc ) { warning("-objc_gc_only overriding -objc_gc"); - fObjCGc = false; + fObjCGc = false; } cannotBeUsedWithBitcode(arg); } @@ -3422,11 +3713,6 @@ void Options::parse(int argc, const char* argv[]) fVersionLoadCommandForcedOn = true; fVersionLoadCommandForcedOff = false; } - else if ( strcmp(arg, "-no_version_load_command") == 0 ) { - fVersionLoadCommandForcedOff = true; - fVersionLoadCommandForcedOn = false; - cannotBeUsedWithBitcode(arg); - } else if ( strcmp(arg, "-function_starts") == 0 ) { fFunctionStartsForcedOn = true; fFunctionStartsForcedOff = false; @@ -3446,9 +3732,7 @@ void Options::parse(int argc, const char* argv[]) fDataInCodeInfoLoadCommandForcedOff = false; } else if ( strcmp(arg, "-object_path_lto") == 0 ) { - fTempLtoObjectPath = argv[++i]; - if ( fTempLtoObjectPath == NULL ) - throw "missing argument to -object_path_lto"; + fTempLtoObjectPath = checkForNullArgument(arg, argv[++i]); } else if ( strcmp(arg, "-no_objc_category_merging") == 0 ) { fObjcCategoryMerging = false; @@ -3510,14 +3794,6 @@ void Options::parse(int argc, const char* argv[]) fSnapshotRequested = true; cannotBeUsedWithBitcode(arg); } - else if ( strcmp(arg, "-new_main") == 0 ) { - fEntryPointLoadCommandForceOn = true; - cannotBeUsedWithBitcode(arg); - } - else if ( strcmp(arg, "-no_new_main") == 0 ) { - fEntryPointLoadCommandForceOff = true; - cannotBeUsedWithBitcode(arg); - } else if ( strcmp(arg, "-source_version") == 0 ) { const char* vers = argv[++i]; if ( vers == NULL ) @@ -3547,7 +3823,7 @@ void Options::parse(int argc, const char* argv[]) fKextsUseStubs = true; cannotBeUsedWithBitcode(arg); } - else if ( strcmp(argv[i], "-dependency_info") == 0 ) { + else if ( strcmp(arg, "-dependency_info") == 0 ) { snapshotArgCount = 0; ++i; // previously handled by buildSearchPaths() @@ -3586,6 +3862,10 @@ void Options::parse(int argc, const char* argv[]) fAllowSimulatorToLinkWithMacOSX = true; cannotBeUsedWithBitcode(arg); } + else if ( strcmp(arg, "-simulator_support") == 0 ) { + fSimulatorSupportDylib = true; + cannotBeUsedWithBitcode(arg); + } else if ( strcmp(arg, "-keep_dwarf_unwind") == 0 ) { fKeepDwarfUnwindForcedOn = true; fKeepDwarfUnwindForcedOff = false; @@ -3731,6 +4011,14 @@ void Options::parse(int argc, const char* argv[]) fUseDataConstSegmentForceOff = true; cannotBeUsedWithBitcode(arg); } + else if ( strcmp(arg, "-text_exec") == 0 ) { + fUseTextExecSegment = true; + cannotBeUsedWithBitcode(arg); + } + else if ( strcmp(arg, "-add_split_seg_info") == 0) { + fSharedRegionEligible = true; + cannotBeUsedWithBitcode(arg); + } else if ( strcmp(arg, "-no_deduplicate") == 0 ) { fDeDupe = false; } @@ -3759,14 +4047,39 @@ void Options::parse(int argc, const char* argv[]) } fMaxDefaultCommonAlign = alignment; } - else if ( strcmp(arg, "-prefer-mod-time-check") == 0 ) { - fFilePreference = kModTime; + else if ( strcmp(arg, "-no_weak_imports") == 0 ) { + fAllowWeakImports = false; } - else if ( strcmp(arg, "-prefer-text-based-stub-file") == 0 ) { - fFilePreference = kTextBasedStub; + else if ( strcmp(arg, "-no_inits") == 0 ) { + fInitializersTreatment = Options::kError; } - else if ( strcmp(arg, "-prefer-macho-file") == 0 ) { - fFilePreference = kMachO; + else if ( strcmp(arg, "-no_warn_inits") == 0 ) { + fInitializersTreatment = Options::kSuppress; + } + else if ( strcmp(arg, "-threaded_starts_section") == 0 ) { + fMakeThreadedStartsSection = true; + } + else if ( strcmp(arg, "-fixup_chains_section") == 0 ) { + fMakeChainedFixups = true; + fMakeChainedFixupsSection = true; + } + else if ( strcmp(arg, "-fixup_chains") == 0 ) { + fMakeChainedFixups = true; + } + else if (strcmp(arg, "-debug_variant") == 0) { + fDebugVariant = true; + } + else if (strcmp(arg, "-no_new_main") == 0) { + // HACK until 39514191 is fixed + } + else if (strcmp(arg, "-init_offsets") == 0) { + fMakeInitializersIntoOffsets = true; + } + else if (strcmp(arg, "-oso_prefix") == 0) { + const char* path = argv[++i]; + if ( path == NULL ) + throw "-oso_prefix missing "; + fOSOPrefixPath = path; } // put this last so that it does not interfer with other options starting with 'i' else if ( strncmp(arg, "-i", 2) == 0 ) { @@ -3808,9 +4121,37 @@ void Options::parse(int argc, const char* argv[]) if (fSnapshotRequested) fLinkSnapshot.createSnapshot(); + + if ( kKextBundle == fOutputKind ) { + if ( fKextObjectsEnable < 0 ) + fKextObjectsEnable = ((fArchitecture == CPU_TYPE_ARM64) || (fArchitecture == CPU_TYPE_ARM)); + + if (fKextObjectsEnable > 0) { + if ( !fKextObjectsDirPath ) { + const char* dstroot; + const char* objdir = getenv("LD_KEXT_OBJECTS_DIR"); + if ( objdir ) + fKextObjectsDirPath = strdup(objdir); + else if ( (dstroot = getenv("DSTROOT")) ) + asprintf((char **)&fKextObjectsDirPath, "%s/AppleInternal/KextObjects", dstroot); + } + fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_KEXT); + fLinkSnapshot.createSnapshot(); + } + } } +bool Options::shouldUseBuildVersion(ld::Platform plat, uint32_t minOSvers) const +{ + // certain dylibs need to use old load commands + if ( forceLegacyVersionLoadCommands() ) + return false; + if ( isSimulatorSupportDylib() && (plat != ld::Platform::iOSMac) ) + return false; + // otherwise, use LC_BUILD_VERSION if minOS is new enough + return (minOSvers >= platformInfo(plat).firstOsVersionUsingBuildVersionLC); +} // // -syslibroot is used for SDK support. @@ -3864,14 +4205,68 @@ void Options::buildSearchPaths(int argc, const char* argv[]) fVerbose = true; extern const char ldVersionString[]; fprintf(stderr, "%s", ldVersionString); + fprintf(stderr, "BUILD " __TIME__ " " __DATE__"\n"); fprintf(stderr, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS); // if only -v specified, exit cleanly if ( argc == 2 ) { + // ld64-port: + // The argc == 2 check before printing the LTO library seems an attempt + // to hide the broken '-lto_library ' implementation. + // The library is normally loaded _after_ command parsing and therefore "-lto_library " + // is ignored and the library is loaded from the default path. + // So as a workaround 'ld -lto_library -v' will not print the LTO version... + // And as a workaround for the workaround I have added "LIBLTO=" + // env. variable to ld64-port. #ifdef LTO_SUPPORT const char* ltoVers = lto::version(); + if ( ltoVers != NULL ) - fprintf(stderr, "LTO support using: %s\n", ltoVers); + fprintf(stderr, "LTO support using: %s (static support for %d, runtime is %d)\n", + ltoVers, lto::static_api_version(), lto::runtime_api_version()); #endif /* LTO_SUPPORT */ +#ifdef TAPI_SUPPORT + fprintf(stderr, "TAPI support using: %s\n", tapi::Version::getFullVersionAsString().c_str()); +#endif /* TAPI_SUPPORT */ + exit(0); + } + } + else if ( strcmp(argv[i], "-version_details") == 0 ) { + fVerbose = true; + extern const char ldVersionString[]; + fprintf(stdout, "{\n"); + fprintf(stdout, "\t\"version\": \"%s\",\n", STRINGIFY(LD64_VERSION_NUM)); + fprintf(stdout, "\t\"architectures\": [\n"); + char all_archs[] = ALL_SUPPORTED_ARCHS; + char* p = strtok(all_archs, " "); + int i = 0; + while (p) { + if (i++ > 0) { + fprintf(stdout, ",\n"); + } + fprintf(stdout, "\t\t\"%s\"", p); + p = strtok(NULL, " "); + } + fprintf(stdout, "\n\t],\n"); + +#ifdef LTO_SUPPORT + const char* ltoVers = lto::version(); + if ( ltoVers != NULL ) { + fprintf(stdout, "\t\"lto\": {\n"); + fprintf(stdout, "\t\t\"runtime_api_version\": %d,\n", lto::runtime_api_version()); + fprintf(stdout, "\t\t\"static_api_version\": %d,\n", lto::static_api_version()); + fprintf(stdout, "\t\t\"version_string\": \"%s\"\n", ltoVers); + fprintf(stdout, "\t},\n"); + } +#endif /* LTO_SUPPORT */ +#ifdef TAPI_SUPPORT + fprintf(stdout, "\t\"tapi\": {\n"); + fprintf(stdout, "\t\t\"version\": \"%s\",\n", tapi::Version::getAsString().c_str()); + fprintf(stdout, "\t\t\"version_string\": \"%s\"\n", tapi::Version::getFullVersionAsString().c_str()); + fprintf(stdout, "\t}\n"); +#endif /* TAPI_SUPPORT */ + fprintf(stdout, "}\n"); + // if only -version_json specified, exit cleanly + if ( argc == 2 ) { exit(0); } } @@ -4049,6 +4444,10 @@ void Options::buildSearchPaths(int argc, const char* argv[]) // this is run before the command line is parsed void Options::parsePreCommandLineEnvironmentSettings() { + if (getenv("LD_FORCE_LEGACY_VERSION_LOAD_CMDS") != NULL) { + fForceLegacyVersionLoadCommands = true; + } + if ((getenv("LD_TRACE_ARCHIVES") != NULL) || (getenv("RC_TRACE_ARCHIVES") != NULL)) fTraceArchives = true; @@ -4058,6 +4457,14 @@ void Options::parsePreCommandLineEnvironmentSettings() fTraceDylibs = true; fTraceIndirectDylibs = true; } + + if ((getenv("LD_TRACE_DEPENDENTS") != NULL)) { + fTraceEmitJSON = true; + // ld64 should ignore LD_TRACE_ARCHIVES and LD_TRACE_DYLIBS if LD_TRACE_DEPENDENTS is set in the environment + fTraceArchives = false; + fTraceDylibs = false; + fTraceIndirectDylibs = false; + } if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL) { fTraceDylibSearching = true; @@ -4066,15 +4473,12 @@ void Options::parsePreCommandLineEnvironmentSettings() if (getenv("LD_PRINT_OPTIONS") != NULL) fPrintOptions = true; - if (fTraceDylibs || fTraceArchives) + if (fTraceDylibs || fTraceArchives || fTraceEmitJSON) fTraceOutputFile = getenv("LD_TRACE_FILE"); if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL) fPrintOrderFileStatistics = true; - if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL) - fSplitSegs = true; - if (getenv("LD_NO_ENCRYPT") != NULL) { fEncryptable = false; fMarkAppExtensionSafe = true; // temporary @@ -4091,6 +4495,9 @@ void Options::parsePreCommandLineEnvironmentSettings() if (getenv("LD_DYLIB_CPU_SUBTYPES_MUST_MATCH") != NULL) fEnforceDylibSubtypesMatch = true; + + if (getenv("LD_WARN_ON_SWIFT_ABI_VERSION_MISMATCHES") != NULL) + fWarnOnSwiftABIVersionMismatches = true; sWarningsSideFilePath = getenv("LD_WARN_FILE"); @@ -4111,9 +4518,29 @@ void Options::parsePreCommandLineEnvironmentSettings() fPipelineFifo = pipeFdString; } - // Workaround for rdar://problem/24301175 - if ((getenv("RC_XBS") != NULL) && !(getenv("RC_BUILDIT") != NULL)) - fForceTextBasedStub = true; + // [Reproducible Builds] If env ZERO_AR_DATE is set, zero out timestamp in N_OSO stab + if ( getenv("ZERO_AR_DATE") != NULL ) + fZeroModTimeInDebugMap = true; + + char rawPath[PATH_MAX]; + char path[PATH_MAX]; + char *base; + uint32_t bufSize = PATH_MAX; + if ( _NSGetExecutablePath(rawPath, &bufSize) != -1 ) { + if ( realpath(rawPath, path) != NULL ) { +#define TOOLCHAINBASEPATH "/Developer/Toolchains/" + if ( (base = strstr(path, TOOLCHAINBASEPATH)) ) + fToolchainPath = strndup(path, base - path + strlen(TOOLCHAINBASEPATH)); + } + } + + // ld64 should consider RC_RELEASE when calculating a binary's UUID + fBuildContextName = getenv("RC_RELEASE"); + +#ifdef TAPI_SUPPORT + if (getenv("LD_PREFER_TAPI_FILE") != NULL) + fPreferTAPIFile = true; +#endif } @@ -4125,15 +4552,6 @@ void Options::parsePostCommandLineEnvironmentSettings() fExecutablePath = fOutputFile; } - // allow build system to set default seg_addr_table - if ( fSegAddrTablePath == NULL ) - fSegAddrTablePath = getenv("LD_SEG_ADDR_TABLE"); - - // allow build system to turn on prebinding - if ( !fPrebind ) { - fPrebind = ( getenv("LD_PREBIND") != NULL ); - } - // allow build system to force on dead-code-stripping if ( !fDeadStrip ) { if ( getenv("LD_DEAD_STRIP") != NULL ) { @@ -4166,8 +4584,71 @@ void Options::parsePostCommandLineEnvironmentSettings() } + +bool Options::sharedCacheEligiblePath(const char* path) const +{ + if ( (strncmp(path, "/usr/lib/", 9) == 0) || (strncmp(path, "/System/Library/", 16) == 0) ) + return true; + + // Dylibs with install_names in /Library/Apple/ should be eligible for dyld shared cache + if ( platforms().contains(ld::Platform::macOS) ) { + if ( (strncmp(path, "/Library/Apple/usr/lib/", 23) == 0) || (strncmp(path, "/Library/Apple/System/Library/", 30) == 0) ) + return true; + } + + uint32_t iosMacVers = platforms().minOS(ld::Platform::iOS); + if ( iosMacVers >= 0x000D0000 ) { + if ( (strncmp(path, "/System/iOSSupport/System/Library/", 34) == 0) || (strncmp(path, "/System/iOSSupport/usr/lib/", 27) == 0) ) + return true; + } + return false; +} + void Options::reconfigureDefaults() { + // -preload maps to "freestanding" platform + if ( fOutputKind == Options::kPreload ) { + // Some EFI builds set -macosx_version_min, even though they are -preload + if ( !platforms().empty() ) + fPlatforms.clear(); + // set platform to freestanding + fPlatforms.insert(ld::PlatformVersion(ld::Platform::freestanding, 0)); + } + // -static maps to "freestanding" platform, unless one already set + else if ( (fOutputKind == Options::kStaticExecutable) && platforms().empty() ) { + fPlatforms.insert(ld::PlatformVersion(ld::Platform::freestanding, 0)); + } + + // if -arch or platform not specified, look at .o files and infer + if ( platforms().empty() || (fArchitecture == 0) ) + inferArchAndPlatform(); + + // if no platform specified in .o files, look for env vars + if ( platforms().empty() ) { + if ( fOutputKind != Options::kObjectFile ) + warning("No platform min-version specified on command line"); + + // check for *_DEPLOYMENT_TARGET env var + ld::forEachSupportedPlatform(^(const ld::PlatformInfo& info, bool& stop) { + if ( info.fallbackEnvVarName != NULL ) { + if ( const char* versStr = getenv(info.fallbackEnvVarName) ) { + stop = true; + uint32_t value; + if ( parsePackedVersion32(versStr, value) ) { + if ( value < info.minimumOsVersion ) { + value = info.minimumOsVersion; + warning("OS version (%s) too small, changing to %s", versStr, getVersionString32(info.minimumOsVersion).c_str()); + } + fPlatforms.insert(ld::PlatformVersion(info.platform, value)); + } + else { + warning("%s env var malformed: '%s'", info.fallbackEnvVarName, versStr); + } + } + } + }); + } + // sync reader options switch ( fOutputKind ) { case Options::kObjectFile: @@ -4193,83 +4674,7 @@ void Options::reconfigureDefaults() break; } - // set default min OS version - if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fWatchOSVersionMin == ld::wOSVersionUnset) ) { - // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables - const char* macVers = getenv("MACOSX_DEPLOYMENT_TARGET"); - const char* iPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET"); - const char* iOSVers = getenv("IOS_DEPLOYMENT_TARGET"); - const char* wOSVers = getenv("WATCHOS_DEPLOYMENT_TARGET"); - if ( macVers != NULL ) - setMacOSXVersionMin(macVers); - else if ( iPhoneVers != NULL ) - setIOSVersionMin(iPhoneVers); - else if ( iOSVers != NULL ) - setIOSVersionMin(iOSVers); - else if ( wOSVers != NULL ) - setWatchOSVersionMin(wOSVers); - else { - // if still nothing, set default based on architecture - switch ( fArchitecture ) { - case CPU_TYPE_I386: - case CPU_TYPE_X86_64: - if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) { - #ifdef DEFAULT_MACOSX_MIN_VERSION - warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION); - setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION); - #else - warning("-macosx_version_min not specified, assuming 10.6"); - setMacOSXVersionMin("10.6"); - #endif - } - break; - case CPU_TYPE_ARM: - if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) { - #if defined(DEFAULT_IPHONEOS_MIN_VERSION) - warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION); - setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION); - #else - if ( fSubArchitecture == CPU_SUBTYPE_ARM_V7K ) { - warning("-watchos_version_min not specified, assuming 2.0"); - setWatchOSVersionMin("2.0"); - } - else { - warning("-ios_version_min not specified, assuming 6.0"); - setIOSVersionMin("6.0"); - } - #endif - } - break; - default: - // architecture will be infered later by examining .o files - break; - } - } - } - - // adjust min based on architecture - switch ( fArchitecture ) { - case CPU_TYPE_I386: - if ( (fPlatform == kPlatformOSX) && (fMacVersionMin < ld::mac10_4) ) { - //warning("-macosx_version_min should be 10.4 or later for i386"); - fMacVersionMin = ld::mac10_4; - } - break; - case CPU_TYPE_X86_64: - if ( (fPlatform == kPlatformOSX) && (fMacVersionMin < ld::mac10_4) ) { - //warning("-macosx_version_min should be 10.4 or later for x86_64"); - fMacVersionMin = ld::mac10_4; - } - break; - case CPU_TYPE_ARM64: - if ( (fPlatform == kPlatformiOS) && (fIOSVersionMin < ld::iOS_7_0) ) { - //warning("-mios_version_min should be 7.0 or later for arm64"); - fIOSVersionMin = ld::iOS_7_0; - } - break; - } - // default to adding functions start for dynamic code, static code must opt-in switch ( fOutputKind ) { case Options::kPreload: @@ -4316,17 +4721,12 @@ void Options::reconfigureDefaults() fUndefinedTreatment = kUndefinedDynamicLookup; break; case CPU_TYPE_ARM: - if ( min_iOS(ld::iOS_5_0) ) { - // iOS 5.0 and later use new MH_KEXT_BUNDLE type - fMakeCompressedDyldInfo = false; - fMakeCompressedDyldInfoForceOff = true; - // kexts are PIC in iOS 6.0 and later - fAllowTextRelocs = !min_iOS(ld::iOS_6_0); - fKextsUseStubs = !fAllowTextRelocs; - fUndefinedTreatment = kUndefinedDynamicLookup; - break; - } - // else use object file + fMakeCompressedDyldInfo = false; + fMakeCompressedDyldInfoForceOff = true; + fAllowTextRelocs = false; + fKextsUseStubs = !fAllowTextRelocs; + fUndefinedTreatment = kUndefinedDynamicLookup; + break; case CPU_TYPE_I386: // use .o files fOutputKind = kObjectFile; @@ -4336,65 +4736,9 @@ void Options::reconfigureDefaults() // disable implicit dylibs when targeting 10.3 // add option to disable implicit load commands for indirectly used public dylibs - if ( !minOS(ld::mac10_4, ld::iOS_2_0) ) + if ( !platforms().minOS(ld::version2007) ) fImplicitlyLinkPublicDylibs = false; - - // allow build system to force linker to ignore -prebind - if ( getenv("LD_FORCE_NO_PREBIND") != NULL ) - fPrebind = false; - - // allow build system to force linker to ignore -seg_addr_table - if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL ) - fSegAddrTablePath = NULL; - - // check for base address specified externally - if ( (fSegAddrTablePath != NULL) && (fOutputKind == Options::kDynamicLibrary) ) { - parseSegAddrTable(fSegAddrTablePath, this->installPath()); - // HACK to support seg_addr_table entries that are physical paths instead of install paths - if ( fBaseAddress == 0 ) { - if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) { - parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.4.dylib"); - if ( fBaseAddress == 0 ) - parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.9.dylib"); - } - - else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 ) - parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libz.1.2.3.dylib"); - - else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 ) - parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libutil1.0.dylib"); - } - } - - // split segs only allowed for dylibs - if ( fSplitSegs ) { - // split seg only supported for i386, and arm. - switch ( fArchitecture ) { - case CPU_TYPE_I386: - if ( fOutputKind != Options::kDynamicLibrary ) - fSplitSegs = false; - // make sure read and write segments are proper distance apart - if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x10000000) ) - fBaseWritableAddress = fBaseAddress + 0x10000000; - break; - case CPU_TYPE_ARM: - if ( fOutputKind != Options::kDynamicLibrary ) { - fSplitSegs = false; - } - else { - // make sure read and write segments are proper distance apart - if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x08000000) ) - fBaseWritableAddress = fBaseAddress + 0x08000000; - } - break; - default: - fSplitSegs = false; - fBaseAddress = 0; - fBaseWritableAddress = 0; - } - } - // set too-large size switch ( fArchitecture ) { case CPU_TYPE_I386: @@ -4426,79 +4770,11 @@ void Options::reconfigureDefaults() break; } - // -r implies no prebinding for all architectures - if ( fOutputKind == Options::kObjectFile ) - fPrebind = false; - - // disable prebinding depending on arch and min OS version - if ( fPrebind ) { - switch ( fArchitecture ) { - case CPU_TYPE_I386: - if ( fMacVersionMin == ld::mac10_4 ) { - // in 10.4 only split seg dylibs are prebound - if ( (fOutputKind != Options::kDynamicLibrary) || ! fSplitSegs ) - fPrebind = false; - } - else if ( fMacVersionMin >= ld::mac10_5 ) { - // in 10.5 nothing is prebound - fPrebind = false; - } - else if ( fIOSVersionMin != ld::iOSVersionUnset ) { - // nothing in simulator is prebound - fPrebind = false; - } - else { - // in 10.3 and earlier only dylibs and main executables could be prebound - switch ( fOutputKind ) { - case Options::kDynamicExecutable: - case Options::kDynamicLibrary: - // only main executables and dylibs can be prebound - break; - case Options::kStaticExecutable: - case Options::kDynamicBundle: - case Options::kObjectFile: - case Options::kDyld: - case Options::kPreload: - case Options::kKextBundle: - // disable prebinding for everything else - fPrebind = false; - break; - } - } - break; - case CPU_TYPE_X86_64: - fPrebind = false; - break; - case CPU_TYPE_ARM: - switch ( fOutputKind ) { - case Options::kDynamicExecutable: - case Options::kDynamicLibrary: - // only main executables and dylibs can be prebound - break; - case Options::kStaticExecutable: - case Options::kDynamicBundle: - case Options::kObjectFile: - case Options::kDyld: - case Options::kPreload: - case Options::kKextBundle: - // disable prebinding for everything else - fPrebind = false; - break; - } - break; - } - } - - // only prebound images can be split-seg - if ( fSplitSegs && !fPrebind ) - fSplitSegs = false; - // determine if info for shared region should be added if ( fOutputKind == Options::kDynamicLibrary ) { - if ( minOS(ld::mac10_5, ld::iOS_3_1) ) - if ( !fPrebind && !fSharedRegionEligibleForceOff ) - if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0) - || (strncmp(this->installPath(), "/System/Library/", 16) == 0) ) + if ( platforms().minOS(ld::version2008Fall) ) + if ( !fSharedRegionEligibleForceOff ) + if ( sharedCacheEligiblePath(this->installPath()) ) fSharedRegionEligible = true; } else if ( fOutputKind == Options::kDyld ) { @@ -4506,20 +4782,85 @@ void Options::reconfigureDefaults() fSharedRegionEligible = true; } - // warn if -rpath is used with OS dylibs - if ( fSharedRegionEligible && !fRPaths.empty() ) - warning("-rpath cannot be used with dylibs that will be in the dyld shared cache"); - - // automatically use __DATA_CONST in iOS dylibs - if ( fSharedRegionEligible && minOS(ld::mac10_Future, ld::iOS_9_0) && !fUseDataConstSegmentForceOff ) { + // A -kext for iOS 10 ==> -data_const, -text_exec, -add_split_seg_info + if ( (fOutputKind == Options::kKextBundle) && (fArchitecture == CPU_TYPE_ARM64) ) { fUseDataConstSegment = true; + fUseTextExecSegment = true; + fSharedRegionEligible = true; } + + // by default, use __DATA_CONST for all userland binaries targeting newer OS + if ( !fSharedRegionEligible && !fUseDataConstSegmentForceOff && platforms().minOS(ld::version2019Fall) ) { + switch ( fOutputKind ) { + case Options::kDynamicExecutable: + // don't auto use __DATA_CONST for -no_pie programs (like emacs) + fUseDataConstSegment = !fDisablePositionIndependentExecutable; + break; + case Options::kDynamicBundle: + // Bundles located at: /System/Library/UserEventPlugins/*plugins need be opted out of __DATA_CONST + if ( (fFinalName != NULL) && (strncmp(fFinalName, "/System/Library/UserEventPlugins/", 33) == 0) ) + fUseDataConstSegment = false; + else + fUseDataConstSegment = true; + break; + case Options::kDynamicLibrary: + case Options::kDyld: + fUseDataConstSegment = true; + break; + case Options::kStaticExecutable: + case Options::kObjectFile: + case Options::kPreload: + case Options::kKextBundle: + break; + } + } + + // Use V2 shared cache info when targetting newer OSs + if ( fSharedRegionEligible && platforms().minOS(ld::supportsSplitSegV2) ) { + fSharedRegionEncodingV2 = true; + if ( platforms().contains(ld::Platform::macOS) && (fArchitecture == CPU_TYPE_X86_64) ) { + fSharedRegionEncodingV2 = false; + // use v2 for stable Swift dylibs in /usr/lib/swift/ + if ( strncmp(this->installPath(), "/usr/lib/swift/", 15) == 0 ) + fSharedRegionEncodingV2 = true; + // any other OS frameworks that use swift need v2 + for (const char* searchPath : fLibrarySearchPaths ) { + if ( strstr(searchPath, "/usr/lib/swift") != NULL ) { + fSharedRegionEncodingV2 = true; + break; + } + } + } + if ( fSharedRegionEncodingV2 && (fArchitecture == CPU_TYPE_I386) ) { + // Disable V2 on i386 as its not qualififed yet. + fSharedRegionEncodingV2 = false; + } + fIgnoreOptimizationHints = true; + } + if ( fUseDataConstSegmentForceOn ) { fUseDataConstSegment = true; } + else if ( fUseDataConstSegmentForceOff ) { + fUseDataConstSegment = false; + } + else if ( fSharedRegionEncodingV2 ) { + // automatically use __DATA_CONST in shared dylibs when V2 is in use + fUseDataConstSegment = true; + } + + + // TEMP until are fixed + if ( (fFinalName != NULL) && ((strcmp(fFinalName, "/usr/libexec/locationd") == 0) || (strcmp(fFinalName, "/usr/libexec/terminusd") == 0)) ) { + fUseDataConstSegment = false; + } + if ( fUseDataConstSegment ) { addSectionRename("__DATA", "__got", "__DATA_CONST", "__got"); - addSectionRename("__DATA", "__la_symbol_ptr", "__DATA_CONST", "__la_symbol_ptr"); +#if SUPPORT_ARCH_arm64e + addSectionRename("__DATA", "__auth_got", "__DATA_CONST", "__auth_got"); + addSectionRename("__DATA", "__auth_ptr", "__DATA_CONST", "__auth_ptr"); +#endif addSectionRename("__DATA", "__nl_symbol_ptr", "__DATA_CONST", "__nl_symbol_ptr"); addSectionRename("__DATA", "__const", "__DATA_CONST", "__const"); addSectionRename("__DATA", "__cfstring", "__DATA_CONST", "__cfstring"); @@ -4531,28 +4872,21 @@ void Options::reconfigureDefaults() addSectionRename("__DATA", "__objc_nlcatlist", "__DATA_CONST", "__objc_nlcatlist"); addSectionRename("__DATA", "__objc_protolist", "__DATA_CONST", "__objc_protolist"); addSectionRename("__DATA", "__objc_imageinfo", "__DATA_CONST", "__objc_imageinfo"); - addSectionRename("__DATA", "__objc_const", "__DATA_CONST", "__objc_const"); - } - - // Use V2 shared cache info when targetting newer OSs - if ( fSharedRegionEligible && minOS(ld::mac10_Future, ld::iOS_9_0)) { - fSharedRegionEncodingV2 = true; - fIgnoreOptimizationHints = true; - } - - // figure out if module table is needed for compatibility with old ld/dyld - if ( fOutputKind == Options::kDynamicLibrary ) { - switch ( fArchitecture ) { - case CPU_TYPE_I386: - if ( fIOSVersionMin != ld::iOSVersionUnset ) // simulator never needs modules - break; - case CPU_TYPE_ARM: - if ( fPrebind ) - fNeedsModuleTable = true; // redo_prebinding requires a module table - break; + if ( fSharedRegionEligible ) { + // these sections are not really read-only, except in the dyld cache (for now) + addSectionRename("__DATA", "__la_symbol_ptr", "__DATA_CONST", "__la_symbol_ptr"); + addSectionRename("__DATA", "__objc_const", "__DATA_CONST", "__objc_const"); } } - + if ( fUseTextExecSegment ) { + addSectionRename("__TEXT", "__text", "__TEXT_EXEC", "__text"); + addSectionRename("__TEXT", "__stubs", "__TEXT_EXEC", "__stubs"); + } + // automatically move thread local data to __DATA_DIRTY if dirty data is in use + if ( fSharedRegionEncodingV2 && fUseDataConstSegment ) { + addSectionRename("__DATA", "__thread_vars", "__DATA_DIRTY", "__thread_vars"); + } + // -r -x implies -S if ( (fOutputKind == Options::kObjectFile) && (fLocalSymbolHandling == kLocalSymbolsNone) ) fDebugInfoStripping = Options::kDebugInfoNone; @@ -4624,11 +4958,12 @@ void Options::reconfigureDefaults() case Options::kDynamicLibrary: case Options::kDynamicBundle: // Add LC_ENCRYPTION_INFO load command to bundled frameworks - if ( !min_iOS(ld::iOS_7_0) ) + if ( !platforms().minOS(ld::version2013) ) fEncryptable = false; break; } - if ( (fArchitecture != CPU_TYPE_ARM) && (fArchitecture != CPU_TYPE_ARM64) ) + if ( (fArchitecture != CPU_TYPE_ARM) && (fArchitecture != CPU_TYPE_ARM64) + ) fEncryptable = false; if ( fEncryptableForceOn ) fEncryptable = true; @@ -4662,37 +4997,34 @@ void Options::reconfigureDefaults() case Options::kDynamicLibrary: case Options::kDynamicBundle: break; + case Options::kDyld: + // arm64e has support for compressed LINKEDIT. + if ( (fArchitecture == CPU_TYPE_ARM64) && (fSubArchitecture == CPU_SUBTYPE_ARM64E) ) + break; case Options::kPreload: case Options::kStaticExecutable: case Options::kObjectFile: - case Options::kDyld: case Options::kKextBundle: fMakeCompressedDyldInfoForceOff = true; break; } - if ( fMakeCompressedDyldInfoForceOff ) - fMakeCompressedDyldInfo = false; - - // only use compressed LINKEDIT for: - // Mac OS X 10.6 or later - // iOS 3.1 or later - if ( fMakeCompressedDyldInfo ) { - if ( !minOS(ld::mac10_6, ld::iOS_3_1) ) - fMakeCompressedDyldInfo = false; - } + // only use legacy LINKEDIT if compressed LINKEDIT is forced off of: + // macOS before 10.6 + // iOS before 3.1 + if ( fMakeCompressedDyldInfoForceOff || !platforms().minOS(ld::version2009) ) + fMakeCompressedDyldInfo = false; // only ARM and x86_64 enforces that cpu-sub-types must match switch ( fArchitecture ) { case CPU_TYPE_ARM: + case CPU_TYPE_ARM64: break; case CPU_TYPE_X86_64: fEnforceDylibSubtypesMatch = false; break; case CPU_TYPE_I386: - case CPU_TYPE_ARM64: fEnforceDylibSubtypesMatch = false; - fAllowCpuSubtypeMismatches = true; break; } @@ -4723,30 +5055,131 @@ void Options::reconfigureDefaults() } // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB - if ( minOS(ld::mac10_5, ld::iOS_2_0) ) + if ( platforms().minOS(ld::version2008) ) fUseSimplifiedDylibReExports = true; // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB - if ( minOS(ld::mac10_7, ld::iOS_4_2) && (fOutputKind == kDynamicLibrary) ) + if ( platforms().minOS(ld::version2010) && (fOutputKind == kDynamicLibrary) ) fCanUseUpwardDylib = true; - + + if (fArchitecture == CPU_TYPE_ARM64) { +#if SUPPORT_ARCH_arm64e + if (fSubArchitecture == CPU_SUBTYPE_ARM64E) + { + // FIXME: Move some of these to arm64 + fNoLazyBinding = true; + switch ( fOutputKind ) { + case Options::kDynamicExecutable: + case Options::kDynamicLibrary: + case Options::kDynamicBundle: + case Options::kDyld: + fUseLinkedListBinding = true; + fUseAuthenticatedStubs = true; + break; + case Options::kPreload: + case Options::kStaticExecutable: + case Options::kObjectFile: + case Options::kKextBundle: + break; + } + switch ( fOutputKind ) { + case Options::kDynamicExecutable: + case Options::kDyld: + case Options::kDynamicLibrary: + case Options::kObjectFile: + case Options::kDynamicBundle: + case Options::kKextBundle: + fSupportsAuthenticatedPointers = true; + break; + case Options::kStaticExecutable: + case Options::kPreload: + fSupportsAuthenticatedPointers = false; + break; + } + } +#endif + } + + if ( fMakeThreadedStartsSection && (fArchitecture != CPU_TYPE_ARM64) ) { + // Threaded starts isn't valid here so ignore it. + warning("-threaded_starts_section ignored ignored for non-arm64"); + fMakeThreadedStartsSection = false; + } + + if (fMakeThreadedStartsSection) { + switch ( fOutputKind ) { + case Options::kDynamicExecutable: + case Options::kDyld: + case Options::kDynamicLibrary: + case Options::kObjectFile: + case Options::kDynamicBundle: + case Options::kKextBundle: + // Threaded starts isn't valid here so ignore it. + warning("-threaded_starts_section ignored for binaries other than -static or -preload"); + fMakeThreadedStartsSection = false; + break; + case Options::kStaticExecutable: + case Options::kPreload: + fUseLinkedListBinding = true; + fNoLazyBinding = true; +#if SUPPORT_ARCH_arm64e + if ( (fArchitecture == CPU_TYPE_ARM64) && (fSubArchitecture == CPU_SUBTYPE_ARM64E) ) + fSupportsAuthenticatedPointers = true; +#endif + break; + } + } + + switch ( fOutputKind ) { + case Options::kDynamicExecutable: + case Options::kDynamicLibrary: + case Options::kDynamicBundle: + if ( platforms().minOS(ld::supportsChainedFixups) && (fArchitecture != CPU_TYPE_I386) ) { + //fMakeChainedFixups = true; + } + break; + case Options::kDyld: + case Options::kStaticExecutable: + case Options::kPreload: + break; + case Options::kObjectFile: + case Options::kKextBundle: + break; + } + if ( fMakeChainedFixups ) { + fMakeCompressedDyldInfo = false; + fNoLazyBinding = true; + fMakeCompressedDyldInfo = false; + fMakeCompressedDyldInfoForceOff = true; + } + + + // Weak binding requires that if we want to use linked list binding, we must + // also be using no lazy binding. + if ( fUseLinkedListBinding ) + assert(fNoLazyBinding); + // MacOSX 10.7 defaults to PIE - if ( ((fArchitecture == CPU_TYPE_X86_64) || (fArchitecture == CPU_TYPE_I386)) + if ( (fArchitecture == CPU_TYPE_I386) && (fOutputKind == kDynamicExecutable) - && (fMacVersionMin >= ld::mac10_7) ) { + && platforms().minOS(ld::mac10_7) ) { fPositionIndependentExecutable = true; } // armv7 for iOS4.3 defaults to PIE if ( (fArchitecture == CPU_TYPE_ARM) && fArchSupportsThumb2 - && (fOutputKind == kDynamicExecutable) - && min_iOS(ld::iOS_4_3) ) { + && (fOutputKind == kDynamicExecutable) + && (platforms().contains(ld::Platform::watchOS) || platforms().minOS(ld::iOS_4_3)) ) { fPositionIndependentExecutable = true; } + // x86_64 defaults PIE (for 10.6 and later) + if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind == kDynamicExecutable) && (platforms().minOS(ld::mac10_6) || platforms().contains(ld::Platform::iOSMac)) ) + fPositionIndependentExecutable = true; + // Simulator defaults to PIE - if ( fTargetIOSSimulator && (fOutputKind == kDynamicExecutable) ) + if ( targetIOSSimulator() && (fOutputKind == kDynamicExecutable) ) fPositionIndependentExecutable = true; // -no_pie anywhere on command line disable PIE @@ -4754,8 +5187,12 @@ void Options::reconfigureDefaults() fPositionIndependentExecutable = false; // arm64 is always PIE - if ( (fArchitecture == CPU_TYPE_ARM64) && (fOutputKind == kDynamicExecutable) ) { + if ( ((fArchitecture == CPU_TYPE_ARM64) + ) + && (fOutputKind == kDynamicExecutable) ) { fPositionIndependentExecutable = true; + if ( fDisablePositionIndependentExecutable ) + warning("-no_pie ignored for arm64"); } // set fOutputSlidable @@ -4778,20 +5215,12 @@ void Options::reconfigureDefaults() break; } - // let linker know if thread local variables are supported - if ( fMacVersionMin >= ld::mac10_7 ) { - fTLVSupport = true; - } - else if ( (fArchitecture == CPU_TYPE_ARM64) && min_iOS(ld::iOS_8_0) ) { - fTLVSupport = true; - } - else if ( (fArchitecture == CPU_TYPE_ARM) && min_iOS(ld::iOS_9_0) ) { - fTLVSupport = true; - } - else if ( fTargetIOSSimulator && (fArchitecture == CPU_TYPE_X86_64) && min_iOS(ld::iOS_8_0) ) { - fTLVSupport = true; - } - else if ( fTargetIOSSimulator && (fArchitecture == CPU_TYPE_I386) && min_iOS(ld::iOS_9_0) ) { + // Let linker know if thread local variables are supported + // This is more complex than normal version checks since + // runtime support varies by architecture + if (platforms().minOS(ld::supportsTLV) + || ((fArchitecture == CPU_TYPE_ARM64) && platforms().minOS(ld::iOS_8_0)) + || ((fArchitecture == CPU_TYPE_X86_64) && platforms().minOS(ld::iOS_9_0))) { fTLVSupport = true; } @@ -4816,7 +5245,7 @@ void Options::reconfigureDefaults() } // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2 - if ( (fOutputKind == kDynamicLibrary) && minOS(ld::mac10_7, ld::iOS_4_2) ) + if ( (fOutputKind == kDynamicLibrary) && platforms().minOS(ld::version2010) ) fCanReExportSymbols = true; // ObjC optimization is only in dynamic final linked images @@ -4843,32 +5272,22 @@ void Options::reconfigureDefaults() // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs switch ( fOutputKind ) { case Options::kDynamicExecutable: - if ( fEntryPointLoadCommandForceOn ) { + if ( platforms().contains(ld::Platform::driverKit) ) + break; + // Linker should look for "_main" not "start" when building for sim regardless of min OS + if ( platforms().minOS(ld::version2012) ) { fEntryPointLoadCommand = true; - if ( fEntryName == NULL ) + if ( fEntryName == NULL ) fEntryName = "_main"; - } - else if ( fEntryPointLoadCommandForceOff ) { - fNeedsThreadLoadCommand = true; - if ( fEntryName == NULL ) - fEntryName = "start"; + if ( strcmp(fEntryName, "start") == 0 ) { + warning("Ignoring '-e start' because entry point 'start' is not used for the targeted OS version"); + fEntryName = "_main"; + } } else { - // Linker should look for "_main" not "start" when building for sim regardless of min OS - if ( minOS(ld::mac10_8, ld::iOS_6_0) || fTargetIOSSimulator ) { - fEntryPointLoadCommand = true; - if ( fEntryName == NULL ) - fEntryName = "_main"; - if ( strcmp(fEntryName, "start") == 0 ) { - warning("Ignoring '-e start' because entry point 'start' is not used for the targeted OS version"); - fEntryName = "_main"; - } - } - else { - fNeedsThreadLoadCommand = true; - if ( fEntryName == NULL ) - fEntryName = "start"; - } + fNeedsThreadLoadCommand = true; + if ( fEntryName == NULL ) + fEntryName = "start"; } break; case Options::kObjectFile: @@ -4901,7 +5320,7 @@ void Options::reconfigureDefaults() fSourceVersionLoadCommand = false; } else { - if ( minOS(ld::mac10_8, ld::iOS_6_0) ) { + if ( platforms().minOS(ld::version2012) ) { fSourceVersionLoadCommand = true; } else @@ -4914,85 +5333,105 @@ void Options::reconfigureDefaults() break; } - // if -sdk_version not on command line, infer from -syslibroot - if ( (fSDKVersion == 0) && (fSDKPaths.size() > 0) ) { - const char* sdkPath = fSDKPaths.front(); - const char* end = &sdkPath[strlen(sdkPath)-1]; - while ( !isdigit(*end) && (end > sdkPath) ) - --end; - const char* start = end-1; - while ( (isdigit(*start) || (*start == '.')) && (start > sdkPath)) - --start; - char sdkVersionStr[32]; - int len = end-start+1; - if ( len > 2 ) { - strlcpy(sdkVersionStr, start+1, len); - fSDKVersion = parseVersionNumber32(sdkVersionStr); + if (fSDKVersion != 0) { + if (platforms().count() > 1) { + throw "-sdk_version may not be used for zippered binaries"; } - } - - // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version - if ( (fSDKVersion == 0) && (fMacVersionMin != ld::macVersionUnset) ) { - // special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos - if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) { - fSDKVersion = fMacVersionMin; + if (fPlatfromVersionCmdFound) { + warning("-sdk_version and -platform_version are not compatible, ignoring -sdk_version"); + } else { + // This is kind of gross, but we will remove it once -platform_version is adopted, so + // there is no point in adding a nicer interface to VersionSet + __block ld::Platform currentPlatform; + fPlatforms.forEach(^(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop) { + currentPlatform = platform; + }); + fPlatforms.updateSDKVersion(currentPlatform, fSDKVersion); + //warning("-sdk_version is deprecated, please switch to -platform_version"); } - else { + } else { + bool inferredFromSDKpath = false; + // if -sdk_version not on command line, infer from -syslibroot + if ( !fPlatfromVersionCmdFound && (fSDKPaths.size() > 0) ) { + const char* sdkPath = fSDKPaths.front(); + const char* end = &sdkPath[strlen(sdkPath)-1]; + while ( !isdigit(*end) && (end > sdkPath) ) + --end; + const char* start = end-1; + while ( (isdigit(*start) || (*start == '.')) && (start > sdkPath)) + --start; + char sdkVersionStr[32]; + int len = end-start+1; + if ( len > 2 ) { + strlcpy(sdkVersionStr, start+1, len); + __block ld::Platform currentPlatform; + fPlatforms.forEach(^(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop) { + if ( platform != ld::Platform::iOSMac ) + currentPlatform = platform; + }); + fPlatforms.updateSDKVersion(currentPlatform, parseVersionNumber32(sdkVersionStr)); + inferredFromSDKpath = true; + } + } + + // if no version was explicitly set on the commandline or by an environemt variable, and the + // the platform is macOS then set the min version to the current + if ( !fPlatfromVersionCmdFound && !inferredFromSDKpath && (fSDKVersion == 0) && platforms().contains(ld::Platform::macOS) + && !(getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET")) ) { #ifdef __APPLE__ // ld64-port int mib[2] = { CTL_KERN, KERN_OSRELEASE }; char kernVersStr[100]; size_t strlen = sizeof(kernVersStr); if ( sysctl(mib, 2, kernVersStr, &strlen, NULL, 0) != -1 ) { -#else - const char *kernVersStr = "10.5"; // ld64-port: claim we are on 10.5 -#endif uint32_t kernVers = parseVersionNumber32(kernVersStr); - int minor = (kernVers >> 16) - 4; // kernel major version is 4 ahead of x in 10.x - fSDKVersion = 0x000A0000 + (minor << 8); -#ifdef __APPLE__ // ld64-port + int minor = (kernVers >> 16) - 4; // kernel major version is 4 ahead of x in 10. + fPlatforms.updateSDKVersion(ld::Platform::macOS, (0x000A0000 + (minor << 8))); } +#else + fPlatforms.updateSDKVersion(ld::Platform::macOS, parseVersionNumber32("10.6")); // ld64-port: claim we are on 10.6 #endif } } - + // allow trie based absolute symbols if targeting new enough OS - if ( fMakeCompressedDyldInfo ) { - if ( minOS(ld::mac10_9, ld::iOS_7_0) ) { + if ( fMakeCompressedDyldInfo || fMakeChainedFixups ) { + if ( platforms().minOS(ld::version2013) ) { fAbsoluteSymbols = true; } } - - // iOS main executables now default to 16KB page size - if ( (fIOSVersionMin != ld::iOSVersionUnset) && (fOutputKind == Options::kDynamicExecutable) ) { - // Only third party apps should have 16KB page segments by default - if ( fEncryptable ) { - if ( fSegmentAlignment == 4096 ) - fSegmentAlignment = 4096*4; - } + + // Only third party apps should have 16KB page segments by default + if ( fEncryptable ) { + if ( fSegmentAlignment == 4096 ) + fSegmentAlignment = 4096*4; } // ARM64 needs 16KB page size for user land code // make armv7[s] use 16KB pages in user land code for iOS 8 or later - if ( fSegmentAlignment == 4096 ) { + if ( fSegmentAlignment == LD_PAGE_SIZE ) { switch ( fOutputKind ) { case Options::kDynamicExecutable: case Options::kDynamicLibrary: case Options::kDynamicBundle: case Options::kDyld: - if ( (fArchitecture == CPU_TYPE_ARM64) - || ((fArchitecture == CPU_TYPE_ARM) && min_iOS(ld::iOS_7_0)) ) { + // 16KB segments for arm64 kexts + if ( (fArchitecture == CPU_TYPE_ARM64) + || (fArchitecture == CPU_TYPE_ARM) ) { fSegmentAlignment = 4096*4; } break; case Options::kStaticExecutable: case Options::kKextBundle: // 16KB segments for arm64 kexts - if ( (fArchitecture == CPU_TYPE_ARM64) && min_iOS(ld::iOS_9_0) ) { + if ( fArchitecture == CPU_TYPE_ARM64 ) { fSegmentAlignment = 4096*4; } break; case Options::kObjectFile: + break; case Options::kPreload: + if ( fArchitecture == CPU_TYPE_ARM ) + fSegmentAlignment = 4096; break; } } @@ -5012,7 +5451,7 @@ void Options::reconfigureDefaults() fKeepDwarfUnwind = false; } else { - if ( minOS(ld::mac10_9, ld::iOS_7_0) ) + if ( platforms().minOS(ld::version2013) ) fKeepDwarfUnwind = false; else fKeepDwarfUnwind = true; @@ -5048,6 +5487,49 @@ void Options::reconfigureDefaults() } } + // if aliases are used with dirty data, allow alias to do the move + if ( !fSymbolsMovesData.empty() && !fAliases.empty() ) { + for (const AliasPair& pair : fAliases) { + for (SymbolsMove& moveInfo : fSymbolsMovesData) { + bool matchBecauseOfWildcard; + if ( moveInfo.symbols.contains(pair.alias, &matchBecauseOfWildcard) ) { + moveInfo.symbols.insert(pair.realName); + } + } + } + } + + + // Look in $SDKROOT/AppleInternal/AccessibilityLinkerSymbols/.axsymbols for objc-class names + if ( fUseDataConstSegment && (fDylibInstallName != NULL) && !fSDKPaths.empty() ) { + const char* dylibLeaf = strrchr(fDylibInstallName, '/'); + if ( dylibLeaf ) { + char path[PATH_MAX]; + strlcpy(path , fSDKPaths.front(), sizeof(path)); + strlcat(path , "/AppleInternal/AccessibilityLinkerSymbols", sizeof(path)); + strlcat(path , dylibLeaf, sizeof(path)); + strlcat(path , ".axsymbols", sizeof(path)); + FileInfo info; + if ( info.checkFileExists(*this, path) ) { + SymbolsMove tmp; + fSymbolsMovesAXMethodLists.push_back(tmp); + loadExportFile(path, ".axsymbols", fSymbolsMovesAXMethodLists.back().symbols); + } + } + } + + // Automatically use OrderFiles found in the AppleInternal SDK + if ( (fFinalName != NULL) && fOrderedSymbols.empty() && !fSDKPaths.empty() ) { + char path[PATH_MAX]; + strlcpy(path , fSDKPaths.front(), sizeof(path)); + strlcat(path , "/AppleInternal/OrderFiles/", sizeof(path)); + strlcat(path , fFinalName, sizeof(path)); + strlcat(path , ".order", sizeof(path)); + FileInfo info; + if ( info.checkFileExists(*this, path) ) + parseOrderFile(path, false); + } + // Reduce the default alignment of structures/arrays to save memory in embedded systems if ( fMaxDefaultCommonAlign == 0 ) { if ( fOutputKind == Options::kPreload ) @@ -5055,6 +5537,51 @@ void Options::reconfigureDefaults() else fMaxDefaultCommonAlign = 15; } + + // Add warnings for issues likely to cause OS verification issues + if ( fSharedRegionEligible && !fRPaths.empty() && !fDebugVariant ) { + // warn if -rpath is used with OS dylibs + warning("OS dylibs should not add rpaths (linker option: -rpath) (Xcode build setting: LD_RUNPATH_SEARCH_PATHS)"); + } + if ( (fOutputKind == Options::kDynamicLibrary) && (fDylibInstallName != NULL) && (fFinalName != NULL) && sharedCacheEligiblePath(fFinalName) && !fDebugVariant ) { + if ( strncmp(fDylibInstallName, "@rpath", 6) == 0 ) + warning("OS dylibs should not use @rpath for -install_name. Use absolute path instead"); + if ( strcmp(fDylibInstallName, fFinalName) != 0 ) + warning("OS dylibs -install_name should match its real absolute path"); + } + +#if SUPPORT_ARCH_arm64e + // arm64e chained fixups do not support misaligned pointers + if ( (fArchitecture == CPU_TYPE_ARM64) && (fSubArchitecture == CPU_SUBTYPE_ARM64E) ) { + if ( fUnalignedPointerTreatment == Options::kUnalignedPointerWarning ) + warning("for arm64e unaligned pointer errors are fatal"); + fUnalignedPointerTreatment = Options::kUnalignedPointerError; + } +#endif + // set if unaligned pointers are warnings or errors + if ( fUnalignedPointerTreatment == Options::kUnalignedPointerIgnore ) { + if ( platforms().minOS(ld::mac10_12) && fSharedRegionEligible ) { + fUnalignedPointerTreatment = Options::kUnalignedPointerWarning; + } + else if ( platforms().minOS(ld::iOS_10_0) ) { + fUnalignedPointerTreatment = Options::kUnalignedPointerWarning; + } + } + + // warn by default for OS dylibs + if ( fInitializersTreatment == Options::kInvalid ) { + if ( fSharedRegionEligible && (fOutputKind == Options::kDynamicLibrary) && !fDebugVariant ) { + fInitializersTreatment = Options::kWarning; + } + else + fInitializersTreatment = Options::kSuppress; + } + + // transform __DATA, __mod_init_funcs to __TEXT offsets + if ( (fArchitecture == CPU_TYPE_ARM64) && (fSubArchitecture == CPU_SUBTYPE_ARM64E) ) { + // uncommment we runtime is ready + //fMakeInitializersIntoOffsets = true; + } } void Options::checkIllegalOptionCombinations() @@ -5064,22 +5591,31 @@ void Options::checkIllegalOptionCombinations() case kUndefinedError: // always legal break; - case kUndefinedDynamicLookup: - switch (fPlatform) { - case kPlatformOSX: - break; - case kPlatformiOS: - case kPlatformWatchOS: - #if SUPPORT_APPLE_TV - case kPlatform_tvOS: - #endif - if ( fOutputKind != kKextBundle ) - warning("-undefined dynamic_lookup is deprecated on %s", platformName(fPlatform)); - break; - default: - break; - } - break; + case kUndefinedDynamicLookup: { + platforms().forEach(^(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop) { + switch (platform) { + case ld::Platform::macOS: + if ( fSharedRegionEligible ) + warning("-undefined dynamic_lookup is incompatible with dyld share cache"); + break; + case ld::Platform::iOSMac: + case ld::Platform::unknown: + break; + case ld::Platform::iOS: + case ld::Platform::iOS_simulator: + case ld::Platform::watchOS: + case ld::Platform::watchOS_simulator: + case ld::Platform::bridgeOS: + case ld::Platform::tvOS: + case ld::Platform::tvOS_simulator: + case ld::Platform::freestanding: + case ld::Platform::driverKit: + if ( fOutputKind != kKextBundle ) + warning("-undefined dynamic_lookup is deprecated on %s", platformInfo(platform).printName); + break; + } + }); + } break; case kUndefinedWarning: case kUndefinedSuppress: // requires flat namespace @@ -5138,19 +5674,25 @@ void Options::checkIllegalOptionCombinations() // sync reader options if ( fNameSpace != kTwoLevelNameSpace ) { fFlatNamespace = true; - switch (fPlatform) { - case kPlatformOSX: - break; - case kPlatformiOS: - case kPlatformWatchOS: - #if SUPPORT_APPLE_TV - case Options::kPlatform_tvOS: - #endif - warning("-flat_namespace is deprecated on %s", platformName(fPlatform)); - break; - default: - break; - } + platforms().forEach(^(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop) { + switch (platform) { + case ld::Platform::unknown: + case ld::Platform::macOS: + case ld::Platform::iOSMac: + break; + case ld::Platform::iOS: + case ld::Platform::iOS_simulator: + case ld::Platform::watchOS: + case ld::Platform::watchOS_simulator: + case ld::Platform::bridgeOS: + case ld::Platform::tvOS: + case ld::Platform::tvOS_simulator: + case ld::Platform::driverKit: + case ld::Platform::freestanding: + warning("-flat_namespace is deprecated on %s", platformInfo(platform).printName); + break; + } + }); } @@ -5176,7 +5718,7 @@ void Options::checkIllegalOptionCombinations() if ( fStackSize != 0 ) { switch (fArchitecture) { case CPU_TYPE_I386: - if ( fPlatform == kPlatformOSX ) { + if ( platforms().contains(ld::Platform::macOS) ) { if ( fStackSize > 0xFFFFFFFF ) throw "-stack_size must be < 4GB for 32-bit processes"; if ( fStackAddr == 0 ) @@ -5200,7 +5742,7 @@ void Options::checkIllegalOptionCombinations() throw "-stack_addr must be < 0x20000000 for arm"; break; case CPU_TYPE_X86_64: - if ( fPlatform == kPlatformOSX ) { + if ( platforms().contains(ld::Platform::macOS) ) { if ( fStackSize > 0x10000000000 ) throw "-stack_size must be <= 1TB"; if ( fStackAddr == 0 ) { @@ -5318,7 +5860,7 @@ void Options::checkIllegalOptionCombinations() throw "-setuid_safe cannot be used with -r"; // compiler driver no longer uses -objc_abi_version, it uses -ios_simulator_version_min instead - if ( !fObjCABIVersion1Override && !fObjCABIVersion2Override && fTargetIOSSimulator ) + if ( !fObjCABIVersion1Override && !fObjCABIVersion2Override && targetIOSSimulator() ) fObjCABIVersion2Override = true; // rdar://problem/4718189 map ObjC class names to new runtime names @@ -5384,7 +5926,8 @@ void Options::checkIllegalOptionCombinations() case Options::kStaticExecutable: case Options::kDyld: case Options::kPreload: - fInitialUndefines.push_back(fEntryName); + if ( !platforms().contains(ld::Platform::driverKit) ) + fInitialUndefines.push_back(fEntryName); break; case Options::kDynamicLibrary: case Options::kDynamicBundle: @@ -5423,7 +5966,7 @@ void Options::checkIllegalOptionCombinations() // zero page size not specified on command line, set default switch (fArchitecture) { case CPU_TYPE_I386: - case CPU_TYPE_ARM: + case CPU_TYPE_ARM: // first 4KB for 32-bit architectures fZeroPageSize = 0x1000; break; @@ -5468,7 +6011,7 @@ void Options::checkIllegalOptionCombinations() // can't use -rpath unless targeting 10.5 or later if ( fRPaths.size() > 0 ) { - if ( !minOS(ld::mac10_5, ld::iOS_2_0) ) + if ( !platforms().minOS(ld::version2008) ) throw "-rpath can only be used when targeting Mac OS X 10.5 or later"; switch ( fOutputKind ) { case Options::kDynamicExecutable: @@ -5488,11 +6031,8 @@ void Options::checkIllegalOptionCombinations() switch ( fOutputKind ) { case Options::kDynamicExecutable: // check -pie is only used when building a dynamic main executable for 10.5 - if ( !minOS(ld::mac10_5, ld::iOS_4_2) ) { - if ( fIOSVersionMin == ld::iOSVersionUnset ) - throw "-pie can only be used when targeting Mac OS X 10.5 or later"; - else - throw "-pie can only be used when targeting iOS 4.2 or later"; + if ( !platforms().minOS(ld::supportsPIE) ) { + throw "-pie requires targetting a newer minimum version"; } break; case Options::kStaticExecutable: @@ -5511,12 +6051,15 @@ void Options::checkIllegalOptionCombinations() } } - // check -read_only_relocs is not used with x86_64 + // check -read_only_relocs is not used with x86_64 or arm64 if ( fAllowTextRelocs ) { if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind != kKextBundle) ) { warning("-read_only_relocs cannot be used with x86_64"); fAllowTextRelocs = false; } + else if ( fArchitecture == CPU_TYPE_ARM64 ) { + warning("-read_only_relocs cannot be used with arm64"); + } } // check -mark_auto_dead_strip is only used with dylibs @@ -5538,7 +6081,7 @@ void Options::checkIllegalOptionCombinations() if ( !fReExportSymbols.empty() ) { if ( fOutputKind != Options::kDynamicLibrary ) throw "-reexported_symbols_list can only used used when created dynamic libraries"; - if ( !minOS(ld::mac10_7, ld::iOS_4_2) ) + if ( !platforms().minOS(ld::version2010) ) throw "targeted OS version does not support -reexported_symbols_list"; } @@ -5546,8 +6089,8 @@ void Options::checkIllegalOptionCombinations() if ( (fOutputKind != Options::kDynamicExecutable) && (fDyldEnvironExtras.size() != 0) ) throw "-dyld_env can only used used when created main executables"; - // -segment_order can only be used with -preload - if ( !fSegmentOrder.empty() && (fOutputKind != Options::kPreload) ) + // -segment_order can only be used with -preload or -static + if ( !fSegmentOrder.empty() && ((fOutputKind != Options::kPreload) && (fOutputKind != kStaticExecutable)) ) throw "-segment_order can only used used with -preload output"; // warn about bitcode option combinations @@ -5560,10 +6103,6 @@ void Options::checkIllegalOptionCombinations() if ( fReverseMapPath != NULL && !fHideSymbols ) { throw "-bitcode_symbol_map can only be used with -bitcode_hide_symbols"; } - if ( fBitcodeKind != kBitcodeProcess && - fOutputKind != Options::kObjectFile ) { - throw "-bitcode_process_mode can only be used together with -r"; - } // auto fix up the process type for strip -S. // when there is only one input and output type is object file, downgrade kBitcodeProcess to kBitcodeAsData. if ( fOutputKind == Options::kObjectFile && fInputFiles.size() == 1 && fBitcodeKind == Options::kBitcodeProcess ) @@ -5571,11 +6110,145 @@ void Options::checkIllegalOptionCombinations() // warn if building an embedded iOS dylib for pre-iOS 8 // How can we suppress "ld: warning: embedded dylibs/frameworks only run on iOS 8 or later" when building XCTest? - if ( (fOutputKind == Options::kDynamicLibrary) && (fIOSVersionMin != ld::iOSVersionUnset) && (fDylibInstallName != NULL) ) { - if ( !min_iOS(ld::iOS_8_0) && (fDylibInstallName[0] == '@') && !fEncryptableForceOff ) + if ( (fOutputKind == Options::kDynamicLibrary) && (fDylibInstallName != NULL) ) { + if ( platforms().contains(ld::Platform::iOS) && !platforms().minOS(ld::iOS_8_0) && (fDylibInstallName[0] == '@') && !fEncryptableForceOff ) warning("embedded dylibs/frameworks only run on iOS 8 or later"); } -} + + // produce nicer error when no input + if ( fInputFiles.empty() ) { + throw "no object files specified"; + } + + // If the platform is only macOS check to see if the dylib is on the implicit zipper list + if (fDylibInstallName && platforms().count() == 1 && platforms().contains(ld::Platform::macOS)) { + std::vector implictZipperPaths; + for (const auto& sdkPath : fSDKPaths) { + char autoZipperPath[MAXPATHLEN]; + strlcpy(autoZipperPath, sdkPath, MAXPATHLEN); + strlcat(autoZipperPath, "/AppleInternal/LinkerAutoZipperList.txt", MAXPATHLEN); + loadImplictZipperFile(autoZipperPath, implictZipperPaths); + } + for (const auto& zipperPath : implictZipperPaths) { + if (strcmp(zipperPath, fDylibInstallName) == 0) { + // FIXME: once we are reading the SDK version out of the actual SDK set this dynamically + // For now hardcode to 13.0 + fPlatforms.insert(ld::PlatformVersion(ld::Platform::iOSMac, 0x000D0000)); + break; + } + } + } + + // Check zippered combinations. + if (platforms().count() > 2) { + throw "Illegal platform count. Only 2 platforms at a maximum can be specified"; + } + + if (platforms().contains(ld::Platform::iOSMac) && !platforms().minOS(ld::iOS_13_0)) { + throwf("%s platform version must be at least 13.0", ld::platformInfo(ld::Platform::iOSMac).printName); + } + + // ld64 shouldn't allow final executables to have more than one version load command + if ( platforms().contains(ld::Platform::iOSMac) && platforms().contains(ld::Platform::macOS) ) { + if ( (fOutputKind != Options::kDynamicLibrary) && (fOutputKind != Options::kDynamicBundle) ) { + warning("Only dylibs and bundles can be zippered, changing output to be macOS only."); + fPlatforms.erase(ld::Platform::iOSMac); + } + } + + for (const char* sdkPath : fSDKPaths) { + std::string possiblePath = std::string(sdkPath) + "/AppleInternal/"; + struct stat statBuffer; + if ( stat(possiblePath.c_str(), &statBuffer) == 0 ) { + fInternalSDK = true; + break; + } + } + + // ld64-port: addded #if 0 +#if 0 + // Linker warning for i386 macOS binaries + if ( (architecture() == CPU_TYPE_I386) && platforms().contains(ld::Platform::macOS) ) { + if ( !fInternalSDK ) + warning("The i386 architecture is deprecated for macOS (remove from the Xcode build setting: ARCHS)"); + } +#endif + + // building chained fixups should not allow a custom load address + if ( fMakeChainedFixups ) { + switch ( fOutputKind ) { + case Options::kDynamicExecutable: + case Options::kDynamicLibrary: + case Options::kDynamicBundle: + case Options::kDyld: + if ( fBaseAddress != 0 ) { + warning("prefered load addresses (-seg1addr) are disabled with chained fixups"); + fBaseAddress = 0; + } + break; + case Options::kPreload: + break; + case Options::kStaticExecutable: + if ( !fMakeChainedFixupsSection ) + throwf("to use chained fixups with static executables, use -fixup_chains_section"); + break; + case Options::kObjectFile: + throwf("chained fixups cannot be used with relocatable object files"); + case Options::kKextBundle: + throwf("chained fixups cannot be used with kext bundles"); + break; + } + } + +} + +void Options::inferArchAndPlatform() +{ + // scan all input files, looking for a thin .o file. + // the first one found is presumably the architecture to link + uint8_t buffer[4096]; + for (const Options::FileInfo& fInfo : fInputFiles) { + int fd = ::open(fInfo.path, O_RDONLY, 0); + if ( fd != -1 ) { + struct stat stat_buf; + if ( fstat(fd, &stat_buf) != -1) { + ssize_t readAmount = stat_buf.st_size; + if ( 4096 < readAmount ) + readAmount = 4096; + ssize_t amount = read(fd, buffer, readAmount); + ::close(fd); + try { + if ( amount >= readAmount ) { + cpu_type_t type; + cpu_subtype_t subtype; + ld::Platform platform; + uint32_t minOsVersion; + if ( mach_o::relocatable::isObjectFile(buffer, amount, &type, &subtype, &platform, &minOsVersion) ) { + if ( fArchitecture == 0 ) + setInferredArch(type, subtype); + if ( platforms().empty() ) { + if ( platform == ld::Platform::unknown ) + platform = ld::Platform::freestanding; + setInferredPlatform(platform, minOsVersion); + } + return; + } + } + } + catch (const char* msg) { + throwf("%s in %s", msg, fInfo.path); + } + } + } + } + + if ( platforms().empty() ) + warning("platform not specified"); + + if ( fArchitecture == 0 ) + warning("-arch not specified"); +} + void Options::checkForClassic(int argc, const char* argv[]) @@ -5712,10 +6385,10 @@ const char* Options::demangleSymbol(const char* sym) const static size_t size = 1024; static char* buff = (char*)malloc(size); - + #if DEMANGLE_SWIFT // only try to demangle symbols that look like Swift symbols - if ( strncmp(sym, "__T", 3) == 0 ) { + if ( strncmp(sym, "_$", 2) == 0 ) { size_t demangledSize = fnd_get_demangled_name(&sym[1], buff, size); if ( demangledSize > size ) { size = demangledSize+2; @@ -5742,26 +6415,50 @@ const char* Options::demangleSymbol(const char* sym) const } -void Options::dumpDependency(uint8_t opcode, const char* path) const +void Options::writeDependencyInfo() const +{ + // do nothing if -dependency_info not used + if ( !dumpDependencyInfo() ) + return; + + // sort entries for build reproducibility + std::sort(fDependencies.begin(), fDependencies.end(), [](const DependencyEntry& a, const DependencyEntry& b) -> bool { + if ( a.opcode != b.opcode ) + return (a.opcode < b.opcode); + return (a.path < b.path); + }); + + // one time open() of -dependency_info file + int fd = open(this->dependencyInfoPath(), O_WRONLY | O_TRUNC | O_CREAT, 0666); + if ( fd == -1 ) + throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath()); + + // write header + uint8_t version = depLinkerVersion; + if ( write(fd, &version, 1) == -1 ) + throwf("write() to -dependency_info failed, errno=%d", errno); + extern const char ldVersionString[]; + if ( write(fd, ldVersionString, strlen(ldVersionString)+1) == -1 ) + throwf("write() to -dependency_info failed, errno=%d", errno); + + // write each dependency + for (const auto& entry: fDependencies) { + //printf("%d %s\n", entry.opcode, entry.path.c_str()); + if ( write(fd, &entry.opcode, 1) == -1 ) + throwf("write() to -dependency_info failed, errno=%d", errno); + if ( write(fd, entry.path.c_str(), entry.path.size()+1) == -1 ) + throwf("write() to -dependency_info failed, errno=%d", errno); + } + + ::close(fd); +} + + +void Options::addDependency(uint8_t opcode, const char* path) const { if ( !this->dumpDependencyInfo() ) return; - // one time open() of -dependency_info file - if ( fDependencyFileDescriptor == -1 ) { - fDependencyFileDescriptor = open(this->dependencyInfoPath(), O_WRONLY | O_TRUNC | O_CREAT, 0666); - if ( fDependencyFileDescriptor == -1 ) - throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath()); - - // write header - uint8_t version = depLinkerVersion; - if ( write(fDependencyFileDescriptor, &version, 1) == -1 ) - throwf("write() to -dependency_info failed, errno=%d", errno); - extern const char ldVersionString[]; - if ( write(fDependencyFileDescriptor, ldVersionString, strlen(ldVersionString)+1) == -1 ) - throwf("write() to -dependency_info failed, errno=%d", errno); - } - char realPath[PATH_MAX]; if ( path[0] != '/' ) { if ( realpath(path, realPath) != NULL ) { @@ -5769,13 +6466,43 @@ void Options::dumpDependency(uint8_t opcode, const char* path) const } } - if ( write(fDependencyFileDescriptor, &opcode, 1) == -1 ) - throwf("write() to -dependency_info failed, errno=%d", errno); - if ( write(fDependencyFileDescriptor, path, strlen(path)+1) == -1 ) - throwf("write() to -dependency_info failed, errno=%d", errno); - - //fprintf(stderr, "0x%02X %s\n", opcode, path); + DependencyEntry entry; + entry.opcode = opcode; + entry.path = path; + fDependencies.push_back(entry); } +void Options::writeToTraceFile(const char* buffer, size_t len) const +{ + // one time open() of custom LD_TRACE_FILE + if ( fTraceFileDescriptor == -1 ) { + if ( fTraceOutputFile != NULL ) { + fTraceFileDescriptor = open(fTraceOutputFile, O_WRONLY | O_APPEND | O_CREAT, 0666); + if ( fTraceFileDescriptor == -1 ) + throwf("Could not open or create trace file (errno=%d): %s", errno, fTraceOutputFile); + } + else { + fTraceFileDescriptor = fileno(stderr); + } + } + + while (len > 0) { + ssize_t amountWritten = write(fTraceFileDescriptor, buffer, len); + if ( amountWritten == -1 ) + /* Failure to write shouldn't fail the build. */ + return; + buffer += amountWritten; + len -= amountWritten; + } +} + + +uint64_t Options::machHeaderVmAddr() const +{ + if ( fOutputKind == Options::kDynamicExecutable ) + return fBaseAddress + fZeroPageSize; + + return fBaseAddress; +} diff --git a/cctools/ld64/src/ld/Options.h b/cctools/ld64/src/ld/Options.h index 8801873..f36a4ef 100644 --- a/cctools/ld64/src/ld/Options.h +++ b/cctools/ld64/src/ld/Options.h @@ -28,6 +28,9 @@ #include #include +#ifdef TAPI_SUPPORT +#include +#endif #include #include @@ -37,6 +40,7 @@ #include "Snapshot.h" #include "MachOFileAbstraction.hpp" + extern void throwf (const char* format, ...) __attribute__ ((noreturn,format(printf, 1, 2))); extern void warning(const char* format, ...) __attribute__((format(printf, 1, 2))); @@ -88,55 +92,46 @@ public: enum LocalSymbolHandling { kLocalSymbolsAll, kLocalSymbolsNone, kLocalSymbolsSelectiveInclude, kLocalSymbolsSelectiveExclude }; enum BitcodeMode { kBitcodeProcess, kBitcodeAsData, kBitcodeMarker, kBitcodeStrip }; enum DebugInfoStripping { kDebugInfoNone, kDebugInfoMinimal, kDebugInfoFull }; -#if SUPPORT_APPLE_TV - enum Platform { kPlatformUnknown, kPlatformOSX, kPlatformiOS, kPlatformWatchOS, kPlatform_tvOS }; -#else - enum Platform { kPlatformUnknown, kPlatformOSX, kPlatformiOS, kPlatformWatchOS }; -#endif + enum UnalignedPointerTreatment { kUnalignedPointerError, kUnalignedPointerWarning, kUnalignedPointerIgnore }; - static Platform platformForLoadCommand(uint32_t lc) { - switch (lc) { - case LC_VERSION_MIN_MACOSX: - return kPlatformOSX; - case LC_VERSION_MIN_IPHONEOS: - return kPlatformiOS; - case LC_VERSION_MIN_WATCHOS: - return kPlatformWatchOS; - #if SUPPORT_APPLE_TV - case LC_VERSION_MIN_TVOS: - return kPlatform_tvOS; - #endif - } - assert(!lc && "unknown LC_VERSION_MIN load command"); - return kPlatformUnknown; - } - - static const char* platformName(Platform platform) { - switch (platform) { - case kPlatformOSX: - return "OSX"; - case kPlatformiOS: - return "iOS"; - case kPlatformWatchOS: - return "watchOS"; - #if SUPPORT_APPLE_TV - case kPlatform_tvOS: - return "tvOS"; - #endif - case kPlatformUnknown: + static void userReadableSwiftVersion(uint8_t value, char versionString[64]) + { + switch (value) { + case 1: + strcpy(versionString, "1.0"); + break; + case 2: + strcpy(versionString, "1.1"); + break; + case 3: + strcpy(versionString, "2.0"); + break; + case 4: + strcpy(versionString, "3.0"); + break; + case 5: + strcpy(versionString, "4.0"); + break; + case 6: + strcpy(versionString, "4.1/4.2"); + break; + case 7: + strcpy(versionString, "5 or later"); + break; default: - return "(unknown)"; + sprintf(versionString, "unknown ABI version 0x%02X", value); } } + class FileInfo { public: const char* path; - uint64_t fileLen; time_t modTime; LibraryOptions options; ld::File::Ordinal ordinal; bool fromFileList; + bool isInlined; // These are used by the threaded input file parsing engine. mutable int inputFileSlot; // The input file "slot" assigned to this particular file @@ -145,25 +140,25 @@ public: // The use pattern for FileInfo is to create one on the stack in a leaf function and return // it to the calling frame by copy. Therefore the copy constructor steals the path string from // the source, which dies with the stack frame. - FileInfo(FileInfo const &other) : path(other.path), fileLen(other.fileLen), modTime(other.modTime), options(other.options), ordinal(other.ordinal), fromFileList(other.fromFileList), inputFileSlot(-1) { ((FileInfo&)other).path = NULL; }; + FileInfo(FileInfo const &other) : path(other.path), modTime(other.modTime), options(other.options), ordinal(other.ordinal), fromFileList(other.fromFileList), isInlined(other.isInlined), inputFileSlot(-1) { ((FileInfo&)other).path = NULL; }; FileInfo &operator=(FileInfo other) { std::swap(path, other.path); - std::swap(fileLen, other.fileLen); std::swap(modTime, other.modTime); std::swap(options, other.options); std::swap(ordinal, other.ordinal); std::swap(fromFileList, other.fromFileList); + std::swap(isInlined, other.isInlined); std::swap(inputFileSlot, other.inputFileSlot); std::swap(readyToParse, other.readyToParse); return *this; } // Create an empty FileInfo. The path can be set implicitly by checkFileExists(). - FileInfo() : path(NULL), fileLen(0), modTime(0), options(), fromFileList(false) {}; + FileInfo() : path(NULL), modTime(-1), options(), fromFileList(false), isInlined(false) {}; // Create a FileInfo for a specific path, but does not stat the file. - FileInfo(const char *_path) : path(strdup(_path)), fileLen(0), modTime(0), options(), fromFileList(false) {}; + FileInfo(const char *_path) : path(strdup(_path)), modTime(-1), options(), fromFileList(false), isInlined(false) {}; ~FileInfo() { if (path) ::free((void*)path); } @@ -175,9 +170,28 @@ public: // Returns true if a previous call to checkFileExists() succeeded. // Returns false if the file does not exist of checkFileExists() has never been called. - bool missing() const { return modTime==0; } + bool missing() const { return modTime == -1; } + + // Serialize the file info as a command line argument that would be parsed as the same file + // info. Best effort if some attributes cannot be preserved through the round trip. + std::vector lib_cli_argument() const; }; +#ifdef TAPI_SUPPORT + class TAPIInterface { + public: + TAPIInterface(tapi::LinkerInterfaceFile* file, const char* path, const char *installName) : + _file(file), _tbdPath(path), _installName(installName) {} + tapi::LinkerInterfaceFile* getInterfaceFile() const { return _file; } + std::string getTAPIFilePath() const { return _tbdPath; } + const std::string &getInstallName() const { return _installName; } + private: + tapi::LinkerInterfaceFile* _file; + std::string _tbdPath; + std::string _installName; + }; +#endif /* TAPI_SUPPORT */ + struct ExtraSection { const char* segmentName; const char* sectionName; @@ -248,7 +262,7 @@ public: depFileList=0x10, depSection=0x10, depBundleLoader=0x10, depMisc=0x10, depNotFound=0x11, depOutputFile = 0x40 }; - void dumpDependency(uint8_t, const char* path) const; + void addDependency(uint8_t, const char* path) const; typedef const char* const* UndefinesIterator; @@ -259,14 +273,18 @@ public: cpu_type_t architecture() const { return fArchitecture; } bool preferSubArchitecture() const { return fHasPreferredSubType; } cpu_subtype_t subArchitecture() const { return fSubArchitecture; } + cpu_type_t fallbackArchitecture() const { return fFallbackArchitecture; } + cpu_subtype_t fallbackSubArchitecture() const { return fFallbackSubArchitecture; } bool allowSubArchitectureMismatches() const { return fAllowCpuSubtypeMismatches; } bool enforceDylibSubtypesMatch() const { return fEnforceDylibSubtypesMatch; } + bool warnOnSwiftABIVersionMismatches() const { return fWarnOnSwiftABIVersionMismatches; } bool forceCpuSubtypeAll() const { return fForceSubtypeAll; } const char* architectureName() const { return fArchitectureName; } - void setArchitecture(cpu_type_t, cpu_subtype_t subtype, Options::Platform platform); + void setInferredArch(cpu_type_t, cpu_subtype_t subtype); + void setInferredPlatform(ld::Platform platform, uint32_t minOsVers); bool archSupportsThumb2() const { return fArchSupportsThumb2; } OutputKind outputKind() const { return fOutputKind; } - bool prebind() const { return fPrebind; } + bool dyldLoadsOutput() const; bool bindAtLoad() const { return fBindAtLoad; } NameSpace nameSpace() const { return fNameSpace; } const char* installPath() const; // only for kDynamicLibrary @@ -278,7 +296,6 @@ public: uint64_t baseAddress() const { return fBaseAddress; } uint64_t maxAddress() const { return fMaxAddress; } bool keepPrivateExterns() const { return fKeepPrivateExterns; } // only for kObjectFile - bool needsModuleTable() const { return fNeedsModuleTable; } // only for kDynamicLibrary bool interposable(const char* name) const; bool hasExportRestrictList() const { return (fExportMode != kExportDefault); } // -exported_symbol or -unexported_symbol bool hasExportMaskList() const { return (fExportMode == kExportSome); } // just -exported_symbol @@ -292,14 +309,10 @@ public: bool ignoreOtherArchInputFiles() const { return fIgnoreOtherArchFiles; } bool traceDylibs() const { return fTraceDylibs; } bool traceArchives() const { return fTraceArchives; } + bool traceEmitJSON() const { return fTraceEmitJSON; } bool deadCodeStrip() const { return fDeadStrip; } UndefinedTreatment undefinedTreatment() const { return fUndefinedTreatment; } - ld::MacVersionMin macosxVersionMin() const { return fMacVersionMin; } - ld::IOSVersionMin iOSVersionMin() const { return fIOSVersionMin; } - ld::WatchOSVersionMin watchOSVersionMin() const { return fWatchOSVersionMin; } - uint32_t minOSversion() const; - bool minOS(ld::MacVersionMin mac, ld::IOSVersionMin iPhoneOS); - bool min_iOS(ld::IOSVersionMin requirediOSMin); + uint32_t minOSversion(const ld::Platform& platform) const; bool messagesPrefixedWithArchitecture(); Treatment picTreatment(); WeakReferenceMismatchTreatment weakReferenceMismatchTreatment() const { return fWeakReferenceMismatchTreatment; } @@ -325,8 +338,12 @@ public: CommonsMode commonsMode() const { return fCommonsMode; } bool warnCommons() const { return fWarnCommons; } bool keepRelocations(); - FileInfo findFile(const std::string &path) const; + FileInfo findFile(const std::string &path, const ld::dylib::File* fromDylib=nullptr) const; bool findFile(const std::string &path, const std::vector &tbdExtensions, FileInfo& result) const; +#ifdef TAPI_SUPPORT + bool hasInlinedTAPIFile(const std::string &path) const; + tapi::LinkerInterfaceFile* findTAPIFile(const std::string &path) const; +#endif UUIDMode UUIDMode() const { return fUUIDMode; } bool warnStabs(); bool pauseAtEnd() { return fPause; } @@ -335,20 +352,22 @@ public: void gotoClassicLinker(int argc, const char* argv[]); bool sharedRegionEligible() const { return fSharedRegionEligible; } bool printOrderFileStatistics() const { return fPrintOrderFileStatistics; } + const char* orderFilePath() const { return fOrderFilePath; } const char* dTraceScriptName() { return fDtraceScriptName; } bool dTrace() { return (fDtraceScriptName != NULL); } unsigned long orderedSymbolsCount() const { return fOrderedSymbols.size(); } OrderedSymbolsIterator orderedSymbolsBegin() const { return &fOrderedSymbols[0]; } OrderedSymbolsIterator orderedSymbolsEnd() const { return &fOrderedSymbols[fOrderedSymbols.size()]; } - bool splitSeg() const { return fSplitSegs; } uint64_t baseWritableAddress() { return fBaseWritableAddress; } uint64_t segmentAlignment() const { return fSegmentAlignment; } uint64_t segPageSize(const char* segName) const; uint64_t customSegmentAddress(const char* segName) const; + uint64_t machHeaderVmAddr() const; bool hasCustomSegmentAddress(const char* segName) const; bool hasCustomSectionAlignment(const char* segName, const char* sectName) const; uint8_t customSectionAlignment(const char* segName, const char* sectName) const; - uint32_t initialSegProtection(const char*) const; + uint32_t initialSegProtection(const char*) const; + bool readOnlyDataSegment(const char*) const; uint32_t maxSegProtection(const char*) const; bool saveTempFiles() const { return fSaveTempFiles; } const std::vector& rpaths() const { return fRPaths; } @@ -356,7 +375,7 @@ public: const std::vector& dylibOverrides() const { return fDylibOverrides; } const char* generatedMapPath() const { return fMapPath; } bool positionIndependentExecutable() const { return fPositionIndependentExecutable; } - Options::FileInfo findFileUsingPaths(const std::string &path) const; + Options::FileInfo findIndirectDylib(const std::string& installName, const ld::dylib::File* fromDylib) const; bool deadStripDylibs() const { return fDeadStripDylibs; } bool allowedUndefined(const char* name) const { return ( fAllowedUndefined.find(name) != fAllowedUndefined.end() ); } bool someAllowedUndefines() const { return (fAllowedUndefined.size() != 0); } @@ -376,6 +395,7 @@ public: const std::vector& dyldEnvironExtras() const{ return fDyldEnvironExtras; } const std::vector& astFilePaths() const{ return fASTFilePaths; } bool makeCompressedDyldInfo() const { return fMakeCompressedDyldInfo; } + bool makeThreadedStartsSection() const { return fMakeThreadedStartsSection; } bool hasExportedSymbolOrder(); bool exportedSymbolOrder(const char* sym, unsigned int* order) const; bool orderData() { return fOrderData; } @@ -403,17 +423,28 @@ public: bool makeTentativeDefinitionsReal() const { return fMakeTentativeDefinitionsReal; } const char* dyldInstallPath() const { return fDyldInstallPath; } bool warnWeakExports() const { return fWarnWeakExports; } + bool noWeakExports() const { return fNoWeakExports; } bool objcGcCompaction() const { return fObjcGcCompaction; } bool objcGc() const { return fObjCGc; } bool objcGcOnly() const { return fObjCGcOnly; } bool canUseThreadLocalVariables() const { return fTLVSupport; } - bool addVersionLoadCommand() const { return fVersionLoadCommand && (fPlatform != kPlatformUnknown); } + bool forceLegacyVersionLoadCommands() const { return fForceLegacyVersionLoadCommands; } + bool shouldUseBuildVersion(ld::Platform plat, uint32_t minOSvers) const; + bool addVersionLoadCommand() const { return fVersionLoadCommand && (platforms().count() != 0) && !platforms().contains(ld::Platform::freestanding); } bool addFunctionStarts() const { return fFunctionStartsLoadCommand; } bool addDataInCodeInfo() const { return fDataInCodeInfoLoadCommand; } bool canReExportSymbols() const { return fCanReExportSymbols; } + const char* ltoCachePath() const { return fLtoCachePath; } + bool ltoPruneIntervalOverwrite() const { return fLtoPruneIntervalOverwrite; } + int ltoPruneInterval() const { return fLtoPruneInterval; } + int ltoPruneAfter() const { return fLtoPruneAfter; } + unsigned ltoMaxCacheSize() const { return fLtoMaxCacheSize; } const char* tempLtoObjectPath() const { return fTempLtoObjectPath; } const char* overridePathlibLTO() const { return fOverridePathlibLTO; } const char* mcpuLTO() const { return fLtoCpu; } + const char* kextObjectsPath() const { return fKextObjectsDirPath; } + int kextObjectsEnable() const { return fKextObjectsEnable; } + const char* toolchainPath() const { return fToolchainPath; } bool objcCategoryMerging() const { return fObjcCategoryMerging; } bool pageAlignDataAtoms() const { return fPageAlignDataAtoms; } bool keepDwarfUnwind() const { return fKeepDwarfUnwind; } @@ -431,14 +462,26 @@ public: bool renameReverseSymbolMap() const { return fReverseMapUUIDRename; } bool deduplicateFunctions() const { return fDeDupe; } bool verboseDeduplicate() const { return fVerboseDeDupe; } + bool makeInitializersIntoOffsets() const { return fMakeInitializersIntoOffsets; } + bool useLinkedListBinding() const { return fUseLinkedListBinding; } + bool makeChainedFixups() const { return fMakeChainedFixups; } +#if SUPPORT_ARCH_arm64e + bool useAuthenticatedStubs() const { return fUseAuthenticatedStubs; } + bool supportsAuthenticatedPointers() const { return fSupportsAuthenticatedPointers; } +#endif + bool noLazyBinding() const { return fNoLazyBinding; } + bool debugVariant() const { return fDebugVariant; } const char* reverseSymbolMapPath() const { return fReverseMapPath; } std::string reverseMapTempPath() const { return fReverseMapTempPath; } bool ltoCodegenOnly() const { return fLTOCodegenOnly; } bool ignoreAutoLink() const { return fIgnoreAutoLink; } bool allowDeadDuplicates() const { return fAllowDeadDups; } + bool allowWeakImports() const { return fAllowWeakImports; } + Treatment initializersTreatment() const { return fInitializersTreatment; } BitcodeMode bitcodeKind() const { return fBitcodeKind; } bool sharedRegionEncodingV2() const { return fSharedRegionEncodingV2; } bool useDataConstSegment() const { return fUseDataConstSegment; } + bool useTextExecSegment() const { return fUseTextExecSegment; } bool hasWeakBitTweaks() const; bool forceWeak(const char* symbolName) const; bool forceNotWeak(const char* symbolName) const; @@ -452,15 +495,15 @@ public: bool needsSourceVersionLoadCommand() const { return fSourceVersionLoadCommand; } bool canUseAbsoluteSymbols() const { return fAbsoluteSymbols; } bool allowSimulatorToLinkWithMacOSX() const { return fAllowSimulatorToLinkWithMacOSX; } + bool isSimulatorSupportDylib() const { return fSimulatorSupportDylib; } uint64_t sourceVersion() const { return fSourceVersion; } - uint32_t sdkVersion() const { return fSDKVersion; } const char* demangleSymbol(const char* sym) const; bool pipelineEnabled() const { return fPipelineFifo != NULL; } const char* pipelineFifo() const { return fPipelineFifo; } bool dumpDependencyInfo() const { return (fDependencyInfoPath != NULL); } const char* dependencyInfoPath() const { return fDependencyInfoPath; } - bool targetIOSSimulator() const { return fTargetIOSSimulator; } - ld::relocatable::File::LinkerOptionsList& + bool targetIOSSimulator() const { return platforms().contains(ld::simulatorPlatforms); } + ld::relocatable::File::LinkerOptionsList& linkerOptions() const { return fLinkerOptions; } FileInfo findFramework(const char* frameworkName) const; FileInfo findLibrary(const char* rootName, bool dylibsOnly=false) const; @@ -469,12 +512,27 @@ public: const std::vector& segmentRenames() const { return fSegmentRenames; } bool moveRoSymbol(const char* symName, const char* filePath, const char*& seg, bool& wildCardMatch) const; bool moveRwSymbol(const char* symName, const char* filePath, const char*& seg, bool& wildCardMatch) const; - Platform platform() const { return fPlatform; } + bool moveAXMethodList(const char* className) const; + const ld::VersionSet& platforms() const { return fPlatforms; } const std::vector& sdkPaths() const { return fSDKPaths; } + bool internalSDK() const { return fInternalSDK; } std::vector writeBitcodeLinkOptions() const; std::string getSDKVersionStr() const; - std::string getPlatformStr() const; uint8_t maxDefaultCommonAlign() const { return fMaxDefaultCommonAlign; } + bool hasDataSymbolMoves() const { return !fSymbolsMovesData.empty(); } + bool hasCodeSymbolMoves() const { return !fSymbolsMovesCode.empty(); } + bool dumpNormalizedLibArgs() const { return fDumpNormalizedLibArgs; } + void writeToTraceFile(const char* buffer, size_t len) const; + UnalignedPointerTreatment unalignedPointerTreatment() const { return fUnalignedPointerTreatment; } + bool zeroModTimeInDebugMap() const { return fZeroModTimeInDebugMap; } + void writeDependencyInfo() const; +#ifdef TAPI_SUPPORT + std::vector &TAPIFiles() { return fTAPIFiles; } + void addTAPIInterface(tapi::LinkerInterfaceFile* interface, const char *path) const; +#endif + const char* buildContextName() const { return fBuildContextName; } + bool sharedCacheEligiblePath(const char* path) const; + const char* debugMapObjectPrefixPath() const { return fOSOPrefixPath; } static uint32_t parseVersionNumber32(const char*); @@ -484,7 +542,6 @@ private: enum ExportMode { kExportDefault, kExportSome, kDontExportSome }; enum LibrarySearchMode { kSearchDylibAndArchiveInEachDir, kSearchAllDirsForDylibsThenAllDirsForArchives }; enum InterposeMode { kInterposeNone, kInterposeAllExternal, kInterposeSome }; - enum FilePreference { kModTime, kTextBasedStub, kMachO }; class SetWithWildcards { public: @@ -512,10 +569,18 @@ private: SetWithWildcards symbols; }; + struct DependencyEntry { + uint8_t opcode; + std::string path; + }; + + const char* checkForNullArgument(const char* argument_name, const char* arg) const; + const char* checkForNullVersionArgument(const char* argument_name, const char* arg) const; void parse(int argc, const char* argv[]); void checkIllegalOptionCombinations(); void buildSearchPaths(int argc, const char* argv[]); void parseArch(const char* architecture); + void selectFallbackArch(const char *architecture); FileInfo findFramework(const char* rootName, const char* suffix) const; bool checkForFile(const char* format, const char* dir, const char* rootName, FileInfo& result) const; @@ -534,9 +599,6 @@ private: void parsePreCommandLineEnvironmentSettings(); void parsePostCommandLineEnvironmentSettings(); void setUndefinedTreatment(const char* treatment); - void setMacOSXVersionMin(const char* version); - void setIOSVersionMin(const char* version); - void setWatchOSVersionMin(const char* version); void setWeakReferenceMismatchTreatment(const char* treatment); void addDylibOverride(const char* paths); void addSectionAlignment(const char* segment, const char* section, const char* alignment); @@ -553,6 +615,8 @@ private: void addSegmentRename(const char* srcSegment, const char* dstSegment); void addSymbolMove(const char* dstSegment, const char* symbolList, std::vector& list, const char* optionName); void cannotBeUsedWithBitcode(const char* arg); + void loadImplictZipperFile(const char *path,std::vector& paths); + void inferArchAndPlatform(); // ObjectFile::ReaderOptions fReaderOptions; @@ -560,14 +624,14 @@ private: std::vector fInputFiles; cpu_type_t fArchitecture; cpu_subtype_t fSubArchitecture; + cpu_type_t fFallbackArchitecture; + cpu_subtype_t fFallbackSubArchitecture; const char* fArchitectureName; OutputKind fOutputKind; bool fHasPreferredSubType; bool fArchSupportsThumb2; - bool fPrebind; bool fBindAtLoad; bool fKeepPrivateExterns; - bool fNeedsModuleTable; bool fIgnoreOtherArchFiles; bool fErrorOnOtherArchFiles; bool fForceSubtypeAll; @@ -582,7 +646,6 @@ private: uint64_t fBaseAddress; uint64_t fMaxAddress; uint64_t fBaseWritableAddress; - bool fSplitSegs; SetWithWildcards fExportSymbols; SetWithWildcards fDontExportSymbols; SetWithWildcards fInterposeList; @@ -608,12 +671,20 @@ private: const char* fExecutablePath; const char* fBundleLoader; const char* fDtraceScriptName; - const char* fSegAddrTablePath; const char* fMapPath; const char* fDyldInstallPath; + const char* fLtoCachePath; + bool fLtoPruneIntervalOverwrite; + int fLtoPruneInterval; + int fLtoPruneAfter; + unsigned fLtoMaxCacheSize; const char* fTempLtoObjectPath; const char* fOverridePathlibLTO; const char* fLtoCpu; + int fKextObjectsEnable; + const char* fKextObjectsDirPath; + const char* fToolchainPath; + const char* fOrderFilePath; uint64_t fZeroPageSize; uint64_t fStackSize; uint64_t fStackAddr; @@ -657,9 +728,11 @@ private: bool fMarkDeadStrippableDylib; bool fMakeCompressedDyldInfo; bool fMakeCompressedDyldInfoForceOff; + bool fMakeThreadedStartsSection; bool fNoEHLabels; bool fAllowCpuSubtypeMismatches; bool fEnforceDylibSubtypesMatch; + bool fWarnOnSwiftABIVersionMismatches; bool fUseSimplifiedDylibReExports; bool fObjCABIVersion2Override; bool fObjCABIVersion1Override; @@ -687,8 +760,10 @@ private: bool fTraceDylibs; bool fTraceIndirectDylibs; bool fTraceArchives; + bool fTraceEmitJSON; bool fOutputSlidable; bool fWarnWeakExports; + bool fNoWeakExports; bool fObjcGcCompaction; bool fObjCGc; bool fObjCGcOnly; @@ -697,6 +772,7 @@ private: bool fVersionLoadCommand; bool fVersionLoadCommandForcedOn; bool fVersionLoadCommandForcedOff; + bool fForceLegacyVersionLoadCommands; bool fFunctionStartsLoadCommand; bool fFunctionStartsForcedOn; bool fFunctionStartsForcedOff; @@ -708,15 +784,13 @@ private: bool fPageAlignDataAtoms; bool fNeedsThreadLoadCommand; bool fEntryPointLoadCommand; - bool fEntryPointLoadCommandForceOn; - bool fEntryPointLoadCommandForceOff; bool fSourceVersionLoadCommand; bool fSourceVersionLoadCommandForceOn; bool fSourceVersionLoadCommandForceOff; - bool fTargetIOSSimulator; bool fExportDynamic; bool fAbsoluteSymbols; bool fAllowSimulatorToLinkWithMacOSX; + bool fSimulatorSupportDylib; bool fKeepDwarfUnwind; bool fKeepDwarfUnwindForcedOn; bool fKeepDwarfUnwindForcedOff; @@ -732,24 +806,37 @@ private: bool fUseDataConstSegment; bool fUseDataConstSegmentForceOn; bool fUseDataConstSegmentForceOff; + bool fUseTextExecSegment; bool fBundleBitcode; bool fHideSymbols; bool fVerifyBitcode; bool fReverseMapUUIDRename; bool fDeDupe; bool fVerboseDeDupe; + bool fMakeInitializersIntoOffsets; + bool fUseLinkedListBinding; + bool fMakeChainedFixups; + bool fMakeChainedFixupsSection; +#if SUPPORT_ARCH_arm64e + bool fUseAuthenticatedStubs = false; + bool fSupportsAuthenticatedPointers = false; +#endif + bool fNoLazyBinding; + bool fDebugVariant; const char* fReverseMapPath; std::string fReverseMapTempPath; bool fLTOCodegenOnly; bool fIgnoreAutoLink; bool fAllowDeadDups; + bool fAllowWeakImports; + Treatment fInitializersTreatment; + bool fZeroModTimeInDebugMap; BitcodeMode fBitcodeKind; - Platform fPlatform; DebugInfoStripping fDebugInfoStripping; const char* fTraceOutputFile; - ld::MacVersionMin fMacVersionMin; - ld::IOSVersionMin fIOSVersionMin; - ld::WatchOSVersionMin fWatchOSVersionMin; + ld::VersionSet fPlatforms; + bool fPlatfromVersionCmdFound; + bool fInternalSDK; std::vector fAliases; std::vector fInitialUndefines; NameSet fAllowedUndefined; @@ -774,16 +861,23 @@ private: std::vector fSegmentRenames; std::vector fSymbolsMovesData; std::vector fSymbolsMovesCode; - std::vector fSymbolsMovesZeroFill; + std::vector fSymbolsMovesAXMethodLists; bool fSaveTempFiles; mutable Snapshot fLinkSnapshot; bool fSnapshotRequested; const char* fPipelineFifo; const char* fDependencyInfoPath; - mutable int fDependencyFileDescriptor; + const char* fBuildContextName; + mutable int fTraceFileDescriptor; uint8_t fMaxDefaultCommonAlign; - FilePreference fFilePreference; - bool fForceTextBasedStub; + bool fDumpNormalizedLibArgs = false; // ld64-port + UnalignedPointerTreatment fUnalignedPointerTreatment; + mutable std::vector fDependencies; +#ifdef TAPI_SUPPORT + mutable std::vector fTAPIFiles; + bool fPreferTAPIFile; +#endif + const char* fOSOPrefixPath; }; diff --git a/cctools/ld64/src/ld/OutputFile.cpp b/cctools/ld64/src/ld/OutputFile.cpp index 682ad90..7d1fa52 100644 --- a/cctools/ld64/src/ld/OutputFile.cpp +++ b/cctools/ld64/src/ld/OutputFile.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include // ld64-port @@ -55,6 +54,8 @@ #include #include #include +#include +#include #include #include @@ -89,17 +90,21 @@ OutputFile::OutputFile(const Options& opts) symbolTableSection(NULL), stringPoolSection(NULL), localRelocationsSection(NULL), externalRelocationsSection(NULL), sectionRelocationsSection(NULL), - indirectSymbolTableSection(NULL), + indirectSymbolTableSection(NULL), + threadedPageStartsSection(NULL), _options(opts), _hasDyldInfo(opts.makeCompressedDyldInfo()), + _hasExportsTrie(opts.makeChainedFixups() && _options.dyldLoadsOutput()), + _hasChainedFixups(opts.makeChainedFixups() && _options.dyldLoadsOutput()), + _hasThreadedPageStarts(opts.makeThreadedStartsSection()), _hasSymbolTable(true), _hasSectionRelocations(opts.outputKind() == Options::kObjectFile), _hasSplitSegInfo(opts.sharedRegionEligible()), _hasFunctionStartsInfo(opts.addFunctionStarts()), _hasDataInCodeInfo(opts.addDataInCodeInfo()), _hasDynamicSymbolTable(true), - _hasLocalRelocations(!opts.makeCompressedDyldInfo()), - _hasExternalRelocations(!opts.makeCompressedDyldInfo()), + _hasLocalRelocations(!opts.makeCompressedDyldInfo() && !opts.makeThreadedStartsSection()), + _hasExternalRelocations(!opts.makeCompressedDyldInfo() && !opts.makeThreadedStartsSection()), _hasOptimizationHints(opts.outputKind() == Options::kObjectFile), _encryptedTEXTstartOffset(0), _encryptedTEXTendOffset(0), @@ -161,10 +166,12 @@ void OutputFile::write(ld::Internal& state) this->makeSplitSegInfoV2(state); else this->makeSplitSegInfo(state); + this->buildChainedFixupInfo(state); this->updateLINKEDITAddresses(state); //this->dumpAtomsBySection(state, false); this->writeOutputFile(state); this->writeMapFile(state); + this->writeJSONEntry(state); } bool OutputFile::findSegment(ld::Internal& state, uint64_t addr, uint64_t* start, uint64_t* end, uint32_t* index) @@ -225,7 +232,14 @@ void OutputFile::assignAtomAddresses(ld::Internal& state) void OutputFile::updateLINKEDITAddresses(ld::Internal& state) { - if ( _options.makeCompressedDyldInfo() ) { + if ( _options.makeChainedFixups() && _options.dyldLoadsOutput() ) { + assert(_exportInfoAtom != NULL); + _exportInfoAtom->encode(); + + assert(_chainedInfoAtom != NULL); + _chainedInfoAtom->encode(); + } + else if ( _options.makeCompressedDyldInfo() ) { // build dylb rebasing info assert(_rebasingInfoAtom != NULL); _rebasingInfoAtom->encode(); @@ -283,7 +297,7 @@ void OutputFile::updateLINKEDITAddresses(ld::Internal& state) _sectionsRelocationsAtom->encode(); } - if ( ! _options.makeCompressedDyldInfo() ) { + if ( !_options.makeCompressedDyldInfo() && !_options.makeThreadedStartsSection() && !_options.makeChainedFixups() ) { // build external relocations assert(_externalRelocsAtom != NULL); _externalRelocsAtom->encode(); @@ -357,11 +371,17 @@ void OutputFile::setLoadCommandsPadding(ld::Internal& state) case Options::kPreload: // mach-o MH_PRELOAD files need no padding between load commands and first section paddingSize = 0; + case Options::kKextBundle: + if ( _options.useTextExecSegment() ) { + paddingSize = 32; + break; + } + // else fall into default case default: // work backwards from end of segment and lay out sections so that extra room goes to padding atom uint64_t addr = 0; uint64_t textSegPageSize = _options.segPageSize("__TEXT"); - if ( _options.sharedRegionEligible() && (_options.iOSVersionMin() >= ld::iOS_8_0) && (textSegPageSize == 0x4000) ) + if ( _options.sharedRegionEligible() && _options.platforms().minOS(ld::iOS_8_0) && (textSegPageSize == 0x4000) ) textSegPageSize = 0x1000; for (std::vector::reverse_iterator it = state.sections.rbegin(); it != state.sections.rend(); ++it) { ld::Internal::FinalSection* sect = *it; @@ -470,13 +490,40 @@ bool OutputFile::targetIsThumb(ld::Internal& state, const ld::Fixup* fixup) uint64_t OutputFile::addressOf(const ld::Internal& state, const ld::Fixup* fixup, const ld::Atom** target) { - if ( !_options.makeCompressedDyldInfo() ) { + // FIXME: Is this right for makeThreadedStartsSection? + if ( !_options.makeCompressedDyldInfo() && !_options.makeThreadedStartsSection() && !_options.makeChainedFixups() ) { // For external relocations the classic mach-o format // has addend only stored in the content. That means // that the address of the target is not used. if ( fixup->contentAddendOnly ) return 0; } + switch ( fixup->binding ) { + case ld::Fixup::bindingNone: + throw "unexpected bindingNone"; + case ld::Fixup::bindingByNameUnbound: + throw "unexpected bindingByNameUnbound"; + case ld::Fixup::bindingByContentBound: + case ld::Fixup::bindingDirectlyBound: + *target = fixup->u.target; + if ( !(*target)->finalAddressMode() && ((*target)->contentType() == ld::Atom::typeLTOtemporary) ) + throwf("reference to bitcode symbol '%s' which LTO has not compiled", (*target)->name()); + return (*target)->finalAddress(); + case ld::Fixup::bindingsIndirectlyBound: + *target = state.indirectBindingTable[fixup->u.bindingIndex]; + if ( ! (*target)->finalAddressMode() ) { + if ( (*target)->contentType() == ld::Atom::typeLTOtemporary ) + throwf("reference to bitcode symbol '%s' which LTO has not compiled", (*target)->name()); + else + throwf("reference to symbol (which has not been assigned an address) %s", (*target)->name()); + } + return (*target)->finalAddress(); + } + throw "unexpected binding"; +} + +uint64_t OutputFile::addressAndTarget(const ld::Internal& state, const ld::Fixup* fixup, const ld::Atom** target) +{ switch ( fixup->binding ) { case ld::Fixup::bindingNone: throw "unexpected bindingNone"; @@ -498,6 +545,7 @@ uint64_t OutputFile::addressOf(const ld::Internal& state, const ld::Fixup* fixup throw "unexpected binding"; } + uint64_t OutputFile::sectionOffsetOf(const ld::Internal& state, const ld::Fixup* fixup) { const ld::Atom* target = NULL; @@ -654,7 +702,7 @@ void OutputFile::rangeCheckRIP32(int64_t displacement, ld::Internal& state, cons printSectionLayout(state); const ld::Atom* target; - throwf("32-bit RIP relative reference out of range (%lld max is +/-4GB): from %s (0x%08llX) to %s (0x%08llX)", + throwf("32-bit RIP relative reference out of range (%lld max is +/-2GB): from %s (0x%08llX) to %s (0x%08llX)", displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup), addressOf(state, fixup, &target)); } @@ -1315,6 +1363,9 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld:: bool is_b; bool thumbTarget = false; std::map usedByHints; +#if SUPPORT_ARCH_arm64e + Fixup::AuthData authData; +#endif for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) { uint8_t* fixUpLocation = &buffer[fit->offsetInAtom]; ld::Fixup::LOH_arm64 lohExtra; @@ -1379,10 +1430,18 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld:: break; case ld::Fixup::kindStoreLittleEndian32: rangeCheckAbsolute32(accumulator, state, atom, fit); - set32LE(fixUpLocation, accumulator); + if ( _options.makeChainedFixups() && !fit->contentAddendOnly && (atom->contentType() != ld::Atom::ContentType::typeCFI) + && (atom->section().type() != ld::Section::typeUnwindInfo) && (atom->section().type() != ld::Section::typeCode) + && (atom->section().type() != ld::Section::typeDtraceDOF) ) + setFixup32(fixUpLocation, accumulator, toTarget); + else + set32LE(fixUpLocation, accumulator); break; case ld::Fixup::kindStoreLittleEndian64: - set64LE(fixUpLocation, accumulator); + if ( _options.makeChainedFixups() && !fit->contentAddendOnly && (atom->contentType() != ld::Atom::ContentType::typeCFI) ) + setFixup64(fixUpLocation, accumulator, toTarget); + else + set64LE(fixUpLocation, accumulator); break; case ld::Fixup::kindStoreBigEndian16: set16BE(fixUpLocation, accumulator); @@ -1596,14 +1655,92 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld:: if ( fit->contentAddendOnly ) accumulator = 0; rangeCheckAbsolute32(accumulator, state, atom, fit); - set32LE(fixUpLocation, accumulator); + if ( _options.makeChainedFixups() && !fit->contentAddendOnly ) + setFixup32(fixUpLocation, accumulator, toTarget); + else + set32LE(fixUpLocation, accumulator); break; case ld::Fixup::kindStoreTargetAddressLittleEndian64: accumulator = addressOf(state, fit, &toTarget); if ( fit->contentAddendOnly ) accumulator = 0; - set64LE(fixUpLocation, accumulator); + if ( _options.makeChainedFixups() && !fit->contentAddendOnly ) + setFixup64(fixUpLocation, accumulator, toTarget); + else + set64LE(fixUpLocation, accumulator); break; +#if SUPPORT_ARCH_arm64e + case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64: { + accumulator = addressOf(state, fit, &toTarget); + if ( fit->contentAddendOnly ) { + // ld -r mode. We want to write out the original relocation again + + // FIXME: Should we zero out the accumulator here as done in kindStoreTargetAddressLittleEndian64? + // Make sure the high bits aren't set. The low-32-bits should be the addend. + assert((accumulator & 0xFFFFFFFF00000000ULL) == 0); + accumulator |= ((uint64_t)authData.discriminator) << 32; + accumulator |= ((uint64_t)authData.hasAddressDiversity) << 48; + accumulator |= ((uint64_t)authData.key) << 49; + // Set the high bit as we are authenticated + accumulator |= 1ULL << 63; + set64LE(fixUpLocation, accumulator); + } + else if (_options.outputKind() == Options::kKextBundle ) { + // kexts dont' handle auth pointers, write unauth pointer + set64LE(fixUpLocation, accumulator); + } + else { + if ( _options.makeChainedFixups() ) { + setFixup64e(fixUpLocation, accumulator, authData, toTarget); + } + else { + auto fixupOffset = (uintptr_t)(fixUpLocation - mhAddress); + assert(_authenticatedFixupData.find(fixupOffset) == _authenticatedFixupData.end()); + auto authneticatedData = std::make_pair(authData, accumulator); + _authenticatedFixupData[fixupOffset] = authneticatedData; + // Zero out this entry which we will expect later. + set64LE(fixUpLocation, 0); + } + } + break; + } + case ld::Fixup::kindStoreLittleEndianAuth64: { + if ( fit->contentAddendOnly ) { + // ld -r mode. We want to write out the original relocation again + + // FIXME: Should we zero out the accumulator here as done in kindStoreTargetAddressLittleEndian64? + // Make sure the high bits aren't set. The low-32-bits should be the addend. + assert((accumulator & 0xFFFFFFFF00000000ULL) == 0); + accumulator |= ((uint64_t)authData.discriminator) << 32; + accumulator |= ((uint64_t)authData.hasAddressDiversity) << 48; + accumulator |= ((uint64_t)authData.key) << 49; + // Set the high bit as we are authenticated + accumulator |= 1ULL << 63; + set64LE(fixUpLocation, accumulator); + } + else if (_options.outputKind() == Options::kKextBundle ) { + // kexts dont' handle auth pointers, write unauth pointer + set64LE(fixUpLocation, accumulator); + } + else { + if ( _options.makeChainedFixups() ) { + setFixup64e(fixUpLocation, accumulator, authData, toTarget); + } + else { + auto fixupOffset = (uintptr_t)(fixUpLocation - mhAddress); + assert(_authenticatedFixupData.find(fixupOffset) == _authenticatedFixupData.end()); + auto authneticatedData = std::make_pair(authData, accumulator); + _authenticatedFixupData[fixupOffset] = authneticatedData; + // Zero out this entry which we will expect later. + set64LE(fixUpLocation, 0); + } + } + break; + } + case ld::Fixup::kindSetAuthData: + authData = fit->u.authData; + break; +#endif case ld::Fixup::kindStoreTargetAddressBigEndian32: accumulator = addressOf(state, fit, &toTarget); if ( fit->contentAddendOnly ) @@ -1678,7 +1815,7 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld:: if ( islandfit->kind == ld::Fixup::kindIslandTarget ) { const ld::Atom* islandTarget = NULL; uint64_t islandTargetAddress = addressOf(state, islandfit, &islandTarget); - delta = islandTargetAddress - (atom->finalAddress() + fit->offsetInAtom + 4); + delta = islandTargetAddress - (atom->finalAddress() + fit->offsetInAtom + 8); if ( checkArmBranch24Displacement(delta) ) { toTarget = islandTarget; accumulator = islandTargetAddress; @@ -1951,6 +2088,10 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld:: } break; case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12: + // In -r mode, the GOT doesn't exist but the relocations track it + // so the address doesn't need to be aligned. + if ( _options.outputKind() == Options::kObjectFile ) + break; case ld::Fixup::kindStoreTargetAddressARM64PageOff12: case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12: accumulator = addressOf(state, fit, &toTarget); @@ -2015,7 +2156,7 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld:: { // GOT entry was optimized away, change LDR instruction to a ADD instruction = get32LE(fixUpLocation); - if ( (instruction & 0xFFC00000) != 0xF9400000 ) + if ( (instruction & 0xBFC00000) != 0xB9400000 ) throwf("GOT load reloc does not point to a LDR instruction in %s", atom->name()); uint32_t offset = accumulator & 0x00000FFF; uint32_t imm12 = offset << 10; @@ -2030,7 +2171,7 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld:: { // TLV thunk in same linkage unit, so LEA it directly, changing LDR instruction to a ADD instruction = get32LE(fixUpLocation); - if ( (instruction & 0xFFC00000) != 0xF9400000 ) + if ( (instruction & 0xBFC00000) != 0xB9400000 ) throwf("TLV load reloc does not point to a LDR instruction in %s", atom->name()); uint32_t offset = accumulator & 0x00000FFF; uint32_t imm12 = offset << 10; @@ -2041,7 +2182,7 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld:: case ld::Fixup::kindStoreARM64PointerToGOT: set64LE(fixUpLocation, accumulator); break; - case ld::Fixup::kindStoreARM64PCRelToGOT: + case ld::Fixup::kindStoreARM64PCRelToGOT: if ( fit->contentAddendOnly ) delta = accumulator; else @@ -2193,6 +2334,7 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld:: // Leave ADRP as-is set32LE(infoB.instructionContent, makeNOP()); ldrInfoC.offset += addInfoB.addend; + ldrInfoC.baseReg = adrpInfoA.destReg; set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC)); if ( _options.verboseOptimizationHints() ) fprintf(stderr, "adrp-add-ldr at 0x%08llX T2 transformed to ADRP/LDR \n", infoC.instructionAddress); @@ -2242,7 +2384,8 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld:: isLDR = parseLoadOrStore(infoB.instruction, ldrInfoB); if ( isLDR ) { // target of GOT is external - LOH_ASSERT(ldrInfoB.size == 8); + LOH_ASSERT((_options.architecture() == CPU_TYPE_ARM64 && ldrInfoB.size == 8) || + (_options.architecture() == CPU_TYPE_ARM64_32 && ldrInfoB.size == 4)); LOH_ASSERT(!ldrInfoB.isFloat); LOH_ASSERT(ldrInfoC.baseReg == ldrInfoB.reg); //fprintf(stderr, "infoA.target=%p, %s, infoA.targetAddress=0x%08llX\n", infoA.target, infoA.target->name(), infoA.targetAddress); @@ -2360,7 +2503,8 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld:: isLDR = parseLoadOrStore(infoB.instruction, ldrInfoB); if ( isLDR ) { // target of GOT is external - LOH_ASSERT(ldrInfoB.size == 8); + LOH_ASSERT((_options.architecture() == CPU_TYPE_ARM64 && ldrInfoB.size == 8) || + (_options.architecture() == CPU_TYPE_ARM64_32 && ldrInfoB.size == 4)); LOH_ASSERT(!ldrInfoB.isFloat); LOH_ASSERT(ldrInfoC.baseReg == ldrInfoB.reg); targetFourByteAligned = ( ((infoA.targetAddress + ldrInfoC.offset) & 0x3) == 0 ); @@ -2503,6 +2647,251 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld:: } +static bool chainedFixupAddendFitsInline(uint64_t accumulator, uint16_t chainedPointerFormat) { + switch (chainedPointerFormat) { + case DYLD_CHAINED_PTR_ARM64E: + return (accumulator <= 0x80000); + case DYLD_CHAINED_PTR_64: + return (accumulator <= 255); + case DYLD_CHAINED_PTR_32: + return (accumulator <= 63); + case DYLD_CHAINED_PTR_32_CACHE: + assert(0 && "Binds are not supported"); + return false; + case DYLD_CHAINED_PTR_32_FIRMWARE: + assert(0 && "Binds are not supported"); + return false; + } + assert(0 && "Unknown pointer format"); + return false; +} + +bool OutputFile::needsBind(const ld::Atom* toTarget, uint64_t* accumulator, uint64_t* inlineAddend, + uint32_t* bindOrdinal, uint32_t* libOrdinal) const { + bool isBind = false; + bool isWeakBind = false; + switch ( toTarget->definition() ) { + case ld::Atom::definitionProxy: + isBind = true; + if ( toTarget->combine() == ld::Atom::combineByName ) { + // This is a use of a weak def symbol from a dylib, eg, operator new from libc++ + isWeakBind = true; + } + break; + case ld::Atom::definitionRegular: + case ld::Atom::definitionTentative: + // references to internal symbol never need binding + if ( toTarget->scope() != ld::Atom::scopeGlobal ) + break; + // reference to global weak def needs weak binding + if ( (toTarget->combine() == ld::Atom::combineByName) && (toTarget->definition() == ld::Atom::definitionRegular) ) { + isWeakBind = true; + } + else if ( _options.outputKind() == Options::kDynamicExecutable ) { + break; + } + else { + // for flat-namespace or interposable two-level-namespace + // all references to exported symbols get indirected + if ( (_options.nameSpace() != Options::kTwoLevelNameSpace) || _options.interposable(toTarget->name()) ) { + break; + } + else if ( _options.forceCoalesce(toTarget->name()) ) { + isWeakBind = true; + } + } + break; + case ld::Atom::definitionAbsolute: + break; + } + if ( isWeakBind ) { + if ( accumulator != nullptr ) { + // Weak binds look like rebases in that they point to the definition in their binary + // Work out the actual addend + *accumulator = *accumulator - toTarget->finalAddress(); + // thumb bit should not be in addend + if ( toTarget->isThumb() ) + *accumulator &= -2; + if ( chainedFixupAddendFitsInline(*accumulator, chainedPointerFormat()) ) { + if ( inlineAddend != nullptr ) + *inlineAddend = *accumulator; + *accumulator = 0; + } + if ( bindOrdinal != nullptr ) + *bindOrdinal = _chainedFixupBinds.ordinal(toTarget, *accumulator); + } + if ( libOrdinal != nullptr ) { + *libOrdinal = BIND_SPECIAL_DYLIB_WEAK_LOOKUP; + } + } + else if ( isBind ) { + if ( accumulator != nullptr ) { + if ( chainedFixupAddendFitsInline(*accumulator, chainedPointerFormat()) ) { + if ( inlineAddend != nullptr ) + *inlineAddend = *accumulator; + *accumulator = 0; + } + } + if ( bindOrdinal != nullptr ) + *bindOrdinal = _chainedFixupBinds.ordinal(toTarget, *accumulator); + if ( libOrdinal != nullptr ) { + const ld::dylib::File* dylib = (ld::dylib::File*)(toTarget->file()); + if ( dylib != nullptr ) { + *libOrdinal = dylibToOrdinal(dylib); + } + else { + // handle undefined dynamic_lookup + if ( _options.undefinedTreatment() == Options::kUndefinedDynamicLookup ) { + if ( _options.sharedRegionEligible() ) + throwf("-undefined dynamic_lookup cannot be used to find '%s' in dylib in dyld shared cache", toTarget->name()); + return BIND_SPECIAL_DYLIB_FLAT_LOOKUP; + } + + // handle -U _foo + if ( _options.allowedUndefined(toTarget->name()) ) + return BIND_SPECIAL_DYLIB_FLAT_LOOKUP; + } + } + } + return isBind || isWeakBind; +} + + +void OutputFile::setFixup64(uint8_t* fixUpLocation, uint64_t accumulator, const ld::Atom* toTarget) +{ + uint32_t bindOrdinal = 0; + uint64_t inlineAddend = 0; + bool isBind = needsBind(toTarget, &accumulator, &inlineAddend, &bindOrdinal); + switch ( chainedPointerFormat() ) { + case DYLD_CHAINED_PTR_64: + if ( isBind ) { + dyld_chained_ptr_64_bind* b = (dyld_chained_ptr_64_bind*)fixUpLocation; + b->bind = 1; + b->next = 0; // chained fixed up later once all fixup locations are known + b->reserved= 0; + b->addend = inlineAddend; + b->ordinal = bindOrdinal; + //fprintf(stderr, "%p bind, ord=%03d, addend=%lld %s\n", b, symOrdinal, accumulator, toTarget->name()); + } + else { + //fprintf(stderr, "%p rebase, target=0x%08llX %s\n", p64, accumulator, toTarget->name()); + dyld_chained_ptr_64_rebase* r = (dyld_chained_ptr_64_rebase*)fixUpLocation; + r->bind = 0; + r->next = 0; // chained fixed up later once all fixup locations are known + r->reserved= 0; + r->high8 = accumulator >> 56; + r->target = accumulator & 0x7FFFFFFFFFF; + uint64_t reconstituted = (((uint64_t)(r->high8)) << 56) + r->target; + assert(reconstituted == accumulator); + } + break; + case DYLD_CHAINED_PTR_ARM64E: + if ( isBind ) { + dyld_chained_ptr_arm64e_bind* b = (dyld_chained_ptr_arm64e_bind*)fixUpLocation; + b->auth = 0; + b->bind = 1; + b->next = 0; // chained fixed up later once all fixup locations are known + b->addend = inlineAddend; + b->zero = 0; + b->ordinal = bindOrdinal; + //fprintf(stderr, "%p bind, ord=%03d, addend=%lld %s\n", b, symOrdinal, accumulator, toTarget->name()); + } + else { + //fprintf(stderr, "%p rebase, target=0x%08llX %s\n", p64, accumulator, toTarget->name()); + dyld_chained_ptr_arm64e_rebase* r = (dyld_chained_ptr_arm64e_rebase*)fixUpLocation; + r->auth = 0; + r->bind = 0; + r->next = 0; // chained fixed up later once all fixup locations are known + r->high8 = (accumulator >> 56); + r->target = accumulator; + uint64_t reconstituted = (((uint64_t)(r->high8)) << 56) + r->target; + assert(reconstituted == accumulator); + } + break; + default: + throw("chained binds not implemented yet"); + } +} + +#if SUPPORT_ARCH_arm64e +void OutputFile::setFixup64e(uint8_t* fixUpLocation, uint64_t accumulator, Fixup::AuthData authData, const ld::Atom* toTarget) +{ + uint32_t bindOrdinal = 0; + uint64_t inlineAddend = 0; + bool isBind = needsBind(toTarget, &accumulator, &inlineAddend, &bindOrdinal); + switch ( chainedPointerFormat() ) { + case DYLD_CHAINED_PTR_ARM64E: + if ( isBind ) { + dyld_chained_ptr_arm64e_auth_bind* b = (dyld_chained_ptr_arm64e_auth_bind*)fixUpLocation; + b->auth = 1; + b->bind = 1; + b->next = 0; + b->key = authData.key; + b->addrDiv = authData.hasAddressDiversity; + b->diversity = authData.discriminator; + b->zero = 0; + b->ordinal = bindOrdinal; + //fprintf(stderr, "%p bind, ord=%03d, addend=%lld %s\n", b, symOrdinal, accumulator, toTarget->name()); + } + else { + //fprintf(stderr, "%p rebase, target=0x%08llX %s\n", p64, accumulator, toTarget->name()); + dyld_chained_ptr_arm64e_auth_rebase* r = (dyld_chained_ptr_arm64e_auth_rebase*)fixUpLocation; + uint64_t vmOffset = (accumulator - _options.machHeaderVmAddr()); + r->auth = 1; + r->bind = 0; + r->next = 0; + r->key = authData.key; + r->addrDiv = authData.hasAddressDiversity; + r->diversity = authData.discriminator; + r->target = vmOffset & 0xFFFFFFFF; + assert(r->target == vmOffset); + } + break; + default: + throw("chained binds not implemented yet"); + } +} +#endif + +void OutputFile::setFixup32(uint8_t* fixUpLocation, uint64_t accumulator, const ld::Atom* toTarget) +{ + uint32_t bindOrdinal = 0; + uint64_t inlineAddend = 0; + bool isBind = needsBind(toTarget, &accumulator, &inlineAddend, &bindOrdinal); + switch ( chainedPointerFormat() ) { + case DYLD_CHAINED_PTR_32: + if ( isBind ) { + dyld_chained_ptr_32_bind* b = (dyld_chained_ptr_32_bind*)fixUpLocation; + b->bind = 1; + b->next = 0; // chained fixed up later once all fixup locations are known + b->addend = inlineAddend; + b->ordinal = bindOrdinal; + //fprintf(stderr, "%p bind, ord=%03d, addend=%lld %s\n", b, symOrdinal, accumulator, toTarget->name()); + } + else { + //fprintf(stderr, "%p rebase, target=0x%08llX %s\n", p64, accumulator, toTarget->name()); + dyld_chained_ptr_32_rebase* r = (dyld_chained_ptr_32_rebase*)fixUpLocation; + r->bind = 0; + r->next = 0; // chained fixed up later once all fixup locations are known + r->target = accumulator & 0x03FFFFFF; + assert(r->target == accumulator); + assert(accumulator < _chainedFixupBinds.maxRebase()); + } + break; + case DYLD_CHAINED_PTR_32_FIRMWARE: + { + dyld_chained_ptr_32_firmware_rebase* r = (dyld_chained_ptr_32_firmware_rebase*)fixUpLocation; + r->next = 0; // chain fixed up later once all fixup locations are known + r->target = accumulator & 0x03FFFFFF; + assert(r->target == accumulator); + assert(accumulator < _chainedFixupBinds.maxRebase()); + } + break; + default: + throw("chained binds not implemented yet"); + } +} + void OutputFile::copyNoOps(uint8_t* from, uint8_t* to, bool thumb) { switch ( _options.architecture() ) { @@ -2563,14 +2952,16 @@ bool OutputFile::hasZeroForFileOffset(const ld::Section* sect) void OutputFile::writeAtoms(ld::Internal& state, uint8_t* wholeBuffer) { + const bool logThreadedFixups = false; + // have each atom write itself uint64_t fileOffsetOfEndOfLastAtom = 0; - uint64_t mhAddress = 0; bool lastAtomUsesNoOps = false; + uint64_t baseAddress = _options.baseAddress(); for (std::vector::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) { ld::Internal::FinalSection* sect = *sit; - if ( sect->type() == ld::Section::typeMachHeader ) - mhAddress = sect->address; + if ( (sect->type() == ld::Section::typeMachHeader) && (_options.outputKind() != Options::kPreload) ) + baseAddress = sect->address; if ( takesNoDiskSpace(sect) ) continue; const bool sectionUsesNops = (sect->type() == ld::Section::typeCode); @@ -2590,14 +2981,14 @@ void OutputFile::writeAtoms(ld::Internal& state, uint8_t* wholeBuffer) // copy atom content atom->copyRawContent(&wholeBuffer[fileOffset]); // apply fix ups - this->applyFixUps(state, mhAddress, atom, &wholeBuffer[fileOffset]); + this->applyFixUps(state, baseAddress, atom, &wholeBuffer[fileOffset]); fileOffsetOfEndOfLastAtom = fileOffset+atom->size(); lastAtomUsesNoOps = sectionUsesNops; lastAtomWasThumb = atom->isThumb(); } catch (const char* msg) { if ( atom->file() != NULL ) - throwf("%s in '%s' from %s", msg, atom->name(), atom->file()->path()); + throwf("%s in '%s' from %s", msg, atom->name(), atom->safeFilePath()); else throwf("%s in '%s'", msg, atom->name()); } @@ -2609,8 +3000,464 @@ void OutputFile::writeAtoms(ld::Internal& state, uint8_t* wholeBuffer) //fprintf(stderr, "ADRPs changed to NOPs: %d\n", sAdrpNoped); //fprintf(stderr, "ADRPs unchanged: %d\n", sAdrpNotNoped); } + + if ( _options.makeThreadedStartsSection() ) { + assert(_threadedRebaseBindIndices.empty()); + + std::vector& bindInfo = _bindingInfo; + std::vector& rebaseInfo = _rebaseInfo; + + std::vector& threadedRebaseBindIndices = _threadedRebaseBindIndices; + threadedRebaseBindIndices.reserve(bindInfo.size() + rebaseInfo.size()); + + for (int64_t i = 0, e = rebaseInfo.size(); i != e; ++i) + threadedRebaseBindIndices.push_back(-i); + + for (int64_t i = 0, e = bindInfo.size(); i != e; ++i) + threadedRebaseBindIndices.push_back(i + 1); + + // Now sort the entries by address. + std::sort(threadedRebaseBindIndices.begin(), threadedRebaseBindIndices.end(), + [&rebaseInfo, &bindInfo](int64_t indexA, int64_t indexB) { + if (indexA == indexB) + return false; + uint64_t addressA = indexA <= 0 ? rebaseInfo[-indexA]._address : bindInfo[indexA - 1]._address; + uint64_t addressB = indexB <= 0 ? rebaseInfo[-indexB]._address : bindInfo[indexB - 1]._address; + assert(addressA != addressB); + return addressA < addressB; + }); + } + + // new rebasing/binding scheme requires making another pass at DATA + // segment and building linked list of rebase locations + if ( _options.useLinkedListBinding() && !_threadedRebaseBindIndices.empty() ) { + uint64_t curSegStart = 0; + uint64_t curSegEnd = 0; + uint32_t curSegIndex = 0; + ld::Internal::FinalSection* curSection = NULL; + + const uint64_t deltaBits = 11; + const uint32_t fixupAlignment = _options.makeThreadedStartsSection() ? 4 : 8; + const bool allowThreadsToCrossPages = _options.makeThreadedStartsSection(); + std::vector threadStarts; + + // Find the thread starts section + ld::Internal::FinalSection* threadStartsSection = nullptr; + uint64_t threadStartsReservedSpace = 0; + if ( _options.makeThreadedStartsSection() ) { + for (ld::Internal::FinalSection* sect : state.sections) { + if ( sect->type() == ld::Section::typeThreadStarts ) { + threadStartsSection = sect; + break; + } + } + assert(threadStartsSection); + threadStartsReservedSpace = (threadStartsSection->size - 4) / 4; + threadStarts.reserve(threadStartsReservedSpace); + } + + auto getAddress = [this](int64_t index) { + if (index <= 0) + return _rebaseInfo[-index]._address; + else + return _bindingInfo[index - 1]._address; + }; + + if ( (_bindingInfo.size() > 1) + && ! findSegment(state, getAddress(_threadedRebaseBindIndices.front()), + &curSegStart, &curSegEnd, &curSegIndex) ) + throw "binding address outside range of any segment"; + + auto applyBind = [&](int64_t currentIndex, int64_t nextIndex) { + uint64_t currentAddress = getAddress(currentIndex); + uint64_t nextAddress = getAddress(nextIndex); + + // The very first pointer we see must be a new chain + if ( _options.makeThreadedStartsSection() && curSection == NULL ) + threadStarts.push_back(currentAddress); + + if ( (curSection == NULL) + || (currentAddress < curSection->address) + || (currentAddress >= curSection->address+curSection->size) ) { + for (ld::Internal::FinalSection* sect : state.sections) { + if ( (sect->address <= currentAddress) + && (currentAddress < sect->address+sect->size) ) { + curSection = sect; + break; + } + } + } + + if (logThreadedFixups) fprintf(stderr, "fixup: %s, address=0x%llX\n", curSection->sectionName(), currentAddress); + + bool makeChainToNextAddress = true; + if ( allowThreadsToCrossPages ) { + // Even if we allow threads to cross pages, we still need to have the same section. + if ( (nextAddress < curSection->address) || (nextAddress >= curSection->address+curSection->size) ) + makeChainToNextAddress = false; + } else { + // If threads can't cross pages then make sure they are on the same page. + uint64_t currentPageIndex = ( currentAddress - curSegStart) / 4096; + uint64_t nextPageIndex = ( nextAddress - curSegStart) / 4096; + if ( currentPageIndex != nextPageIndex ) + makeChainToNextAddress = false; + } + + uint64_t delta = 0; + if (makeChainToNextAddress) { + delta = nextAddress - currentAddress; + + // The value should already be aligned to 4 or 8, so make sure the low bits are zeroes + assert( (delta & (fixupAlignment - 1)) == 0 ); + delta /= fixupAlignment; + if ( delta >= (1 << deltaBits) ) { + // Current and next are both in the same segment, so see if they are + // on the same page. If so, patch current to point to next. + makeChainToNextAddress = false; + } + } + + if (!makeChainToNextAddress) { + delta = 0; + if (_options.makeThreadedStartsSection()) + threadStarts.push_back(nextAddress); + } + + uint8_t* lastBindLocation = wholeBuffer + curSection->fileOffset + currentAddress - curSection->address; + switch ( _options.architecture() ) { + case CPU_TYPE_X86_64: + case CPU_TYPE_ARM64: + uint64_t value = 0; + if (currentIndex <= 0) { + // For rebases, bits [0..50] is the mh offset which is already set + // Bit 62 is a 0 to say this is a rebase + value = get64LE(lastBindLocation); +#if SUPPORT_ARCH_arm64e + auto fixupOffset = (uintptr_t)(lastBindLocation - baseAddress); + auto it = _authenticatedFixupData.find(fixupOffset); + if (it != _authenticatedFixupData.end()) { + // For authenticated data, we zeroed out the location + assert(value == 0); + const auto &authData = it->second.first; + uint64_t accumulator = it->second.second; + assert(accumulator >= baseAddress); + accumulator -= baseAddress; + + // Make sure the high bits aren't set. The low 32-bits may + // be the target value. + assert((accumulator & 0xFFFFFFFF00000000ULL) == 0); + accumulator |= ((uint64_t)authData.discriminator) << 32; + accumulator |= ((uint64_t)authData.hasAddressDiversity) << 48; + accumulator |= ((uint64_t)authData.key) << 49; + // Set the high bit as we are authenticated + accumulator |= 1ULL << 63; + + value = accumulator; + } else +#endif + { + // Regular pointer which needs to fit in 51-bits of value. + // C++ RTTI uses the top bit, so we'll allow the whole top-byte + // and the bottom 43-bits with sign-extension to be fit in to 51-bits. + uint64_t top8Bits = value & 0xFF00000000000000ULL; + uint64_t bottom43Bits = value & 0x000007FFFFFFFFFFULL; + // Ensure that the sign-extended bottom 43-bits is equivalent in sign to the gap bits + assert( ((value & ~0xFF0003FFFFFFFFFF) == 0) || ((value & ~0xFF0003FFFFFFFFFF) == ~0xFF0003FFFFFFFFFF) ); + value = ( top8Bits >> 13 ) | bottom43Bits; + } + } else { + // The ordinal in [0..15] + // Bit 62 is a 1 to say this is a bind + value = get64LE(lastBindLocation); +#if SUPPORT_ARCH_arm64e + auto fixupOffset = (uintptr_t)(lastBindLocation - baseAddress); + auto it = _authenticatedFixupData.find(fixupOffset); + if (it != _authenticatedFixupData.end()) { + // For authenticated data, we zeroed out the location + assert(value == 0); + const auto &authData = it->second.first; + uint64_t accumulator = it->second.second; + + // Make sure the high bits aren't set. The low 32-bits may + // be the target value. + // Note, this doesn't work for binds to a weak def as we actually + // manage to resolve their address to an address in this binary so + // its not 0. + if (_bindingInfo[currentIndex - 1]._libraryOrdinal == BIND_SPECIAL_DYLIB_WEAK_LOOKUP) + accumulator = 0; + assert((accumulator & 0xFFFFFFFF00000000ULL) == 0); + accumulator |= ((uint64_t)authData.discriminator) << 32; + accumulator |= ((uint64_t)authData.hasAddressDiversity) << 48; + accumulator |= ((uint64_t)authData.key) << 49; + // Set the high bit as we are authenticated + accumulator |= 1ULL << 63; + + value = accumulator; + } else +#endif + { + // Regular pointer + // The current data is unused as we get a new address from the bind table. + // So zero it out to avoid the bits interfering with the authentication bits. + value = 0; + } + value &= 0xFFFFFFFFFFFF0000; + value |= _bindingInfo[currentIndex - 1]._threadedBindOrdinal; + value |= 1ULL << 62; + } + + // The delta is bits [51..61] + value |= ( delta << 51 ); + set64LE(lastBindLocation, value); + break; + } + }; + + // Loop over every value and see if it needs to point to its successor. + // Note that on every iteration, info[i] is already known to be in the current + // segment. + for (int64_t i = 0, e = _threadedRebaseBindIndices.size() - 1; i != e; ++i) { + int64_t currentIndex = _threadedRebaseBindIndices[i]; + int64_t nextIndex = _threadedRebaseBindIndices[i + 1]; + uint64_t nextAddress = getAddress(nextIndex); + if ( (nextAddress < curSegStart) || ( nextAddress >= curSegEnd) ) { + // The next pointer is in a new segment. + // This means current is the end of a chain, and we need to move + // the segment addresses on to be the next ones. + if ( ! findSegment(state, nextAddress, &curSegStart, &curSegEnd, &curSegIndex) ) + throw "binding address outside range of any segment"; + } + + applyBind(currentIndex, nextIndex); + } + + applyBind(_threadedRebaseBindIndices.back(), _threadedRebaseBindIndices.back()); + + if ( _options.makeThreadedStartsSection() ) { + if ( threadStarts.size() > threadStartsReservedSpace ) + throw "overflow in thread starts section"; + + // Now write over this section content with the new array. + const ld::Atom *threadStartsAtom = nullptr; + for (const ld::Atom *atom : threadStartsSection->atoms) { + if ( (atom->contentType() == ld::Atom::typeSectionStart) || (atom->contentType() == ld::Atom::typeSectionEnd) ) { + assert(atom->size() == 0); + continue; + } + assert(threadStartsAtom == nullptr); + threadStartsAtom = atom; + } + uint64_t threadStartsFileOffset = threadStartsAtom->finalAddress() - threadStartsSection->address + threadStartsSection->fileOffset; + // Skip the header + if (logThreadedFixups) fprintf(stderr, "thread start[0x%llX]: header=0x%X\n", threadStartsFileOffset, get32LE(&wholeBuffer[threadStartsFileOffset])); + threadStartsFileOffset += sizeof(uint32_t); + for (uint64_t threadStart : threadStarts) { + uint64_t offset = threadStart - baseAddress; + assert(offset < 0x100000000); + set32LE(&wholeBuffer[threadStartsFileOffset], offset); + if (logThreadedFixups) fprintf(stderr, "thread start[0x%llX]: address=0x%llX -> offset=0x%llX\n", threadStartsFileOffset, threadStart, offset); + threadStartsFileOffset += sizeof(uint32_t); + } + } + } + + if ( _options.makeChainedFixups() ) { + + // for firmware, chains are not page based. We just make the chains as long as possible + if ( chainedPointerFormat() == DYLD_CHAINED_PTR_32_FIRMWARE ) { + std::vector startOffsets; + uint8_t* prevLoc = nullptr; + for (ChainedFixupSegInfo& segInfo : _chainedFixupSegments) { + //fprintf(stderr, "0x%08llX 0x%08llX %s\n", segInfo.startAddr, segInfo.endAddr-segInfo.startAddr, segInfo.name); + uint8_t* segBufferStart = &wholeBuffer[segInfo.fileOffset]; + uint8_t* pageBufferStart = segBufferStart; + for (ChainedFixupPageInfo& pageInfo : segInfo.pages) { + //fprintf(stderr, " fixup count: %lu\n", pageInfo.fixupOffsets.size()); + for (uint16_t pageOffset : pageInfo.fixupOffsets) { + uint8_t* loc = (uint8_t*)pageBufferStart + pageOffset; + if ( prevLoc == nullptr ) { + startOffsets.push_back(loc-wholeBuffer); + } + else { + uint64_t delta = (uint8_t*)loc - (uint8_t*)prevLoc; + if ( delta < 255 ) { + // delta fits in 6-bit size of "next" field + ((dyld_chained_ptr_32_firmware_rebase*)prevLoc)->next = delta/4; + } + else { + // need to start new chain + //fprintf(stderr, "delta=%lld\n", delta); + ((dyld_chained_ptr_32_firmware_rebase*)prevLoc)->next = 0; + startOffsets.push_back(loc-wholeBuffer); + } + } + prevLoc = loc; + } + pageBufferStart += segInfo.pageSize; + } + } + // now update section with chain starts + for (ld::Internal::FinalSection* sect : state.sections) { + if ( sect->type() == ld::Section::typeChainStarts ) { + size_t startsArraySize = startOffsets.size() * sizeof(uint32_t); + size_t startsSectionSize = offsetof(dyld_chained_starts_offsets, chain_starts[startOffsets.size()]); + if ( sect->size < startsSectionSize ) + throwf("pre-computed __chain_starts section too small"); + dyld_chained_starts_offsets* startsSection = (dyld_chained_starts_offsets*)(&wholeBuffer[sect->fileOffset]); + startsSection->pointer_format = DYLD_CHAINED_PTR_32_FIRMWARE; + startsSection->starts_count = startOffsets.size(); + memcpy(startsSection->chain_starts, &startOffsets[0], startsArraySize); + } + } + } + else { + // chain together fixups + uint32_t segIndex = 0; + for (ChainedFixupSegInfo& segInfo : _chainedFixupSegments) { + //fprintf(stderr, "0x%08llX 0x%08llX %s\n", segInfo.startAddr, segInfo.endAddr-segInfo.startAddr, segInfo.name); + uint8_t* segBufferStart = &wholeBuffer[segInfo.fileOffset]; + uint8_t* pageBufferStart = segBufferStart; + uint32_t pageIndex = 0; + uint32_t nextOverflowSlot = segInfo.pages.size(); + for (ChainedFixupPageInfo& pageInfo : segInfo.pages) { + //fprintf(stderr, " fixup count: %lu\n", pageInfo.fixupOffsets.size()); + uint8_t* prevLoc = nullptr; + for (uint16_t pageOffset : pageInfo.fixupOffsets) { + uint8_t* loc = (uint8_t*)pageBufferStart + pageOffset; + //fprintf(stderr, "%p, pageOffset=0x%04X, bind=%d\n", loc, pageOffset, ((dyld_chained_ptr_64_rebase*)loc)->bind); + if ( prevLoc != nullptr ) { + uint64_t delta = (uint8_t*)loc - (uint8_t*)prevLoc; + switch ( segInfo.pointerFormat ) { + case DYLD_CHAINED_PTR_ARM64E: + ((dyld_chained_ptr_arm64e_rebase*)prevLoc)->next = delta/8; + assert(((dyld_chained_ptr_arm64e_rebase*)prevLoc)->next == delta/8 && "next out of range"); + break; + case DYLD_CHAINED_PTR_64: + ((dyld_chained_ptr_64_rebase*)prevLoc)->next = delta/4; + assert(((dyld_chained_ptr_64_rebase*)prevLoc)->next == delta/4 && "next out of range"); + break; + case DYLD_CHAINED_PTR_32: + chain32bitPointers((dyld_chained_ptr_32_rebase*)prevLoc, (dyld_chained_ptr_32_rebase*)loc, + segInfo, pageBufferStart, pageIndex); + break; + default: + assert(0 && "unknown pointer format"); + } + } + prevLoc = loc; + } + if ( !pageInfo.chainOverflows.empty() ) { + uint8_t* chainHeader = NULL; + for (ld::Internal::FinalSection* sect : state.sections) { + //fprintf(stderr, "file offset=0x%08llX, section %s\n", sect->fileOffset, sect->sectionName()); + if ( (sect->type() == ld::Section::typeLinkEdit) && (strcmp(sect->sectionName(), "__chainfixups") == 0) ) + chainHeader = &wholeBuffer[sect->fileOffset]; + } + dyld_chained_fixups_header* header = (dyld_chained_fixups_header*)chainHeader; + dyld_chained_starts_in_image* chains = (dyld_chained_starts_in_image*)((uint8_t*)header + header->starts_offset); + dyld_chained_starts_in_segment* segChains = (dyld_chained_starts_in_segment*)((uint8_t*)chains + chains->seg_info_offset[segIndex]); + for (uint16_t extraStart : pageInfo.chainOverflows ) { + if ( (segChains->page_start[pageIndex] & DYLD_CHAINED_PTR_START_MULTI) == 0 ) { + uint16_t first = segChains->page_start[pageIndex]; + segChains->page_start[pageIndex] = DYLD_CHAINED_PTR_START_MULTI | nextOverflowSlot; + segChains->page_start[nextOverflowSlot++] = first; + } + if ( extraStart == pageInfo.chainOverflows.back() ) + segChains->page_start[nextOverflowSlot++] = extraStart | DYLD_CHAINED_PTR_START_LAST; + else + segChains->page_start[nextOverflowSlot++] = extraStart; + } + } + pageBufferStart += segInfo.pageSize; + ++pageIndex; + } + ++segIndex; + } + } + } } + + + +// decode: if target26 > max_pointer, then value = signext(target26)-max_pointer +// encode: if value >= 0 and value < 32MB, then target26 = value+max_pointer +// if value < 0 and value > -32MB+max_pointer, then target26 = value+max_pointer + + + +// range = (64MB-max_pointer)/2 +// bias = (64MB+max_pointer)/2 +// decode: if target26 > max_pointer, then value = zeroext(target26)-bias +// encode: if ( -range < value < range ), then target26 = value+bias + +dyld_chained_ptr_32_rebase* OutputFile::farthestChainableLocation(dyld_chained_ptr_32_rebase* start) +{ + const uint32_t maxTargetOffset = 1 << 26; // 0x04000000, 26 == bitsizeof(dyld_chained_ptr_32_rebase.target) + assert(_chainedFixupBinds.maxRebase() < maxTargetOffset); + int32_t range = (maxTargetOffset-_chainedFixupBinds.maxRebase())/2; + int32_t* values = (int32_t*)start; + for (int i=31; i > 0; --i) { + if ( (values[i] < range) && (values[i] > -range) ) { + return (dyld_chained_ptr_32_rebase*)&values[i]; + } + } + return nullptr; +} + +void OutputFile::chain32bitPointers(dyld_chained_ptr_32_rebase* prevLoc, dyld_chained_ptr_32_rebase* finalLoc, + ChainedFixupSegInfo& segInfo, uint8_t* pageBufferStart, uint32_t pageIndex) +{ + const uint32_t maxDelta = 127; // 5-bit "next" means farthest reach is (2^5-1)*4 = 124 bytes + const uint32_t delta = (uint8_t*)finalLoc - (uint8_t*)prevLoc; + if ( delta < maxDelta ) { + // simple case: delta fits in 5-bit size of "next" field + prevLoc->next = delta/4; + return; + } + + // delta is too far, see if we can steal non-pointer values + bool chainPossible = false; + dyld_chained_ptr_32_rebase* endZone = &finalLoc[-31]; + for (dyld_chained_ptr_32_rebase* p = prevLoc; p != nullptr; p = farthestChainableLocation(p) ) { + if ( p >= endZone ) { + chainPossible = true; + break; + } + } + if ( chainPossible ) { + uint32_t bias = (0x04000000+_chainedFixupBinds.maxRebase())/2; + dyld_chained_ptr_32_rebase* curLoc = farthestChainableLocation(prevLoc); + // start location is a real pointer, so just set ->next + // all subsequent locations are non-pointers co-opted into the chain + uint32_t firstSteps = curLoc - prevLoc; + prevLoc->next = firstSteps; + while (curLoc < endZone) { + prevLoc = curLoc; + curLoc = farthestChainableLocation(prevLoc); + uint32_t steps = curLoc - prevLoc; + uint32_t value = *((uint32_t*)prevLoc); + prevLoc->bind = 0; + prevLoc->next = steps; + prevLoc->target = value + bias; + assert(prevLoc->next == steps); + } + uint32_t lastSteps = finalLoc - curLoc; + uint32_t value = *((uint32_t*)curLoc); + curLoc->bind = 0; + curLoc->next = lastSteps; + curLoc->target = value + bias; + assert(curLoc->next == lastSteps); + return; + } + + // no way to make chain, add a new chain start + uint16_t newChainStartOffset = (uint8_t*)finalLoc - pageBufferStart; + ChainedFixupPageInfo& pageInfo = segInfo.pages[pageIndex]; + pageInfo.chainOverflows.push_back(newChainStartOffset); +} + + void OutputFile::computeContentUUID(ld::Internal& state, uint8_t* wholeBuffer) { const bool log = false; @@ -2637,19 +3484,23 @@ void OutputFile::computeContentUUID(ld::Internal& state, uint8_t* wholeBuffer) bitcodeSectOffset, bitcodePaddingEnd); excludeRegions.emplace_back(std::pair(bitcodeSectOffset, bitcodePaddingEnd)); } + const uint64_t pointerSize = (_options.architecture() & CPU_ARCH_ABI64) ? 8 : 4; uint32_t stabsStringsOffsetStart; uint32_t tabsStringsOffsetEnd; uint32_t stabsOffsetStart; uint32_t stabsOffsetEnd; if ( _symbolTableAtom->hasStabs(stabsStringsOffsetStart, tabsStringsOffsetEnd, stabsOffsetStart, stabsOffsetEnd) ) { // find two areas of file that are stabs info and should not contribute to checksum - uint64_t stringPoolFileOffset = 0; + uint64_t stringPoolFileOffset = 0; + uint64_t stringPoolFileSize = 0; uint64_t symbolTableFileOffset = 0; for (std::vector::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) { ld::Internal::FinalSection* sect = *sit; if ( sect->type() == ld::Section::typeLinkEdit ) { - if ( strcmp(sect->sectionName(), "__string_pool") == 0 ) + if ( strcmp(sect->sectionName(), "__string_pool") == 0 ) { stringPoolFileOffset = sect->fileOffset; + stringPoolFileSize = sect->size; + } else if ( strcmp(sect->sectionName(), "__symbol_table") == 0 ) symbolTableFileOffset = sect->fileOffset; } @@ -2658,13 +3509,26 @@ void OutputFile::computeContentUUID(ld::Internal& state, uint8_t* wholeBuffer) uint64_t lastStabNlistFileOffset = symbolTableFileOffset + stabsOffsetEnd; uint64_t firstStabStringFileOffset = stringPoolFileOffset + stabsStringsOffsetStart; uint64_t lastStabStringFileOffset = stringPoolFileOffset + tabsStringsOffsetEnd; - if ( log ) fprintf(stderr, "firstStabNlistFileOffset=0x%08llX\n", firstStabNlistFileOffset); - if ( log ) fprintf(stderr, "lastStabNlistFileOffset=0x%08llX\n", lastStabNlistFileOffset); - if ( log ) fprintf(stderr, "firstStabStringFileOffset=0x%08llX\n", firstStabStringFileOffset); - if ( log ) fprintf(stderr, "lastStabStringFileOffset=0x%08llX\n", lastStabStringFileOffset); + if ( log ) fprintf(stderr, "stabNlist offset=0x%08llX, size=0x%08llX\n", firstStabNlistFileOffset, lastStabNlistFileOffset-firstStabNlistFileOffset); + if ( log ) fprintf(stderr, "stabString offset=0x%08llX, size=0x%08llX\n", firstStabStringFileOffset, lastStabStringFileOffset-firstStabStringFileOffset); assert(firstStabNlistFileOffset <= firstStabStringFileOffset); excludeRegions.emplace_back(std::pair(firstStabNlistFileOffset, lastStabNlistFileOffset)); - excludeRegions.emplace_back(std::pair(firstStabStringFileOffset, lastStabStringFileOffset)); + // don't MD5 the zero padding at the end of the string pool, after the stabs strings + if ( (stringPoolFileSize - tabsStringsOffsetEnd) < pointerSize ) + excludeRegions.emplace_back(std::pair(firstStabStringFileOffset, stringPoolFileOffset + stringPoolFileSize)); + else + excludeRegions.emplace_back(std::pair(firstStabStringFileOffset, lastStabStringFileOffset)); + // exclude LINKEDIT LC_SEGMENT (size field depends on stabs size) + uint64_t linkeditSegCmdOffset; + uint64_t linkeditSegCmdSize; + _headersAndLoadCommandAtom->linkeditCmdInfo(linkeditSegCmdOffset, linkeditSegCmdSize); + excludeRegions.emplace_back(std::pair(linkeditSegCmdOffset, linkeditSegCmdOffset+linkeditSegCmdSize)); + if ( log ) fprintf(stderr, "linkedit SegCmdOffset=0x%08llX, size=0x%08llX\n", linkeditSegCmdOffset, linkeditSegCmdSize); + uint64_t symbolTableCmdOffset; + uint64_t symbolTableCmdSize; + _headersAndLoadCommandAtom->symbolTableCmdInfo(symbolTableCmdOffset, symbolTableCmdSize); + excludeRegions.emplace_back(std::pair(symbolTableCmdOffset, symbolTableCmdOffset+symbolTableCmdSize)); + if ( log ) fprintf(stderr, "linkedit SegCmdOffset=0x%08llX, size=0x%08llX\n", symbolTableCmdOffset, symbolTableCmdSize); } if ( !excludeRegions.empty() ) { CC_MD5_CTX md5state; @@ -2674,6 +3538,12 @@ void OutputFile::computeContentUUID(ld::Internal& state, uint8_t* wholeBuffer) if ( lastSlash != NULL ) { CC_MD5_Update(&md5state, lastSlash, strlen(lastSlash)); } + // use train name when calculating a binary's UUID + const char* buildName = _options.buildContextName(); + if ( buildName != NULL ) { + CC_MD5_Update(&md5state, buildName, strlen(buildName)); + } + std::sort(excludeRegions.begin(), excludeRegions.end()); uint64_t checksumStart = 0; for ( auto& region : excludeRegions ) { uint64_t regionStart = region.first; @@ -2683,8 +3553,10 @@ void OutputFile::computeContentUUID(ld::Internal& state, uint8_t* wholeBuffer) CC_MD5_Update(&md5state, &wholeBuffer[checksumStart], regionStart - checksumStart); checksumStart = regionEnd; } - if ( log ) fprintf(stderr, "checksum 0x%08llX -> 0x%08llX\n", checksumStart, _fileSize); - CC_MD5_Update(&md5state, &wholeBuffer[checksumStart], _fileSize-checksumStart); + if ( checksumStart < _fileSize ) { + if ( log ) fprintf(stderr, "checksum 0x%08llX -> 0x%08llX\n", checksumStart, _fileSize); + CC_MD5_Update(&md5state, &wholeBuffer[checksumStart], _fileSize-checksumStart); + } CC_MD5_Final(digest, &md5state); if ( log ) fprintf(stderr, "uuid=%02X, %02X, %02X, %02X, %02X, %02X, %02X, %02X\n", digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7]); @@ -2714,7 +3586,8 @@ static void removePathAndExit(int sig) fprintf(stderr, "%s should be unreachable on non-Apple OSs; please report this!", __func__); #endif fprintf(stderr, "ld: interrupted\n"); - exit(1); + // we are in a sig handler, don't do clean ups + _exit(1); } void OutputFile::writeOutputFile(ld::Internal& state) @@ -2743,7 +3616,7 @@ void OutputFile::writeOutputFile(ld::Internal& state) #ifdef __APPLE__ // ld64-port struct statfs fsInfo; if ( statfs(_options.outputFilePath(), &fsInfo) != -1 ) { - if ( strcmp(fsInfo.f_fstypename, "hfs") == 0) { + if ( (strcmp(fsInfo.f_fstypename, "hfs") == 0) || (strcmp(fsInfo.f_fstypename, "apfs") == 0) ) { (void)unlink(_options.outputFilePath()); outputIsMappableFile = true; } @@ -2771,7 +3644,7 @@ void OutputFile::writeOutputFile(ld::Internal& state) #ifdef __APPLE__ // ld64-port struct statfs fsInfo; if ( statfs(dirPath, &fsInfo) != -1 ) { - if ( strcmp(fsInfo.f_fstypename, "hfs") == 0) { + if ( (strcmp(fsInfo.f_fstypename, "hfs") == 0) || (strcmp(fsInfo.f_fstypename, "apfs") == 0) ) { outputIsMappableFile = true; } } @@ -2883,13 +3756,24 @@ void OutputFile::writeOutputFile(ld::Internal& state) } struct AtomByNameSorter -{ - bool operator()(const ld::Atom* left, const ld::Atom* right) - { - return (strcmp(left->name(), right->name()) < 0); - } +{ + bool operator()(const ld::Atom* left, const ld::Atom* right) const + { + return (strcmp(left->name(), right->name()) < 0); + } + + bool operator()(const ld::Atom* left, const char* right) const + { + return (strcmp(left->name(), right) < 0); + } + + bool operator()(const char* left, const ld::Atom* right) const + { + return (strcmp(left, right->name()) < 0); + } }; + class NotInSet { public: @@ -2913,7 +3797,7 @@ void OutputFile::buildSymbolTable(ld::Internal& state) ++machoSectionIndex; for (std::vector::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) { const ld::Atom* atom = *ait; - if ( setMachoSectionIndex ) + if ( setMachoSectionIndex ) (const_cast(atom))->setMachoSection(machoSectionIndex); else if ( sect->type() == ld::Section::typeMachHeader ) (const_cast(atom))->setMachoSection(1); // __mh_execute_header is not in any section by needs n_sect==1 @@ -2924,7 +3808,9 @@ void OutputFile::buildSymbolTable(ld::Internal& state) // in -r mode, clarify symbolTableNotInFinalLinkedImages if ( _options.outputKind() == Options::kObjectFile ) { - if ( (_options.architecture() == CPU_TYPE_X86_64) || (_options.architecture() == CPU_TYPE_ARM64) ) { + if ( (_options.architecture() == CPU_TYPE_X86_64) + || (_options.architecture() == CPU_TYPE_ARM64) + ) { // x86_64 .o files need labels on anonymous literal strings if ( (sect->type() == ld::Section::typeCString) && (atom->combine() == ld::Atom::combineByNameAndContent) ) { (const_cast(atom))->setSymbolTableInclusion(ld::Atom::symbolTableIn); @@ -3021,7 +3907,14 @@ void OutputFile::buildSymbolTable(ld::Internal& state) case ld::Atom::scopeLinkageUnit: if ( _options.outputKind() == Options::kObjectFile ) { if ( _options.keepPrivateExterns() ) { - _exportedAtoms.push_back(atom); + if ( atom->symbolTableInclusion() == ld::Atom::symbolTableInWithRandomAutoStripLabel ) { + // ld -r should not promote static 'l' labels to hidden + (const_cast(atom))->setScope(ld::Atom::scopeTranslationUnit); + _localAtoms.push_back(atom); + } + else { + _exportedAtoms.push_back(atom); + } } else if ( _options.keepLocalSymbol(atom->name()) ) { _localAtoms.push_back(atom); @@ -3036,7 +3929,7 @@ void OutputFile::buildSymbolTable(ld::Internal& state) _localAtoms.push_back(atom); // ld should never have a symbol in the non-lazy indirect symbol table with index 0 // this works by making __mh_execute_header be a local symbol which takes symbol index 0 - else if ( (atom->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip) && !_options.makeCompressedDyldInfo() ) + else if ( (atom->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip) && !_options.makeCompressedDyldInfo() && !_options.makeThreadedStartsSection() ) _localAtoms.push_back(atom); else (const_cast(atom))->setSymbolTableInclusion(ld::Atom::symbolTableNotIn); @@ -3075,6 +3968,72 @@ void OutputFile::buildSymbolTable(ld::Internal& state) // sort by name std::sort(_exportedAtoms.begin(), _exportedAtoms.end(), AtomByNameSorter()); std::sort(_importedAtoms.begin(), _importedAtoms.end(), AtomByNameSorter()); + + std::map> addedSymbols; + std::map> hiddenSymbols; + for (const auto *atom : _exportedAtoms) { + // The exported symbols have already been sorted. Early exit the loop + // once we see a symbol that is lexicographically past the special + // linker symbol. + if (atom->name()[0] > '$') + break; + + std::string name(atom->name()); + if (name.rfind("$ld$add$", 7) == 0) { + auto pos = name.find_first_of('$', 10); + if (pos == std::string::npos) { + warning("bad special linker symbol '%s'", atom->name()); + continue; + } + auto &&symbolName = name.substr(pos+1); + auto it = addedSymbols.emplace(symbolName, std::initializer_list{name}); + if (!it.second) + it.first->second.emplace_back(name); + } else if (name.rfind("$ld$hide$", 8) == 0) { + auto pos = name.find_first_of('$', 11); + if (pos == std::string::npos) { + warning("bad special linker symbol '%s'", atom->name()); + continue; + } + auto &&symbolName = name.substr(pos+1); + auto it = hiddenSymbols.emplace(symbolName, std::initializer_list{name}); + if (!it.second) + it.first->second.emplace_back(name); + } + } + + for (const auto &it : addedSymbols) { + if (!std::binary_search(_exportedAtoms.begin(), _exportedAtoms.end(), it.first.c_str(), AtomByNameSorter())) + continue; + for (const auto &symbol : it.second) + warning("linker symbol '%s' adds already existing symbol '%s'", symbol.c_str(), it.first.c_str()); + } + + auto it = hiddenSymbols.begin(); + while (it != hiddenSymbols.end()) { + if (std::binary_search(_exportedAtoms.begin(), _exportedAtoms.end(), it->first.c_str(), AtomByNameSorter())) + it = hiddenSymbols.erase(it); + else + ++it; + } + + for (const auto &it : hiddenSymbols) { + for (const auto &symbol : it.second) { + // ok for umbrella to hide symbol that is in re-exported dylib + bool isReExported = false; + const char* symbolName = it.first.c_str(); + for (const ld::dylib::File* aDylib : _dylibsToLoad) { + if (aDylib->willBeReExported()) { + if ( aDylib->hasDefinition(symbolName) ) { + isReExported = true; + break; + } + } + } + if ( !isReExported ) + warning("linker symbol '%s' hides a non-existent symbol '%s'", symbol.c_str(), it.first.c_str()); + } + } } void OutputFile::addPreloadLinkEdit(ld::Internal& state) @@ -3090,6 +4049,10 @@ void OutputFile::addPreloadLinkEdit(ld::Internal& state) _externalRelocsAtom = new ExternalRelocationsAtom(_options, state, *this); externalRelocationsSection = state.addAtom(*_externalRelocsAtom); } + if ( _hasDataInCodeInfo ) { + _dataInCodeAtom = new DataInCodeAtom(_options, state, *this); + dataInCodeSection = state.addAtom(*_dataInCodeAtom); + } if ( _hasSymbolTable ) { _indirectSymbolTableAtom = new IndirectSymbolTableAtom(_options, state, *this); indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom); @@ -3110,6 +4073,10 @@ void OutputFile::addPreloadLinkEdit(ld::Internal& state) _externalRelocsAtom = new ExternalRelocationsAtom(_options, state, *this); externalRelocationsSection = state.addAtom(*_externalRelocsAtom); } + if ( _hasDataInCodeInfo ) { + _dataInCodeAtom = new DataInCodeAtom(_options, state, *this); + dataInCodeSection = state.addAtom(*_dataInCodeAtom); + } if ( _hasSymbolTable ) { _indirectSymbolTableAtom = new IndirectSymbolTableAtom(_options, state, *this); indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom); @@ -3130,6 +4097,10 @@ void OutputFile::addPreloadLinkEdit(ld::Internal& state) _externalRelocsAtom = new ExternalRelocationsAtom(_options, state, *this); externalRelocationsSection = state.addAtom(*_externalRelocsAtom); } + if ( _hasDataInCodeInfo ) { + _dataInCodeAtom = new DataInCodeAtom(_options, state, *this); + dataInCodeSection = state.addAtom(*_dataInCodeAtom); + } if ( _hasSymbolTable ) { _indirectSymbolTableAtom = new IndirectSymbolTableAtom(_options, state, *this); indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom); @@ -3150,6 +4121,10 @@ void OutputFile::addPreloadLinkEdit(ld::Internal& state) _externalRelocsAtom = new ExternalRelocationsAtom(_options, state, *this); externalRelocationsSection = state.addAtom(*_externalRelocsAtom); } + if ( _hasDataInCodeInfo ) { + _dataInCodeAtom = new DataInCodeAtom(_options, state, *this); + dataInCodeSection = state.addAtom(*_dataInCodeAtom); + } if ( _hasSymbolTable ) { _indirectSymbolTableAtom = new IndirectSymbolTableAtom(_options, state, *this); indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom); @@ -3180,6 +4155,14 @@ void OutputFile::addLinkEdit(ld::Internal& state) _sectionsRelocationsAtom = new SectionRelocationsAtom(_options, state, *this); sectionRelocationsSection = state.addAtom(*_sectionsRelocationsAtom); } + if ( _hasChainedFixups ) { + _chainedInfoAtom = new ChainedInfoAtom(_options, state, *this); + chainInfoSection = state.addAtom(*_chainedInfoAtom); + } + if ( _hasExportsTrie ) { + _exportInfoAtom = new ExportInfoAtom(_options, state, *this); + exportSection = state.addAtom(*_exportInfoAtom); + } if ( _hasDyldInfo ) { _rebasingInfoAtom = new RebaseInfoAtom(_options, state, *this); rebaseSection = state.addAtom(*_rebasingInfoAtom); @@ -3201,7 +4184,10 @@ void OutputFile::addLinkEdit(ld::Internal& state) localRelocationsSection = state.addAtom(*_localRelocsAtom); } if ( _hasSplitSegInfo ) { - _splitSegInfoAtom = new SplitSegInfoV1Atom(_options, state, *this); + if ( _options.sharedRegionEncodingV2() ) + _splitSegInfoAtom = new SplitSegInfoV2Atom(_options, state, *this); + else + _splitSegInfoAtom = new SplitSegInfoV1Atom(_options, state, *this); splitSegInfoSection = state.addAtom(*_splitSegInfoAtom); } if ( _hasFunctionStartsInfo ) { @@ -3238,6 +4224,14 @@ void OutputFile::addLinkEdit(ld::Internal& state) _sectionsRelocationsAtom = new SectionRelocationsAtom(_options, state, *this); sectionRelocationsSection = state.addAtom(*_sectionsRelocationsAtom); } + if ( _hasChainedFixups ) { + _chainedInfoAtom = new ChainedInfoAtom(_options, state, *this); + chainInfoSection = state.addAtom(*_chainedInfoAtom); + } + if ( _hasExportsTrie ) { + _exportInfoAtom = new ExportInfoAtom(_options, state, *this); + exportSection = state.addAtom(*_exportInfoAtom); + } if ( _hasDyldInfo ) { _rebasingInfoAtom = new RebaseInfoAtom(_options, state, *this); rebaseSection = state.addAtom(*_rebasingInfoAtom); @@ -3259,7 +4253,10 @@ void OutputFile::addLinkEdit(ld::Internal& state) localRelocationsSection = state.addAtom(*_localRelocsAtom); } if ( _hasSplitSegInfo ) { - _splitSegInfoAtom = new SplitSegInfoV1Atom(_options, state, *this); + if ( _options.sharedRegionEncodingV2() ) + _splitSegInfoAtom = new SplitSegInfoV2Atom(_options, state, *this); + else + _splitSegInfoAtom = new SplitSegInfoV1Atom(_options, state, *this); splitSegInfoSection = state.addAtom(*_splitSegInfoAtom); } if ( _hasFunctionStartsInfo ) { @@ -3296,6 +4293,14 @@ void OutputFile::addLinkEdit(ld::Internal& state) _sectionsRelocationsAtom = new SectionRelocationsAtom(_options, state, *this); sectionRelocationsSection = state.addAtom(*_sectionsRelocationsAtom); } + if ( _hasChainedFixups ) { + _chainedInfoAtom = new ChainedInfoAtom(_options, state, *this); + chainInfoSection = state.addAtom(*_chainedInfoAtom); + } + if ( _hasExportsTrie ) { + _exportInfoAtom = new ExportInfoAtom(_options, state, *this); + exportSection = state.addAtom(*_exportInfoAtom); + } if ( _hasDyldInfo ) { _rebasingInfoAtom = new RebaseInfoAtom(_options, state, *this); rebaseSection = state.addAtom(*_rebasingInfoAtom); @@ -3357,6 +4362,14 @@ void OutputFile::addLinkEdit(ld::Internal& state) _sectionsRelocationsAtom = new SectionRelocationsAtom(_options, state, *this); sectionRelocationsSection = state.addAtom(*_sectionsRelocationsAtom); } + if ( _hasChainedFixups ) { + _chainedInfoAtom = new ChainedInfoAtom(_options, state, *this); + chainInfoSection = state.addAtom(*_chainedInfoAtom); + } + if ( _hasExportsTrie ) { + _exportInfoAtom = new ExportInfoAtom(_options, state, *this); + exportSection = state.addAtom(*_exportInfoAtom); + } if ( _hasDyldInfo ) { _rebasingInfoAtom = new RebaseInfoAtom(_options, state, *this); rebaseSection = state.addAtom(*_rebasingInfoAtom); @@ -3473,9 +4486,11 @@ bool OutputFile::hasOrdinalForInstallPath(const char* path, int* ordinal) return false; } -uint32_t OutputFile::dylibToOrdinal(const ld::dylib::File* dylib) +uint32_t OutputFile::dylibToOrdinal(const ld::dylib::File* dylib) const { - return _dylibToOrdinal[dylib]; + auto it = _dylibToOrdinal.find(dylib); + assert(it != _dylibToOrdinal.end()); + return it->second; } @@ -3490,6 +4505,7 @@ void OutputFile::buildDylibOrdinalMapping(ld::Internal& state) } // look at each dylib supplied in state + __block std::unordered_map allReExports; bool hasReExports = false; bool haveLazyDylibs = false; for (std::vector::iterator it = state.dylibs.begin(); it != state.dylibs.end(); ++it) { @@ -3515,8 +4531,20 @@ void OutputFile::buildDylibOrdinalMapping(ld::Internal& state) _dylibsToLoad.push_back(aDylib); _dylibToOrdinal[aDylib] = _dylibsToLoad.size(); } - if ( aDylib->explicitlyLinked() && aDylib->willBeReExported() ) + if ( aDylib->explicitlyLinked() && aDylib->willBeReExported() ) { hasReExports = true; + aDylib->forEachExportedSymbol(^(const char* symbolName, bool weakDef) { + // don't warn about duplicate weak-def re-exports + if ( weakDef ) + return; + if ( allReExports.count(symbolName) ) { + warning("symbol '%s' re-exported from %s and %s", _options.demangleSymbol(symbolName), allReExports[symbolName]->leafName(), aDylib->leafName()); + } + else { + allReExports[symbolName] = aDylib; + } + }); + } } if ( haveLazyDylibs ) { // second pass to determine ordinals for lazy loaded dylibs @@ -3573,8 +4601,11 @@ int OutputFile::compressedOrdinalForAtom(const ld::Atom* target) } // handle undefined dynamic_lookup - if ( _options.undefinedTreatment() == Options::kUndefinedDynamicLookup ) + if ( _options.undefinedTreatment() == Options::kUndefinedDynamicLookup ) { + if ( _options.sharedRegionEligible() ) + throwf("-undefined dynamic_lookup cannot be used to find '%s' in dylib in dyld shared cache", target->name()); return BIND_SPECIAL_DYLIB_FLAT_LOOKUP; + } // handle -U _foo if ( _options.allowedUndefined(target->name()) ) @@ -3584,66 +4615,9 @@ int OutputFile::compressedOrdinalForAtom(const ld::Atom* target) } -bool OutputFile::isPcRelStore(ld::Fixup::Kind kind) +bool OutputFile::isPcRelStore(const ld::Fixup* fixup) { - switch ( kind ) { - case ld::Fixup::kindStoreX86BranchPCRel8: - case ld::Fixup::kindStoreX86BranchPCRel32: - case ld::Fixup::kindStoreX86PCRel8: - case ld::Fixup::kindStoreX86PCRel16: - case ld::Fixup::kindStoreX86PCRel32: - case ld::Fixup::kindStoreX86PCRel32_1: - case ld::Fixup::kindStoreX86PCRel32_2: - case ld::Fixup::kindStoreX86PCRel32_4: - case ld::Fixup::kindStoreX86PCRel32GOTLoad: - case ld::Fixup::kindStoreX86PCRel32GOTLoadNowLEA: - case ld::Fixup::kindStoreX86PCRel32GOT: - case ld::Fixup::kindStoreX86PCRel32TLVLoad: - case ld::Fixup::kindStoreX86PCRel32TLVLoadNowLEA: - case ld::Fixup::kindStoreARMBranch24: - case ld::Fixup::kindStoreThumbBranch22: - case ld::Fixup::kindStoreARMLoad12: - case ld::Fixup::kindStoreTargetAddressX86PCRel32: - case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad: - case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA: - case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad: - case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA: - case ld::Fixup::kindStoreTargetAddressARMBranch24: - case ld::Fixup::kindStoreTargetAddressThumbBranch22: - case ld::Fixup::kindStoreTargetAddressARMLoad12: -#if SUPPORT_ARCH_arm64 - case ld::Fixup::kindStoreARM64Page21: - case ld::Fixup::kindStoreARM64PageOff12: - case ld::Fixup::kindStoreARM64GOTLoadPage21: - case ld::Fixup::kindStoreARM64GOTLoadPageOff12: - case ld::Fixup::kindStoreARM64GOTLeaPage21: - case ld::Fixup::kindStoreARM64GOTLeaPageOff12: - case ld::Fixup::kindStoreARM64TLVPLoadPage21: - case ld::Fixup::kindStoreARM64TLVPLoadPageOff12: - case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPage21: - case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPageOff12: - case ld::Fixup::kindStoreARM64PCRelToGOT: - case ld::Fixup::kindStoreTargetAddressARM64Page21: - case ld::Fixup::kindStoreTargetAddressARM64PageOff12: - case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21: - case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12: - case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21: - case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12: - case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21: - case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12: - case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21: - case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12: -#endif - return true; - case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32: -#if SUPPORT_ARCH_arm64 - case ld::Fixup::kindStoreTargetAddressARM64Branch26: -#endif - return (_options.outputKind() != Options::kKextBundle); - default: - break; - } - return false; + return fixup->isPcRelStore(_options.outputKind() == Options::kKextBundle); } bool OutputFile::isStore(ld::Fixup::Kind kind) @@ -3661,6 +4635,9 @@ bool OutputFile::isStore(ld::Fixup::Kind kind) case ld::Fixup::kindSubtractAddend: case ld::Fixup::kindSetTargetImageOffset: case ld::Fixup::kindSetTargetSectionOffset: +#if SUPPORT_ARCH_arm64e + case ld::Fixup::kindSetAuthData: +#endif return false; default: break; @@ -3669,52 +4646,9 @@ bool OutputFile::isStore(ld::Fixup::Kind kind) } -bool OutputFile::setsTarget(ld::Fixup::Kind kind) +bool OutputFile::setsTarget(const ld::Fixup &fixup) { - switch ( kind ) { - case ld::Fixup::kindSetTargetAddress: - case ld::Fixup::kindLazyTarget: - case ld::Fixup::kindStoreTargetAddressLittleEndian32: - case ld::Fixup::kindStoreTargetAddressLittleEndian64: - case ld::Fixup::kindStoreTargetAddressBigEndian32: - case ld::Fixup::kindStoreTargetAddressBigEndian64: - case ld::Fixup::kindStoreTargetAddressX86PCRel32: - case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32: - case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad: - case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA: - case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad: - case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA: - case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoad: - case ld::Fixup::kindStoreTargetAddressARMBranch24: - case ld::Fixup::kindStoreTargetAddressThumbBranch22: - case ld::Fixup::kindStoreTargetAddressARMLoad12: -#if SUPPORT_ARCH_arm64 - case ld::Fixup::kindStoreTargetAddressARM64Branch26: - case ld::Fixup::kindStoreTargetAddressARM64Page21: - case ld::Fixup::kindStoreTargetAddressARM64PageOff12: - case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21: - case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12: - case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21: - case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12: - case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21: - case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12: - case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21: - case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12: -#endif - return true; - case ld::Fixup::kindStoreX86DtraceCallSiteNop: - case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear: - case ld::Fixup::kindStoreARMDtraceCallSiteNop: - case ld::Fixup::kindStoreARMDtraceIsEnableSiteClear: - case ld::Fixup::kindStoreARM64DtraceCallSiteNop: - case ld::Fixup::kindStoreARM64DtraceIsEnableSiteClear: - case ld::Fixup::kindStoreThumbDtraceCallSiteNop: - case ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear: - return (_options.outputKind() == Options::kObjectFile); - default: - break; - } - return false; + return fixup.setsTarget(_options.outputKind() == Options::kObjectFile); } bool OutputFile::isPointerToTarget(ld::Fixup::Kind kind) @@ -3723,6 +4657,9 @@ bool OutputFile::isPointerToTarget(ld::Fixup::Kind kind) case ld::Fixup::kindSetTargetAddress: case ld::Fixup::kindStoreTargetAddressLittleEndian32: case ld::Fixup::kindStoreTargetAddressLittleEndian64: +#if SUPPORT_ARCH_arm64e + case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64: +#endif case ld::Fixup::kindStoreTargetAddressBigEndian32: case ld::Fixup::kindStoreTargetAddressBigEndian64: case ld::Fixup::kindLazyTarget: @@ -3790,7 +4727,7 @@ void OutputFile::generateLinkEditInfo(ld::Internal& state) for (std::vector::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) { ld::Internal::FinalSection* sect = *sit; // record end of last __TEXT section encrypted iPhoneOS apps. - if ( _options.makeEncryptable() && (strcmp(sect->segmentName(), "__TEXT") == 0) ) { + if ( _options.makeEncryptable() && (strcmp(sect->segmentName(), "__TEXT") == 0) && (strcmp(sect->sectionName(), "__oslogstring") != 0) ) { _encryptedTEXTendOffset = pageAlign(sect->fileOffset + sect->size); } bool objc1ClassRefSection = ( (sect->type() == ld::Section::typeCStringPointer) @@ -3804,7 +4741,10 @@ void OutputFile::generateLinkEditInfo(ld::Internal& state) if ( _options.makeCompressedDyldInfo() ) { uint8_t wtype = BIND_TYPE_OVERRIDE_OF_WEAKDEF_IN_DYLIB; bool nonWeakDef = (atom->combine() == ld::Atom::combineNever); - _weakBindingInfo.push_back(BindingInfo(wtype, atom->name(), nonWeakDef, atom->finalAddress(), 0)); + // Don't push weak binding info for threaded bind. + // Instead we use a special ordinal in the regular bind info + if ( !_options.useLinkedListBinding() ) + _weakBindingInfo.push_back(BindingInfo(wtype, atom->name(), nonWeakDef, atom->finalAddress(), 0)); } this->overridesWeakExternalSymbols = true; if ( _options.warnWeakExports() ) @@ -3819,6 +4759,9 @@ void OutputFile::generateLinkEditInfo(ld::Internal& state) const ld::Atom* minusTarget = NULL; uint64_t targetAddend = 0; uint64_t minusTargetAddend = 0; +#if SUPPORT_ARCH_arm64e + ld::Fixup* fixupWithAuthData = NULL; +#endif for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) { if ( fit->firstInCluster() ) { fixupWithTarget = NULL; @@ -3828,8 +4771,11 @@ void OutputFile::generateLinkEditInfo(ld::Internal& state) minusTarget = NULL; targetAddend = 0; minusTargetAddend = 0; +#if SUPPORT_ARCH_arm64e + fixupWithAuthData = NULL; +#endif } - if ( this->setsTarget(fit->kind) ) { + if ( this->setsTarget(*fit) ) { switch ( fit->binding ) { case ld::Fixup::bindingNone: case ld::Fixup::bindingByNameUnbound: @@ -3880,22 +4826,50 @@ void OutputFile::generateLinkEditInfo(ld::Internal& state) case ld::Fixup::kindDataInCodeEnd: hasDataInCode = true; break; +#if SUPPORT_ARCH_arm64e + case ld::Fixup::kindSetAuthData: + fixupWithAuthData = fit; + break; +#endif default: break; } - if ( this->isStore(fit->kind) ) { + if ( fit->isStore() ) { fixupWithStore = fit; } if ( fit->lastInCluster() ) { if ( (fixupWithStore != NULL) && (target != NULL) ) { if ( _options.outputKind() == Options::kObjectFile ) { this->addSectionRelocs(state, sect, atom, fixupWithTarget, fixupWithMinusTarget, fixupWithAddend, fixupWithStore, +#if SUPPORT_ARCH_arm64e + fixupWithAuthData, +#endif target, minusTarget, targetAddend, minusTargetAddend); } else { - if ( _options.makeCompressedDyldInfo() ) { + if ( _options.makeChainedFixups() ) { + addChainedFixupLocation(state, sect, atom, fixupWithTarget, fixupWithMinusTarget, fixupWithStore, + target, minusTarget, targetAddend, minusTargetAddend); + } + else if ( _options.makeCompressedDyldInfo() ) { +#if SUPPORT_ARCH_arm64e + if ( _options.sharedRegionEligible() && (fixupWithAuthData != NULL) ) { + switch ( fixupWithAuthData->u.authData.key ) { + case ld::Fixup::AuthData::ptrauth_key_asib: + case ld::Fixup::AuthData::ptrauth_key_asdb: + throwf("dylibs for dyld cache cannot use B key of auth-pointer, found in %s", atom->name()); + case ld::Fixup::AuthData::ptrauth_key_asia: + case ld::Fixup::AuthData::ptrauth_key_asda: + break; + } + } +#endif this->addDyldInfo(state, sect, atom, fixupWithTarget, fixupWithMinusTarget, fixupWithStore, - target, minusTarget, targetAddend, minusTargetAddend); + target, minusTarget, targetAddend, minusTargetAddend); + } + else if ( _options.makeThreadedStartsSection() ) { + this->addThreadedRebaseInfo(state, sect, atom, fixupWithTarget, fixupWithMinusTarget, fixupWithStore, + target, minusTarget, targetAddend, minusTargetAddend); } else { this->addClassicRelocs(state, sect, atom, fixupWithTarget, fixupWithMinusTarget, fixupWithStore, @@ -3915,6 +4889,190 @@ void OutputFile::generateLinkEditInfo(ld::Internal& state) } } +bool OutputFile::isFixupForChain(ld::Fixup::iterator fit) +{ + switch (fit->kind) { + case ld::Fixup::kindStoreLittleEndian64: + case ld::Fixup::kindStoreTargetAddressLittleEndian64: + return true; + default: + break; + } + return false; +} + +uint16_t OutputFile::chainedPointerFormat() const +{ +#if SUPPORT_ARCH_arm64e + if ( _options.architecture() == CPU_TYPE_ARM64 && _options.subArchitecture() == CPU_SUBTYPE_ARM64E ) + return DYLD_CHAINED_PTR_ARM64E; +#endif + if ( _options.architecture() & CPU_ARCH_ABI64) + return DYLD_CHAINED_PTR_64; + else if ( _options.dyldLoadsOutput() ) + return DYLD_CHAINED_PTR_32; + else + return DYLD_CHAINED_PTR_32_FIRMWARE; +} + +void OutputFile::buildChainedFixupInfo(ld::Internal& state) +{ + if ( !_options.makeChainedFixups() ) + return; + + // build table of segments, fixup locations, and symbol targets + const uint32_t pageSize = _options.segmentAlignment(); + const char* curSegName = ""; + const ld::Internal::FinalSection* firstSegSect = nullptr; + const ld::Internal::FinalSection* lastSect = nullptr; + for (ld::Internal::FinalSection* sect : state.sections) { + if ( strcmp(sect->segmentName(), curSegName) != 0 ) { + if ( firstSegSect != nullptr ) { + uint64_t segSize = pageAlign(lastSect->address + lastSect->size - firstSegSect->address); + _chainedFixupSegments.back().endAddr = _chainedFixupSegments.back().startAddr + segSize; + } + curSegName = sect->segmentName(); + firstSegSect = sect; + ChainedFixupSegInfo seg; + seg.name = curSegName; + seg.startAddr = sect->address; + seg.endAddr = 0; // updated when next segment found + seg.fileOffset = sect->fileOffset; + seg.pageSize = pageSize; + seg.pointerFormat = chainedPointerFormat(); + _chainedFixupSegments.push_back(seg); + } + for (const ld::Atom* atom : sect->atoms) { + const ld::Atom* target; + const ld::Atom* fromTarget; + bool hadSubtract; + uint64_t accumulator; + bool isBind = false; + for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) { + if ( fit->firstInCluster() ) { + accumulator = 0; + target = NULL; + hadSubtract = false; + isBind = false; + } + if ( this->setsTarget(*fit) ) { + switch ( fit->binding ) { + case ld::Fixup::bindingNone: + case ld::Fixup::bindingByNameUnbound: + break; + case ld::Fixup::bindingByContentBound: + case ld::Fixup::bindingDirectlyBound: + target = fit->u.target; + break; + case ld::Fixup::bindingsIndirectlyBound: + target = state.indirectBindingTable[fit->u.bindingIndex]; + break; + } + assert(target != NULL); + } + switch ( fit->kind ) { + case ld::Fixup::kindSetTargetAddress: + accumulator = addressOf(state, fit, &target); + if ( targetIsThumb(state, fit) ) + accumulator |= 1; + if ( fit->contentAddendOnly || fit->contentDetlaToAddendOnly ) + accumulator = 0; + break; + case ld::Fixup::kindSubtractTargetAddress: + accumulator -= addressOf(state, fit, &fromTarget); + hadSubtract = true; + break; + case ld::Fixup::kindAddAddend: + accumulator += fit->u.addend; + break; + case ld::Fixup::kindSubtractAddend: + accumulator -= fit->u.addend; + break; + case ld::Fixup::kindSetTargetImageOffset: + hadSubtract = true; + break; + case ld::Fixup::kindStoreLittleEndian32: + case ld::Fixup::kindStoreLittleEndian64: + isBind = true; + break; + case ld::Fixup::kindStoreTargetAddressLittleEndian32: + accumulator = addressOf(state, fit, &target); + if ( targetIsThumb(state, fit) ) + accumulator |= 1; + if ( fit->contentAddendOnly ) + accumulator = 0; + isBind = true; + break; + case ld::Fixup::kindStoreTargetAddressLittleEndian64: + accumulator = addressOf(state, fit, &target); + if ( fit->contentAddendOnly ) + accumulator = 0; + isBind = true; + break; +#if SUPPORT_ARCH_arm64e + case ld::Fixup::kindStoreLittleEndianAuth64: + if ( fit->contentAddendOnly ) { + // ld -r mode. We want to write out the original relocation again + break; + } + if (_options.outputKind() == Options::kKextBundle ) { + // kexts dont' handle auth pointers, write unauth pointer + break; + } + isBind = true; + break; + case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64: + if (_options.outputKind() == Options::kKextBundle ) { + // kexts dont' handle auth pointers, write unauth pointer + break; + } + accumulator = addressOf(state, fit, &target); + if ( fit->contentAddendOnly ) + accumulator = 0; + isBind = true; + break; +#endif + default: + break; + } + if ( fit->lastInCluster() && isBind ) { + // this is an absolute pointer which means it needs to be in fixup chain + if ( (target != NULL) && !hadSubtract ) { + uint64_t fixUpAddr = atom->finalAddress() + fit->offsetInAtom; + //fprintf(stderr, "fixUpAddr=0x%0llX\n",fixUpAddr); + unsigned pageIndex = (fixUpAddr - _chainedFixupSegments.back().startAddr)/pageSize; + while ( pageIndex >= _chainedFixupSegments.back().pages.size() ) { + ChainedFixupPageInfo emptyPage; + _chainedFixupSegments.back().pages.push_back(emptyPage); + } + uint16_t pageOffset = fixUpAddr - (_chainedFixupSegments.back().startAddr + pageIndex*pageSize); + _chainedFixupSegments.back().pages[pageIndex].fixupOffsets.push_back(pageOffset); + // build map for binds + if ( needsBind(target, &accumulator) ) + _chainedFixupBinds.ensureTarget(target, accumulator); + } + } + } + } + lastSect = sect; + } + // sort all fixups on each page, so chain can be built + for (ChainedFixupSegInfo& segInfo : _chainedFixupSegments) { + for (ChainedFixupPageInfo& pageInfo : segInfo.pages) { + std::sort(pageInfo.fixupOffsets.begin(), pageInfo.fixupOffsets.end()); + } + } + // remember largest legal rebase target + uint64_t baseAddress = 0; + uint64_t maxRebaseAddress = 0; + for (OutputFile::ChainedFixupSegInfo& segInfo : _chainedFixupSegments) { + if ( strcmp(segInfo.name, "__TEXT") == 0 ) + baseAddress = segInfo.startAddr; + else if ( strcmp(segInfo.name, "__LINKEDIT") == 0 ) + maxRebaseAddress = (segInfo.startAddr - baseAddress + 0x00100000-1) & -0x00100000; // align to 1MB + } + _chainedFixupBinds.setMaxRebase(maxRebaseAddress); +} void OutputFile::noteTextReloc(const ld::Atom* atom, const ld::Atom* target) { @@ -3926,30 +5084,33 @@ void OutputFile::noteTextReloc(const ld::Atom* atom, const ld::Atom* target) warning("text reloc in %s to %s", atom->name(), target->name()); } else if ( _options.positionIndependentExecutable() && (_options.outputKind() == Options::kDynamicExecutable) - && ((_options.iOSVersionMin() >= ld::iOS_4_3) || (_options.macosxVersionMin() >= ld::mac10_7)) ) { + && _options.platforms().minOS(ld::version2010Fall)) { if ( ! this->pieDisabled ) { + switch ( _options.architecture()) { #if SUPPORT_ARCH_arm64 - if ( _options.architecture() == CPU_TYPE_ARM64 ) { + case CPU_TYPE_ARM64: +#endif +#if SUPPORT_ARCH_arm64 + { const char* demangledName = strdup(_options.demangleSymbol(atom->name())); throwf("Absolute addressing not allowed in arm64 code but used in '%s' referencing '%s'", demangledName, _options.demangleSymbol(target->name())); } - else #endif - { + default: warning("PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in code signed PIE, " "but used in %s from %s. " "To fix this warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie", - atom->name(), atom->file()->path()); + atom->name(), atom->safeFilePath()); } } this->pieDisabled = true; } else if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName) ) { - throwf("illegal text-relocoation (direct reference) to (global,weak) %s in %s from %s in %s", target->name(), target->file()->path(), atom->name(), atom->file()->path()); + throwf("illegal text-relocoation (direct reference) to (global,weak) %s in %s from %s in %s", target->name(), target->safeFilePath(), atom->name(), atom->safeFilePath()); } else { if ( (target->file() != NULL) && (atom->file() != NULL) ) - throwf("illegal text-relocation to '%s' in %s from '%s' in %s", target->name(), target->file()->path(), atom->name(), atom->file()->path()); + throwf("illegal text-relocation to '%s' in %s from '%s' in %s", target->name(), target->safeFilePath(), atom->name(), atom->safeFilePath()); else throwf("illegal text reloc in '%s' to '%s'", atom->name(), target->name()); } @@ -3964,7 +5125,7 @@ void OutputFile::addDyldInfo(ld::Internal& state, ld::Internal::FinalSection* s return; // no need to rebase or bind PCRel stores - if ( this->isPcRelStore(fixupWithStore->kind) ) { + if ( this->isPcRelStore(fixupWithStore) ) { // as long as target is in same linkage unit if ( (target == NULL) || (target->definition() != ld::Atom::definitionProxy) ) { // make sure target is not global and weak @@ -3982,9 +5143,18 @@ void OutputFile::addDyldInfo(ld::Internal& state, ld::Internal::FinalSection* s } // Have direct reference to weak-global. This should be an indrect reference const char* demangledName = strdup(_options.demangleSymbol(atom->name())); - warning("direct access in %s to global weak symbol %s means the weak symbol cannot be overridden at runtime. " + // ld64-port: [OSXCROSS] Silence 'operator new[]' warning when linking GCC libsdtc++ statically + const char* fileName = strrchr(target->safeFilePath(), '/'); + if ( !fileName ) + fileName = target->safeFilePath(); + else + fileName++; // '/' + if ( !getenv("OSXCROSS_GCC_LIBSTDCXX") || strncmp(atom->name(), "__Zna", 5) || strcmp(fileName, "libstdc++.a(new_opvnt.o)") ) { + // ld64-port end + warning("direct access in function '%s' from file '%s' to global weak symbol '%s' from file '%s' means the weak symbol cannot be overridden at runtime. " "This was likely caused by different translation units being compiled with different visibility settings.", - demangledName, _options.demangleSymbol(target->name())); + demangledName, atom->safeFilePath(), _options.demangleSymbol(target->name()), target->safeFilePath()); + } // ld64-port } return; } @@ -4011,9 +5181,9 @@ void OutputFile::addDyldInfo(ld::Internal& state, ld::Internal::FinalSection* s } // Have direct reference to weak-global. This should be an indrect reference const char* demangledName = strdup(_options.demangleSymbol(atom->name())); - warning("direct access in %s to global weak symbol %s means the weak symbol cannot be overridden at runtime. " + warning("direct access in function '%s' from file '%s' to global weak symbol '%s' from file '%s' means the weak symbol cannot be overridden at runtime. " "This was likely caused by different translation units being compiled with different visibility settings.", - demangledName, _options.demangleSymbol(target->name())); + demangledName, atom->safeFilePath(), _options.demangleSymbol(target->name()), target->safeFilePath()); } return; } @@ -4026,6 +5196,7 @@ void OutputFile::addDyldInfo(ld::Internal& state, ld::Internal::FinalSection* s if ( target == NULL ) return; + const uint64_t pointerSize = (_options.architecture() & CPU_ARCH_ABI64) ? 8 : 4; bool inReadOnlySeg = ((_options.initialSegProtection(sect->segmentName()) & VM_PROT_WRITE) == 0); bool needsRebase = false; bool needsBinding = false; @@ -4142,7 +5313,21 @@ void OutputFile::addDyldInfo(ld::Internal& state, ld::Internal::FinalSection* s } } } - } + } + + // Find the ordinal for the bind target + int compressedOrdinal = 0; + if ( needsBinding || needsLazyBinding || needsWeakBinding ) { + compressedOrdinal = this->compressedOrdinalForAtom(target); + } + // Linked list binding puts the weak binds in to the regular binds but with a special ordinal. + if ( needsWeakBinding && _options.useLinkedListBinding() ) { + assert(!needsLazyBinding); + needsWeakBinding = false; + needsBinding = true; + needsRebase = false; + compressedOrdinal = BIND_SPECIAL_DYLIB_WEAK_LOOKUP; + } // record dyld info for this cluster if ( needsRebase ) { @@ -4154,7 +5339,8 @@ void OutputFile::addDyldInfo(ld::Internal& state, ld::Internal::FinalSection* s if ( _options.sharedRegionEligible() ) { // when range checking, ignore high byte of arm64 addends uint64_t checkAddend = addend; - if ( _options.architecture() == CPU_TYPE_ARM64 ) + if ( (_options.architecture() == CPU_TYPE_ARM64) + ) checkAddend &= 0x0FFFFFFFFFFFFFFFULL; if ( checkAddend != 0 ) { // make sure the addend does not cause the pointer to point outside the target's segment @@ -4167,32 +5353,238 @@ void OutputFile::addDyldInfo(ld::Internal& state, ld::Internal::FinalSection* s if ( (targetAddress+checkAddend) > sctEnd ) { warning("data symbol %s from %s has pointer to %s + 0x%08llX. " "That large of an addend may disable %s from being put in the dyld shared cache.", - atom->name(), atom->file()->path(), target->name(), addend, _options.installPath() ); + atom->name(), atom->safeFilePath(), target->name(), addend, _options.installPath() ); } } } } } + if ( ((address & (pointerSize-1)) != 0) && (rebaseType == REBASE_TYPE_POINTER) ) { + switch ( _options.unalignedPointerTreatment() ) { + case Options::kUnalignedPointerError: + throwf("pointer not aligned at address 0x%llX (%s + %lld from %s)", + address, atom->name(), (address - atom->finalAddress()), atom->safeFilePath()); + break; + case Options::kUnalignedPointerWarning: + warning("pointer not aligned at address 0x%llX (%s + %lld from %s)", + address, atom->name(), (address - atom->finalAddress()), atom->safeFilePath()); + break; + case Options::kUnalignedPointerIgnore: + // do nothing + break; + } + _hasUnalignedFixup = true; + } _rebaseInfo.push_back(RebaseInfo(rebaseType, address)); } + if ( needsBinding ) { if ( inReadOnlySeg ) { noteTextReloc(atom, target); sect->hasExternalRelocs = true; // so dyld knows to change permissions on __TEXT segment } - _bindingInfo.push_back(BindingInfo(type, this->compressedOrdinalForAtom(target), target->name(), weak_import, address, addend)); + if ( ((address & (pointerSize-1)) != 0) && (type == BIND_TYPE_POINTER) ) { + switch ( _options.unalignedPointerTreatment() ) { + case Options::kUnalignedPointerError: + throwf("pointer not aligned at address 0x%llX (%s + %lld from %s)", + address, atom->name(), (address - atom->finalAddress()), atom->safeFilePath()); + break; + case Options::kUnalignedPointerWarning: + warning("pointer not aligned at address 0x%llX (%s + %lld from %s)", + address, atom->name(), (address - atom->finalAddress()), atom->safeFilePath()); + break; + case Options::kUnalignedPointerIgnore: + // do nothing + break; + } + _hasUnalignedFixup = true; + } + _bindingInfo.push_back(BindingInfo(type, compressedOrdinal, target->name(), weak_import, address, addend)); } if ( needsLazyBinding ) { if ( _options.bindAtLoad() ) - _bindingInfo.push_back(BindingInfo(type, this->compressedOrdinalForAtom(target), target->name(), weak_import, address, addend)); + _bindingInfo.push_back(BindingInfo(type, compressedOrdinal, target->name(), weak_import, address, addend)); else - _lazyBindingInfo.push_back(BindingInfo(type, this->compressedOrdinalForAtom(target), target->name(), weak_import, address, addend)); + _lazyBindingInfo.push_back(BindingInfo(type, compressedOrdinal, target->name(), weak_import, address, addend)); } if ( needsWeakBinding ) _weakBindingInfo.push_back(BindingInfo(type, 0, target->name(), false, address, addend)); } +void OutputFile::addChainedFixupLocation(ld::Internal& state, ld::Internal::FinalSection* sect, + const ld::Atom* atom, ld::Fixup* fixupWithTarget, + ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore, + const ld::Atom* target, const ld::Atom* minusTarget, + uint64_t targetAddend, uint64_t minusTargetAddend) +{ + if ( sect->isSectionHidden() ) + return; + + // no need to rebase or bind PCRel stores + if ( this->isPcRelStore(fixupWithStore) ) { + // as long as target is in same linkage unit + if ( (target == NULL) || (target->definition() != ld::Atom::definitionProxy) ) { + // make sure target is not global and weak + if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName) && (target->definition() == ld::Atom::definitionRegular)) { + if ( (atom->section().type() == ld::Section::typeCFI) + || (atom->section().type() == ld::Section::typeDtraceDOF) + || (atom->section().type() == ld::Section::typeUnwindInfo) ) { + // ok for __eh_frame and __uwind_info to use pointer diffs to global weak symbols + return; + } + // spurious warning when weak function has reference to itself + if ( fixupWithTarget->binding == ld::Fixup::bindingDirectlyBound ) { + // ok to ignore pc-rel references within a weak function to itself + return; + } + // Have direct reference to weak-global. This should be an indrect reference + const char* demangledName = strdup(_options.demangleSymbol(atom->name())); + warning("direct access in function '%s' from file '%s' to global weak symbol '%s' from file '%s' means the weak symbol cannot be overridden at runtime. " + "This was likely caused by different translation units being compiled with different visibility settings.", + demangledName, atom->safeFilePath(), _options.demangleSymbol(target->name()), target->safeFilePath()); + } + return; + } + } + + // no need to rebase or bind PIC internal pointer diff + if ( minusTarget != NULL ) { + // with pointer diffs, both need to be in same linkage unit + assert(minusTarget->definition() != ld::Atom::definitionProxy); + assert(target != NULL); + assert(target->definition() != ld::Atom::definitionProxy); + if ( target == minusTarget ) { + // This is a compile time constant and could have been optimized away by compiler + return; + } + + // check if target of pointer-diff is global and weak + if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName) && (target->definition() == ld::Atom::definitionRegular) ) { + if ( (atom->section().type() == ld::Section::typeCFI) + || (atom->section().type() == ld::Section::typeDtraceDOF) + || (atom->section().type() == ld::Section::typeUnwindInfo) ) { + // ok for __eh_frame and __uwind_info to use pointer diffs to global weak symbols + return; + } + // Have direct reference to weak-global. This should be an indrect reference + const char* demangledName = strdup(_options.demangleSymbol(atom->name())); + warning("direct access in function '%s' from file '%s' to global weak symbol '%s' from file '%s' means the weak symbol cannot be overridden at runtime. " + "This was likely caused by different translation units being compiled with different visibility settings.", + demangledName, atom->safeFilePath(), _options.demangleSymbol(target->name()), target->safeFilePath()); + } + return; + } + + //bool isRebase = ( target->definition() != ld::Atom::definitionProxy ); + //fprintf(stderr, "chain: in %s/%s %d %s\n", sect->segmentName(), sect->sectionName(), isRebase, atom->name()); +} + +void OutputFile::addThreadedRebaseInfo(ld::Internal& state, ld::Internal::FinalSection* sect, const ld::Atom* atom, + ld::Fixup* fixupWithTarget, ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore, + const ld::Atom* target, const ld::Atom* minusTarget, + uint64_t targetAddend, uint64_t minusTargetAddend) +{ + if ( sect->isSectionHidden() ) + return; + + // no need to rebase or bind PCRel stores + if ( this->isPcRelStore(fixupWithStore) ) { + // as long as target is in same linkage unit + if ( (target == NULL) || (target->definition() != ld::Atom::definitionProxy) ) { + // make sure target is not global and weak + if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName) && (target->definition() == ld::Atom::definitionRegular)) { + if ( (atom->section().type() == ld::Section::typeCFI) + || (atom->section().type() == ld::Section::typeDtraceDOF) + || (atom->section().type() == ld::Section::typeUnwindInfo) ) { + // ok for __eh_frame and __uwind_info to use pointer diffs to global weak symbols + return; + } + // spurious warning when weak function has reference to itself + if ( fixupWithTarget->binding == ld::Fixup::bindingDirectlyBound ) { + // ok to ignore pc-rel references within a weak function to itself + return; + } + // Have direct reference to weak-global. This should be an indrect reference + const char* demangledName = strdup(_options.demangleSymbol(atom->name())); + warning("direct access in function '%s' from file '%s' to global weak symbol '%s' from file '%s' means the weak symbol cannot be overridden at runtime. " + "This was likely caused by different translation units being compiled with different visibility settings.", + demangledName, atom->safeFilePath(), _options.demangleSymbol(target->name()), target->safeFilePath()); + } + return; + } + } + + // no need to rebase or bind PIC internal pointer diff + if ( minusTarget != NULL ) { + // with pointer diffs, both need to be in same linkage unit + assert(minusTarget->definition() != ld::Atom::definitionProxy); + assert(target != NULL); + assert(target->definition() != ld::Atom::definitionProxy); + if ( target == minusTarget ) { + // This is a compile time constant and could have been optimized away by compiler + return; + } + + // check if target of pointer-diff is global and weak + if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName) && (target->definition() == ld::Atom::definitionRegular) ) { + if ( (atom->section().type() == ld::Section::typeCFI) + || (atom->section().type() == ld::Section::typeDtraceDOF) + || (atom->section().type() == ld::Section::typeUnwindInfo) ) { + // ok for __eh_frame and __uwind_info to use pointer diffs to global weak symbols + return; + } + // Have direct reference to weak-global. This should be an indrect reference + const char* demangledName = strdup(_options.demangleSymbol(atom->name())); + warning("direct access in function '%s' from file '%s' to global weak symbol '%s' from file '%s' means the weak symbol cannot be overridden at runtime. " + "This was likely caused by different translation units being compiled with different visibility settings.", + demangledName, atom->safeFilePath(), _options.demangleSymbol(target->name()), target->safeFilePath()); + } + return; + } + + // no need to rebase or bind an atom's references to itself if the output is not slidable + if ( (atom == target) && !_options.outputSlidable() ) + return; + + // cluster has no target, so needs no rebasing or binding + if ( target == NULL ) + return; + + const uint64_t minAlignment = 4; + bool inReadOnlySeg = ( strcmp(sect->segmentName(), "__TEXT") == 0 ); + bool needsRebase = false; + + uint8_t rebaseType = REBASE_TYPE_POINTER; + uint64_t address = atom->finalAddress() + fixupWithTarget->offsetInAtom; + + // special case lazy pointers + switch ( target->definition() ) { + case ld::Atom::definitionProxy: + break; + case ld::Atom::definitionRegular: + case ld::Atom::definitionTentative: + needsRebase = true; + break; + case ld::Atom::definitionAbsolute: + break; + } + + // record dyld info for this cluster + if ( needsRebase ) { + if ( inReadOnlySeg ) { + noteTextReloc(atom, target); + sect->hasLocalRelocs = true; // so dyld knows to change permissions on __TEXT segment + } + if ( ((address & (minAlignment-1)) != 0) ) { + throwf("pointer not aligned to at least 4-bytes at address 0x%llX (%s + %lld from %s)", + address, atom->name(), (address - atom->finalAddress()), atom->safeFilePath()); + } + _rebaseInfo.push_back(RebaseInfo(rebaseType, address)); + } +} + + void OutputFile::addClassicRelocs(ld::Internal& state, ld::Internal::FinalSection* sect, const ld::Atom* atom, ld::Fixup* fixupWithTarget, ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore, const ld::Atom* target, const ld::Atom* minusTarget, @@ -4219,7 +5611,7 @@ void OutputFile::addClassicRelocs(ld::Internal& state, ld::Internal::FinalSectio } // no need to rebase or bind PCRel stores - if ( this->isPcRelStore(fixupWithStore->kind) ) { + if ( this->isPcRelStore(fixupWithStore) ) { // as long as target is in same linkage unit if ( (target == NULL) || (target->definition() != ld::Atom::definitionProxy) ) return; @@ -4231,14 +5623,19 @@ void OutputFile::addClassicRelocs(ld::Internal& state, ld::Internal::FinalSectio assert(minusTarget->definition() != ld::Atom::definitionProxy); assert(target != NULL); assert(target->definition() != ld::Atom::definitionProxy); - // make sure target is not global and weak - if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName) - && (atom->section().type() != ld::Section::typeCFI) - && (atom->section().type() != ld::Section::typeDtraceDOF) - && (atom->section().type() != ld::Section::typeUnwindInfo) - && (minusTarget != target) ) { - // ok for __eh_frame and __uwind_info to use pointer diffs to global weak symbols - throwf("bad codegen, pointer diff in %s to global weak symbol %s", atom->name(), target->name()); + // check if target of pointer-diff is global and weak + if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName) && (target->definition() == ld::Atom::definitionRegular) ) { + if ( (atom->section().type() == ld::Section::typeCFI) + || (atom->section().type() == ld::Section::typeDtraceDOF) + || (atom->section().type() == ld::Section::typeUnwindInfo) ) { + // ok for __eh_frame and __uwind_info to use pointer diffs to global weak symbols + return; + } + // Have direct reference to weak-global. This should be an indrect reference + const char* demangledName = strdup(_options.demangleSymbol(atom->name())); + warning("direct access in function '%s' from file '%s' to global weak symbol '%s' from file '%s' means the weak symbol cannot be overridden at runtime. " + "This was likely caused by different translation units being compiled with different visibility settings.", + demangledName, atom->safeFilePath(), _options.demangleSymbol(target->name()), target->safeFilePath()); } return; } @@ -4264,6 +5661,9 @@ void OutputFile::addClassicRelocs(ld::Internal& state, ld::Internal::FinalSectio case ld::Fixup::kindStoreBigEndian64: case ld::Fixup::kindStoreTargetAddressLittleEndian32: case ld::Fixup::kindStoreTargetAddressLittleEndian64: +#if SUPPORT_ARCH_arm64e + case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64: +#endif case ld::Fixup::kindStoreTargetAddressBigEndian32: case ld::Fixup::kindStoreTargetAddressBigEndian64: // is pointer @@ -4344,16 +5744,34 @@ void OutputFile::addClassicRelocs(ld::Internal& state, ld::Internal::FinalSectio case ld::Fixup::kindStoreThumbLow16: // no way to encode rebasing of binding for these instructions if ( _options.outputSlidable() || (target->definition() == ld::Atom::definitionProxy) ) - throwf("no supported runtime lo16 relocation in %s from %s to %s", atom->name(), atom->file()->path(), target->name()); + throwf("no supported runtime lo16 relocation in %s from %s to %s", atom->name(), atom->safeFilePath(), target->name()); break; case ld::Fixup::kindStoreARMHigh16: case ld::Fixup::kindStoreThumbHigh16: // no way to encode rebasing of binding for these instructions if ( _options.outputSlidable() || (target->definition() == ld::Atom::definitionProxy) ) - throwf("no supported runtime hi16 relocation in %s from %s to %s", atom->name(), atom->file()->path(), target->name()); + throwf("no supported runtime hi16 relocation in %s from %s to %s", atom->name(), atom->safeFilePath(), target->name()); break; +#if SUPPORT_ARCH_arm64e + case ld::Fixup::kindStoreLittleEndianAuth64: + if ( _options.outputKind() == Options::kKextBundle ) { + if ( target->definition() == ld::Atom::definitionProxy ) { + _externalRelocsAtom->addExternalPointerReloc(relocAddress, target); + sect->hasExternalRelocs = true; + fixupWithTarget->contentAddendOnly = true; + } + else { + _localRelocsAtom->addPointerReloc(relocAddress, target->machoSection()); + sect->hasLocalRelocs = true; + } + } + else { + throwf("authenticated pointer in atom %s from %s to %s is not supported", atom->name(), atom->safeFilePath(), target->name()); + } + break; +#endif default: break; } @@ -4362,7 +5780,9 @@ void OutputFile::addClassicRelocs(ld::Internal& state, ld::Internal::FinalSectio bool OutputFile::useExternalSectionReloc(const ld::Atom* atom, const ld::Atom* target, ld::Fixup* fixupWithTarget) { - if ( (_options.architecture() == CPU_TYPE_X86_64) || (_options.architecture() == CPU_TYPE_ARM64) ) { + if ( (_options.architecture() == CPU_TYPE_X86_64) + || (_options.architecture() == CPU_TYPE_ARM64) + ) { // x86_64 and ARM64 use external relocations for everthing that has a symbol return ( target->symbolTableInclusion() != ld::Atom::symbolTableNotIn ); } @@ -4423,7 +5843,10 @@ bool OutputFile::useSectionRelocAddend(ld::Fixup* fixupWithTarget) void OutputFile::addSectionRelocs(ld::Internal& state, ld::Internal::FinalSection* sect, const ld::Atom* atom, ld::Fixup* fixupWithTarget, ld::Fixup* fixupWithMinusTarget, - ld::Fixup* fixupWithAddend, ld::Fixup* fixupWithStore, + ld::Fixup* fixupWithAddend, ld::Fixup* fixupWithStore, +#if SUPPORT_ARCH_arm64e + ld::Fixup* fixupWithAuthData, +#endif const ld::Atom* target, const ld::Atom* minusTarget, uint64_t targetAddend, uint64_t minusTargetAddend) { @@ -4448,7 +5871,9 @@ void OutputFile::addSectionRelocs(ld::Internal& state, ld::Internal::FinalSectio bool minusTargetUsesExternalReloc = (minusTarget != NULL) && this->useExternalSectionReloc(atom, minusTarget, fixupWithMinusTarget); // in x86_64 and arm64 .o files an external reloc means the content contains just the addend - if ( (_options.architecture() == CPU_TYPE_X86_64) ||(_options.architecture() == CPU_TYPE_ARM64) ) { + if ( (_options.architecture() == CPU_TYPE_X86_64) + || (_options.architecture() == CPU_TYPE_ARM64) + ) { if ( targetUsesExternalReloc ) { fixupWithTarget->contentAddendOnly = true; fixupWithStore->contentAddendOnly = true; @@ -4471,7 +5896,7 @@ void OutputFile::addSectionRelocs(ld::Internal& state, ld::Internal::FinalSectio fixupWithTarget->contentAddendOnly = true; fixupWithStore->contentAddendOnly = true; } - else if ( isPcRelStore(fixupWithStore->kind) ) { + else if ( isPcRelStore(fixupWithStore) ) { fixupWithTarget->contentDetlaToAddendOnly = true; fixupWithStore->contentDetlaToAddendOnly = true; } @@ -4485,6 +5910,9 @@ void OutputFile::addSectionRelocs(ld::Internal& state, ld::Internal::FinalSectio if ( fixupWithStore != NULL ) { _sectionsRelocationsAtom->addSectionReloc(sect, fixupWithStore->kind, atom, fixupWithStore->offsetInAtom, targetUsesExternalReloc, minusTargetUsesExternalReloc, +#if SUPPORT_ARCH_arm64e + fixupWithAuthData, +#endif target, targetAddend, minusTarget, minusTargetAddend); } @@ -4499,6 +5927,8 @@ void OutputFile::makeSplitSegInfo(ld::Internal& state) ld::Internal::FinalSection* sect = *sit; if ( sect->isSectionHidden() ) continue; + if ( (_options.outputKind() == Options::kDynamicLibrary) && (strcmp(sect->sectionName(), "__interpose") == 0) && (strncmp(sect->segmentName(),"__DATA",6) == 0) ) + warning("__interpose sections cannot be used in dylibs put in the dyld cache"); if ( strcmp(sect->segmentName(), "__TEXT") != 0 ) continue; for (std::vector::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) { @@ -4511,8 +5941,8 @@ void OutputFile::makeSplitSegInfo(ld::Internal& state) for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) { if ( fit->firstInCluster() ) target = NULL; - if ( this->setsTarget(fit->kind) ) { - accumulator = addressOf(state, fit, &target); + if ( this->setsTarget(*fit) ) { + accumulator = addressOf(state, fit, &target); thumbTarget = targetIsThumb(state, fit); if ( thumbTarget ) accumulator |= 1; @@ -4582,10 +6012,17 @@ void OutputFile::makeSplitSegInfo(ld::Internal& state) } break; case ld::Fixup::kindSetTargetImageOffset: - accumulator = addressOf(state, fit, &target); + accumulator = addressOf(state, fit, &target); assert(target != NULL); hadSubtract = true; break; +#if SUPPORT_ARCH_arm64e + case ld::Fixup::kindStoreLittleEndianAuth64: + case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64: + case ld::Fixup::kindSetAuthData: + throw "authenticated pointers are not supported in split seg v1"; + break; +#endif default: break; } @@ -4604,6 +6041,8 @@ void OutputFile::makeSplitSegInfoV2(ld::Internal& state) ld::Internal::FinalSection* sect = *sit; if ( sect->isSectionHidden() ) continue; + if ( (_options.outputKind() == Options::kDynamicLibrary) && (strcmp(sect->sectionName(), "__interpose") == 0) && (strncmp(sect->segmentName(),"__DATA",6) == 0) ) + warning("__interpose sections cannot be used in dylibs put in the dyld cache"); bool codeSection = (sect->type() == ld::Section::typeCode); if (log) fprintf(stderr, "sect: %s, address=0x%llX\n", sect->sectionName(), sect->address); for (std::vector::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) { @@ -4623,14 +6062,15 @@ void OutputFile::makeSplitSegInfoV2(ld::Internal& state) for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) { if ( fit->firstInCluster() ) { target = NULL; + hadSubtract = false; fromTarget = NULL; kind = 0; addend = 0; toSectionIndex = 255; fromOffset = atom->finalAddress() + fit->offsetInAtom - sect->address; } - if ( this->setsTarget(fit->kind) ) { - accumulator = addressOf(state, fit, &target); + if ( this->setsTarget(*fit) ) { + accumulator = addressAndTarget(state, fit, &target); thumbTarget = targetIsThumb(state, fit); if ( thumbTarget ) accumulator |= 1; @@ -4644,7 +6084,7 @@ void OutputFile::makeSplitSegInfoV2(ld::Internal& state) } switch ( fit->kind ) { case ld::Fixup::kindSubtractTargetAddress: - accumulator -= addressOf(state, fit, &fromTarget); + accumulator -= addressAndTarget(state, fit, &fromTarget); hadSubtract = true; break; case ld::Fixup::kindAddAddend: @@ -4671,9 +6111,19 @@ void OutputFile::makeSplitSegInfoV2(ld::Internal& state) case ld::Fixup::kindStoreTargetAddressLittleEndian64: if ( hadSubtract ) kind = DYLD_CACHE_ADJ_V2_DELTA_64; + else if ( _options.useLinkedListBinding() && !this->_hasUnalignedFixup ) + kind = DYLD_CACHE_ADJ_V2_THREADED_POINTER_64; else kind = DYLD_CACHE_ADJ_V2_POINTER_64; break; +#if SUPPORT_ARCH_arm64e + case ld::Fixup::kindStoreLittleEndianAuth64: + case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64: + // FIXME: Do we need to handle subtracts on authenticated pointers? + assert(!hadSubtract); + kind = DYLD_CACHE_ADJ_V2_THREADED_POINTER_64; + break; +#endif case ld::Fixup::kindStoreX86PCRel32: case ld::Fixup::kindStoreX86PCRel32_1: case ld::Fixup::kindStoreX86PCRel32_2: @@ -4749,7 +6199,7 @@ void OutputFile::makeSplitSegInfoV2(ld::Internal& state) break; case ld::Fixup::kindSetTargetImageOffset: kind = DYLD_CACHE_ADJ_V2_IMAGE_OFF_32; - accumulator = addressOf(state, fit, &target); + accumulator = addressAndTarget(state, fit, &target); assert(target != NULL); toSectionIndex = target->machoSection(); toOffset = accumulator - state.atomToSection[target]->address; @@ -4801,7 +6251,7 @@ void OutputFile::writeMapFile(ld::Internal& state) continue; for (std::vector::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) { const ld::Atom* atom = *ait; - const ld::File* reader = atom->file(); + const ld::File* reader = atom->originalFile(); if ( reader == NULL ) continue; ld::File::Ordinal readerOrdinal = reader->ordinal(); @@ -4812,6 +6262,17 @@ void OutputFile::writeMapFile(ld::Internal& state) } } } + for (const ld::Atom* atom : state.deadAtoms) { + const ld::File* reader = atom->originalFile(); + if ( reader == NULL ) + continue; + ld::File::Ordinal readerOrdinal = reader->ordinal(); + std::map::iterator pos = readerToOrdinal.find(reader); + if ( pos == readerToOrdinal.end() ) { + readerToOrdinal[reader] = readerOrdinal; + ordinalToReader[readerOrdinal] = reader; + } + } fprintf(mapFile, "# Object files:\n"); fprintf(mapFile, "[%3u] %s\n", 0, "linker synthesized"); uint32_t fileIndex = 1; @@ -4846,7 +6307,21 @@ void OutputFile::writeMapFile(ld::Internal& state) continue; if ( atom->contentType() == ld::Atom::typeCString ) { strcpy(buffer, "literal string: "); - strlcat(buffer, (char*)atom->rawContentPointer(), 4096); + const char* s = (char*)atom->rawContentPointer(); + char* e = &buffer[4094]; + for (char* b = &buffer[strlen(buffer)]; b < e;) { + char c = *s++; + if ( c == '\n' ) { + *b++ = '\\'; + *b++ = 'n'; + } + else { + *b++ = c; + } + if ( c == '\0' ) + break; + } + buffer[4095] = '\0'; name = buffer; } else if ( (atom->contentType() == ld::Atom::typeCFI) && (strcmp(name, "FDE") == 0) ) { @@ -4878,7 +6353,41 @@ void OutputFile::writeMapFile(ld::Internal& state) name = buffer; } fprintf(mapFile, "0x%08llX\t0x%08llX\t[%3u] %s\n", atom->finalAddress(), atom->size(), - readerToFileOrdinal[atom->file()], name); + readerToFileOrdinal[atom->originalFile()], name); + } + } + // preload check is hack until 26613948 is fixed + if ( _options.deadCodeStrip() && (_options.outputKind() != Options::kPreload) ) { + fprintf(mapFile, "\n"); + fprintf(mapFile, "# Dead Stripped Symbols:\n"); + fprintf(mapFile, "# \tSize \tFile Name\n"); + for (const ld::Atom* atom : state.deadAtoms) { + char buffer[4096]; + const char* name = atom->name(); + // don't add auto-stripped aliases to .map file + if ( (atom->size() == 0) && (atom->symbolTableInclusion() == ld::Atom::symbolTableNotInFinalLinkedImages) ) + continue; + if ( atom->contentType() == ld::Atom::typeCString ) { + strcpy(buffer, "literal string: "); + const char* s = (char*)atom->rawContentPointer(); + char* e = &buffer[4094]; + for (char* b = &buffer[strlen(buffer)]; b < e;) { + char c = *s++; + if ( c == '\n' ) { + *b++ = '\\'; + *b++ = 'n'; + } + else { + *b++ = c; + } + if ( c == '\0' ) + break; + } + buffer[4095] = '\0'; + name = buffer; + } + fprintf(mapFile, "<> \t0x%08llX\t[%3u] %s\n", atom->size(), + readerToFileOrdinal[atom->originalFile()], name); } } fclose(mapFile); @@ -4889,6 +6398,141 @@ void OutputFile::writeMapFile(ld::Internal& state) } } +static std::string realPathString(const char* path) +{ + char realName[MAXPATHLEN]; + if ( realpath(path, realName) != NULL ) + return realName; + return path; +} + +void OutputFile::writeJSONEntry(ld::Internal& state) +{ + if ( _options.traceEmitJSON() && (_options.UUIDMode() != Options::kUUIDNone) && (_options.traceOutputFile() != NULL) ) { + + // Convert the UUID to a string. + const uint8_t* uuid = _headersAndLoadCommandAtom->getUUID(); + +#ifdef HAVE_UUID_UUID_H // ld64-port + uuid_string_t uuidString; + + uuid_unparse(uuid, uuidString); +#else + const char *uuidString = ""; + throwf("uuid support via libuuid not compiled in"); +#endif + + // Enumerate the dylibs. + std::vector dynamicList; + std::vector upwardList; + std::vector reexportList; + std::vector weakList; + + for (const ld::dylib::File* dylib : _dylibsToLoad) { + + if (dylib->willBeUpwardDylib()) { + + upwardList.push_back(dylib); + } else if (dylib->willBeReExported()) { + + reexportList.push_back(dylib); + } else if (dylib->forcedWeakLinked() || dylib->allSymbolsAreWeakImported()) { + + weakList.push_back(dylib); + dynamicList.push_back(dylib); + } else { + + dynamicList.push_back(dylib); + } + } + + /* + * Build the JSON entry. + */ + + std::string jsonEntry = "{"; + + jsonEntry += "\"uuid\":\"" + std::string(uuidString) + "\","; + + // installPath() returns -final_output for non-dylibs + const char* lastNameSlash = strrchr(_options.installPath(), '/'); + const char* leafName = (lastNameSlash != NULL) ? lastNameSlash+1 : _options.outputFilePath(); + jsonEntry += "\"name\":\"" + std::string(leafName) + "\","; + + jsonEntry += "\"arch\":\"" + std::string(_options.architectureName()) + "\""; + + if (dynamicList.size() > 0) { + jsonEntry += ",\"dynamic\":["; + for (const ld::dylib::File* dylib : dynamicList) { + jsonEntry += "\"" + realPathString(dylib->path()) + "\""; + if ((dylib != dynamicList.back())) { + jsonEntry += ","; + } + } + jsonEntry += "]"; + } + + if (upwardList.size() > 0) { + jsonEntry += ",\"upward-dynamic\":["; + for (const ld::dylib::File* dylib : upwardList) { + jsonEntry += "\"" + realPathString(dylib->path()) + "\""; + if ((dylib != upwardList.back())) { + jsonEntry += ","; + } + } + jsonEntry += "]"; + } + + if (reexportList.size() > 0) { + jsonEntry += ",\"re-exports\":["; + for (const ld::dylib::File* dylib : reexportList) { + jsonEntry += "\"" + realPathString(dylib->path()) + "\""; + if ((dylib != reexportList.back())) { + jsonEntry += ","; + } + } + jsonEntry += "]"; + } + + if (weakList.size() > 0) { + jsonEntry += ",\"weak\":["; + for (const ld::dylib::File* dylib : weakList) { + jsonEntry += "\"" + realPathString(dylib->path()) + "\""; + if ((dylib != weakList.back())) { + jsonEntry += ","; + } + } + jsonEntry += "]"; + } + + if (state.archivePaths.size() > 0) { + jsonEntry += ",\"archives\":["; + for (const std::string& archivePath : state.archivePaths) { + jsonEntry += "\"" + realPathString(archivePath.c_str()) + "\""; + if ((archivePath != state.archivePaths.back())) { + jsonEntry += ","; + } + } + jsonEntry += "]"; + } + + if (state.bundleLoader != NULL) { + jsonEntry += ",\"bundle-loader\":"; + jsonEntry += "\"" + realPathString(state.bundleLoader->path()) + "\""; + } + + if ( const char* orderFilePath = _options.orderFilePath() ) { + jsonEntry += ",\"order-file\":"; + jsonEntry += "\"" + realPathString(orderFilePath) + "\""; + } + + jsonEntry += "}\n"; + + // Write the JSON entry to the trace file. + _options.writeToTraceFile(jsonEntry.c_str(), jsonEntry.size()); + } +} + // used to sort atoms with debug notes class DebugNoteSorter { @@ -4908,6 +6552,19 @@ public: } }; +const char* OutputFile::canonicalOSOPath(const char* path) +{ + const char* fullPath = assureFullPath(path); + const char* prefix = _options.debugMapObjectPrefixPath(); + if ( prefix == NULL ) + return fullPath; + + int prefixLen = strlen(prefix); + if ( strncmp(fullPath, prefix, prefixLen) == 0 ) { + return &fullPath[prefixLen]; + } + return fullPath; +} const char* OutputFile::assureFullPath(const char* path) { @@ -4940,6 +6597,7 @@ void OutputFile::synthesizeDebugNotes(ld::Internal& state) // make a vector of atoms that come from files compiled with dwarf debug info std::vector atomsNeedingDebugNotes; std::set atomsWithStabs; + std::set filesSeenWithStabs; atomsNeedingDebugNotes.reserve(1024); const ld::relocatable::File* objFile = NULL; bool objFileHasDwarf = false; @@ -4989,8 +6647,11 @@ void OutputFile::synthesizeDebugNotes(ld::Internal& state) } if ( objFileHasDwarf ) atomsNeedingDebugNotes.push_back(atom); - if ( objFileHasStabs ) + if ( objFileHasStabs ) { atomsWithStabs.insert(atom); + if ( objFile != NULL ) + filesSeenWithStabs.insert(objFile); + } } } } @@ -4999,16 +6660,23 @@ void OutputFile::synthesizeDebugNotes(ld::Internal& state) std::sort(atomsNeedingDebugNotes.begin(), atomsNeedingDebugNotes.end(), DebugNoteSorter()); // Add -add_ast_path option to linker which add N_AST stab entry to output + std::set seenAstPaths; const std::vector& astPaths = _options.astFilePaths(); for (std::vector::const_iterator it=astPaths.begin(); it != astPaths.end(); it++) { const char* path = *it; + if ( seenAstPaths.count(path) != 0 ) + continue; + seenAstPaths.insert(path); // emit N_AST ld::relocatable::File::Stab astStab; astStab.atom = NULL; astStab.type = N_AST; astStab.other = 0; astStab.desc = 0; - astStab.value = fileModTime(path); + if ( _options.zeroModTimeInDebugMap() ) + astStab.value = 0; + else + astStab.value = fileModTime(path); astStab.string = path; state.stabs.push_back(astStab); } @@ -5074,12 +6742,18 @@ void OutputFile::synthesizeDebugNotes(ld::Internal& state) objStab.other = atomFile->cpuSubType(); objStab.desc = 1; if ( atomObjFile != NULL ) { - objStab.string = assureFullPath(atomObjFile->debugInfoPath()); - objStab.value = atomObjFile->debugInfoModificationTime(); + objStab.string = canonicalOSOPath(atomObjFile->debugInfoPath()); + if ( _options.zeroModTimeInDebugMap() ) + objStab.value = 0; + else + objStab.value = atomObjFile->debugInfoModificationTime(); } else { - objStab.string = assureFullPath(atomFile->path()); - objStab.value = atomFile->modificationTime(); + objStab.string = canonicalOSOPath(atomFile->path()); + if ( _options.zeroModTimeInDebugMap() ) + objStab.value = 0; + else + objStab.value = atomFile->modificationTime(); } state.stabs.push_back(objStab); wroteStartSO = true; @@ -5089,6 +6763,25 @@ void OutputFile::synthesizeDebugNotes(ld::Internal& state) asprintf(&fullFilePath, "%s%s", newDirPath, newFilename); // add both leaf path and full path seenFiles.insert(fullFilePath); + + // Add linker support for propagating N_AST debug notes from .o files to linked image + if ( const std::vector* asts = atomObjFile->astFiles() ) { + for (const relocatable::File::AstTimeAndPath& file : *asts) { + const char* cpath = file.path.c_str(); + if ( seenAstPaths.count(cpath) != 0 ) + continue; + seenAstPaths.insert(cpath); + // generate N_AST in output + ld::relocatable::File::Stab astStab; + astStab.atom = NULL; + astStab.type = N_AST; + astStab.other = 0; + astStab.desc = 0; + astStab.value = file.time; + astStab.string = cpath; + state.stabs.push_back(astStab); + } + } } filename = newFilename; dirPath = newDirPath; @@ -5184,28 +6877,40 @@ void OutputFile::synthesizeDebugNotes(ld::Internal& state) endFileStab.string = ""; state.stabs.push_back(endFileStab); } - - // copy any stabs from .o file - std::set filesSeenWithStabs; - for (std::set::iterator it=atomsWithStabs.begin(); it != atomsWithStabs.end(); it++) { - const ld::Atom* atom = *it; - objFile = dynamic_cast(atom->file()); - if ( objFile != NULL ) { - if ( filesSeenWithStabs.count(objFile) == 0 ) { - filesSeenWithStabs.insert(objFile); - const std::vector* stabs = objFile->stabs(); - if ( stabs != NULL ) { - for(std::vector::const_iterator sit = stabs->begin(); sit != stabs->end(); ++sit) { - ld::relocatable::File::Stab stab = *sit; - // ignore stabs associated with atoms that were dead stripped or coalesced away - if ( (sit->atom != NULL) && (atomsWithStabs.count(sit->atom) == 0) ) + + // copy any stabs from .o files + bool deadStripping = _options.deadCodeStrip(); + for (const ld::relocatable::File* obj : filesSeenWithStabs) { + const std::vector* filesStabs = obj->stabs(); + if ( filesStabs != NULL ) { + for (const ld::relocatable::File::Stab& stab : *filesStabs ) { + // ignore stabs associated with atoms that were dead stripped or coalesced away + if ( (stab.atom != NULL) && (atomsWithStabs.count(stab.atom) == 0) ) + continue; + // Value of N_SO stabs should be address of first atom from translation unit + if ( (stab.type == N_SO) && (stab.string != NULL) && (stab.string[0] != '\0') ) { + uint64_t lowestAtomAddress = 0; + const ld::Atom* lowestAddressAtom = NULL; + for (const ld::relocatable::File::Stab& stab2 : *filesStabs ) { + if ( stab2.atom == NULL ) continue; - // Value of N_SO stabs should be address of first atom from translation unit - if ( (stab.type == N_SO) && (stab.string != NULL) && (stab.string[0] != '\0') ) { - stab.atom = atom; + // skip over atoms that were dead stripped + if ( deadStripping && !stab2.atom->live() ) + continue; + if ( stab2.atom->coalescedAway() ) + continue; + uint64_t atomAddr = stab2.atom->objectAddress(); + if ( (lowestAddressAtom == NULL) || (atomAddr < lowestAtomAddress) ) { + lowestAddressAtom = stab2.atom; + lowestAtomAddress = atomAddr; } - state.stabs.push_back(stab); } + ld::relocatable::File::Stab altStab = stab; + altStab.atom = lowestAddressAtom; + state.stabs.push_back(altStab); + } + else { + state.stabs.push_back(stab); } } } @@ -5213,6 +6918,72 @@ void OutputFile::synthesizeDebugNotes(ld::Internal& state) } +void OutputFile::ChainedFixupBinds::ensureTarget(const ld::Atom* atom, uint64_t addend) +{ + if ( addend == 0 ) { + // special case normal case of addend==0 to use map to be fast + if ( _bindOrdinalsWithNoAddend.count(atom) ) + return; + _bindOrdinalsWithNoAddend[atom] = _bindsTargets.size(); + _bindsTargets.push_back({atom, 0}); + return; + } + unsigned index = 0; + for (const AtomAndAddend& entry : _bindsTargets) { + if ( entry.atom == atom && entry.addend == addend ) + return; + ++index; + } + _bindsTargets.push_back({atom, addend}); + if ( addend > 0xFFFFFFFF ) + _hasHugeAddends = true; + else if ( addend > 255 ) + _hasLargeAddends = true; +} + +uint32_t OutputFile::ChainedFixupBinds::count() const +{ + return (uint32_t)_bindsTargets.size(); +} + +bool OutputFile::ChainedFixupBinds::hasLargeAddends() const +{ + return _hasLargeAddends; +} + +bool OutputFile::ChainedFixupBinds::hasHugeAddends() const +{ + return _hasHugeAddends; +} + +void OutputFile::ChainedFixupBinds::forEachBind(void (^callback)(unsigned bindOrdinal, const ld::Atom* importAtom, uint64_t addend)) +{ + unsigned index = 0; + for (const AtomAndAddend& entry : _bindsTargets) { + callback(index, entry.atom, entry.addend); + ++index; + } +} + +uint32_t OutputFile::ChainedFixupBinds::ordinal(const ld::Atom* atom, uint64_t addend) const +{ + if ( addend == 0 ) { + auto it = _bindOrdinalsWithNoAddend.find(atom); + assert(it != _bindOrdinalsWithNoAddend.end()); + return it->second; + } + unsigned index = 0; + for (const AtomAndAddend& entry : _bindsTargets) { + if ( entry.atom == atom && entry.addend == addend ) + return index; + ++index; + } + assert(0 && "bind ordinal missing"); + abort(); // ld64-port + __builtin_unreachable(); // ld64-port +} + + } // namespace tool } // namespace ld diff --git a/cctools/ld64/src/ld/OutputFile.h b/cctools/ld64/src/ld/OutputFile.h index 5fd27d8..9d75278 100644 --- a/cctools/ld64/src/ld/OutputFile.h +++ b/cctools/ld64/src/ld/OutputFile.h @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -61,11 +60,15 @@ public: void setLazyBindingInfoOffset(uint64_t lpAddress, uint32_t lpInfoOffset); uint32_t dylibCount(); const ld::dylib::File* dylibByOrdinal(unsigned int ordinal); - uint32_t dylibToOrdinal(const ld::dylib::File*); + uint32_t dylibToOrdinal(const ld::dylib::File*) const; uint32_t encryptedTextStartOffset() { return _encryptedTEXTstartOffset; } uint32_t encryptedTextEndOffset() { return _encryptedTEXTendOffset; } int compressedOrdinalForAtom(const ld::Atom* target); uint64_t fileSize() const { return _fileSize; } + + bool needsBind(const ld::Atom* toTarget, uint64_t* accumulator = nullptr, + uint64_t* inlineAddend = nullptr, uint32_t* bindOrdinal = nullptr, + uint32_t* libOrdinal = nullptr) const; bool usesWeakExternalSymbols; @@ -89,6 +92,8 @@ public: ld::Internal::FinalSection* externalRelocationsSection; ld::Internal::FinalSection* sectionRelocationsSection; ld::Internal::FinalSection* indirectSymbolTableSection; + ld::Internal::FinalSection* threadedPageStartsSection; + ld::Internal::FinalSection* chainInfoSection; struct RebaseInfo { RebaseInfo(uint8_t t, uint64_t addr) : _type(t), _address(addr) {} @@ -105,13 +110,15 @@ public: struct BindingInfo { BindingInfo(uint8_t t, int ord, const char* sym, bool weak_import, uint64_t addr, int64_t add) - : _type(t), _flags(weak_import ? BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0 ), _libraryOrdinal(ord), + : _type(t), _flags(weak_import ? BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0 ), + _threadedBindOrdinal(0), _libraryOrdinal(ord), _symbolName(sym), _address(addr), _addend(add) {} BindingInfo(uint8_t t, const char* sym, bool non_weak_definition, uint64_t addr, int64_t add) : _type(t), _flags(non_weak_definition ? BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION : 0 ), - _libraryOrdinal(0), _symbolName(sym), _address(addr), _addend(add) {} + _threadedBindOrdinal(0), _libraryOrdinal(0), _symbolName(sym), _address(addr), _addend(add) {} uint8_t _type; uint8_t _flags; + uint16_t _threadedBindOrdinal; int _libraryOrdinal; const char* _symbolName; uint64_t _address; @@ -149,6 +156,23 @@ public: }; static void dumpAtomsBySection(ld::Internal& state, bool); + struct ChainedFixupPageInfo + { + std::vector fixupOffsets; + std::vector chainOverflows; + }; + + struct ChainedFixupSegInfo + { + const char* name; + uint64_t startAddr; + uint64_t endAddr; + uint32_t fileOffset; + uint32_t pageSize; + uint32_t pointerFormat; + std::vector pages; + }; + private: void writeAtoms(ld::Internal& state, uint8_t* wholeBuffer); void computeContentUUID(ld::Internal& state, uint8_t* wholeBuffer); @@ -164,6 +188,9 @@ private: const ld::Atom* atom, ld::Fixup* fixupWithTarget, ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithAddend, ld::Fixup* fixupWithStore, +#if SUPPORT_ARCH_arm64e + ld::Fixup* fixupWithAuthData, +#endif const ld::Atom* target, const ld::Atom* minusTarget, uint64_t targetAddend, uint64_t minusTargetAddend); void addDyldInfo(ld::Internal& state, ld::Internal::FinalSection* sect, @@ -171,7 +198,17 @@ private: ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore, const ld::Atom* target, const ld::Atom* minusTarget, uint64_t targetAddend, uint64_t minusTargetAddend); - void addClassicRelocs(ld::Internal& state, ld::Internal::FinalSection* sect, + void addThreadedRebaseInfo(ld::Internal& state, ld::Internal::FinalSection* sect, + const ld::Atom* atom, ld::Fixup* fixupWithTarget, + ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore, + const ld::Atom* target, const ld::Atom* minusTarget, + uint64_t targetAddend, uint64_t minusTargetAddend); + void addChainedFixupLocation(ld::Internal& state, ld::Internal::FinalSection* sect, + const ld::Atom* atom, ld::Fixup* fixupWithTarget, + ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore, + const ld::Atom* target, const ld::Atom* minusTarget, + uint64_t targetAddend, uint64_t minusTargetAddend); + void addClassicRelocs(ld::Internal& state, ld::Internal::FinalSection* sect, const ld::Atom* atom, ld::Fixup* fixupWithTarget, ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore, const ld::Atom* target, const ld::Atom* minusTarget, @@ -189,22 +226,25 @@ private: void updateLINKEDITAddresses(ld::Internal& state); void applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::Atom* atom, uint8_t* buffer); uint64_t addressOf(const ld::Internal& state, const ld::Fixup* fixup, const ld::Atom** target); + uint64_t addressAndTarget(const ld::Internal& state, const ld::Fixup* fixup, const ld::Atom** target); bool targetIsThumb(ld::Internal& state, const ld::Fixup* fixup); uint32_t lazyBindingInfoOffsetForLazyPointerAddress(uint64_t lpAddress); void copyNoOps(uint8_t* from, uint8_t* to, bool thumb); bool isPointerToTarget(ld::Fixup::Kind kind); bool isPointerFromTarget(ld::Fixup::Kind kind); - bool isPcRelStore(ld::Fixup::Kind kind); + bool isPcRelStore(const ld::Fixup* fixup); bool isStore(ld::Fixup::Kind kind); bool storeAddendOnly(const ld::Atom* inAtom, const ld::Atom* target, bool pcRel=false); - bool setsTarget(ld::Fixup::Kind kind); + bool setsTarget(const ld::Fixup &fixup); void addFixupOutInfo(ld::Internal& state); void makeRelocations(ld::Internal& state); void makeSectionRelocations(ld::Internal& state); void makeDyldInfo(ld::Internal& state); + void buildChainedFixupInfo(ld::Internal& state); void makeSplitSegInfo(ld::Internal& state); void makeSplitSegInfoV2(ld::Internal& state); void writeMapFile(ld::Internal& state); + void writeJSONEntry(ld::Internal& state); uint64_t lookBackAddend(ld::Fixup::iterator fit); bool takesNoDiskSpace(const ld::Section* sect); bool hasZeroForFileOffset(const ld::Section* sect); @@ -240,9 +280,23 @@ private: uint64_t tlvTemplateOffsetOf(const ld::Internal& state, const ld::Fixup* fixup); void synthesizeDebugNotes(ld::Internal& state); const char* assureFullPath(const char* path); + const char* canonicalOSOPath(const char* path); void noteTextReloc(const ld::Atom* atom, const ld::Atom* target); + void setFixup64(uint8_t* fixUpLocation, uint64_t accumulator, const ld::Atom* toTarget); + void setFixup32(uint8_t* fixUpLocation, uint64_t accumulator, const ld::Atom* toTarget); +#if SUPPORT_ARCH_arm64e + void setFixup64e(uint8_t* fixUpLocation, uint64_t accumulator, Fixup::AuthData authData, const ld::Atom* toTarget); +#endif + bool isFixupForChain(ld::Fixup::iterator fit); + uint16_t chainedPointerFormat() const; + void chain32bitPointers(dyld_chained_ptr_32_rebase* prevLoc, dyld_chained_ptr_32_rebase* loc, + ChainedFixupSegInfo& segInfo, uint8_t* pageBufferStart, uint32_t pageIndex); + dyld_chained_ptr_32_rebase* farthestChainableLocation(dyld_chained_ptr_32_rebase* start); + bool chainableNonPointer(uint32_t value); + void chain32bitFirmwarePointers(dyld_chained_ptr_32_firmware_rebase* prevLoc, dyld_chained_ptr_32_firmware_rebase* finalLoc, + ChainedFixupSegInfo& segInfo, uint8_t* pageBufferStart, uint32_t pageIndex); + dyld_chained_ptr_32_firmware_rebase* farthestChainableLocation(dyld_chained_ptr_32_firmware_rebase* start); - struct InstructionInfo { uint32_t offsetInAtom; const ld::Fixup* fixup; @@ -253,6 +307,32 @@ private: uint32_t instruction; }; + + class ChainedFixupBinds + { + public: + void ensureTarget(const ld::Atom* atom, uint64_t addend); + uint32_t count() const; + bool hasLargeAddends() const; + bool hasHugeAddends() const; + void forEachBind(void (^callback)(unsigned bindOrdinal, const ld::Atom* importAtom, uint64_t addend)); + uint32_t ordinal(const ld::Atom* atom, uint64_t addend) const; + void setMaxRebase(uint64_t max) { _maxRebase = max; } + uint64_t maxRebase() const { return _maxRebase; } + + private: + struct AtomAndAddend { + const ld::Atom* atom; + uint64_t addend; + }; + std::unordered_map _bindOrdinalsWithNoAddend; + std::vector _bindsTargets; + uint64_t _maxRebase = 0; + bool _hasLargeAddends = false; + bool _hasHugeAddends = false; + }; + + void setInfo(ld::Internal& state, const ld::Atom* atom, uint8_t* buffer, const std::map& usedHints, uint32_t offsetInAtom, uint32_t delta, InstructionInfo* info); @@ -277,6 +357,9 @@ private: std::vector _dylibsToLoad; std::vector _dylibOrdinalPaths; const bool _hasDyldInfo; + const bool _hasExportsTrie; + const bool _hasChainedFixups; + const bool _hasThreadedPageStarts; const bool _hasSymbolTable; const bool _hasSectionRelocations; const bool _hasSplitSegInfo; @@ -305,6 +388,16 @@ public: std::vector _bindingInfo; std::vector _lazyBindingInfo; std::vector _weakBindingInfo; + bool _hasUnalignedFixup = false; + // Note, <= 0 values are indices in to rebases, > 0 are binds. + std::vector _threadedRebaseBindIndices; + std::vector _chainedFixupAddresses; + std::unordered_map _chainedFixupNoAddendBindOrdinals; + ChainedFixupBinds _chainedFixupBinds; + std::vector _chainedFixupSegments; +#if SUPPORT_ARCH_arm64e + std::map> _authenticatedFixupData; +#endif std::vector _splitSegInfos; std::vector _splitSegV2Infos; class HeaderAndLoadCommandsAbtract* _headersAndLoadCommandAtom; @@ -323,6 +416,8 @@ public: class LinkEditAtom* _functionStartsAtom; class LinkEditAtom* _dataInCodeAtom; class LinkEditAtom* _optimizationHintsAtom; + class LinkEditAtom* _chainedInfoAtom; + }; } // namespace tool diff --git a/cctools/ld64/src/ld/PlatformSupport.cpp b/cctools/ld64/src/ld/PlatformSupport.cpp new file mode 100644 index 0000000..f8cb4c7 --- /dev/null +++ b/cctools/ld64/src/ld/PlatformSupport.cpp @@ -0,0 +1,255 @@ +/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-* + * + * Copyright (c) 2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include "PlatformSupport.h" + +//FIXME: Only needed until we move VersionSet into PlatformSupport +#include "ld.hpp" +#include "Options.h" + +namespace ld { + +const Platform basePlatform(Platform platform) +{ + switch(platform) { + case ld::Platform::iOSMac: + case ld::Platform::iOS_simulator: + return ld::Platform::iOS; + + case ld::Platform::watchOS_simulator: + return Platform::watchOS; + + case ld::Platform::tvOS_simulator: + return ld::Platform::tvOS; + + default: + return platform; + } +} + +static const PlatformInfo sAllSupportedPlatforms[] = { + { Platform::unknown, Platform::unknown, "unknown", "", NULL, 0x00000000, 0x00000000, 0, false, true, PlatEnforce::error, PlatEnforce::error }, + { Platform::macOS, Platform::macOS, "macOS", "-macos_version_min", "MACOSX_DEPLOYMENT_TARGET", 0x000A0E00, 0x000A0400, LC_VERSION_MIN_MACOSX, false, true, PlatEnforce::warning, PlatEnforce::warning }, + { Platform::iOS, Platform::iOS, "iOS", "-ios_version_min", "IPHONEOS_DEPLOYMENT_TARGET", 0x000C0000, 0x00070000, LC_VERSION_MIN_IPHONEOS, true, true, PlatEnforce::warning, PlatEnforce::warning }, + { Platform::tvOS, Platform::tvOS, "tvOS", "-tvos_version_min", "TVOS_DEPLOYMENT_TARGET", 0x000C0000, 0x00070000, LC_VERSION_MIN_TVOS, true, true, PlatEnforce::warning, PlatEnforce::warning }, + { Platform::watchOS, Platform::watchOS, "watchOS", "-watchos_version_min", "WATCHOS_DEPLOYMENT_TARGET", 0x00050000, 0x00020000, LC_VERSION_MIN_WATCHOS, true, true, PlatEnforce::warning, PlatEnforce::warning }, + { Platform::bridgeOS, Platform::bridgeOS, "bridgeOS", "-bridgeos_version_min", "BRIDGEOS_DEPLOYMENT_TARGET", 0x00010000, 0x00010000, 0, false, true, PlatEnforce::warning, PlatEnforce::warning }, + { Platform::iOSMac, Platform::iOSMac, "Mac Catalyst", "-maccatalyst_version_min", NULL, 0x000D0000, 0x000D0000, 0, false, true, PlatEnforce::warnInternalErrorExternal, PlatEnforce::warnInternalErrorExternal }, + { Platform::iOS_simulator, Platform::iOS, "iOS Simulator", "-ios_simulator_version_min", NULL, 0x000D0000, 0x00080000, LC_VERSION_MIN_IPHONEOS, false, true, PlatEnforce::warning, PlatEnforce::warning }, + { Platform::tvOS_simulator, Platform::tvOS, "tvOS Simulator", "-tvos_simulator_version_min", NULL, 0x000D0000, 0x00080000, LC_VERSION_MIN_TVOS, false, true, PlatEnforce::warning, PlatEnforce::warning }, + { Platform::watchOS_simulator, Platform::watchOS, "watchOS Simulator", "-watchos_simulator_version_min", NULL, 0x00060000, 0x00020000, LC_VERSION_MIN_WATCHOS, false, true, PlatEnforce::warning, PlatEnforce::warning }, + { Platform::driverKit, Platform::driverKit, "DriverKit", "-driverkit_version_min", NULL, 0x00130000, 0x00130000, 0, false, true, PlatEnforce::error, PlatEnforce::error }, + + { Platform::freestanding, Platform::freestanding, "free standing", "-preload", NULL, 0x00000000, 0, 0, false, false, PlatEnforce::allow, PlatEnforce::allow }, +}; + +static void versionToString(uint32_t value, char buffer[32]) +{ + if ( value & 0xFF ) + sprintf(buffer, "%d.%d.%d", value >> 16, (value >> 8) & 0xFF, value & 0xFF); + else + sprintf(buffer, "%d.%d", value >> 16, (value >> 8) & 0xFF); +} + +void VersionSet::checkObjectCrosslink(const VersionSet& objectPlatforms, const std::string& targetPath, bool internalSDK, + bool bitcode) const { + // Check platform cross-linking. + __block bool warned = false; + forEach(^(ld::Platform cmdLinePlatform, uint32_t cmdLineMinVersion, uint32_t cmdLineSDKVersion, bool& stop) { + // if .o file is old and has no platform specified, don't complain (unless building for iOSMac) + if ( objectPlatforms.empty() && !contains(ld::Platform::iOSMac)) + return; + + if ( !objectPlatforms.contains(cmdLinePlatform) ) { + if (bitcode) { + throwf("building for %s, but linking in object file (%s) built for %s,", + to_str().c_str(), targetPath.c_str(), objectPlatforms.to_str().c_str()); + } else if ( (count() == 2) && (cmdLinePlatform == ld::Platform::iOSMac) ) { + // clang is not emitting second LC_BUILD_VERSION in zippered .o files + } + else { + auto enforce = platformInfo(cmdLinePlatform)._linkingObjectFiles; + if (enforce == PlatEnforce::warnInternalErrorExternal) { + if (internalSDK) { + enforce = PlatEnforce::warning; + } else { + enforce = PlatEnforce::error; + } + } + switch (enforce) { + case PlatEnforce::allow: + break; + case PlatEnforce::warnBI: + // only warn during B&I builds + if ( (getenv("RC_XBS") != NULL) && (getenv("RC_BUILDIT") == NULL) ) + break; + case PlatEnforce::warning: { + if ( !warned ) { + warning("building for %s, but linking in object file (%s) built for %s", + to_str().c_str(), targetPath.c_str(), objectPlatforms.to_str().c_str()); + warned = true; + } + } break; + case PlatEnforce::error: + throwf("building for %s, but linking in object file built for %s,", + to_str().c_str(), objectPlatforms.to_str().c_str()); + break; + case PlatEnforce::warnInternalErrorExternal: + assert(0); + break; + } + } + } + else if ( (cmdLineMinVersion != 0) && (minOS(cmdLinePlatform) > cmdLineMinVersion) ) { + char t1[32]; + char t2[32]; + versionToString(minOS(cmdLinePlatform), t1); + versionToString(cmdLineMinVersion, t2); + warning("object file (%s) was built for newer %s version (%s) than being linked (%s)", + targetPath.c_str(), platformInfo(cmdLinePlatform).printName, t1, t2); + } + }); +} + +void VersionSet::checkDylibCrosslink(const VersionSet& dylibPlatforms, const std::string& targetPath, + const std::string& dylibType, bool internalSDK, bool indirectDylib, + bool bitcode) const { + // Check platform cross-linking. + __block bool warned = false; + forEach(^(ld::Platform cmdLinePlatform, uint32_t cmdLineMinVersion, uint32_t cmdLineSDKVersion, bool& stop) { + // if dylib is old and has no platform specified, don't complain (unless building for iOSMac) + if ( dylibPlatforms.empty() && !contains(ld::Platform::iOSMac)) + return; + if ( !dylibPlatforms.contains(cmdLinePlatform) ) { + // Normally linked dylibs need to support all the platforms we are building for, + // with the exception of zippered binaries linking to macOS only libraries in the OS. + // To handle that case we exit early when the commandline platform is iOSMac, if + // the platforms also contain macOS. + if (cmdLinePlatform == ld::Platform::iOSMac && contains(ld::Platform::macOS)) + return; + // spurious warnings when iOSMac binary is built links with zippered dylib that links with macOS dylib + // iOSMac app links simulator frameworks without warning/error + if ( indirectDylib && dylibPlatforms.contains(ld::Platform::macOS) && contains(ld::Platform::iOSMac) ) + return; + if ( bitcode ) { + throwf("building for %s, but linking in %s file (%s) built for %s,", + to_str().c_str(), dylibType.c_str(), targetPath.c_str(), dylibPlatforms.to_str().c_str()); + } else if ( (count() == 2) && (cmdLinePlatform == ld::Platform::iOSMac) ) { + // clang is not emitting second LC_BUILD_VERSION in zippered .o files + } + else { + auto enforce = platformInfo(cmdLinePlatform)._linkingObjectFiles; + if (enforce == PlatEnforce::warnInternalErrorExternal) { + if (internalSDK) { + enforce = PlatEnforce::warning; + } else { + enforce = PlatEnforce::error; + } + } + switch (enforce) { + case PlatEnforce::allow: + break; + case PlatEnforce::warnBI: + // only warn during B&I builds + if ( (getenv("RC_XBS") != NULL) && (getenv("RC_BUILDIT") == NULL) ) + break; + case PlatEnforce::warning: { + if ( !warned ) { + warning("building for %s, but linking in %s file (%s) built for %s", + to_str().c_str(), dylibType.c_str(), targetPath.c_str(), dylibPlatforms.to_str().c_str()); + warned = true; + } + } break; + case PlatEnforce::error: + throwf("building for %s, but linking in %s built for %s,", + to_str().c_str(), dylibType.c_str(), dylibPlatforms.to_str().c_str()); + break; + case PlatEnforce::warnInternalErrorExternal: + assert(0); + break; + } + } + } + }); +} + +const PlatformInfo& platformInfo(Platform platform) +{ + for (const PlatformInfo& info : sAllSupportedPlatforms) { + if ( info.platform == platform ) + return info; + } + assert(0 && "unknown platform"); + abort(); // ld64-port + __builtin_unreachable(); // ld64-port +} + +void forEachSupportedPlatform(void (^handler)(const PlatformInfo& info, bool& stop)) +{ + bool stop = false; + for (const PlatformInfo& info : sAllSupportedPlatforms) { + handler(info, stop); + if ( stop ) + break; + } +} + +Platform platformForLoadCommand(uint32_t lc, const mach_header* mh) +{ + Platform result = Platform::unknown; + bool isIntel = ((mh->cputype & ~CPU_ARCH_MASK) == CPU_TYPE_I386); + for (const PlatformInfo& info : sAllSupportedPlatforms) { + if ( info.loadCommandIfNotUsingBuildVersionLC == lc ) { + // some LC_ are in multiple rows, disabiguate by only setting sim row on intel + bool isSim = (info.platform != info.basePlatform); + if ( !isSim || isIntel ) + result = info.platform; + } + } + return result; +} + +// clang puts PLATFORM_IOS into sim .o files instead of PLATFORM_IOSSIMULATOR +Platform platformFromBuildVersion(uint32_t plat, const mach_header* mh) +{ + bool isIntel = ((mh->cputype & ~CPU_ARCH_MASK) == CPU_TYPE_I386); + if ( (Platform)plat == Platform::iOS ) { + if (isIntel) + return Platform::iOS_simulator; + } + else if ( (Platform)plat == Platform::tvOS ) { + if (isIntel) + return Platform::tvOS_simulator; + } + else if ( (Platform)plat == Platform::watchOS ) { + if (isIntel) + return Platform::watchOS_simulator; + } + return (Platform)plat; +} + + + +} // namespace diff --git a/cctools/ld64/src/ld/PlatformSupport.h b/cctools/ld64/src/ld/PlatformSupport.h new file mode 100644 index 0000000..37d3497 --- /dev/null +++ b/cctools/ld64/src/ld/PlatformSupport.h @@ -0,0 +1,87 @@ +/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-* + * + * Copyright (c) 2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef PlatformSupport_h +#define PlatformSupport_h + +#include + +#include + +namespace ld { + + +enum class Platform +{ + unknown = 0, + macOS = 1, // PLATFORM_MACOS + iOS = 2, // PLATFORM_IOS + tvOS = 3, // PLATFORM_TVOS + watchOS = 4, // PLATFORM_WATCHOS + bridgeOS = 5, // PLATFORM_BRIDGEOS + iOSMac = 6, // PLATFORM_IOSMAC + iOS_simulator = 7, // PLATFORM_IOSSIMULATOR + tvOS_simulator = 8, // PLATFORM_TVOSSIMULATOR + watchOS_simulator = 9, // PLATFORM_WATCHOSSIMULATOR + driverKit = 10, // PLATFORM_DRIVERKIT + + freestanding = 100 // this never shows up in mach-o files, it is for internal tracking in ld64 +}; + + +const Platform basePlatform(Platform platform); + +typedef std::set PlatformSet; + +enum class PlatEnforce { allow, warning, error, warnBI, warnInternalErrorExternal }; + +struct PlatformInfo +{ + Platform platform; + Platform basePlatform; + const char* printName; + const char* commandLineArg; + const char* fallbackEnvVarName; + uint32_t firstOsVersionUsingBuildVersionLC; + uint32_t minimumOsVersion; + uint32_t loadCommandIfNotUsingBuildVersionLC; + bool supportsEmbeddedBitcode; + bool warnIfObjectFileTooNew; + // DO NOT ACCESS DIRECTLY + // Use checkObjectCrosslink() / checkDylibCrosslink() + PlatEnforce _linkingObjectFiles; + PlatEnforce _linkingDylibs; +}; + +const PlatformInfo& platformInfo(Platform platform); + +void forEachSupportedPlatform(void (^handler)(const PlatformInfo& info, bool& stop)); + +Platform platformForLoadCommand(uint32_t lc, const mach_header* mh); +Platform platformFromBuildVersion(uint32_t plat, const mach_header* mh); + + +} // namespace + +#endif // PlatformSupport_h diff --git a/cctools/ld64/src/ld/Resolver.cpp b/cctools/ld64/src/ld/Resolver.cpp index cee41bd..bfb67a3 100644 --- a/cctools/ld64/src/ld/Resolver.cpp +++ b/cctools/ld64/src/ld/Resolver.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -51,7 +50,6 @@ #include #include "Options.h" - #include "ld.hpp" #include "Bitcode.hpp" #include "InputFiles.h" @@ -59,6 +57,10 @@ #include "Resolver.h" #include "parsers/lto_file.h" +#include "configure.h" + +#define VAL(x) #x +#define STRINGIFY(x) VAL(x) namespace ld { namespace tool { @@ -147,7 +149,7 @@ private: class SectionBoundaryAtom : public ld::Atom { public: - static SectionBoundaryAtom* makeSectionBoundaryAtom(const char* name, bool start, const char* segSectName); + static SectionBoundaryAtom* makeSectionBoundaryAtom(const char* name, bool start, const char* segSectName, const Options& opts); static SectionBoundaryAtom* makeOldSectionBoundaryAtom(const char* name, bool start); // overrides of ld::Atom @@ -174,9 +176,9 @@ private: const char* _name; }; -SectionBoundaryAtom* SectionBoundaryAtom::makeSectionBoundaryAtom(const char* name, bool start, const char* segSectName) +SectionBoundaryAtom* SectionBoundaryAtom::makeSectionBoundaryAtom(const char* name, bool start, const char* segSectName, const Options& opts) { - + const char* segSectDividor = strrchr(segSectName, '$'); if ( segSectDividor == NULL ) throwf("malformed section$ symbol name: %s", name); @@ -186,8 +188,20 @@ SectionBoundaryAtom* SectionBoundaryAtom::makeSectionBoundaryAtom(const char* na throwf("malformed section$ symbol name: %s", name); char segName[18]; strlcpy(segName, segSectName, segNameLen+1); - - const ld::Section* section = new ld::Section(strdup(segName), sectionName, ld::Section::typeUnclassified); + + ld::Section::Type sectType = ld::Section::typeUnclassified; + if (!strcmp(segName, "__TEXT") && !strcmp(sectionName, "__thread_starts")) + sectType = ld::Section::typeThreadStarts; + else if (!strcmp(segName, "__TEXT") && !strcmp(sectionName, "__chain_starts")) + sectType = ld::Section::typeChainStarts; + else if (!strcmp(segName, "__DATA") && !strcmp(sectionName, "__zerofill")) { + if ( opts.mergeZeroFill() ) + sectType = ld::Section::typeZeroFill; + else + warning("reference to non-existent __zerofill section because -merge_zero_fill_sections option not used"); + } + + const ld::Section* section = new ld::Section(strdup(segName), sectionName, sectType); return new SectionBoundaryAtom(name, *section, (start ? ld::Atom::typeSectionStart : typeSectionEnd)); } @@ -276,15 +290,7 @@ SegmentBoundaryAtom* SegmentBoundaryAtom::makeOldSegmentBoundaryAtom(const char* void Resolver::initializeState() { - // set initial objc constraint based on command line options - if ( _options.objcGc() ) - _internal.objcObjectConstraint = ld::File::objcConstraintRetainReleaseOrGC; - else if ( _options.objcGcOnly() ) - _internal.objcObjectConstraint = ld::File::objcConstraintGC; - _internal.cpuSubType = _options.subArchitecture(); - _internal.minOSVersion = _options.minOSversion(); - _internal.derivedPlatformLoadCommand = 0; // In -r mode, look for -linker_option additions if ( _options.outputKind() == Options::kObjectFile ) { @@ -293,6 +299,11 @@ void Resolver::initializeState() doLinkerOption(*it, "command line"); } } +#ifdef LD64_VERSION_NUM + uint32_t packedNum = Options::parseVersionNumber32(STRINGIFY(LD64_VERSION_NUM)); + uint64_t combined = (uint64_t)TOOL_LD << 32 | packedNum; + _internal.toolsVersions.insert(combined); +#endif } void Resolver::buildAtomList() @@ -311,8 +322,10 @@ void Resolver::doLinkerOption(const std::vector& linkerOption, cons { if ( linkerOption.size() == 1 ) { const char* lo1 = linkerOption.front(); - if ( strncmp(lo1, "-l", 2) == 0 ) { - _internal.linkerOptionLibraries.insert(&lo1[2]); + if ( strncmp(lo1, "-l", 2) == 0) { + if (_internal.linkerOptionLibraries.count(&lo1[2]) == 0) { + _internal.unprocessedLinkerOptionLibraries.insert(&lo1[2]); + } } else { warning("unknown linker option from object file ignored: '%s' in %s", lo1, fileName); @@ -321,8 +334,10 @@ void Resolver::doLinkerOption(const std::vector& linkerOption, cons else if ( linkerOption.size() == 2 ) { const char* lo2a = linkerOption[0]; const char* lo2b = linkerOption[1]; - if ( strcmp(lo2a, "-framework") == 0 ) { - _internal.linkerOptionFrameworks.insert(lo2b); + if ( strcmp(lo2a, "-framework") == 0) { + if (_internal.linkerOptionFrameworks.count(lo2b) == 0) { + _internal.unprocessedLinkerOptionFrameworks.insert(lo2b); + } } else { warning("unknown linker option from object file ignored: '%s' '%s' from %s", lo2a, lo2b, fileName); @@ -333,22 +348,6 @@ void Resolver::doLinkerOption(const std::vector& linkerOption, cons } } -static void userReadableSwiftVersion(uint8_t value, char versionString[64]) -{ - switch (value) { - case 1: - strcpy(versionString, "1.0"); - break; - case 2: - strcpy(versionString, "1.1"); - break; - case 3: - strcpy(versionString, "2.0"); - break; - default: - sprintf(versionString, "unknown ABI version 0x%02X", value); - } -} void Resolver::doFile(const ld::File& file) { @@ -368,32 +367,31 @@ void Resolver::doFile(const ld::File& file) _inputFiles.createIndirectDylibs(); } } + // update which form of ObjC is being used + if ( objFile->hasObjC() ) + _internal.hasObjC = true; + // Resolve bitcode section in the object file if ( _options.bundleBitcode() ) { if ( objFile->getBitcode() == NULL ) { - // No bitcode section, figure out if the object file comes from LTO/compiler static library - if (objFile->sourceKind() != ld::relocatable::File::kSourceLTO && - objFile->sourceKind() != ld::relocatable::File::kSourceCompilerArchive ) { - switch ( _options.platform() ) { - case Options::kPlatformOSX: - case Options::kPlatformUnknown: - warning("all bitcode will be dropped because '%s' was built without bitcode. " - "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. ", file.path()); - _internal.filesWithBitcode.clear(); - _internal.dropAllBitcode = true; - break; - case Options::kPlatformiOS: - throwf("'%s' does not contain bitcode. " - "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.", file.path()); - break; - case Options::kPlatformWatchOS: -#if SUPPORT_APPLE_TV - case Options::kPlatform_tvOS: -#endif - throwf("'%s' does not contain bitcode. " - "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE) or obtain an updated library from the vendor", file.path()); - break; - } + // Handle the special case for compiler_rt objects. Add the file to the list to be process. + if ( objFile->sourceKind() == ld::relocatable::File::kSourceCompilerArchive ) { + _internal.filesFromCompilerRT.push_back(objFile); + } + else if (objFile->sourceKind() != ld::relocatable::File::kSourceLTO ) { + // No bitcode section, figure out if the object file comes from LTO/compiler static library + _options.platforms().forEach(^(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop) { + if ( platformInfo(platform).supportsEmbeddedBitcode ) { + throwf("'%s' does not contain bitcode. " + "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.", file.path()); + } + else { + warning("all bitcode will be dropped because '%s' was built without bitcode. " + "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. ", file.path()); + _internal.filesWithBitcode.clear(); + _internal.dropAllBitcode = true; + } + }); } } else { // contains bitcode, check if it is just a marker @@ -413,65 +411,43 @@ void Resolver::doFile(const ld::File& file) } } - // update which form of ObjC is being used - switch ( file.objCConstraint() ) { - case ld::File::objcConstraintNone: - break; - case ld::File::objcConstraintRetainRelease: - if ( _internal.objcObjectConstraint == ld::File::objcConstraintGC ) - throwf("%s built with incompatible Garbage Collection settings to link with previous .o files", file.path()); - if ( _options.objcGcOnly() ) - throwf("command line specified -objc_gc_only, but file is retain/release based: %s", file.path()); - if ( _options.objcGc() ) - throwf("command line specified -objc_gc, but file is retain/release based: %s", file.path()); - if ( !_options.targetIOSSimulator() && (_internal.objcObjectConstraint != ld::File::objcConstraintRetainReleaseForSimulator) ) - _internal.objcObjectConstraint = ld::File::objcConstraintRetainRelease; - break; - case ld::File::objcConstraintRetainReleaseOrGC: - if ( _internal.objcObjectConstraint == ld::File::objcConstraintNone ) - _internal.objcObjectConstraint = ld::File::objcConstraintRetainReleaseOrGC; - if ( _options.targetIOSSimulator() ) - warning("linking ObjC for iOS Simulator, but object file (%s) was compiled for MacOSX", file.path()); - break; - case ld::File::objcConstraintGC: - if ( _internal.objcObjectConstraint == ld::File::objcConstraintRetainRelease ) - throwf("%s built with incompatible Garbage Collection settings to link with previous .o files", file.path()); - _internal.objcObjectConstraint = ld::File::objcConstraintGC; - if ( _options.targetIOSSimulator() ) - warning("linking ObjC for iOS Simulator, but object file (%s) was compiled for MacOSX", file.path()); - break; - case ld::File::objcConstraintRetainReleaseForSimulator: - if ( _internal.objcObjectConstraint == ld::File::objcConstraintNone ) { - if ( !_options.targetIOSSimulator() && (_options.outputKind() != Options::kObjectFile) ) - warning("ObjC object file (%s) was compiled for iOS Simulator, but linking for MacOSX", file.path()); - _internal.objcObjectConstraint = ld::File::objcConstraintRetainReleaseForSimulator; - } - else if ( _internal.objcObjectConstraint != ld::File::objcConstraintRetainReleaseForSimulator ) { - _internal.objcObjectConstraint = ld::File::objcConstraintRetainReleaseForSimulator; - } - break; - } - // verify all files use same version of Swift language if ( file.swiftVersion() != 0 ) { + _internal.someObjectFileHasSwift = true; if ( _internal.swiftVersion == 0 ) { _internal.swiftVersion = file.swiftVersion(); } else if ( file.swiftVersion() != _internal.swiftVersion ) { char fileVersion[64]; char otherVersion[64]; - userReadableSwiftVersion(file.swiftVersion(), fileVersion); - userReadableSwiftVersion(_internal.swiftVersion, otherVersion); + Options::userReadableSwiftVersion(file.swiftVersion(), fileVersion); + Options::userReadableSwiftVersion(_internal.swiftVersion, otherVersion); if ( file.swiftVersion() > _internal.swiftVersion ) { - throwf("%s compiled with newer version of Swift language (%s) than previous files (%s)", - file.path(), fileVersion, otherVersion); + if ( _options.warnOnSwiftABIVersionMismatches() ) { + warning("%s compiled with newer version of Swift language (%s) than previous files (%s)", + file.path(), fileVersion, otherVersion); + } else { + throwf("not all .o files built with same Swift language version. Started with (%s), now found (%s) in", + otherVersion, fileVersion); + } } else { - throwf("%s compiled with older version of Swift language (%s) than previous files (%s)", - file.path(), fileVersion, otherVersion); + if ( _options.warnOnSwiftABIVersionMismatches() ) { + warning("%s compiled with older version of Swift language (%s) than previous files (%s)", + file.path(), fileVersion, otherVersion); + } else { + throwf("not all .o files built with same Swift language version. Started with (%s), now found (%s) in", + otherVersion, fileVersion); + } } } } + + // record minimums swift language version used + if ( file.swiftLanguageVersion() != 0 ) { + if ( (_internal.swiftLanguageVersion == 0) || (_internal.swiftLanguageVersion > file.swiftLanguageVersion()) ) + _internal.swiftLanguageVersion = file.swiftLanguageVersion(); + } // in -r mode, if any .o files have dwarf then add UUID to output .o file if ( objFile->debugInfo() == ld::relocatable::File::kDebugInfoDwarf ) @@ -480,18 +456,24 @@ void Resolver::doFile(const ld::File& file) // remember if any .o file did not have MH_SUBSECTIONS_VIA_SYMBOLS bit set if ( ! objFile->canScatterAtoms() ) _internal.allObjectFilesScatterable = false; - + + // remember if building for profiling (so we don't warn about initializers) + if ( objFile->hasllvmProfiling() ) + _havellvmProfiling = true; + +#if MULTI // update minOSVersion off all .o files uint32_t objMinOS = objFile->minOSVersion(); if ( !objMinOS ) _internal.objectFileFoundWithNoVersion = true; - - uint32_t objPlatformLC = objFile->platformLoadCommand(); - if ( (objPlatformLC != 0) && (_internal.derivedPlatformLoadCommand == 0) && (_options.outputKind() == Options::kObjectFile) ) - _internal.derivedPlatformLoadCommand = objPlatformLC; - if ( (_options.outputKind() == Options::kObjectFile) && (objMinOS > _internal.minOSVersion) ) _internal.minOSVersion = objMinOS; +#endif + // update set of known tools used + for (const std::pair& entry : objFile->toolVersions()) { + uint64_t combined = (uint64_t)entry.first << 32 | entry.second; + _internal.toolsVersions.insert(combined); + } // update cpu-sub-type cpu_subtype_t nextObjectSubType = file.cpuSubType(); @@ -515,12 +497,28 @@ void Resolver::doFile(const ld::File& file) } break; + case CPU_TYPE_ARM64: + if ( _options.subArchitecture() != nextObjectSubType ) { + if ( _options.allowSubArchitectureMismatches() ) { + warning("object file %s was built for different arm64 sub-type (%d) than link command line (%d)", + file.path(), nextObjectSubType, _options.subArchitecture()); + } + else { + throwf("object file %s was built for different arm64 sub-type (%d) than link command line (%d)", + file.path(), nextObjectSubType, _options.subArchitecture()); + } + } + break; + case CPU_TYPE_I386: _internal.cpuSubType = CPU_SUBTYPE_I386_ALL; break; case CPU_TYPE_X86_64: if ( _options.subArchitecture() != nextObjectSubType ) { + // allow x86_64h to link with x86_64 .o files + if ( (_options.subArchitecture() == CPU_SUBTYPE_X86_64_H) && (nextObjectSubType == CPU_SUBTYPE_X86_64_ALL) ) + break; if ( _options.allowSubArchitectureMismatches() ) { warning("object file %s was built for different x86_64 sub-type (%d) than link command line (%d)", file.path(), nextObjectSubType, _options.subArchitecture()); @@ -537,6 +535,19 @@ void Resolver::doFile(const ld::File& file) // Check dylib for bitcode, if the library install path is relative path or @rpath, it has to contain bitcode if ( _options.bundleBitcode() ) { bool isSystemFramework = ( dylibFile->installPath() != NULL ) && ( dylibFile->installPath()[0] == '/' ); + if (!isSystemFramework) { + // rdar://52804818 The swift dylibs in the SDK do not have absolute installnames in order to support + // back deployment + for (const auto& sdkPath : _options.sdkPaths()) { + char swiftPath[MAXPATHLEN]; + strlcpy(swiftPath, sdkPath, MAXPATHLEN); + strlcat(swiftPath, "/usr/lib/swift/", MAXPATHLEN); + if (strncmp(swiftPath, dylibFile->path(), strlen(swiftPath)) == 0) { + isSystemFramework = true; + break; + } + } + } if ( dylibFile->getBitcode() == NULL && !isSystemFramework ) { // Check if the dylib is from toolchain by checking the path char tcLibPath[PATH_MAX]; @@ -555,26 +566,18 @@ void Resolver::doFile(const ld::File& file) if ( realpath(tempPath, tcLibPath) == NULL || realpath(dylibFile->path(), tempPath) == NULL || strncmp(tcLibPath, tempPath, strlen(tcLibPath)) != 0 ) { - switch ( _options.platform() ) { - case Options::kPlatformOSX: - case Options::kPlatformUnknown: - warning("all bitcode will be dropped because '%s' was built without bitcode. " - "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.", file.path()); - _internal.filesWithBitcode.clear(); - _internal.dropAllBitcode = true; - break; - case Options::kPlatformiOS: - throwf("'%s' does not contain bitcode. " - "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.", file.path()); - break; - case Options::kPlatformWatchOS: -#if SUPPORT_APPLE_TV - case Options::kPlatform_tvOS: -#endif - throwf("'%s' does not contain bitcode. " - "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE) or obtain an updated library from the vendor", file.path()); - break; - } + _options.platforms().forEach(^(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop) { + if ( platformInfo(platform).supportsEmbeddedBitcode ) { + throwf("'%s' does not contain bitcode. " + "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.", file.path()); + } + else { + warning("all bitcode will be dropped because '%s' was built without bitcode. " + "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.", file.path()); + _internal.filesWithBitcode.clear(); + _internal.dropAllBitcode = true; + } + }); } } // Error on bitcode marker in non-system frameworks if -bitcode_verify is used @@ -585,69 +588,81 @@ void Resolver::doFile(const ld::File& file) dylibFile->path()); } - // update which form of ObjC dylibs are being linked - switch ( dylibFile->objCConstraint() ) { - case ld::File::objcConstraintNone: - break; - case ld::File::objcConstraintRetainRelease: - if ( _internal.objcDylibConstraint == ld::File::objcConstraintGC ) - throwf("%s built with incompatible Garbage Collection settings to link with previous dylibs", file.path()); - if ( _options.objcGcOnly() ) - throwf("command line specified -objc_gc_only, but dylib is retain/release based: %s", file.path()); - if ( _options.objcGc() ) - throwf("command line specified -objc_gc, but dylib is retain/release based: %s", file.path()); - if ( _options.targetIOSSimulator() ) - warning("linking ObjC for iOS Simulator, but dylib (%s) was compiled for MacOSX", file.path()); - _internal.objcDylibConstraint = ld::File::objcConstraintRetainRelease; - break; - case ld::File::objcConstraintRetainReleaseOrGC: - if ( _internal.objcDylibConstraint == ld::File::objcConstraintNone ) - _internal.objcDylibConstraint = ld::File::objcConstraintRetainReleaseOrGC; - if ( _options.targetIOSSimulator() ) - warning("linking ObjC for iOS Simulator, but dylib (%s) was compiled for MacOSX", file.path()); - break; - case ld::File::objcConstraintGC: - if ( _internal.objcDylibConstraint == ld::File::objcConstraintRetainRelease ) - throwf("%s built with incompatible Garbage Collection settings to link with previous dylibs", file.path()); - if ( _options.targetIOSSimulator() ) - warning("linking ObjC for iOS Simulator, but dylib (%s) was compiled for MacOSX", file.path()); - _internal.objcDylibConstraint = ld::File::objcConstraintGC; - break; - case ld::File::objcConstraintRetainReleaseForSimulator: - if ( _internal.objcDylibConstraint == ld::File::objcConstraintNone ) - _internal.objcDylibConstraint = ld::File::objcConstraintRetainReleaseForSimulator; - else if ( _internal.objcDylibConstraint != ld::File::objcConstraintRetainReleaseForSimulator ) { - warning("ObjC dylib (%s) was compiled for iOS Simulator, but dylibs others were compiled for MacOSX", file.path()); - _internal.objcDylibConstraint = ld::File::objcConstraintRetainReleaseForSimulator; + // Don't allow swift frameworks to link other swift frameworks. + if ( !_internal.firstSwiftDylibFile && _options.outputKind() == Options::kDynamicLibrary + && file.swiftVersion() != 0 && getenv("LD_DISALLOW_SWIFT_LINKING_SWIFT")) { + // Check that we aren't a whitelisted path. + bool inWhiteList = false; + const char *whitelistedPaths[] = { "/System/Library/PrivateFrameworks/Swift" }; + for (auto whitelistedPath : whitelistedPaths) { + if (!strncmp(whitelistedPath, dylibFile->installPath(), strlen(whitelistedPath))) { + inWhiteList = true; + break; } - break; + } + if (!inWhiteList) { + _internal.firstSwiftDylibFile = dylibFile; + } } + + // verify dylibs use same version of Swift language + if ( file.swiftVersion() != 0 ) { + if ( _internal.swiftVersion == 0 ) { + _internal.swiftVersion = file.swiftVersion(); + } + else if ( file.swiftVersion() != _internal.swiftVersion ) { + char fileVersion[64]; + char otherVersion[64]; + Options::userReadableSwiftVersion(file.swiftVersion(), fileVersion); + Options::userReadableSwiftVersion(_internal.swiftVersion, otherVersion); + if ( file.swiftVersion() > _internal.swiftVersion ) { + if ( _options.warnOnSwiftABIVersionMismatches() ) { + warning("%s compiled with newer version of Swift language (%s) than previous files (%s)", + file.path(), fileVersion, otherVersion); + } else { + throwf("%s compiled with newer version of Swift language (%s) than previous files (%s)", + file.path(), fileVersion, otherVersion); + } + } + else { + if ( _options.warnOnSwiftABIVersionMismatches() ) { + warning("%s compiled with older version of Swift language (%s) than previous files (%s)", + file.path(), fileVersion, otherVersion); + } else { + throwf("%s compiled with older version of Swift language (%s) than previous files (%s)", + file.path(), fileVersion, otherVersion); + } + } + } + } + if ( _options.checkDylibsAreAppExtensionSafe() && !dylibFile->appExtensionSafe() ) { warning("linking against a dylib which is not safe for use in application extensions: %s", file.path()); } const char* depInstallName = dylibFile->installPath(); // embedded frameworks are only supported on iOS 8 and later if ( (depInstallName != NULL) && (depInstallName[0] != '/') ) { - if ( (_options.iOSVersionMin() != iOSVersionUnset) && (_options.iOSVersionMin() < iOS_8_0) ) { + if ( _options.platforms().contains(ld::Platform::iOS) && !_options.platforms().minOS(iOS_8_0) ) { // only warn about linking against embedded dylib if it is built for iOS 8 or later - if ( dylibFile->minOSVersion() >= iOS_8_0 ) + if ( dylibFile->platforms().minOS(ld::iOS_8_0) ) throwf("embedded dylibs/frameworks are only supported on iOS 8.0 and later (%s)", depInstallName); } } - if ( _options.sharedRegionEligible() ) { + if ( _options.sharedRegionEligible() && !_options.debugVariant() ) { assert(depInstallName != NULL); if ( depInstallName[0] == '@' ) { warning("invalid -install_name (%s) in dependent dylib (%s). Dylibs/frameworks which might go in dyld shared cache " "cannot link with dylib that uses @rpath, @loader_path, etc.", depInstallName, dylibFile->path()); - } else if ( (strncmp(depInstallName, "/usr/lib/", 9) != 0) && (strncmp(depInstallName, "/System/Library/", 16) != 0) ) { + } + else if ( !_options.sharedCacheEligiblePath(depInstallName) ) { warning("invalid -install_name (%s) in dependent dylib (%s). Dylibs/frameworks which might go in dyld shared cache " "cannot link with dylibs that won't be in the shared cache", depInstallName, dylibFile->path()); } } } - } + void Resolver::doAtom(const ld::Atom& atom) { //fprintf(stderr, "Resolver::doAtom(%p), name=%s, sect=%s, scope=%d\n", &atom, atom.name(), atom.section().sectionName(), atom.scope()); @@ -678,14 +693,14 @@ void Resolver::doAtom(const ld::Atom& atom) } else if ( _options.outputKind() == Options::kDynamicLibrary ) { if ( atom.file() != NULL ) - warning("target OS does not support re-exporting symbol %s from %s\n", _options.demangleSymbol(name), atom.file()->path()); + warning("target OS does not support re-exporting symbol %s from %s\n", _options.demangleSymbol(name), atom.safeFilePath()); else warning("target OS does not support re-exporting symbol %s\n", _options.demangleSymbol(name)); } } else { if ( atom.file() != NULL ) - warning("cannot export hidden symbol %s from %s", _options.demangleSymbol(name), atom.file()->path()); + warning("cannot export hidden symbol %s from %s", _options.demangleSymbol(name), atom.safeFilePath()); else warning("cannot export hidden symbol %s", _options.demangleSymbol(name)); } @@ -697,7 +712,7 @@ void Resolver::doAtom(const ld::Atom& atom) (const_cast(&atom))->setScope(ld::Atom::scopeGlobal); } else { - throwf("requested re-export symbol %s is not from a dylib, but from %s\n", _options.demangleSymbol(name), atom.file()->path()); + throwf("requested re-export symbol %s is not from a dylib, but from %s\n", _options.demangleSymbol(name), atom.safeFilePath()); } } break; @@ -707,8 +722,8 @@ void Resolver::doAtom(const ld::Atom& atom) (const_cast(&atom))->setScope(ld::Atom::scopeLinkageUnit); //fprintf(stderr, "demote %s to hidden\n", name); } - if ( _options.canReExportSymbols() && _options.shouldReExport(name) ) { - throwf("requested re-export symbol %s is not from a dylib, but from %s\n", _options.demangleSymbol(name), atom.file()->path()); + if ( _options.canReExportSymbols() && _options.shouldReExport(name) && (atom.definition() != ld::Atom::definitionProxy) ) { + throwf("requested re-export symbol %s is not from a dylib, but from %s\n", _options.demangleSymbol(name), atom.safeFilePath()); } break; } @@ -723,16 +738,28 @@ void Resolver::doAtom(const ld::Atom& atom) // tell symbol table about non-static atoms if ( atom.scope() != ld::Atom::scopeTranslationUnit ) { - _symbolTable.add(atom, _options.deadCodeStrip() && (_completedInitialObjectFiles || _options.allowDeadDuplicates())); + Options::Treatment duplicates = Options::Treatment::kError; + if (_options.deadCodeStrip() ) { + if ( _options.allowDeadDuplicates() ) + duplicates = Options::Treatment::kSuppress; + else if ( _completedInitialObjectFiles ) + duplicates = Options::Treatment::kWarning; + } + _symbolTable.add(atom, duplicates); // add symbol aliases defined on the command line if ( _options.haveCmdLineAliases() ) { const std::vector& aliases = _options.cmdLineAliases(); for (std::vector::const_iterator it=aliases.begin(); it != aliases.end(); ++it) { if ( strcmp(it->realName, atom.name()) == 0 ) { - const AliasAtom* alias = new AliasAtom(atom, it->alias); - _aliasesFromCmdLine.push_back(alias); - this->doAtom(*alias); + if ( strcmp(it->realName, it->alias) == 0 ) { + warning("ignoring alias of itself '%s'", it->realName); + } + else { + const AliasAtom* alias = new AliasAtom(atom, it->alias); + _aliasesFromCmdLine.push_back(alias); + this->doAtom(*alias); + } } } } @@ -749,6 +776,19 @@ void Resolver::doAtom(const ld::Atom& atom) if ( atom.section().type() == ld::Section::typeTempAlias ) _haveAliases = true; + // error or warn about initializers + if ( (atom.section().type() == ld::Section::typeInitializerPointers) && !_havellvmProfiling ) { + switch ( _options.initializersTreatment() ) { + case Options::kError: + throwf("static initializer found in '%s'",atom.safeFilePath()); + case Options::kWarning: + warning("static initializer found in '%s'. Use -no_inits to make this an error. Use -no_warn_inits to suppress warning",atom.safeFilePath()); + break; + default: + break; + } + } + if ( _options.deadCodeStrip() ) { // add to set of dead-strip-roots, all symbols that the compiler marks as don't strip if ( atom.dontDeadStrip() ) @@ -858,18 +898,18 @@ void Resolver::resolveUndefines() if ( !_symbolTable.hasName(undef) && (_options.outputKind() != Options::kObjectFile) ) { if ( strncmp(undef, "section$", 8) == 0 ) { if ( strncmp(undef, "section$start$", 14) == 0 ) { - this->doAtom(*SectionBoundaryAtom::makeSectionBoundaryAtom(undef, true, &undef[14])); + this->doAtom(*SectionBoundaryAtom::makeSectionBoundaryAtom(undef, true, &undef[14], _options)); } else if ( strncmp(undef, "section$end$", 12) == 0 ) { - this->doAtom(*SectionBoundaryAtom::makeSectionBoundaryAtom(undef, false, &undef[12])); + this->doAtom(*SectionBoundaryAtom::makeSectionBoundaryAtom(undef, false, &undef[12], _options)); } } else if ( strncmp(undef, "segment$", 8) == 0 ) { if ( strncmp(undef, "segment$start$", 14) == 0 ) { - this->doAtom(*SegmentBoundaryAtom::makeSegmentBoundaryAtom(undef, true, &undef[14])); + this->doAtom(*SegmentBoundaryAtom::makeSegmentBoundaryAtom(undef, true, &undef[14])); } else if ( strncmp(undef, "segment$end$", 12) == 0 ) { - this->doAtom(*SegmentBoundaryAtom::makeSegmentBoundaryAtom(undef, false, &undef[12])); + this->doAtom(*SegmentBoundaryAtom::makeSegmentBoundaryAtom(undef, false, &undef[12])); } } else if ( _options.outputKind() == Options::kPreload ) { @@ -961,12 +1001,12 @@ void Resolver::markLive(const ld::Atom& atom, WhyLiveBackChain* previous) //fprintf(stderr, "markLive(%p) %s\n", &atom, atom.name()); // if -why_live cares about this symbol, then dump chain if ( (previous->referer != NULL) && _options.printWhyLive(atom.name()) ) { - fprintf(stderr, "%s from %s\n", atom.name(), atom.file()->path()); + fprintf(stderr, "%s from %s\n", atom.name(), atom.safeFilePath()); int depth = 1; for(WhyLiveBackChain* p = previous; p != NULL; p = p->previous, ++depth) { for(int i=depth; i > 0; --i) fprintf(stderr, " "); - fprintf(stderr, "%s from %s\n", p->referer->name(), p->referer->file()->path()); + fprintf(stderr, "%s from %s\n", p->referer->name(), p->referer->safeFilePath()); } } @@ -994,6 +1034,9 @@ void Resolver::markLive(const ld::Atom& atom, WhyLiveBackChain* previous) case ld::Fixup::kindSubtractTargetAddress: case ld::Fixup::kindStoreTargetAddressLittleEndian32: case ld::Fixup::kindStoreTargetAddressLittleEndian64: +#if SUPPORT_ARCH_arm64e + case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64: +#endif case ld::Fixup::kindStoreTargetAddressBigEndian32: case ld::Fixup::kindStoreTargetAddressBigEndian64: case ld::Fixup::kindStoreTargetAddressX86PCRel32: @@ -1135,8 +1178,14 @@ void Resolver::deadStripOptimize(bool force) // unset liveness, so markLive() will recurse (const_cast(atom))->setLive(0); } + // if doing LTO, mark all libclang_rt* mach-o atoms as live since the backend may suddenly codegen uses of them + else if ( _haveLLVMObjs && !force && (atom->contentType() != ld::Atom::typeLTOtemporary) ) { + if ( strstr(atom->safeFilePath(), "libclang_rt") != nullptr ) { + _deadStripRoots.insert(atom); + } + } } - + // mark all roots as live, and all atoms they reference for (std::set::iterator it=_deadStripRoots.begin(); it != _deadStripRoots.end(); ++it) { WhyLiveBackChain rootChain; @@ -1188,11 +1237,13 @@ void Resolver::deadStripOptimize(bool force) } if ( _haveLLVMObjs && !force ) { + std::copy_if(_atoms.begin(), _atoms.end(), std::back_inserter(_internal.deadAtoms), NotLiveLTO() ); // don't remove combinable atoms, they may come back in lto output _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(), NotLiveLTO()), _atoms.end()); _symbolTable.removeDeadAtoms(); } else { + std::copy_if(_atoms.begin(), _atoms.end(), std::back_inserter(_internal.deadAtoms), NotLive() ); _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(), NotLive()), _atoms.end()); } @@ -1359,11 +1410,11 @@ bool Resolver::printReferencedBy(const char* name, SymbolTable::IndirectBindingS ++foundReferenceCount; } else if ( atom->contentType() == ld::Atom::typeCFI ) { - fprintf(stderr, " Dwarf Exception Unwind Info (__eh_frame) in %s\n", pathLeafName(atom->file()->path())); + fprintf(stderr, " Dwarf Exception Unwind Info (__eh_frame) in %s\n", pathLeafName(atom->safeFilePath())); ++foundReferenceCount; } else { - fprintf(stderr, " %s in %s\n", _options.demangleSymbol(atom->name()), pathLeafName(atom->file()->path())); + fprintf(stderr, " %s in %s\n", _options.demangleSymbol(atom->name()), pathLeafName(atom->safeFilePath())); ++foundReferenceCount; break; // if undefined used twice in a function, only show first } @@ -1423,6 +1474,10 @@ void Resolver::checkUndefines(bool force) int unresolvableExportsCount = 0; if ( unresolvableCount != 0 ) { if ( doPrint ) { + for (const auto& lib : _internal.missingLinkerOptionLibraries) + warning("Could not find or use auto-linked library '%s'", lib); + for (const auto& frm : _internal.missingLinkerOptionFrameworks) + warning("Could not find or use auto-linked framework '%s'", frm); if ( _options.printArchPrefix() ) fprintf(stderr, "Undefined symbols for architecture %s:\n", _options.architectureName()); else @@ -1470,11 +1525,11 @@ void Resolver::checkUndefines(bool force) const ld::Atom* atom = *sit; if ( (atom != NULL) && (atom->symbolTableInclusion() == ld::Atom::symbolTableIn) && (strstr(atom->name(), name) != NULL) ) { if ( ! printedStart ) { - fprintf(stderr, " (maybe you meant: %s", atom->name()); + fprintf(stderr, " (maybe you meant: %s", _options.demangleSymbol(atom->name())); printedStart = true; } else { - fprintf(stderr, ", %s ", atom->name()); + fprintf(stderr, ", %s ", _options.demangleSymbol(atom->name())); } } } @@ -1579,7 +1634,8 @@ void Resolver::fillInHelpersInInternalState() } _internal.classicBindingHelper = NULL; - if ( needsStubHelper && !_options.makeCompressedDyldInfo() ) { + // FIXME: What about fMakeThreadedStartsSection? + if ( needsStubHelper && !_options.makeCompressedDyldInfo() && !_options.makeChainedFixups() ) { // "dyld_stub_binding_helper" comes from .o file, so should already exist in symbol table if ( _symbolTable.hasName("dyld_stub_binding_helper") ) { SymbolTable::IndirectBindingSlot slot = _symbolTable.findSlotForName("dyld_stub_binding_helper"); @@ -1599,6 +1655,7 @@ void Resolver::fillInHelpersInInternalState() } _internal.compressedFastBinderProxy = NULL; + // FIXME: What about fMakeThreadedStartsSection? if ( needsStubHelper && _options.makeCompressedDyldInfo() ) { // "dyld_stub_binder" comes from libSystem.dylib so will need to manually resolve if ( !_symbolTable.hasName("dyld_stub_binder") ) { @@ -1629,6 +1686,11 @@ void Resolver::fillInInternalState() // make sure there is a __text section so that codesigning works if ( (_options.outputKind() == Options::kDynamicLibrary) || (_options.outputKind() == Options::kDynamicBundle) ) _internal.getFinalSection(*new ld::Section("__TEXT", "__text", ld::Section::typeCode)); + + // Don't allow swift frameworks to link other swift frameworks. + if ( _internal.someObjectFileHasSwift && _internal.firstSwiftDylibFile != nullptr ) + throwf("linking swift frameworks against other swift frameworks (%s) is not permitted", + _internal.firstSwiftDylibFile->path()); } void Resolver::fillInEntryPoint() @@ -1698,6 +1760,11 @@ void Resolver::linkTimeOptimize() lto::OptimizeOptions optOpt; optOpt.outputFilePath = _options.outputFilePath(); optOpt.tmpObjectFilePath = _options.tempLtoObjectPath(); + optOpt.ltoCachePath = _options.ltoCachePath(); + optOpt.ltoPruneIntervalOverwrite = _options.ltoPruneIntervalOverwrite(); + optOpt.ltoPruneInterval = _options.ltoPruneInterval(); + optOpt.ltoPruneAfter = _options.ltoPruneAfter(); + optOpt.ltoMaxCacheSize = _options.ltoMaxCacheSize(); optOpt.preserveAllGlobals = _options.allGlobalsAreDeadStripRoots() || _options.hasExportRestrictList(); optOpt.verbose = _options.verbose(); optOpt.saveTemps = _options.saveTempFiles(); @@ -1705,6 +1772,7 @@ void Resolver::linkTimeOptimize() optOpt.pie = _options.positionIndependentExecutable(); optOpt.mainExecutable = _options.linkingMainExecutable();; optOpt.staticExecutable = (_options.outputKind() == Options::kStaticExecutable); + optOpt.preload = (_options.outputKind() == Options::kPreload); optOpt.relocatable = (_options.outputKind() == Options::kObjectFile); optOpt.allowTextRelocs = _options.allowTextRelocs(); optOpt.linkerDeadStripping = _options.deadCodeStrip(); @@ -1713,12 +1781,14 @@ void Resolver::linkTimeOptimize() optOpt.verboseOptimizationHints = _options.verboseOptimizationHints(); optOpt.armUsesZeroCostExceptions = _options.armUsesZeroCostExceptions(); optOpt.simulator = _options.targetIOSSimulator(); - optOpt.ignoreMismatchPlatform = ((_options.outputKind() == Options::kPreload) || (_options.outputKind() == Options::kStaticExecutable)); - optOpt.bitcodeBundle = _options.bundleBitcode(); +#if SUPPORT_ARCH_arm64e + optOpt.supportsAuthenticatedPointers = _options.supportsAuthenticatedPointers(); +#endif + optOpt.bitcodeBundle = (_options.bundleBitcode() && (_options.bitcodeKind() != Options::kBitcodeMarker)); optOpt.maxDefaultCommonAlignment = _options.maxDefaultCommonAlign(); optOpt.arch = _options.architecture(); optOpt.mcpu = _options.mcpuLTO(); - optOpt.platform = _options.platform(); + optOpt.platforms = _options.platforms(); optOpt.llvmOptions = &_options.llvmOptions(); optOpt.initialUndefines = &_options.initialUndefines(); @@ -1761,14 +1831,21 @@ void Resolver::linkTimeOptimize() // if -dead_strip on command line if ( _options.deadCodeStrip() ) { - // clear liveness bit + // run through all atoms again and make live_section LTO atoms are preserved from dead_stripping if needed + _dontDeadStripIfReferencesLive.clear(); for (std::vector::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) { + const ld::Atom* atom = *it; + if ( atom->dontDeadStripIfReferencesLive() ) { + _dontDeadStripIfReferencesLive.push_back(atom); + } + + // clear liveness bit (const_cast(*it))->setLive((*it)->dontDeadStrip()); } // and re-compute dead code this->deadStripOptimize(true); } - + // if -exported_symbols_list on command line, re-force scope if ( _options.hasExportMaskList() ) { for (std::vector::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) { @@ -1792,6 +1869,23 @@ void Resolver::linkTimeOptimize() // check new code does not override some dylib this->checkDylibSymbolCollisions(); + + // remove undefs from LTO objects that gets optimized away + std::unordered_set mustPreserve; + if ( _internal.classicBindingHelper != NULL ) + mustPreserve.insert(_internal.classicBindingHelper); + if ( _internal.compressedFastBinderProxy != NULL ) + mustPreserve.insert(_internal.compressedFastBinderProxy); + if ( _internal.lazyBindingHelper != NULL ) + mustPreserve.insert(_internal.lazyBindingHelper); + if ( const ld::Atom* entry = this->entryPoint(true) ) + mustPreserve.insert(entry); + for (Options::UndefinesIterator uit=_options.initialUndefinesBegin(); uit != _options.initialUndefinesEnd(); ++uit) { + SymbolTable::IndirectBindingSlot slot = _symbolTable.findSlotForName(*uit); + if ( _internal.indirectBindingTable[slot] != NULL ) + mustPreserve.insert(_internal.indirectBindingTable[slot]); + } + _symbolTable.removeDeadUndefs(_atoms, mustPreserve); } #else throwf("no builtin LTO support"); // ld64-port @@ -1831,6 +1925,12 @@ void Resolver::tweakWeakness() } } +void Resolver::buildArchivesList() +{ + // Determine which archives were linked and update the internal state. + _inputFiles.archives(_internal); +} + void Resolver::dumpAtoms() { fprintf(stderr, "Resolver all atoms:\n"); @@ -1857,6 +1957,7 @@ void Resolver::resolve() this->fillInInternalState(); this->tweakWeakness(); _symbolTable.checkDuplicateSymbols(); + this->buildArchivesList(); } diff --git a/cctools/ld64/src/ld/Resolver.h b/cctools/ld64/src/ld/Resolver.h index 6631d11..cced947 100644 --- a/cctools/ld64/src/ld/Resolver.h +++ b/cctools/ld64/src/ld/Resolver.h @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -64,7 +63,7 @@ public: _haveLLVMObjs(false), _completedInitialObjectFiles(false), _ltoCodeGenFinished(false), - _haveAliases(false) {} + _haveAliases(false), _havellvmProfiling(false) {} virtual void doAtom(const ld::Atom&); @@ -72,7 +71,7 @@ public: void resolve(); - + private: struct WhyLiveBackChain { @@ -102,6 +101,7 @@ private: void remainingUndefines(std::vector&); bool printReferencedBy(const char* name, SymbolTable::IndirectBindingSlot slot); void tweakWeakness(); + void buildArchivesList(); void doLinkerOption(const std::vector& linkerOption, const char* fileName); void dumpAtoms(); @@ -134,6 +134,7 @@ private: bool _completedInitialObjectFiles; bool _ltoCodeGenFinished; bool _haveAliases; + bool _havellvmProfiling; }; diff --git a/cctools/ld64/src/ld/Snapshot.cpp b/cctools/ld64/src/ld/Snapshot.cpp index bb7e549..5306bfe 100644 --- a/cctools/ld64/src/ld/Snapshot.cpp +++ b/cctools/ld64/src/ld/Snapshot.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -22,6 +23,10 @@ #include "compile_stubs.h" +#ifndef __APPLE__ // ld64-port +#include "mkpath_np.h" +#endif + //#define STORE_PID_IN_SNAPSHOT 1 // Well known snapshot file/directory names. These appear in the root of the snapshot. @@ -29,18 +34,19 @@ static const char *frameworksString = "frameworks"; // directory containing framework stubs (mach-o files) static const char *dylibsString = "dylibs"; // directory containing dylib stubs (mach-o files) static const char *archiveFilesString = "archive_files"; // directory containing .a files -static const char *origCommandLineString = "orig_command_line"; // text file containing the original command line -static const char *linkCommandString = "link_command"; // text file containing the snapshot equivalent command line -static const char *dataFilesString = "data_files"; // arbitrary data files referenced on the command line static const char *objectsString = "objects"; // directory containing object files static const char *frameworkStubsString = "framework_stubs"; // directory containing framework stub info (text files) +static const char *dataFilesString = "data_files"; // arbitrary data files referenced on the command line static const char *dylibStubsString = "dylib_stubs"; // directory containing dylib stub info (text files) +static const char *filesString = "files"; // directory containing files +static const char *origCommandLineString = "orig_command_line"; // text file containing the original command line +static const char *linkCommandString = "link_command"; // text file containing the snapshot equivalent command line static const char *assertFileString = "assert_info"; // text file containing assertion failure logs static const char *compileFileString = "compile_stubs"; // text file containing compile_stubs script Snapshot *Snapshot::globalSnapshot = NULL; -Snapshot::Snapshot() : fRecordArgs(false), fRecordObjects(false), fRecordDylibSymbols(false), fRecordArchiveFiles(false), fRecordUmbrellaFiles(false), fRecordDataFiles(false), fFrameworkArgAdded(false), fSnapshotLocation(NULL), fSnapshotName(NULL), fRootDir(NULL), fFilelistFile(-1), fCopiedArchives(NULL) +Snapshot::Snapshot(const Options * opts) : fOptions(opts), fRecordArgs(false), fRecordObjects(false), fRecordDylibSymbols(false), fRecordArchiveFiles(false), fRecordUmbrellaFiles(false), fRecordDataFiles(false), fFrameworkArgAdded(false), fRecordKext(false), fSnapshotLocation(NULL), fSnapshotName(NULL), fRootDir(NULL), fFilelistFile(-1), fCopiedArchives(NULL) { if (globalSnapshot != NULL) throw "only one snapshot supported"; @@ -65,6 +71,11 @@ void Snapshot::setSnapshotPath(const char *path) void Snapshot::setSnapshotMode(SnapshotMode mode) { + if (fRootDir == NULL) { + // free stuff + fRootDir = NULL; + } + if (fRootDir == NULL) { fRecordArgs = false; fRecordObjects = false; @@ -72,29 +83,52 @@ void Snapshot::setSnapshotMode(SnapshotMode mode) fRecordArchiveFiles = false; fRecordUmbrellaFiles = false; fRecordDataFiles = false; - + fRecordKext = false; + switch (mode) { case SNAPSHOT_DISABLED: break; case SNAPSHOT_DEBUG: fRecordArgs = fRecordObjects = fRecordDylibSymbols = fRecordArchiveFiles = fRecordUmbrellaFiles = fRecordDataFiles = true; break; + case SNAPSHOT_KEXT: + fRecordKext = fRecordArgs = fRecordObjects = fRecordDylibSymbols = fRecordArchiveFiles = fRecordUmbrellaFiles = fRecordDataFiles = true; + break; default: break; } } } -void Snapshot::setSnapshotName(const char *path) +void Snapshot::setOutputPath(const char *path) +{ + fOutputPath = strdup(path); +} + +void Snapshot::setSnapshotName() { if (fRootDir == NULL) { - const char *base = basename((char *)path); - time_t now = time(NULL); - struct tm t; - localtime_r(&now, &t); - char buf[PATH_MAX]; - snprintf(buf, sizeof(buf)-1, "%s-%4.4d-%2.2d-%2.2d-%2.2d%2.2d%2.2d.ld-snapshot", base, t.tm_year+1900, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); - fSnapshotName = strdup(buf); + if (fOutputPath == NULL) { + fSnapshotName = strdup("ld_snapshot"); + } else { + const char *base = basename((char *)fOutputPath); + if (fRecordKext) { + const char *kextobjects; + if ((kextobjects = fOptions->kextObjectsPath())) { + fSnapshotLocation = strdup(kextobjects); + } else { + fSnapshotLocation = strdup(dirname((char *)fOutputPath)); + } + asprintf((char **)&fSnapshotName, "%s.%s.ld", base, fArchString); + } else { + time_t now = time(NULL); + struct tm t; + localtime_r(&now, &t); + char buf[PATH_MAX]; + snprintf(buf, sizeof(buf)-1, "%s-%4.4d-%2.2d-%2.2d-%2.2d%2.2d%2.2d.ld-snapshot", base, t.tm_year+1900, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); + fSnapshotName = strdup(buf); + } + } } } @@ -112,7 +146,8 @@ void Snapshot::buildPath(char *buf, const char *subdir, const char *file) if (subdir) { strcat(buf, subdir); // implicitly create the subdirectory - mkdir(buf, S_IRUSR|S_IWUSR|S_IXUSR); + mode_t mode = fRecordKext ? (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) : (S_IRUSR|S_IWUSR|S_IXUSR); + mkdir(buf, mode); strcat(buf, "/"); } if (file != NULL) @@ -128,7 +163,7 @@ void Snapshot::buildUniquePath(char *buf, const char *subdir, const char *file) { buildPath(buf, subdir, file); struct stat st; - if (stat(buf, &st)==0) { + if (!fRecordKext && (stat(buf, &st)==0)) { // make it unique int counter=1; char *number = strrchr(buf, 0); @@ -140,6 +175,13 @@ void Snapshot::buildUniquePath(char *buf, const char *subdir, const char *file) } } +const char * Snapshot::subdir(const char *subdir) +{ + if (fRecordKext) { + return filesString; + } + return subdir; +} // Copy a file to the snapshot. // sourcePath is the original file @@ -150,6 +192,23 @@ void Snapshot::copyFileToSnapshot(const char *sourcePath, const char *subdir, ch { const int copyBufSize=(1<<14); // 16kb buffer static void *copyBuf = NULL; + bool inSdk; + + if (fRecordKext) { + for (const char* sdkPath : fOptions->sdkPaths()) { + const char *toolchainPath; + inSdk = (!strncmp(sdkPath, sourcePath, strlen(sdkPath))); + if (!inSdk && (toolchainPath = fOptions->toolchainPath())) + inSdk = (!strncmp(toolchainPath, sourcePath, strlen(toolchainPath))); + if (inSdk) { + if (path) { + strcpy(path, sourcePath); + } + return; + } + } + } + if (copyBuf == NULL) copyBuf = malloc(copyBufSize); @@ -157,7 +216,8 @@ void Snapshot::copyFileToSnapshot(const char *sourcePath, const char *subdir, ch char buf[PATH_MAX]; if (path == NULL) path = buf; buildUniquePath(path, subdir, file); - int out_fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); + mode_t mode = fRecordKext ? (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) : (S_IRUSR|S_IWUSR); + int out_fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, mode); int in_fd = open(sourcePath, O_RDONLY); int len; if (out_fd != -1 && in_fd != -1) { @@ -168,34 +228,42 @@ void Snapshot::copyFileToSnapshot(const char *sourcePath, const char *subdir, ch } close(in_fd); close(out_fd); -} + const char * relPath = snapshotRelativePath(path); + memmove(path, relPath, 1+strlen(relPath)); +} // Create the snapshot root directory. void Snapshot::createSnapshot() { if (fRootDir == NULL) { + + mode_t mask = umask(0); + // provide default name and location + setSnapshotName(); if (fSnapshotLocation == NULL) fSnapshotLocation = "/tmp"; - if (fSnapshotName == NULL) { - setSnapshotName("ld_snapshot"); - } - + char buf[PATH_MAX]; fRootDir = (char *)fSnapshotLocation; buildUniquePath(buf, NULL, fSnapshotName); fRootDir = strdup(buf); - if (mkdir(fRootDir, S_IRUSR|S_IWUSR|S_IXUSR)!=0) { + + int mkpatherr = mkpath_np(fRootDir, (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH|S_IXUSR|S_IXGRP|S_IXOTH)); + if ((mkpatherr!=0) && !(fRecordKext && (mkpatherr==EEXIST))) { warning("unable to create link snapshot directory: %s", fRootDir); fRootDir = NULL; setSnapshotMode(SNAPSHOT_DISABLED); // don't try to write anything if we can't create snapshot dir } - - buildPath(buf, NULL, compileFileString); - int compileScript = open(buf, O_WRONLY|O_CREAT|O_TRUNC, S_IXUSR|S_IRUSR|S_IWUSR); - write(compileScript, compile_stubs, strlen(compile_stubs)); - close(compileScript); + + if (!fRecordKext) { + buildPath(buf, NULL, compileFileString); + mode_t mode = fRecordKext ? (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) : (S_IXUSR|S_IRUSR|S_IWUSR); + int compileScript = open(buf, O_WRONLY|O_CREAT|O_TRUNC, mode); + write(compileScript, compile_stubs, strlen(compile_stubs)); + close(compileScript); + } SnapshotLog::iterator it; for (it = fLog.begin(); it != fLog.end(); it++) { @@ -206,50 +274,77 @@ void Snapshot::createSnapshot() fLog.erase(fLog.begin(), fLog.end()); if (fRecordArgs) { - writeCommandLine(fRawArgs, origCommandLineString, true); - writeCommandLine(fArgs); + writeCommandLine(true); + writeCommandLine(); } #if STORE_PID_IN_SNAPSHOT char path[PATH_MAX]; buildUniquePath(path, NULL, pidString); - int pidfile = open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); + mode = fRecordKext ? (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) : (S_IRUSR|S_IWUSR); + int pidfile = open(path, O_WRONLY|O_CREAT|O_TRUNC, mode); char pid_buf[32]; sprintf(pid_buf, "%lu\n", (long unsigned)getpid()); write(pidfile, pid_buf, strlen(pid_buf)); write(pidfile, "\n", 1); close(pidfile); #endif - + umask(mask); } } // Write the current command line vector to filename. -void Snapshot::writeCommandLine(StringVector &args, const char *filename, bool includeCWD) +void Snapshot::writeCommandLine(bool rawArgs) { + StringVector &args = rawArgs ? fRawArgs : fArgs; + const char *filename; + + if (rawArgs) { + args = fRawArgs; + filename = origCommandLineString; + } else { + args = fArgs; + filename = linkCommandString; + } + if (!isLazy() && fRecordArgs) { - // Figure out the file name and open it. - if (filename == NULL) - filename = linkCommandString; + // Open the file char path[PATH_MAX]; buildPath(path, NULL, filename); - int argsFile = open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IXUSR|S_IRUSR|S_IWUSR); + + mode_t mode = fRecordKext ? (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) : (S_IXUSR|S_IRUSR|S_IWUSR); + int argsFile = open(path, O_WRONLY|O_CREAT|O_TRUNC, mode); FILE *argsStream = fdopen(argsFile, "w"); - if (includeCWD) - fprintf(argsStream, "cd %s\n", getcwd(path, sizeof(path))); + const char* cwdPath = getcwd(path, sizeof(path)); + if (rawArgs && cwdPath) + fprintf(argsStream, "cd %s\n", cwdPath); // iterate to write args, quoting as needed - StringVector::iterator it; - for (it = args.begin(); it != args.end(); it++) { - const char *arg = *it; + unsigned idx; + unsigned idxidx; + bool inner = false; + + for (idx = idxidx = 0; idx < args.size(); idx++) { + const char *arg = args[idx]; bool needQuotes = false; + + if (fRecordKext && !rawArgs) { + if (idx == fArgIndicies[idxidx]) { + idxidx++; + if (idx > 0) { + fprintf(argsStream, "\n"); + inner = false; + } + } + } for (const char *c = arg; *c != 0 && !needQuotes; c++) { if (isspace(*c)) needQuotes = true; } - if (it != args.begin()) fprintf(argsStream, " "); + if (inner) fprintf(argsStream, " "); + inner = true; if (needQuotes) fprintf(argsStream, "\""); fprintf(argsStream, "%s", arg); if (needQuotes) fprintf(argsStream, "\""); @@ -267,7 +362,9 @@ void Snapshot::recordRawArgs(int argc, const char *argv[]) for (int i=0; iaddSnapshotLinkArg(argIndex, argCount, fileArg); })); } else { char buf[PATH_MAX]; - const char *subdir = dataFilesString; + fArgIndicies.push_back(fArgs.size()); for (int i=0, arg=argIndex; ipath(); + it = fDylibSymbols.find(dylibPath); bool isFramework = (strstr(dylibPath, "framework") != NULL); int dylibFd; if (it == fDylibSymbols.end()) { // Didn't find a file descriptor for this dylib. Create one and add it to the dylib map. char path_buf[PATH_MAX]; - buildUniquePath(path_buf, isFramework ? frameworkStubsString : dylibStubsString, dylibPath); - dylibFd = open(path_buf, O_WRONLY|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR); + buildUniquePath(path_buf, subdir(isFramework ? frameworkStubsString : dylibStubsString), dylibPath); + + mode_t mode = fRecordKext ? (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) : (S_IRUSR|S_IWUSR); + dylibFd = open(path_buf, O_WRONLY|O_APPEND|O_CREAT, mode); fDylibSymbols.insert(std::pair(dylibPath, dylibFd)); char *base_name = strdup(basename(path_buf)); if (isFramework) { @@ -419,7 +531,7 @@ void Snapshot::recordDylibSymbol(ld::dylib::File* dylibFile, const char *name) } else { addDylibArg(base_name); } - writeCommandLine(fArgs); + writeCommandLine(); } else { dylibFd = it->second; } @@ -459,6 +571,7 @@ void Snapshot::recordArchive(const char *archiveFile) fLog.push_back(Block_copy(^{ this->recordArchive(archiveFile); ::free((void *)copy); })); } else { if (fRecordArchiveFiles) { + // lazily create a vector of .a files that have been added if (fCopiedArchives == NULL) { fCopiedArchives = new StringVector; @@ -476,9 +589,15 @@ void Snapshot::recordArchive(const char *archiveFile) if (!found) { char path[PATH_MAX]; fCopiedArchives->push_back(archiveFile); - copyFileToSnapshot(archiveFile, archiveFilesString, path); - fArgs.push_back(strdup(snapshotRelativePath(path))); - writeCommandLine(fArgs); + + if (fRecordKext) { + recordObjectFile(archiveFile); + } else { + copyFileToSnapshot(archiveFile, subdir(archiveFilesString), path); + fArgIndicies.push_back(fArgs.size()); + fArgs.push_back(strdup(path)); + writeCommandLine(); + } } } } @@ -493,7 +612,7 @@ void Snapshot::recordSubUmbrella(const char *frameworkPath) if (fRecordUmbrellaFiles) { const char *framework = basename((char *)frameworkPath); char buf[PATH_MAX], wrapper[PATH_MAX]; - strcpy(wrapper, frameworksString); + strcpy(wrapper, subdir(frameworksString)); buildPath(buf, wrapper, NULL); // ensure the frameworks directory exists strcat(wrapper, "/"); strcat(wrapper, framework); @@ -511,7 +630,7 @@ void Snapshot::recordSubLibrary(const char *dylibPath) fLog.push_back(Block_copy(^{ this->recordSubLibrary(copy); ::free((void *)copy); })); } else { if (fRecordUmbrellaFiles) { - copyFileToSnapshot(dylibPath, dylibsString); + copyFileToSnapshot(dylibPath, subdir(dylibsString)); addDylibArg(basename((char *)dylibPath)); } } @@ -530,7 +649,8 @@ void Snapshot::recordAssertionMessage(const char *fmt, ...) } else { char path[PATH_MAX]; buildPath(path, NULL, assertFileString); - int log = open(path, O_WRONLY|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR); + mode_t mode = fRecordKext ? (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) : (S_IRUSR|S_IWUSR); + int log = open(path, O_WRONLY|O_APPEND|O_CREAT, mode); write(log, msg, strlen(msg)); close(log); free(msg); diff --git a/cctools/ld64/src/ld/Snapshot.h b/cctools/ld64/src/ld/Snapshot.h index c670ada..596b167 100644 --- a/cctools/ld64/src/ld/Snapshot.h +++ b/cctools/ld64/src/ld/Snapshot.h @@ -26,9 +26,10 @@ public: typedef enum { SNAPSHOT_DISABLED, // nothing is recorded SNAPSHOT_DEBUG, // records: .o, .dylib, .framework, .a, and other data files + SNAPSHOT_KEXT, // records: .o, .a, and other data files } SnapshotMode; - Snapshot(); + Snapshot(const Options * opts); ~Snapshot(); // Control the data captured in the snapshot @@ -36,7 +37,7 @@ public: // Use the basename of path to construct the snapshot name. // Must be called prior to createSnapshot(). - void setSnapshotName(const char *path); + void setOutputPath(const char *path); // Set the directory in which the snapshot will be created. // Must be called prior to createSnapshot(). @@ -96,12 +97,18 @@ private: typedef std::vector StringVector; typedef std::map DylibMap; typedef std::map PathMap; - + typedef std::vector IntVector; // Write the current contents of the args vector to a file in the snapshot. // If filename is NULL then "link_command" is used. // This is used to write both the original and the "cooked" versions of the link command - void writeCommandLine(StringVector &args, const char *filename=NULL, bool includeCWD=false); + void writeCommandLine(bool rawArgs=false); + + // + void setSnapshotName(); + + // + const char * subdir(const char *subdir); // Construct a path in the snapshot. // buf is a sring buffer in which the path is constructed @@ -127,6 +134,8 @@ private: void addFrameworkArg(const char *framework); void addDylibArg(const char *dylib); + + const Options * fOptions; #if __has_extension(blocks) // ld64-port SnapshotLog fLog; // log of events that recorded data in a snapshot prior to createSnapshot() #endif @@ -137,14 +146,18 @@ private: bool fRecordUmbrellaFiles; // record re-exported sub frameworks/dylibs bool fRecordDataFiles; // record other data files bool fFrameworkArgAdded; + bool fRecordKext; const char *fSnapshotLocation; // parent directory of frootDir const char *fSnapshotName; // a string to use in constructing the snapshot name + const char *fOutputPath; // -o path char *fRootDir; // root directory of the snapshot + const char *fArchString; int fFilelistFile; // file descriptor to the open text file used for the -filelist StringVector fRawArgs; // stores the raw command line args StringVector fArgs; // stores the "cooked" command line args + IntVector fArgIndicies; // where args start in fArgs PathMap fPathMap; // mapping of original paths->snapshot paths for copied files DylibMap fDylibSymbols; // map of dylib names to string vector containing referenced symbol names diff --git a/cctools/ld64/src/ld/SymbolTable.cpp b/cctools/ld64/src/ld/SymbolTable.cpp index c8dbcba..023c429 100644 --- a/cctools/ld64/src/ld/SymbolTable.cpp +++ b/cctools/ld64/src/ld/SymbolTable.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -117,31 +116,44 @@ bool SymbolTable::ReferencesHashFuncs::operator()(const ld::Atom* left, const ld } -void SymbolTable::addDuplicateSymbol(const char *name, const ld::Atom *atom) +void SymbolTable::addDuplicateSymbolError(const char* name, const ld::Atom* atom) +{ + addDuplicateSymbol(_duplicateSymbolErrors, name, atom); +} + +void SymbolTable::addDuplicateSymbolWarning(const char* name, const ld::Atom* atom) +{ + addDuplicateSymbol(_duplicateSymbolWarnings, name, atom); +} + +void SymbolTable::addDuplicateSymbol(DuplicateSymbols& dups, const char *name, const ld::Atom *atom) { // Look up or create the file list for name. - DuplicateSymbols::iterator symbolsIterator = _duplicateSymbols.find(name); + DuplicateSymbols::iterator symbolsIterator = dups.find(name); DuplicatedSymbolAtomList *atoms = NULL; - if (symbolsIterator != _duplicateSymbols.end()) { + if (symbolsIterator != dups.end()) { atoms = symbolsIterator->second; - } else { - atoms = new std::vector; - _duplicateSymbols.insert(std::pair(name, atoms)); } - + else { + atoms = new std::vector; + dups.insert(std::pair(name, atoms)); + } + // check if file is already in the list, add it if not bool found = false; for (DuplicatedSymbolAtomList::iterator it = atoms->begin(); !found && it != atoms->end(); it++) - if (strcmp((*it)->file()->path(), atom->file()->path()) == 0) + if (strcmp((*it)->safeFilePath(), atom->safeFilePath()) == 0) found = true; if (!found) atoms->push_back(atom); } + void SymbolTable::checkDuplicateSymbols() const { + // print duplicate errors bool foundDuplicate = false; - for (DuplicateSymbols::const_iterator symbolIt = _duplicateSymbols.begin(); symbolIt != _duplicateSymbols.end(); symbolIt++) { + for (DuplicateSymbols::const_iterator symbolIt = _duplicateSymbolErrors.begin(); symbolIt != _duplicateSymbolErrors.end(); symbolIt++) { DuplicatedSymbolAtomList *atoms = symbolIt->second; bool reportDuplicate; if (_options.deadCodeStrip()) { @@ -156,20 +168,29 @@ void SymbolTable::checkDuplicateSymbols() const } if (reportDuplicate) { foundDuplicate = true; - fprintf(stderr, "duplicate symbol %s in:\n", symbolIt->first); + fprintf(stderr, "duplicate symbol '%s' in:\n", _options.demangleSymbol(symbolIt->first)); for (DuplicatedSymbolAtomList::iterator atomIt = atoms->begin(); atomIt != atoms->end(); atomIt++) { - fprintf(stderr, " %s\n", (*atomIt)->file()->path()); + fprintf(stderr, " %s\n", (*atomIt)->safeFilePath()); } } } if (foundDuplicate) - throwf("%d duplicate symbol%s", (int)_duplicateSymbols.size(), _duplicateSymbols.size()==1?"":"s"); + throwf("%d duplicate symbol%s", (int)_duplicateSymbolErrors.size(), _duplicateSymbolErrors.size()==1?"":"s"); + + // print duplicates warnings + for (DuplicateSymbols::const_iterator symbolIt = _duplicateSymbolWarnings.begin(); symbolIt != _duplicateSymbolWarnings.end(); symbolIt++) { + std::string msg = "duplicate symbol '" + std::string(_options.demangleSymbol(symbolIt->first)) + "' in:"; + for (const ld::Atom* atom : *symbolIt->second) { + msg += "\n " + std::string(atom->safeFilePath()); + } + warning("%s", msg.c_str()); + } } // AtomPicker encapsulates the logic for picking which atom to use when adding an atom by name results in a collision class NameCollisionResolution { public: - NameCollisionResolution(const ld::Atom& a, const ld::Atom& b, bool ignoreDuplicates, const Options& options) : _atomA(a), _atomB(b), _options(options), _reportDuplicate(false), _ignoreDuplicates(ignoreDuplicates) { + NameCollisionResolution(const ld::Atom& a, const ld::Atom& b, Options::Treatment duplicates, const Options& options) : _atomA(a), _atomB(b), _options(options), _reportDuplicate(false), _duplicates(duplicates) { pickAtom(); } @@ -178,15 +199,16 @@ public: bool choseAtom(const ld::Atom& atom) { return _chosen == &atom; } // Returns true if the two atoms should be reported as a duplicate symbol - bool reportDuplicate() { return _reportDuplicate; } - + bool reportDuplicateError() { return _reportDuplicate && (_duplicates == Options::Treatment::kError); } + bool reportDuplicateWarning() { return _reportDuplicate && (_duplicates == Options::Treatment::kWarning); } + private: const ld::Atom& _atomA; const ld::Atom& _atomB; const Options& _options; const ld::Atom* _chosen; bool _reportDuplicate; - bool _ignoreDuplicates; + Options::Treatment _duplicates; void pickAtom(const ld::Atom& atom) { _chosen = &atom; } // primitive to set which atom is picked void pickAtomA() { pickAtom(_atomA); } // primitive to pick atom A @@ -266,11 +288,19 @@ private: pickAtomB(); } else { - if ( _ignoreDuplicates ) { - pickLowerOrdinal(); - } - else { - _reportDuplicate = true; + switch (_duplicates) { + case Options::Treatment::kError: + _reportDuplicate = true; + break; + case Options::Treatment::kWarning: + pickLowerOrdinal(); + _reportDuplicate = true; + break; + case Options::Treatment::kSuppress: + pickLowerOrdinal(); + break; + default: + break; } } } @@ -284,18 +314,18 @@ private: case Options::kCommonsIgnoreDylibs: if ( _options.warnCommons() ) warning("using common symbol %s from %s and ignoring defintion from dylib %s", - proxy.name(), proxy.file()->path(), dylib.file()->path()); + proxy.name(), proxy.safeFilePath(), dylib.safeFilePath()); pickAtom(dylib); break; case Options::kCommonsOverriddenByDylibs: if ( _options.warnCommons() ) warning("replacing common symbol %s from %s with true definition from dylib %s", - proxy.name(), proxy.file()->path(), dylib.file()->path()); + proxy.name(), proxy.safeFilePath(), dylib.safeFilePath()); pickAtom(proxy); break; case Options::kCommonsConflictsDylibsError: throwf("common symbol %s from %s conflicts with defintion from dylib %s", - proxy.name(), proxy.file()->path(), dylib.file()->path()); + proxy.name(), proxy.safeFilePath(), dylib.safeFilePath()); } } @@ -307,7 +337,7 @@ private: } else if ( _atomB.combine() == ld::Atom::combineByName ) { pickAtomA(); } else { - throwf("symbol %s exported from both %s and %s\n", _atomA.name(), _atomA.file()->path(), _atomB.file()->path()); + throwf("symbol %s exported from both %s and %s\n", _atomA.name(), _atomA.safeFilePath(), _atomB.safeFilePath()); } } @@ -322,10 +352,8 @@ private: break; case ld::Atom::definitionTentative: if ( _atomB.size() > _atomA.size() ) { - const char* atomApath = (_atomA.file() != NULL) ? _atomA.file()->path() : ""; - const char* atomBpath = (_atomB.file() != NULL) ? _atomB.file()->path() : ""; warning("tentative definition of '%s' with size %llu from '%s' is being replaced by real definition of smaller size %llu from '%s'", - _atomA.name(), _atomB.size(), atomBpath, _atomA.size(), atomApath); + _atomA.name(), _atomB.size(), _atomB.safeFilePath(), _atomA.size(), _atomA.safeFilePath()); } pickAtomA(); break; @@ -342,10 +370,8 @@ private: switch (_atomB.definition()) { case ld::Atom::definitionRegular: if ( _atomA.size() > _atomB.size() ) { - const char* atomApath = (_atomA.file() != NULL) ? _atomA.file()->path() : ""; - const char* atomBpath = (_atomB.file() != NULL) ? _atomB.file()->path() : ""; warning("tentative definition of '%s' with size %llu from '%s' is being replaced by real definition of smaller size %llu from '%s'", - _atomA.name(), _atomA.size(),atomApath, _atomB.size(), atomBpath); + _atomA.name(), _atomA.size(),_atomA.safeFilePath(), _atomB.size(), _atomB.safeFilePath()); } pickAtomB(); break; @@ -408,7 +434,7 @@ private: #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif -bool SymbolTable::addByName(const ld::Atom& newAtom, bool ignoreDuplicates) +bool SymbolTable::addByName(const ld::Atom& newAtom, Options::Treatment duplicates) { bool useNew = true; assert(newAtom.name() != NULL); @@ -418,10 +444,14 @@ bool SymbolTable::addByName(const ld::Atom& newAtom, bool ignoreDuplicates) //fprintf(stderr, "addByName(%p) name=%s, slot=%u, existing=%p\n", &newAtom, newAtom.name(), slot, existingAtom); if ( existingAtom != NULL ) { assert(&newAtom != existingAtom); - NameCollisionResolution picker(newAtom, *existingAtom, ignoreDuplicates, _options); - if (picker.reportDuplicate()) { - addDuplicateSymbol(name, existingAtom); - addDuplicateSymbol(name, &newAtom); + NameCollisionResolution picker(newAtom, *existingAtom, duplicates, _options); + if ( picker.reportDuplicateError() ) { + addDuplicateSymbolError(name, existingAtom); + addDuplicateSymbolError(name, &newAtom); + } + else if ( picker.reportDuplicateWarning() ) { + addDuplicateSymbolWarning(name, existingAtom); + addDuplicateSymbolWarning(name, &newAtom); } useNew = picker.choseAtom(newAtom); } @@ -496,14 +526,14 @@ bool SymbolTable::addByReferences(const ld::Atom& newAtom) } -bool SymbolTable::add(const ld::Atom& atom, bool ignoreDuplicates) +bool SymbolTable::add(const ld::Atom& atom, Options::Treatment duplicates) { //fprintf(stderr, "SymbolTable::add(%p), name=%s\n", &atom, atom.name()); assert(atom.scope() != ld::Atom::scopeTranslationUnit); switch ( atom.combine() ) { case ld::Atom::combineNever: case ld::Atom::combineByName: - return this->addByName(atom, ignoreDuplicates); + return this->addByName(atom, duplicates); break; case ld::Atom::combineByNameAndContent: return this->addByContent(atom); @@ -519,7 +549,7 @@ bool SymbolTable::add(const ld::Atom& atom, bool ignoreDuplicates) void SymbolTable::markCoalescedAway(const ld::Atom* atom) { // remove this from list of all atoms used - //fprintf(stderr, "markCoalescedAway(%p) from %s\n", atom, atom->file()->path()); + //fprintf(stderr, "markCoalescedAway(%p) from %s\n", atom, atom->safeFilePath()); (const_cast(atom))->setCoalescedAway(); // @@ -878,6 +908,41 @@ const ld::Atom* SymbolTable::indirectAtom(IndirectBindingSlot slot) const return _indirectBindingTable[slot]; } + +void SymbolTable::removeDeadUndefs(std::vector& allAtoms, const std::unordered_set& keep) +{ + // mark the indirect entries in use + std::vector indirectUsed; + for (size_t i=0; i < _indirectBindingTable.size(); ++i) + indirectUsed.push_back(false); + for (const ld::Atom* atom : allAtoms) { + for (auto it = atom->fixupsBegin(); it != atom->fixupsEnd(); ++it) { + switch (it->binding) { + case ld::Fixup::bindingsIndirectlyBound: + indirectUsed[it->u.bindingIndex] = true; + break; + default: + break; + } + } + } + + // any indirect entry not in use which points to an undefined proxy can be removed + for (size_t slot=0; slot < indirectUsed.size(); ++slot) { + if ( !indirectUsed[slot] ) { + const ld::Atom* atom = _indirectBindingTable[slot]; + if ( (atom != nullptr) && (atom->definition() == ld::Atom::definitionProxy) && (keep.count(atom) == 0) ) { + const char* name = atom->name(); + _indirectBindingTable[slot] = NULL; + _byNameReverseTable.erase(slot); + _byNameTable.erase(name); + allAtoms.erase(std::remove(allAtoms.begin(), allAtoms.end(), atom), allAtoms.end()); + } + } + } + +} + void SymbolTable::printStatistics() { // fprintf(stderr, "cstring table size: %lu, bucket count: %lu, hash func called %u times\n", @@ -907,7 +972,7 @@ void SymbolTable::printStatistics() //ReferencesHash obj; //for(ReferencesHashToSlot::iterator it=_byReferencesTable.begin(); it != _byReferencesTable.end(); ++it) { // if ( obj.operator()(it->first) == 0x2F3AC0EAC744EA70 ) { - // fprintf(stderr, "hash=0x2F3AC0EAC744EA70 for %p %s from %s\n", it->first, it->first->name(), it->first->file()->path()); + // fprintf(stderr, "hash=0x2F3AC0EAC744EA70 for %p %s from %s\n", it->first, it->first->name(), it->first->safeFilePath()); // // } //} diff --git a/cctools/ld64/src/ld/SymbolTable.h b/cctools/ld64/src/ld/SymbolTable.h index 2708f1f..bb5dec5 100644 --- a/cctools/ld64/src/ld/SymbolTable.h +++ b/cctools/ld64/src/ld/SymbolTable.h @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -112,7 +111,7 @@ public: SymbolTable(const Options& opts, std::vector& ibt); - bool add(const ld::Atom& atom, bool ignoreDuplicates); + bool add(const ld::Atom& atom, Options::Treatment duplicates); IndirectBindingSlot findSlotForName(const char* name); IndirectBindingSlot findSlotForContent(const ld::Atom* atom, const ld::Atom** existingAtom); IndirectBindingSlot findSlotForReferences(const ld::Atom* atom, const ld::Atom** existingAtom); @@ -127,7 +126,8 @@ public: byNameIterator begin() { return byNameIterator(_byNameTable.begin(),_indirectBindingTable); } byNameIterator end() { return byNameIterator(_byNameTable.end(),_indirectBindingTable); } void printStatistics(); - + void removeDeadUndefs(std::vector& allAtoms, const std::unordered_set& keep); + // from ld::IndirectBindingTable virtual const char* indirectName(IndirectBindingSlot slot) const; virtual const ld::Atom* indirectAtom(IndirectBindingSlot slot) const; @@ -137,14 +137,16 @@ public: private: - bool addByName(const ld::Atom& atom, bool ignoreDuplicates); + bool addByName(const ld::Atom& atom, Options::Treatment duplicates); bool addByContent(const ld::Atom& atom); bool addByReferences(const ld::Atom& atom); void markCoalescedAway(const ld::Atom* atom); // Tracks duplicated symbols. Each call adds file to the list of files defining symbol. // The file list is uniqued per symbol, so calling multiple times for the same symbol/file pair is permitted. - void addDuplicateSymbol(const char *symbol, const ld::Atom* atom); + void addDuplicateSymbol(DuplicateSymbols& dups, const char* symbol, const ld::Atom* atom); + void addDuplicateSymbolError(const char* name, const ld::Atom* atom); + void addDuplicateSymbolWarning(const char* name, const ld::Atom* atom); const Options& _options; NameToSlot _byNameTable; @@ -163,8 +165,8 @@ private: std::vector& _indirectBindingTable; bool _hasExternalTentativeDefinitions; - DuplicateSymbols _duplicateSymbols; - + DuplicateSymbols _duplicateSymbolErrors; + DuplicateSymbols _duplicateSymbolWarnings; }; } // namespace tool diff --git a/cctools/ld64/src/ld/debugline.c b/cctools/ld64/src/ld/debugline.c index c4e151d..dd43c63 100644 --- a/cctools/ld64/src/ld/debugline.c +++ b/cctools/ld64/src/ld/debugline.c @@ -22,6 +22,7 @@ */ #ifndef KLD #include +#include /* cctools-port: For bcmp, bzero ... */ #include #include #include diff --git a/cctools/ld64/src/ld/ld.cpp b/cctools/ld64/src/ld/ld.cpp index f4c48d8..8d42aca 100644 --- a/cctools/ld64/src/ld/ld.cpp +++ b/cctools/ld64/src/ld/ld.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -49,6 +48,7 @@ #include #include +#include #include #include #include @@ -75,9 +75,11 @@ #include "passes/got.h" #include "passes/tlvp.h" #include "passes/huge.h" +#include "passes/inits.h" #include "passes/compact_unwind.h" #include "passes/order.h" #include "passes/branch_island.h" +#include "passes/thread_starts.h" #include "passes/branch_shim.h" #include "passes/objc.h" #include "passes/dylibs.h" @@ -91,6 +93,8 @@ #include "parsers/opaque_section_file.h" +const ld::VersionSet ld::File::_platforms; + struct PerformanceStatistics { uint64_t startTool; uint64_t startInputFileProcessing; @@ -120,12 +124,13 @@ public: virtual ~InternalState() {} private: + bool inMoveRWChain(const ld::Atom& atom, const char* filePath, const char*& dstSeg, bool& wildCardMatch); + bool inMoveROChain(const ld::Atom& atom, const char* filePath, const char*& dstSeg, bool& wildCardMatch); class FinalSection : public ld::Internal::FinalSection { public: FinalSection(const ld::Section& sect, uint32_t sectionsSeen, const Options&); - static int sectionComparer(const void* l, const void* r); static const ld::Section& outputSection(const ld::Section& sect, bool mergeZeroFill); static const ld::Section& objectOutputSection(const ld::Section& sect, const Options&); private: @@ -163,6 +168,7 @@ private: SectionInToOut _sectionInToFinalMap; const Options& _options; bool _atomsOrderedInSections; + std::unordered_map _pendingSegMove; }; ld::Section InternalState::FinalSection::_s_DATA_data( "__DATA", "__data", ld::Section::typeUnclassified); @@ -198,7 +204,7 @@ InternalState::FinalSection::FinalSection(const ld::Section& sect, uint32_t sect _segmentOrder(segmentOrder(sect, opts)), _sectionOrder(sectionOrder(sect, sectionsSeen, opts)) { - //fprintf(stderr, "FinalSection(%s, %s) _segmentOrder=%d, _sectionOrder=%d\n", + //fprintf(stderr, "FinalSection(%16s, %16s) _segmentOrder=%3d, _sectionOrder=0x%08X\n", // this->segmentName(), this->sectionName(), _segmentOrder, _sectionOrder); } @@ -292,18 +298,36 @@ uint32_t InternalState::FinalSection::segmentOrder(const ld::Section& sect, cons if ( strcmp(sect.segmentName(), "__DATA") == 0 ) return order.size()+2; } + else if ( options.outputKind() == Options::kStaticExecutable ) { + const std::vector& order = options.segmentOrder(); + for (size_t i=0; i != order.size(); ++i) { + if ( strcmp(sect.segmentName(), order[i]) == 0 ) + return i+1; + } + if ( strcmp(sect.segmentName(), "__PAGEZERO") == 0 ) + return 0; + if ( strcmp(sect.segmentName(), "__TEXT") == 0 ) + return order.size()+1; + if ( strcmp(sect.segmentName(), "__DATA") == 0 ) + return order.size()+2; + } else { + bool armCloseStubs = (options.architecture() == CPU_TYPE_ARM) && !options.sharedRegionEligible() && !options.makeEncryptable() && !options.makeChainedFixups(); if ( strcmp(sect.segmentName(), "__PAGEZERO") == 0 ) return 0; if ( strcmp(sect.segmentName(), "__TEXT") == 0 ) return 1; + if ( strcmp(sect.segmentName(), "__TEXT_EXEC") == 0 ) + return 2; + if ( strcmp(sect.segmentName(), "__DATA_CONST") == 0 ) + return ((options.outputKind() == Options::kKextBundle) || armCloseStubs) ? 5 : 3; // in -r mode, want __DATA last so zerofill sections are at end - if ( strcmp(sect.segmentName(), "__DATA") == 0 ) - return (options.outputKind() == Options::kObjectFile) ? 5 : 2; + if ( strcmp(sect.segmentName(), "__DATA") == 0 ) + return (options.outputKind() == Options::kObjectFile) ? 7 : 4; if ( strcmp(sect.segmentName(), "__OBJC") == 0 ) - return 3; - if ( strcmp(sect.segmentName(), "__IMPORT") == 0 ) - return 4; + return 5; + if ( strcmp(sect.segmentName(), "__IMPORT") == 0 ) + return 6; } // layout non-standard segments in order seen (+100 to shift beyond standard segments) for (uint32_t i=0; i < _s_segmentsSeen.size(); ++i) { @@ -342,14 +366,30 @@ uint32_t InternalState::FinalSection::sectionOrder(const ld::Section& sect, uint return 12; case ld::Section::typeStubHelper: return 13; + case ld::Section::typeInitOffsets: + return 14; + case ld::Section::typeThreadStarts: + return INT_MAX-8; case ld::Section::typeLSDA: - return INT_MAX-3; + return INT_MAX-7; case ld::Section::typeUnwindInfo: - return INT_MAX-2; + return INT_MAX-6; case ld::Section::typeCFI: - return INT_MAX-1; + return INT_MAX-5; case ld::Section::typeStubClose: - return INT_MAX; + return INT_MAX - 3; + case ld::Section::typeNonStdCString: + if ( (strcmp(sect.sectionName(), "__oslogstring") == 0) && options.makeEncryptable() ) + return INT_MAX-4; + if ( options.sharedRegionEligible() ) { + if ( (strcmp(sect.sectionName(), "__objc_classname") == 0) ) + return INT_MAX - 2; + if ( (strcmp(sect.sectionName(), "__objc_methname") == 0) ) + return INT_MAX - 1; + if ( (strcmp(sect.sectionName(), "__objc_methtype") == 0) ) + return INT_MAX; + } + return sectionsSeen+20; default: return sectionsSeen+20; } @@ -369,16 +409,18 @@ uint32_t InternalState::FinalSection::sectionOrder(const ld::Section& sect, uint case ld::Section::typeTerminatorPointers: return 13; case ld::Section::typeTLVInitialValues: - return INT_MAX-4; // need TLV zero-fill to follow TLV init values + return INT_MAX-259; // need TLV zero-fill to follow TLV init values case ld::Section::typeTLVZeroFill: - return INT_MAX-3; + return INT_MAX-258; case ld::Section::typeZeroFill: // make sure __huge is always last zerofill section if ( strcmp(sect.sectionName(), "__huge") == 0 ) return INT_MAX-1; else - return INT_MAX-2; + return INT_MAX-256+sectionsSeen; // zero fill need to be last and in "seen" order default: + if ( strcmp(sect.sectionName(), "__auth_ptr") == 0 ) + return 11; // __DATA,__const section should be near __mod_init_func not __data if ( strcmp(sect.sectionName(), "__const") == 0 ) return 14; @@ -414,13 +456,15 @@ uint32_t InternalState::FinalSection::sectionOrder(const ld::Section& sect, uint return 32; else if ( strcmp(sect.sectionName(), "__objc_data") == 0 ) return 33; + else if ( strcmp(sect.sectionName(), "__objc_const_ax") == 0 ) + return 34; else return sectionsSeen+40; } } // make sure zerofill in any other section is at end of segment if ( sect.type() == ld::Section::typeZeroFill ) - return INT_MAX-1; + return INT_MAX-256+sectionsSeen; return sectionsSeen+20; } @@ -539,10 +583,90 @@ bool InternalState::hasReferenceToWeakExternal(const ld::Atom& atom) return false; } +bool InternalState::inMoveRWChain(const ld::Atom& atom, const char* filePath, const char*& dstSeg, bool& wildCardMatch) +{ + if ( !_options.hasDataSymbolMoves() ) + return false; + + auto pos = _pendingSegMove.find(&atom); + if ( pos != _pendingSegMove.end() ) { + dstSeg = pos->second; + return true; + } + + bool result = false; + if ( _options.moveRwSymbol(atom.name(), filePath, dstSeg, wildCardMatch) ) + result = true; + + for (ld::Fixup::iterator fit=atom.fixupsBegin(); fit != atom.fixupsEnd(); ++fit) { + if ( fit->kind == ld::Fixup::kindNoneFollowOn ) { + if ( fit->binding == ld::Fixup::bindingDirectlyBound ) { + if ( inMoveRWChain(*(fit->u.target), filePath, dstSeg, wildCardMatch) ) + result = true; + } + } + } + + if ( result ) { + for (ld::Fixup::iterator fit=atom.fixupsBegin(); fit != atom.fixupsEnd(); ++fit) { + if ( fit->kind == ld::Fixup::kindNoneFollowOn ) { + if ( fit->binding == ld::Fixup::bindingDirectlyBound ) { + _pendingSegMove[fit->u.target] = dstSeg; + } + } + } + } + + return result; +} + + +bool InternalState::inMoveROChain(const ld::Atom& atom, const char* filePath, const char*& dstSeg, bool& wildCardMatch) +{ + if ( !_options.hasCodeSymbolMoves() ) + return false; + + auto pos = _pendingSegMove.find(&atom); + if ( pos != _pendingSegMove.end() ) { + dstSeg = pos->second; + return true; + } + + bool result = false; + if ( _options.moveRoSymbol(atom.name(), filePath, dstSeg, wildCardMatch) ) + result = true; + + for (ld::Fixup::iterator fit=atom.fixupsBegin(); fit != atom.fixupsEnd(); ++fit) { + if ( fit->kind == ld::Fixup::kindNoneFollowOn ) { + if ( fit->binding == ld::Fixup::bindingDirectlyBound ) { + if ( inMoveROChain(*(fit->u.target), filePath, dstSeg, wildCardMatch) ) + result = true; + } + } + } + + if ( result ) { + for (ld::Fixup::iterator fit=atom.fixupsBegin(); fit != atom.fixupsEnd(); ++fit) { + if ( fit->kind == ld::Fixup::kindNoneFollowOn ) { + if ( fit->binding == ld::Fixup::bindingDirectlyBound ) { + _pendingSegMove[fit->u.target] = dstSeg; + } + } + } + } + + return result; +} + + + + ld::Internal::FinalSection* InternalState::addAtom(const ld::Atom& atom) { + //fprintf(stderr, "addAtom: %s\n", atom.name()); ld::Internal::FinalSection* fs = NULL; - const char* sectName = atom.section().sectionName(); + const char* curSectName = atom.section().sectionName(); + const char* curSegName = atom.section().segmentName(); ld::Section::Type sectType = atom.section().type(); const ld::File* f = atom.file(); const char* path = (f != NULL) ? f->path() : NULL; @@ -550,79 +674,98 @@ ld::Internal::FinalSection* InternalState::addAtom(const ld::Atom& atom) // tentative defintions don't have a real section name yet sectType = ld::Section::typeZeroFill; if ( _options.mergeZeroFill() ) - sectName = FinalSection::_s_DATA_zerofill.sectionName(); + curSectName = FinalSection::_s_DATA_zerofill.sectionName(); else - sectName = FinalSection::_s_DATA_common.sectionName(); + curSectName = FinalSection::_s_DATA_common.sectionName(); } // Support for -move_to_r._segment if ( atom.symbolTableInclusion() == ld::Atom::symbolTableIn ) { const char* dstSeg; - //fprintf(stderr, "%s\n", atom.name()); bool wildCardMatch; - if ( _options.moveRwSymbol(atom.name(), path, dstSeg, wildCardMatch) ) { + if ( inMoveRWChain(atom, path, dstSeg, wildCardMatch) ) { if ( (sectType != ld::Section::typeZeroFill) && (sectType != ld::Section::typeUnclassified) && (sectType != ld::Section::typeTentativeDefs) + && (sectType != ld::Section::typeTLVDefs) && (sectType != ld::Section::typeDyldInfo) ) { if ( !wildCardMatch ) warning("cannot move symbol '%s' from file %s to segment '%s' because symbol is not data (is %d)", atom.name(), path, dstSeg, sectType); } else { + curSegName = dstSeg; if ( _options.traceSymbolLayout() ) - printf("symbol '%s', -move_to_rw_segment mapped it to %s/%s\n", atom.name(), dstSeg, sectName); - fs = this->getFinalSection(dstSeg, sectName, sectType); + printf("symbol '%s', -move_to_rw_segment mapped it to %s/%s\n", atom.name(), curSegName, curSectName); + fs = this->getFinalSection(curSegName, curSectName, sectType); } } - if ( (fs == NULL) && _options.moveRoSymbol(atom.name(), path, dstSeg, wildCardMatch) ) { + if ( (fs == NULL) && inMoveROChain(atom, path, dstSeg, wildCardMatch) ) { if ( (sectType != ld::Section::typeCode) && (sectType != ld::Section::typeUnclassified) ) { if ( !wildCardMatch ) warning("cannot move symbol '%s' from file %s to segment '%s' because symbol is not code (is %d)", atom.name(), path, dstSeg, sectType); } else { + curSegName = dstSeg; if ( _options.traceSymbolLayout() ) - printf("symbol '%s', -move_to_ro_segment mapped it to %s/%s\n", atom.name(), dstSeg, sectName); - fs = this->getFinalSection(dstSeg, sectName, ld::Section::typeCode); + printf("symbol '%s', -move_to_ro_segment mapped it to %s/%s\n", atom.name(), curSegName, curSectName); + fs = this->getFinalSection(curSegName, curSectName, ld::Section::typeCode); } } } - // support for -rename_section and -rename_segment - if ( fs == NULL ) { - const std::vector& sectRenames = _options.sectionRenames(); - const std::vector& segRenames = _options.segmentRenames(); - for ( std::vector::const_iterator it=sectRenames.begin(); it != sectRenames.end(); ++it) { - if ( (strcmp(sectName, it->fromSection) == 0) && (strcmp(atom.section().segmentName(), it->fromSegment) == 0) ) { - if ( _options.useDataConstSegment() && (strcmp(sectName, "__const") == 0) - && (strcmp(atom.section().segmentName(), "__DATA") == 0) && hasReferenceToWeakExternal(atom) ) { - // if __DATA,__const atom has pointer to weak external symbol, don't move to __DATA_CONST - fs = this->getFinalSection("__DATA", "__const_weak", sectType); - if ( _options.traceSymbolLayout() ) - printf("symbol '%s', contains pointers to weak symbols, so mapped it to __DATA/_const_weak\n", atom.name()); - } - else if ( _options.useDataConstSegment() && (sectType == ld::Section::typeNonLazyPointer) && hasReferenceToWeakExternal(atom) ) { - // if __DATA,__nl_symbol_ptr atom has pointer to weak external symbol, don't move to __DATA_CONST - fs = this->getFinalSection("__DATA", "__got_weak", sectType); - if ( _options.traceSymbolLayout() ) - printf("symbol '%s', contains pointers to weak symbols, so mapped it to __DATA/__got_weak\n", atom.name()); - } - else { - fs = this->getFinalSection(it->toSegment, it->toSection, sectType); - if ( _options.traceSymbolLayout() ) - printf("symbol '%s', -rename_section mapped it to %s/%s\n", atom.name(), fs->segmentName(), fs->sectionName()); - } + else if ( atom.symbolTableInclusion() == ld::Atom::symbolTableNotInFinalLinkedImages ) { + const char* symName = atom.name(); + if ( strncmp(symName, "l_OBJC_$_INSTANCE_METHODS_", 26) == 0 ) { + if ( _options.moveAXMethodList(&symName[26]) ) { + curSectName = "__objc_const_ax"; + fs = this->getFinalSection(curSegName, curSectName, sectType); + if ( _options.traceSymbolLayout() ) + printf("symbol '%s', .axsymbol mapped it to %s/%s\n", atom.name(), curSegName, curSectName); } } - if ( fs == NULL ) { - for ( std::vector::const_iterator it=segRenames.begin(); it != segRenames.end(); ++it) { - if ( strcmp(atom.section().segmentName(), it->fromSegment) == 0 ) { - if ( _options.traceSymbolLayout() ) - printf("symbol '%s', -rename_segment mapped it to %s/%s\n", atom.name(), it->toSegment, sectName); - fs = this->getFinalSection(it->toSegment, sectName, sectType); - } + else if ( strncmp(symName, "l_OBJC_$_CLASS_METHODS_", 23) == 0 ) { + if ( _options.moveAXMethodList(&symName[23]) ) { + curSectName = "__objc_const_ax"; + fs = this->getFinalSection(curSegName, curSectName, sectType); + if ( _options.traceSymbolLayout() ) + printf("symbol '%s', .axsymbol mapped it to %s/%s\n", atom.name(), curSegName, curSectName); } } } + // support for -rename_section and -rename_segment + for (const Options::SectionRename& rename : _options.sectionRenames()) { + if ( (strcmp(curSectName, rename.fromSection) == 0) && (strcmp(curSegName, rename.fromSegment) == 0) ) { + if ( _options.useDataConstSegment() && _options.sharedRegionEligible() && (strcmp(curSectName, "__const") == 0) && (strcmp(curSegName, "__DATA") == 0) && hasReferenceToWeakExternal(atom) ) { + // if __DATA,__const atom has pointer to weak external symbol, don't move to __DATA_CONST + curSectName = "__const_weak"; + fs = this->getFinalSection(curSegName, curSectName, sectType); + if ( _options.traceSymbolLayout() ) + printf("symbol '%s', contains pointers to weak symbols, so mapped it to __DATA/__const_weak\n", atom.name()); + } + else if ( _options.useDataConstSegment() && _options.sharedRegionEligible() && (sectType == ld::Section::typeNonLazyPointer) && hasReferenceToWeakExternal(atom) ) { + // if __DATA,__nl_symbol_ptr atom has pointer to weak external symbol, don't move to __DATA_CONST + curSectName = "__got_weak"; + fs = this->getFinalSection("__DATA", curSectName, sectType); + if ( _options.traceSymbolLayout() ) + printf("symbol '%s', contains pointers to weak symbols, so mapped it to __DATA/__got_weak\n", atom.name()); + } + else { + curSegName = rename.toSegment; + curSectName = rename.toSection; + fs = this->getFinalSection(rename.toSegment, rename.toSection, sectType); + if ( _options.traceSymbolLayout() ) + printf("symbol '%s', -rename_section mapped it to %s/%s\n", atom.name(), fs->segmentName(), fs->sectionName()); + } + } + } + for (const Options::SegmentRename& rename : _options.segmentRenames()) { + if ( strcmp(curSegName, rename.fromSegment) == 0 ) { + if ( _options.traceSymbolLayout() ) + printf("symbol '%s', -rename_segment mapped it to %s/%s\n", atom.name(), rename.toSegment, curSectName); + fs = this->getFinalSection(rename.toSegment, curSectName, sectType); + } + } + // if no override, use default location if ( fs == NULL ) { fs = this->getFinalSection(atom.section()); @@ -630,7 +773,7 @@ ld::Internal::FinalSection* InternalState::addAtom(const ld::Atom& atom) printf("symbol '%s', use default mapping to %s/%s\n", atom.name(), fs->segmentName(), fs->sectionName()); } - //fprintf(stderr, "InternalState::doAtom(%p), name=%s, sect=%s, finalsect=%p\n", &atom, atom.name(), atom.section().sectionName(), fs); + //fprintf(stderr, "InternalState::doAtom(%p), name=%s, sect=%s, finalseg=%s\n", &atom, atom.name(), atom.section().sectionName(), fs->segmentName()); #ifndef NDEBUG validateFixups(atom); #endif @@ -721,22 +864,19 @@ ld::Internal::FinalSection* InternalState::getFinalSection(const ld::Section& in } -int InternalState::FinalSection::sectionComparer(const void* l, const void* r) -{ - const FinalSection* left = *(FinalSection**)l; - const FinalSection* right = *(FinalSection**)r; - if ( left->_segmentOrder != right->_segmentOrder ) - return (left->_segmentOrder - right->_segmentOrder); - return (left->_sectionOrder - right->_sectionOrder); -} - void InternalState::sortSections() { //fprintf(stderr, "UNSORTED final sections:\n"); //for (std::vector::iterator it = sections.begin(); it != sections.end(); ++it) { // fprintf(stderr, "final section %p %s/%s\n", (*it), (*it)->segmentName(), (*it)->sectionName()); //} - qsort(§ions[0], sections.size(), sizeof(FinalSection*), &InternalState::FinalSection::sectionComparer); + std::stable_sort(sections.begin(), sections.end(), [](const ld::Internal::FinalSection* l, const ld::Internal::FinalSection* r) { + const FinalSection* left = (FinalSection*)l; + const FinalSection* right = (FinalSection*)r; + if ( left->_segmentOrder != right->_segmentOrder ) + return (left->_segmentOrder < right->_segmentOrder); + return (left->_sectionOrder < right->_sectionOrder); + }); //fprintf(stderr, "SORTED final sections:\n"); //for (std::vector::iterator it = sections.begin(); it != sections.end(); ++it) { // fprintf(stderr, "final section %p %s/%s\n", (*it), (*it)->segmentName(), (*it)->sectionName()); @@ -846,6 +986,8 @@ void InternalState::setSectionSizesAndAlignments() this->hasWeakExternalSymbols = true; if ( _options.warnWeakExports() ) warning("weak external symbol: %s", atom->name()); + else if ( _options.noWeakExports() ) + throwf("weak external symbol: %s", atom->name()); } } sect->size = offset; @@ -863,6 +1005,21 @@ void InternalState::setSectionSizesAndAlignments() this->hasThreadLocalVariableDefinitions = true; } } + + // All __thread_data and __thread_bss sections must have same alignment + uint8_t maxThreadAlign = 0; + for (ld::Internal::FinalSection* sect : sections) { + if ( (sect->type() == ld::Section::typeTLVInitialValues) || (sect->type() == ld::Section::typeTLVZeroFill) ) { + if ( sect->alignment > maxThreadAlign ) + maxThreadAlign = sect->alignment; + } + } + for (ld::Internal::FinalSection* sect : sections) { + if ( (sect->type() == ld::Section::typeTLVInitialValues) || (sect->type() == ld::Section::typeTLVZeroFill) ) { + sect->alignment = maxThreadAlign; + } + } + } uint64_t InternalState::assignFileOffsets() @@ -1159,39 +1316,33 @@ static void getVMInfo(vm_statistics_data_t& info) -static const char* sOverridePathlibLTO = NULL; - -// -// This is magic glue that overrides the default behaviour -// of lazydylib1.o which is used to lazily load libLTO.dylib. -// -extern "C" const char* dyld_lazy_dylib_path_fix(const char* path); -const char* dyld_lazy_dylib_path_fix(const char* path) -{ - if ( sOverridePathlibLTO != NULL ) - return sOverridePathlibLTO; - else - return path; -} - - int main(int argc, const char* argv[]) { const char* archName = NULL; bool showArch = false; - bool archInferred = false; try { PerformanceStatistics statistics; statistics.startTool = mach_absolute_time(); // create object to track command line arguments Options options(argc, argv); + if (options.dumpNormalizedLibArgs()) { + for (auto info : options.getInputFiles()) { + for (auto arg : info.lib_cli_argument()) { + std::cout << arg << '\0'; + } + } + exit(0); + } InternalState state(options); - + +#ifdef LTO_SUPPORT // allow libLTO to be overridden by command line -lto_library - sOverridePathlibLTO = options.overridePathlibLTO(); - + if (const char *dylib = options.overridePathlibLTO()) + lto::set_library(dylib); +#endif + // gather vm stats if ( options.printStatistics() ) getVMInfo(statistics.vmStart); @@ -1199,11 +1350,10 @@ int main(int argc, const char* argv[]) // update strings for error messages showArch = options.printArchPrefix(); archName = options.architectureName(); - archInferred = (options.architecture() == 0); // open and parse input files statistics.startInputFileProcessing = mach_absolute_time(); - ld::tool::InputFiles inputFiles(options, &archName); + ld::tool::InputFiles inputFiles(options); // load and resolve all references statistics.startResolver = mach_absolute_time(); @@ -1221,6 +1371,7 @@ int main(int argc, const char* argv[]) statistics.startPasses = mach_absolute_time(); ld::passes::objc::doPass(options, state); ld::passes::stubs::doPass(options, state); + ld::passes::inits::doPass(options, state); ld::passes::huge::doPass(options, state); ld::passes::got::doPass(options, state); ld::passes::tlvp::doPass(options, state); @@ -1236,9 +1387,15 @@ int main(int argc, const char* argv[]) ld::passes::bitcode_bundle::doPass(options, state); // must be after dylib #endif // HAVE_XAR_XAR_H && LTO_SUPPORT + // Sort again so that we get the segments in order. + state.sortSections(); + ld::passes::thread_starts::doPass(options, state); // must be after dylib + // sort final sections state.sortSections(); + options.writeDependencyInfo(); + // write output file statistics.startOutput = mach_absolute_time(); ld::tool::OutputFile out(options); @@ -1278,9 +1435,9 @@ int main(int argc, const char* argv[]) } } catch (const char* msg) { - if ( archInferred ) - fprintf(stderr, "ld: %s for inferred architecture %s\n", msg, archName); - else if ( showArch ) + if ( strstr(msg, "malformed") != NULL ) + fprintf(stderr, "ld: %s\n", msg); + else if ( showArch && (strstr(msg, archName) == NULL) ) fprintf(stderr, "ld: %s for architecture %s\n", msg, archName); else fprintf(stderr, "ld: %s\n", msg); diff --git a/cctools/ld64/src/ld/ld.hpp b/cctools/ld64/src/ld/ld.hpp index 291bbe1..afb44d1 100644 --- a/cctools/ld64/src/ld/ld.hpp +++ b/cctools/ld64/src/ld/ld.hpp @@ -30,18 +30,226 @@ #include #include #include -#include "configure.h" #include #include #include #include #include +#include // ld64-port: for std::find_if -#include "configure.h" // ld64-port +#include "configure.h" +#include "PlatformSupport.h" + +//FIXME: Only needed until we move VersionSet into PlatformSupport +class Options; namespace ld { +// +// minumum OS versions +// + +struct PlatformVersion { + Platform platform; + uint32_t minVersion; + uint32_t sdkVersion; + PlatformVersion(Platform P) : PlatformVersion(P, 0, 0) {} + PlatformVersion(Platform P, uint32_t V) : PlatformVersion(P, V, V) {} + PlatformVersion(Platform P, uint32_t M, uint32_t S) : platform(P), minVersion(M), sdkVersion(S) {} + bool operator==(const PlatformVersion& other) const { return platform == other.platform; } + bool operator<(const PlatformVersion& other) const { return platform < other.platform; } +}; + +struct VersionSet { +private: + std::set _versions; +public: + VersionSet() {} + VersionSet(const std::set& V) : _versions(V) {} + void insert(PlatformVersion platformVersion) { + assert(_versions.find(platformVersion) == _versions.end()); + _versions.insert(platformVersion); + } + void erase(const Platform& platform) { + auto i = std::find_if(_versions.begin(), _versions.end(), [&platform](const PlatformVersion& version) { + return platform == version.platform; + }); + if (i == _versions.end()) return; + _versions.erase(i); + } + void updateMinVersion(const Platform& platform, uint32_t minVersion) { + auto i = std::find_if(_versions.begin(), _versions.end(), [&platform](const PlatformVersion& version) { + return platform == version.platform; + }); + if (i == _versions.end()) return; + auto newVersion = *i; + newVersion.minVersion = minVersion; + newVersion.sdkVersion = i->sdkVersion; + _versions.erase(i); + _versions.insert(newVersion); + } + void updateSDKVersion(const Platform& platform, uint32_t sdkVersion) { + auto i = std::find_if(_versions.begin(), _versions.end(), [&platform](const PlatformVersion& version) { + return platform == version.platform; + }); + if (i == _versions.end()) return; + auto newVersion = *i; + newVersion.minVersion = i->minVersion; + newVersion.sdkVersion = sdkVersion; + _versions.erase(i); + _versions.insert(newVersion); + } + size_t count() const { return _versions.size(); } + size_t empty() const { return _versions.empty(); } + void clear() { _versions.clear(); } + + void forEach(void (^callback)(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop)) const { + bool stop = false; + for (const auto& version : _versions) { + callback(version.platform, version.minVersion, version.sdkVersion, stop); + if (stop) + return; + } + } + + bool contains(ld::Platform platform) const { + auto i = std::find_if(_versions.begin(), _versions.end(), [&platform](const PlatformVersion& version) { + return platform == version.platform; + }); + return (i != _versions.end()); + } + + bool contains(const ld::PlatformSet& platforms) const { + __block bool retval = true; + forEach(^(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop) { + if (platforms.find(platform) == platforms.end()) { + stop = true; + retval = false; + } + }); + return retval; + } + + uint32_t minOS(ld::Platform platform) const { + for (const auto& version : _versions) { + if (basePlatform(version.platform) == platform) { + return version.minVersion; + } + } + return 0; + } + + bool minOS(const PlatformVersion& version) const { + return minOS(version.platform) >= version.minVersion; + } + + bool minOS(const ld::VersionSet& requiredMinVersions) const { + __block bool retval = true; + forEach(^(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop) { + if (!requiredMinVersions.contains(basePlatform(platform))) + return; + if (minVersion < requiredMinVersions.minOS(basePlatform(platform))) { + stop = true; + retval = false; + } + }); + return retval; + } + + std::string to_str() const { + std::string retval; + auto appendPlatform = [&](const std::string& platform) { + if (retval.empty()) { + retval = platform; + } else { + retval += "/"; + retval += platform; + } + }; + + forEach(^(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop) { + appendPlatform(platformInfo(platform).printName); + }); + + return retval; + } + + void checkObjectCrosslink(const VersionSet& objectPlatforms, const std::string& targetPath, bool internalSDK, + bool bitcode) const; + void checkDylibCrosslink(const VersionSet& dylibPlatforms, const std::string& targetPath, + const std::string& dylibType, bool internalSDK, bool indirectDylib, + bool bitcode) const; + bool operator==(const VersionSet& other) const { return _versions == other._versions; } + bool operator<(const VersionSet& other) const { return _versions < other._versions; } +}; + +static const PlatformVersion mac10_4 (Platform::macOS, 0x000A0400); +static const PlatformVersion mac10_5 (Platform::macOS, 0x000A0500); +static const PlatformVersion mac10_6 (Platform::macOS, 0x000A0600); +static const PlatformVersion mac10_7 (Platform::macOS, 0x000A0700); +static const PlatformVersion mac10_8 (Platform::macOS, 0x000A0800); +static const PlatformVersion mac10_9 (Platform::macOS, 0x000A0900); +static const PlatformVersion mac10_12 (Platform::macOS, 0x000A0C00); +static const PlatformVersion mac10_14 (Platform::macOS, 0x000A0E00); +static const PlatformVersion mac10_15 (Platform::macOS, 0x000A0F00); +static const PlatformVersion mac10_Future (Platform::macOS, 0x10000000); + +static const PlatformVersion iOS_2_0 (Platform::iOS, 0x00020000); +static const PlatformVersion iOS_3_1 (Platform::iOS, 0x00030100); +static const PlatformVersion iOS_4_2 (Platform::iOS, 0x00040200); +static const PlatformVersion iOS_4_3 (Platform::iOS, 0x00040300); +static const PlatformVersion iOS_5_0 (Platform::iOS, 0x00050000); +static const PlatformVersion iOS_6_0 (Platform::iOS, 0x00060000); +static const PlatformVersion iOS_7_0 (Platform::iOS, 0x00070000); +static const PlatformVersion iOS_8_0 (Platform::iOS, 0x00080000); +static const PlatformVersion iOS_9_0 (Platform::iOS, 0x00090000); +static const PlatformVersion iOS_10_0 (Platform::iOS, 0x000A0000); +static const PlatformVersion iOS_11_0 (Platform::iOS, 0x000B0000); +static const PlatformVersion iOS_12_0 (Platform::iOS, 0x000C0000); +static const PlatformVersion iOS_13_0 (Platform::iOS, 0x000D0000); +static const PlatformVersion iOS_Future (Platform::iOS, 0x10000000); + +static const PlatformVersion watchOS_1_0 (Platform::watchOS, 0x00010000); +static const PlatformVersion watchOS_2_0 (Platform::watchOS, 0x00020000); +static const PlatformVersion watchOS_5_0 (Platform::watchOS, 0x00050000); +static const PlatformVersion watchOS_6_0 (Platform::watchOS, 0x00060000); +static const PlatformVersion watchOS_Future (Platform::watchOS, 0x10000000); + +static const PlatformVersion tvOS_9_0 (Platform::tvOS, 0x00090000); +static const PlatformVersion tvOS_12_0 (Platform::tvOS, 0x000C0000); +static const PlatformVersion tvOS_13_0 (Platform::tvOS, 0x000D0000); +static const PlatformVersion tvOS_Future (Platform::tvOS, 0x10000000); + +static const PlatformVersion bridgeOS_1_0 (Platform::bridgeOS, 0x00010000); +static const PlatformVersion bridgeOS_4_0 (Platform::bridgeOS, 0x00040000); +static const PlatformVersion bridgeOS_Future (Platform::bridgeOS, 0x10000000); + + +// Platform Sets + +static const PlatformSet simulatorPlatforms ( {Platform::iOS_simulator, Platform::tvOS_simulator, Platform::watchOS_simulator} ); + +//FIXME do we need to add simulatots to these? +//FIXME Are the dates correct? +static const VersionSet version2007 ({mac10_4, iOS_2_0}); +static const VersionSet version2008 ({mac10_5, iOS_2_0}); +static const VersionSet version2008Fall ({mac10_5, iOS_3_1}); +static const VersionSet version2009 ({mac10_6, iOS_3_1}); +static const VersionSet version2010 ({mac10_7, iOS_4_2}); +static const VersionSet version2010Fall ({mac10_7, iOS_4_3}); + +static const VersionSet version2012 ({mac10_8, iOS_6_0}); +static const VersionSet version2013 ({mac10_9, iOS_7_0}); +static const VersionSet version2019Fall ({mac10_15, iOS_13_0, watchOS_6_0, tvOS_13_0, bridgeOS_4_0}); + +static const VersionSet supportsSplitSegV2 ({mac10_12, iOS_9_0, watchOS_2_0, tvOS_9_0}); +// FIXME: Use the comment out line instead. +static const VersionSet supportsLCBuildVersion ({mac10_14, iOS_12_0, watchOS_5_0, tvOS_12_0, bridgeOS_1_0}); +static const VersionSet supportsPIE ({mac10_5, iOS_4_2}); +static const VersionSet supportsTLV ({mac10_7, iOS_9_0}); +static const VersionSet supportsChainedFixups ({mac10_15, iOS_13_0, watchOS_6_0, tvOS_13_0, bridgeOS_Future}); + // Forward declaration for bitcode support class Bitcode; @@ -59,10 +267,7 @@ class Bitcode; class File { public: - enum ObjcConstraint { objcConstraintNone, objcConstraintRetainRelease, - objcConstraintRetainReleaseOrGC, objcConstraintGC, - objcConstraintRetainReleaseForSimulator }; - + class AtomHandler { public: virtual ~AtomHandler() {} @@ -94,7 +299,7 @@ public: Ordinal (uint64_t ordinal) : _ordinal(ordinal) {} - enum { kArgListPartition=0, kIndirectDylibPartition=1, kLTOPartition = 2, kLinkerOptionPartition = 2, InvalidParition=0xffff }; + enum { kArgListPartition=0, kIndirectDylibPartition=1, kLTOPartition = 2, kLinkerOptionPartition = 3, InvalidParition=0xffff }; Ordinal(uint16_t partition, uint16_t majorIndex, uint16_t minorIndex, uint16_t counter) { _ordinal = ((uint64_t)partition<<48) | ((uint64_t)majorIndex<<32) | ((uint64_t)minorIndex<<16) | ((uint64_t)counter<<0); } @@ -103,14 +308,14 @@ public: const uint16_t majorIndex() const { return (_ordinal>>32)&0xffff; } const uint16_t minorIndex() const { return (_ordinal>>16)&0xffff; } const uint16_t counter() const { return (_ordinal>>00)&0xffff; } - + const Ordinal nextMajorIndex() const { assert(majorIndex() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<32)); } const Ordinal nextMinorIndex() const { assert(minorIndex() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<16)); } const Ordinal nextCounter() const { assert(counter() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<0)); } public: Ordinal() : _ordinal(0) {}; - + static const Ordinal NullOrdinal() { return Ordinal((uint64_t)0); } const bool validOrdinal() const { return _ordinal != 0; } @@ -127,7 +332,7 @@ public: // Thus, an object pulled in from a .a that was listed in a file list could use all three fields. static const Ordinal makeArgOrdinal(uint16_t argIndex) { return Ordinal(kArgListPartition, argIndex, 0, 0); }; const Ordinal nextFileListOrdinal() const { return nextMinorIndex(); } - const Ordinal archiveOrdinalWithMemberIndex(uint16_t index) const { return Ordinal(kArgListPartition, majorIndex(), minorIndex(), index); } + const Ordinal archiveOrdinalWithMemberIndex(uint16_t memberIndex) const { return Ordinal(partition(), majorIndex(), minorIndex(), memberIndex); } // For indirect libraries the partition is IndirectDylibPartition and the counter is used or order the libraries. static const ld::File::Ordinal indirectDylibBase() { return Ordinal(kIndirectDylibPartition, 0, 0, 0); } @@ -138,8 +343,8 @@ public: // For linker options embedded in object files static const ld::File::Ordinal linkeOptionBase() { return Ordinal(kIndirectDylibPartition, 1, 0, 0); } - const Ordinal nextLinkerOptionOrdinal() { nextCounter(); return *this; }; - + const Ordinal nextLinkerOptionOrdinal() { return nextCounter(); }; + }; typedef enum { Reloc, Dylib, Archive, Other } Type; @@ -152,34 +357,33 @@ public: Ordinal ordinal() const { return _ordinal; } virtual bool forEachAtom(AtomHandler&) const = 0; virtual bool justInTimeforEachAtom(const char* name, AtomHandler&) const = 0; - virtual ObjcConstraint objCConstraint() const { return objcConstraintNone; } - virtual uint8_t swiftVersion() const { return 0; } + virtual uint8_t swiftVersion() const { return 0; } // ABI version, now fixed + virtual uint16_t swiftLanguageVersion() const { return 0; } // language version in 4.4 format virtual uint32_t cpuSubType() const { return 0; } virtual uint32_t subFileCount() const { return 1; } - virtual uint32_t minOSVersion() const { return 0; } - virtual uint32_t platformLoadCommand() const { return 0; } + virtual const VersionSet& platforms() const { return _platforms; } bool fileExists() const { return _modTime != 0; } Type type() const { return _type; } virtual Bitcode* getBitcode() const { return NULL; } + const char* leafName() const; + private: const char* _path; time_t _modTime; const Ordinal _ordinal; const Type _type; + // Note this is just a placeholder as platforms() needs something to return + static const VersionSet _platforms; }; -// -// minumum OS versions -// -enum MacVersionMin { macVersionUnset=0, mac10_4=0x000A0400, mac10_5=0x000A0500, - mac10_6=0x000A0600, mac10_7=0x000A0700, mac10_8=0x000A0800, - mac10_9=0x000A0900, mac10_Future=0x10000000 }; -enum IOSVersionMin { iOSVersionUnset=0, iOS_2_0=0x00020000, iOS_3_1=0x00030100, - iOS_4_2=0x00040200, iOS_4_3=0x00040300, iOS_5_0=0x00050000, - iOS_6_0=0x00060000, iOS_7_0=0x00070000, iOS_8_0=0x00080000, - iOS_9_0=0x00090000, iOS_Future=0x10000000}; -enum WatchOSVersionMin { wOSVersionUnset=0, wOS_1_0=0x00010000, wOS_2_0=0x00020000 }; +inline const char* File::leafName() const { + const char* pth = this->path(); + if ( pth == NULL ) + return ""; + const char* lastSlash = strrchr(pth, '/'); + return (lastSlash != NULL) ? lastSlash+1 : pth; +} namespace relocatable { @@ -213,6 +417,8 @@ namespace relocatable { const char* string; }; typedef const std::vector< std::vector > LinkerOptionsList; + typedef std::vector> ToolVersionList; + struct AstTimeAndPath { uint64_t time; std::string path; }; File(const char* pth, time_t modTime, Ordinal ord) : ld::File(pth, modTime, ord, Reloc) { } @@ -223,8 +429,14 @@ namespace relocatable { virtual const std::vector* stabs() const = 0; virtual bool canScatterAtoms() const = 0; virtual bool hasLongBranchStubs() { return false; } + virtual bool hasllvmProfiling() const { return false; } + virtual bool hasObjC() const { return false; } + virtual bool objcHasCategoryClassPropertiesField() const { return false; } virtual LinkerOptionsList* linkerOptions() const = 0; + virtual const ToolVersionList& toolVersions() const = 0; virtual SourceKind sourceKind() const { return kSourceUnknown; } + virtual const uint8_t* fileContent() const { return nullptr; } + virtual const std::vector* astFiles() const { return nullptr; } }; } // namespace relocatable @@ -243,13 +455,13 @@ namespace dylib { { public: virtual ~DylibHandler() {} - virtual File* findDylib(const char* installPath, const char* fromPath) = 0; + virtual File* findDylib(const char* installPath, const ld::dylib::File* fromDylib, bool speculative) = 0; }; File(const char* pth, time_t modTime, Ordinal ord) : ld::File(pth, modTime, ord, Dylib), _dylibInstallPath(NULL), _frameworkName(NULL), _dylibTimeStamp(0), _dylibCurrentVersion(0), _dylibCompatibilityVersion(0), - _explicitlyLinked(false), _implicitlyLinked(false), + _explicitlyLinked(false), _implicitlyLinked(false), _speculativelyLoaded(false), _lazyLoadedDylib(false), _forcedWeakLinked(false), _reExported(false), _upward(false), _dead(false) { } const char* installPath() const { return _dylibInstallPath; } @@ -261,7 +473,9 @@ namespace dylib { bool explicitlyLinked() const { return _explicitlyLinked; } void setImplicitlyLinked() { _implicitlyLinked = true; } bool implicitlyLinked() const { return _implicitlyLinked; } - + void setSpeculativelyLoaded() { _speculativelyLoaded = true; } + bool speculativelyLoaded() const { return _speculativelyLoaded; } + // attributes of how dylib will be used when linked void setWillBeLazyLoadedDylb() { _lazyLoadedDylib = true; } bool willBeLazyLoadedDylib() const { return _lazyLoadedDylib; } @@ -279,13 +493,16 @@ namespace dylib { virtual bool providedExportAtom() const = 0; virtual const char* parentUmbrella() const = 0; virtual const std::vector* allowableClients() const = 0; + virtual const std::vector& rpaths() const = 0; virtual bool hasWeakExternals() const = 0; virtual bool deadStrippable() const = 0; virtual bool hasWeakDefinition(const char* name) const = 0; + virtual bool hasDefinition(const char* name) const = 0; virtual bool hasPublicInstallName() const = 0; virtual bool allSymbolsAreWeakImported() const = 0; virtual bool installPathVersionSpecific() const { return false; } virtual bool appExtensionSafe() const = 0; + virtual void forEachExportedSymbol(void (^handler)(const char* symbolName, bool weakDef)) const = 0; public: const char* _dylibInstallPath; @@ -295,6 +512,7 @@ namespace dylib { uint32_t _dylibCompatibilityVersion; bool _explicitlyLinked; bool _implicitlyLinked; + bool _speculativelyLoaded; bool _lazyLoadedDylib; bool _forcedWeakLinked; bool _reExported; @@ -333,9 +551,9 @@ public: typeCFI, typeLSDA, typeDtraceDOF, typeUnwindInfo, typeObjCClassRefs, typeObjC2CategoryList, typeZeroFill, typeTentativeDefs, typeLazyPointer, typeStub, typeNonLazyPointer, typeDyldInfo, typeLazyDylibPointer, typeStubHelper, typeInitializerPointers, typeTerminatorPointers, - typeStubClose, typeLazyPointerClose, typeAbsoluteSymbols, + typeStubClose, typeLazyPointerClose, typeAbsoluteSymbols, typeThreadStarts, typeChainStarts, typeTLVDefs, typeTLVZeroFill, typeTLVInitialValues, typeTLVInitializerPointers, typeTLVPointers, - typeFirstSection, typeLastSection, typeDebug, typeSectCreate }; + typeFirstSection, typeLastSection, typeDebug, typeSectCreate, typeInitOffsets }; Section(const char* sgName, const char* sctName, @@ -479,14 +697,38 @@ struct Fixup kindStoreTargetAddressARM64TLVPLoadPageOff12,// kindSetTargetAddress + kindStoreARM64TLVPLoadPageOff12 kindStoreTargetAddressARM64TLVPLoadNowLeaPage21, // kindSetTargetAddress + kindStoreARM64TLVPLoadNowLeaPage21 kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12, // kindSetTargetAddress + kindStoreARM64TLVPLoadNowLeaPageOff12 +#endif +#if SUPPORT_ARCH_arm64e + kindStoreLittleEndianAuth64, + kindStoreTargetAddressLittleEndianAuth64, // kindSetTargetAddress + kindStoreLittleEndianAuth64 + kindSetAuthData, #endif }; +#if SUPPORT_ARCH_arm64e + struct AuthData { + // clang encodes the combination of the key bits as these values. + typedef enum { + ptrauth_key_asia = 0, + ptrauth_key_asib = 1, + ptrauth_key_asda = 2, + ptrauth_key_asdb = 3, + } ptrauth_key; + + uint16_t discriminator; + bool hasAddressDiversity; + ptrauth_key key; + }; +#endif + union { const Atom* target; const char* name; uint64_t addend; uint32_t bindingIndex; +#if SUPPORT_ARCH_arm64e + AuthData authData; +#endif } u; uint32_t offsetInAtom; Kind kind : 8; @@ -543,6 +785,14 @@ struct Fixup binding(Fixup::bindingNone), contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) { u.addend = addend; } + +#if SUPPORT_ARCH_arm64e + Fixup(uint32_t off, Cluster c, Kind k, AuthData authData) : + offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), + binding(Fixup::bindingNone), + contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) + { u.authData = authData; } +#endif Fixup(Kind k, uint32_t lohKind, uint32_t off1, uint32_t off2) : offsetInAtom(off1), kind(k), clusterSize(k1of1), @@ -586,6 +836,146 @@ struct Fixup } return false; } + + bool isStore() const { + switch ( kind ) { + case ld::Fixup::kindNone: + case ld::Fixup::kindNoneFollowOn: + case ld::Fixup::kindNoneGroupSubordinate: + case ld::Fixup::kindNoneGroupSubordinateFDE: + case ld::Fixup::kindNoneGroupSubordinateLSDA: + case ld::Fixup::kindNoneGroupSubordinatePersonality: + case ld::Fixup::kindSetTargetAddress: + case ld::Fixup::kindSubtractTargetAddress: + case ld::Fixup::kindAddAddend: + case ld::Fixup::kindSubtractAddend: + case ld::Fixup::kindSetTargetImageOffset: + case ld::Fixup::kindSetTargetSectionOffset: +#if SUPPORT_ARCH_arm64e + case ld::Fixup::kindSetAuthData: +#endif + return false; + default: + break; + } + return true; + } + + + bool setsTarget(bool isObjectFile) const { + switch ( kind ) { + case ld::Fixup::kindSetTargetAddress: + case ld::Fixup::kindLazyTarget: + case ld::Fixup::kindStoreTargetAddressLittleEndian32: + case ld::Fixup::kindStoreTargetAddressLittleEndian64: +#if SUPPORT_ARCH_arm64e + case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64: +#endif + case ld::Fixup::kindStoreTargetAddressBigEndian32: + case ld::Fixup::kindStoreTargetAddressBigEndian64: + case ld::Fixup::kindStoreTargetAddressX86PCRel32: + case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32: + case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad: + case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA: + case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad: + case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA: + case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoad: + case ld::Fixup::kindStoreTargetAddressARMBranch24: + case ld::Fixup::kindStoreTargetAddressThumbBranch22: + case ld::Fixup::kindStoreTargetAddressARMLoad12: +#if SUPPORT_ARCH_arm64 + case ld::Fixup::kindStoreTargetAddressARM64Branch26: + case ld::Fixup::kindStoreTargetAddressARM64Page21: + case ld::Fixup::kindStoreTargetAddressARM64PageOff12: + case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21: + case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12: + case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21: + case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12: + case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21: + case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12: + case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21: + case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12: +#endif + return true; + case ld::Fixup::kindStoreX86DtraceCallSiteNop: + case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear: + case ld::Fixup::kindStoreARMDtraceCallSiteNop: + case ld::Fixup::kindStoreARMDtraceIsEnableSiteClear: + case ld::Fixup::kindStoreARM64DtraceCallSiteNop: + case ld::Fixup::kindStoreARM64DtraceIsEnableSiteClear: + case ld::Fixup::kindStoreThumbDtraceCallSiteNop: + case ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear: + return isObjectFile; + default: + break; + } + return false; + } + + bool isPcRelStore(bool isKextBundle) const { + switch ( kind ) { + case ld::Fixup::kindStoreX86BranchPCRel8: + case ld::Fixup::kindStoreX86BranchPCRel32: + case ld::Fixup::kindStoreX86PCRel8: + case ld::Fixup::kindStoreX86PCRel16: + case ld::Fixup::kindStoreX86PCRel32: + case ld::Fixup::kindStoreX86PCRel32_1: + case ld::Fixup::kindStoreX86PCRel32_2: + case ld::Fixup::kindStoreX86PCRel32_4: + case ld::Fixup::kindStoreX86PCRel32GOTLoad: + case ld::Fixup::kindStoreX86PCRel32GOTLoadNowLEA: + case ld::Fixup::kindStoreX86PCRel32GOT: + case ld::Fixup::kindStoreX86PCRel32TLVLoad: + case ld::Fixup::kindStoreX86PCRel32TLVLoadNowLEA: + case ld::Fixup::kindStoreARMBranch24: + case ld::Fixup::kindStoreThumbBranch22: + case ld::Fixup::kindStoreARMLoad12: + case ld::Fixup::kindStoreTargetAddressX86PCRel32: + case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad: + case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA: + case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad: + case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA: + case ld::Fixup::kindStoreTargetAddressARMBranch24: + case ld::Fixup::kindStoreTargetAddressThumbBranch22: + case ld::Fixup::kindStoreTargetAddressARMLoad12: +#if SUPPORT_ARCH_arm64 + case ld::Fixup::kindStoreARM64Page21: + case ld::Fixup::kindStoreARM64PageOff12: + case ld::Fixup::kindStoreARM64GOTLoadPage21: + case ld::Fixup::kindStoreARM64GOTLoadPageOff12: + case ld::Fixup::kindStoreARM64GOTLeaPage21: + case ld::Fixup::kindStoreARM64GOTLeaPageOff12: + case ld::Fixup::kindStoreARM64TLVPLoadPage21: + case ld::Fixup::kindStoreARM64TLVPLoadPageOff12: + case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPage21: + case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPageOff12: + case ld::Fixup::kindStoreARM64PCRelToGOT: + case ld::Fixup::kindStoreTargetAddressARM64Page21: + case ld::Fixup::kindStoreTargetAddressARM64PageOff12: + case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21: + case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12: + case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21: + case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12: + case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21: + case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12: + case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21: + case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12: +#endif + return true; + case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32: +#if SUPPORT_ARCH_arm64 + case ld::Fixup::kindStoreTargetAddressARM64Branch26: +#endif + return !isKextBundle; +#if SUPPORT_ARCH_arm64 + case ld::Fixup::kindStoreARM64Branch26: +#endif + return !isKextBundle; + default: + break; + } + return false; + } union LOH_arm64 { uint64_t addend; @@ -685,14 +1075,14 @@ public: }; Atom(const Section& sect, Definition d, Combine c, Scope s, ContentType ct, - SymbolTableInclusion i, bool dds, bool thumb, bool al, Alignment a) : + SymbolTableInclusion i, bool dds, bool thumb, bool al, Alignment a, bool cold=false) : _section(§), _address(0), _alignmentModulus(a.modulus), _alignmentPowerOf2(a.powerOf2), _definition(d), _combine(c), _dontDeadStrip(dds), _thumb(thumb), _alias(al), _autoHide(false), _contentType(ct), _symbolTableInclusion(i), _scope(s), _mode(modeSectionOffset), _overridesADylibsWeakDef(false), _coalescedAway(false), - _live(false), _dontDeadStripIfRefLive(false), + _live(false), _dontDeadStripIfRefLive(false), _cold(cold), _machoSection(0), _weakImportState(weakImportUnset) { #ifndef NDEBUG @@ -726,6 +1116,7 @@ public: bool weakImported() const { return _weakImportState == weakImportTrue; } WeakImportState weakImportState() const { return _weakImportState; } bool autoHide() const { return _autoHide; } + bool cold() const { return _cold; } bool live() const { return _live; } uint8_t machoSection() const { assert(_machoSection != 0); return _machoSection; } @@ -745,10 +1136,12 @@ public: void setSectionStartAddress(uint64_t a) { assert(_mode == modeSectionOffset); _address += a; _mode = modeFinalAddress; } uint64_t sectionOffset() const { assert(_mode == modeSectionOffset); return _address; } uint64_t finalAddress() const { assert(_mode == modeFinalAddress); return _address; } -#ifndef NDEBUG bool finalAddressMode() const { return (_mode == modeFinalAddress); } -#endif + virtual const File* file() const = 0; + // Return the original file this atom belongs to, for instance for an LTO atom, + // file() would return the LTO MachO file instead of the original bitcode file. + virtual const ld::File* originalFile() const { return file(); } virtual const char* translationUnitSource() const { return NULL; } virtual const char* name() const = 0; virtual uint64_t objectAddress() const = 0; @@ -779,7 +1172,10 @@ public: _definition = a._definition; _combine = a._combine; _dontDeadStrip = a._dontDeadStrip; + _dontDeadStripIfRefLive = a._dontDeadStripIfRefLive; + _cold = a._cold; _thumb = a._thumb; + _alias = a._alias; _autoHide = a._autoHide; _contentType = a._contentType; _symbolTableInclusion = a._symbolTableInclusion; @@ -790,6 +1186,14 @@ public: _weakImportState = a._weakImportState; } + const char* safeFilePath() const { + const File* f = this->file(); + if ( f != NULL ) + return f->path(); + else + return ""; + } + protected: enum AddressMode { modeSectionOffset, modeFinalAddress }; @@ -811,6 +1215,7 @@ protected: bool _coalescedAway : 1; bool _live : 1; bool _dontDeadStripIfRefLive : 1; + bool _cold : 1; unsigned _machoSection : 8; WeakImportState _weakImportState : 2; }; @@ -818,13 +1223,14 @@ protected: class IndirectBindingTable { -public: +public: + virtual ~IndirectBindingTable() { } virtual const char* indirectName(uint32_t bindingIndex) const = 0; virtual const ld::Atom* indirectAtom(uint32_t bindingIndex) const = 0; }; - + // utility classes for using std::unordered_map with c-strings struct CStringHash { size_t operator()(const char* __s) const { @@ -876,49 +1282,59 @@ public: Internal() : bundleLoader(NULL), entryPoint(NULL), classicBindingHelper(NULL), lazyBindingHelper(NULL), compressedFastBinderProxy(NULL), - objcObjectConstraint(ld::File::objcConstraintNone), - objcDylibConstraint(ld::File::objcConstraintNone), - swiftVersion(0), cpuSubType(0), minOSVersion(0), + hasObjC(false), + swiftVersion(0), swiftLanguageVersion(0), + cpuSubType(0), minOSVersion(0), objectFileFoundWithNoVersion(false), allObjectFilesScatterable(true), someObjectFileHasDwarf(false), usingHugeSections(false), + someObjectFileHasSwift(false), firstSwiftDylibFile(nullptr), hasThreadLocalVariableDefinitions(false), hasWeakExternalSymbols(false), someObjectHasOptimizationHints(false), - dropAllBitcode(false), embedMarkerOnly(false) { } + dropAllBitcode(false), embedMarkerOnly(false), + forceLoadCompilerRT(false) { } std::vector sections; std::vector dylibs; + std::vector archivePaths; std::vector stabs; AtomToSection atomToSection; + CStringSet unprocessedLinkerOptionLibraries; + CStringSet unprocessedLinkerOptionFrameworks; CStringSet linkerOptionLibraries; CStringSet linkerOptionFrameworks; - CStringSet linkerOptionLibrariesProcessed; - CStringSet linkerOptionFrameworksProcessed; + CStringSet missingLinkerOptionLibraries; + CStringSet missingLinkerOptionFrameworks; std::vector indirectBindingTable; std::vector filesWithBitcode; + std::vector filesFromCompilerRT; + std::vector deadAtoms; std::unordered_set allUndefProxies; + std::unordered_set toolsVersions; const ld::dylib::File* bundleLoader; const Atom* entryPoint; const Atom* classicBindingHelper; const Atom* lazyBindingHelper; const Atom* compressedFastBinderProxy; - ld::File::ObjcConstraint objcObjectConstraint; - ld::File::ObjcConstraint objcDylibConstraint; + bool hasObjC; uint8_t swiftVersion; + uint16_t swiftLanguageVersion; uint32_t cpuSubType; uint32_t minOSVersion; - uint32_t derivedPlatformLoadCommand; bool objectFileFoundWithNoVersion; bool allObjectFilesScatterable; bool someObjectFileHasDwarf; bool usingHugeSections; + bool someObjectFileHasSwift; + const ld::dylib::File* firstSwiftDylibFile; bool hasThreadLocalVariableDefinitions; bool hasWeakExternalSymbols; bool someObjectHasOptimizationHints; bool dropAllBitcode; bool embedMarkerOnly; - std::string ltoBitcodePath; + bool forceLoadCompilerRT; + std::vector ltoBitcodePath; }; diff --git a/cctools/ld64/src/ld/parsers/Makefile.am b/cctools/ld64/src/ld/parsers/Makefile.am index f82aee6..71adc73 100644 --- a/cctools/ld64/src/ld/parsers/Makefile.am +++ b/cctools/ld64/src/ld/parsers/Makefile.am @@ -15,6 +15,7 @@ libParsers_la_CXXFLAGS = \ -D__DARWIN_UNIX03 \ $(WARNINGS) \ $(LTO_DEF) \ + $(TAPI_DEF) \ $(ENDIAN_FLAG) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/include/foreign \ diff --git a/cctools/ld64/src/ld/parsers/Makefile.in b/cctools/ld64/src/ld/parsers/Makefile.in new file mode 100644 index 0000000..bfda0aa --- /dev/null +++ b/cctools/ld64/src/ld/parsers/Makefile.in @@ -0,0 +1,664 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = ld64/src/ld/parsers +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libParsers_la_DEPENDENCIES = \ + $(top_builddir)/ld64/src/3rd/libhelper.la +am_libParsers_la_OBJECTS = libParsers_la-archive_file.lo \ + libParsers_la-lto_file.lo libParsers_la-macho_dylib_file.lo \ + libParsers_la-macho_relocatable_file.lo \ + libParsers_la-opaque_section_file.lo \ + libParsers_la-textstub_dylib_file.lo +libParsers_la_OBJECTS = $(am_libParsers_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libParsers_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libParsers_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(libParsers_la_SOURCES) +DIST_SOURCES = $(libParsers_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libParsers.la +noinst_HEADERS = \ + archive_file.h \ + lto_file.h \ + macho_dylib_file.h \ + macho_relocatable_file.h \ + opaque_section_file.h \ + textstub_dylib_file.hpp + +libParsers_la_LIBADD = \ + $(top_builddir)/ld64/src/3rd/libhelper.la + +libParsers_la_CXXFLAGS = \ + -D__DARWIN_UNIX03 \ + $(WARNINGS) \ + $(LTO_DEF) \ + $(TAPI_DEF) \ + $(ENDIAN_FLAG) \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/include/foreign \ + -I$(top_srcdir)/ld64/src/abstraction \ + -I$(top_srcdir)/ld64/src/ld \ + -I$(top_srcdir)/ld64/src/3rd \ + -I$(top_srcdir)/ld64/src + +libParsers_la_SOURCES = \ + archive_file.cpp \ + lto_file.cpp \ + macho_dylib_file.cpp \ + macho_relocatable_file.cpp \ + opaque_section_file.cpp \ + textstub_dylib_file.cpp + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps ld64/src/ld/parsers/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps ld64/src/ld/parsers/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libParsers.la: $(libParsers_la_OBJECTS) $(libParsers_la_DEPENDENCIES) $(EXTRA_libParsers_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libParsers_la_LINK) $(libParsers_la_OBJECTS) $(libParsers_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + $(AM_V_CXX)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(AM_V_CXX)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: + $(AM_V_CXX)$(LTCXXCOMPILE) -c -o $@ $< + +libParsers_la-archive_file.lo: archive_file.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libParsers_la_CXXFLAGS) $(CXXFLAGS) -c -o libParsers_la-archive_file.lo `test -f 'archive_file.cpp' || echo '$(srcdir)/'`archive_file.cpp + +libParsers_la-lto_file.lo: lto_file.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libParsers_la_CXXFLAGS) $(CXXFLAGS) -c -o libParsers_la-lto_file.lo `test -f 'lto_file.cpp' || echo '$(srcdir)/'`lto_file.cpp + +libParsers_la-macho_dylib_file.lo: macho_dylib_file.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libParsers_la_CXXFLAGS) $(CXXFLAGS) -c -o libParsers_la-macho_dylib_file.lo `test -f 'macho_dylib_file.cpp' || echo '$(srcdir)/'`macho_dylib_file.cpp + +libParsers_la-macho_relocatable_file.lo: macho_relocatable_file.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libParsers_la_CXXFLAGS) $(CXXFLAGS) -c -o libParsers_la-macho_relocatable_file.lo `test -f 'macho_relocatable_file.cpp' || echo '$(srcdir)/'`macho_relocatable_file.cpp + +libParsers_la-opaque_section_file.lo: opaque_section_file.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libParsers_la_CXXFLAGS) $(CXXFLAGS) -c -o libParsers_la-opaque_section_file.lo `test -f 'opaque_section_file.cpp' || echo '$(srcdir)/'`opaque_section_file.cpp + +libParsers_la-textstub_dylib_file.lo: textstub_dylib_file.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libParsers_la_CXXFLAGS) $(CXXFLAGS) -c -o libParsers_la-textstub_dylib_file.lo `test -f 'textstub_dylib_file.cpp' || echo '$(srcdir)/'`textstub_dylib_file.cpp + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/ld64/src/ld/parsers/archive_file.cpp b/cctools/ld64/src/ld/parsers/archive_file.cpp index e34574b..0b729c9 100644 --- a/cctools/ld64/src/ld/parsers/archive_file.cpp +++ b/cctools/ld64/src/ld/parsers/archive_file.cpp @@ -45,7 +45,6 @@ namespace archive { -typedef const struct ranlib* ConstRanLibPtr; // forward reference template class File; @@ -89,7 +88,9 @@ public: virtual bool justInTimeDataOnlyforEachAtom(const char* name, ld::File::AtomHandler& handler) const; private: - static bool validMachOFile(const uint8_t* fileContent, uint64_t fileLength, + friend bool isArchiveFile(const uint8_t* fileContent, uint64_t fileLength, ld::Platform* platform, const char** archiveArchName); + + static bool validMachOFile(const uint8_t* fileContent, uint64_t fileLength, const mach_o::relocatable::ParserOptions& opts); #ifdef LTO_SUPPORT static bool validLTOFile(const uint8_t* fileContent, uint64_t fileLength, @@ -114,32 +115,37 @@ private: struct MemberState { ld::relocatable::File* file; const Entry *entry; bool logged; bool loaded; uint32_t index;}; bool loadMember(MemberState& state, ld::File::AtomHandler& handler, const char *format, ...) const; - typedef std::unordered_map NameToEntryMap; + typedef std::unordered_map NameToOffsetMap; typedef typename A::P P; typedef typename A::P::E E; typedef std::map MemberToStateMap; - const struct ranlib* ranlibHashSearch(const char* name) const; MemberState& makeObjectFileForMember(const Entry* member) const; bool memberHasObjCCategories(const Entry* member) const; void dumpTableOfContents(); void buildHashTable(); - +#ifdef SYMDEF_64 + void buildHashTable64(); +#endif const uint8_t* _archiveFileContent; uint64_t _archiveFilelength; const struct ranlib* _tableOfContents; +#ifdef SYMDEF_64 + const struct ranlib_64* _tableOfContents64; +#endif uint32_t _tableOfContentCount; const char* _tableOfContentStrings; mutable MemberToStateMap _instantiatedEntries; - NameToEntryMap _hashTable; + NameToOffsetMap _hashTable; const bool _forceLoadAll; const bool _forceLoadObjC; const bool _forceLoadThis; const bool _objc2ABI; const bool _verboseLoad; const bool _logAllFiles; + mutable bool _alreadyLoadedAll; const mach_o::relocatable::ParserOptions _objOpts; }; @@ -227,7 +233,6 @@ template <> cpu_type_t File::architecture() { return CPU_TYPE_X86_64; } template <> cpu_type_t File::architecture() { return CPU_TYPE_ARM; } template <> cpu_type_t File::architecture() { return CPU_TYPE_ARM64; } - template bool File::validMachOFile(const uint8_t* fileContent, uint64_t fileLength, const mach_o::relocatable::ParserOptions& opts) { @@ -238,6 +243,11 @@ bool File::validMachOFile(const uint8_t* fileContent, uint64_t fileLength, co template bool File::validLTOFile(const uint8_t* fileContent, uint64_t fileLength, const mach_o::relocatable::ParserOptions& opts) { + if ( fileLength < 32 ) + return false; + uint32_t magic = *((uint32_t*)fileContent); + if ( (magic == MH_MAGIC) || (magic == MH_MAGIC_64) ) + return false; return lto::isObjectFile(fileContent, fileLength, opts.architecture, opts.subType); } #endif /* LTO_SUPPORT */ @@ -260,6 +270,10 @@ bool File::validFile(const uint8_t* fileContent, uint64_t fileLength, const m // skip option table-of-content member if ( (p==start) && ((strcmp(memberName, SYMDEF_SORTED) == 0) || (strcmp(memberName, SYMDEF) == 0)) ) continue; +#ifdef SYMDEF_64 + if ( (p==start) && ((strcmp(memberName, SYMDEF_64_SORTED) == 0) || (strcmp(memberName, SYMDEF_64) == 0)) ) + continue; +#endif // archive is valid if first .o file is valid return (validMachOFile(p->content(), p->contentSize(), opts) #ifdef LTO_SUPPORT @@ -277,15 +291,18 @@ File::File(const uint8_t fileContent[], uint64_t fileLength, const char* pth, ld::File::Ordinal ord, const ParserOptions& opts) : ld::archive::File(strdup(pth), modTime, ord), _archiveFileContent(fileContent), _archiveFilelength(fileLength), - _tableOfContents(NULL), _tableOfContentCount(0), _tableOfContentStrings(NULL), + _tableOfContents(NULL), +#ifdef SYMDEF_64 + _tableOfContents64(NULL), +#endif + _tableOfContentCount(0), _tableOfContentStrings(NULL), _forceLoadAll(opts.forceLoadAll), _forceLoadObjC(opts.forceLoadObjC), _forceLoadThis(opts.forceLoadThisArchive), _objc2ABI(opts.objcABI2), _verboseLoad(opts.verboseLoad), - _logAllFiles(opts.logAllFiles), _objOpts(opts.objOpts) + _logAllFiles(opts.logAllFiles), _alreadyLoadedAll(false), _objOpts(opts.objOpts) { if ( strncmp((const char*)fileContent, "!\n", 8) != 0 ) throw "not an archive"; - if ( !_forceLoadAll ) { const Entry* const firstMember = (Entry*)&_archiveFileContent[8]; char memberName[256]; firstMember->getName(memberName, sizeof(memberName)); @@ -300,9 +317,21 @@ File::File(const uint8_t fileContent[], uint64_t fileLength, const char* pth, throw "malformed archive, perhaps wrong architecture"; this->buildHashTable(); } +#ifdef SYMDEF_64 + else if ( (strcmp(memberName, SYMDEF_64_SORTED) == 0) || (strcmp(memberName, SYMDEF_64) == 0) ) { + const uint8_t* contents = firstMember->content(); + uint64_t ranlibArrayLen = E::get64(*((uint64_t*)contents)); + _tableOfContents64 = (const struct ranlib_64*)&contents[8]; + _tableOfContentCount = ranlibArrayLen / sizeof(struct ranlib_64); + _tableOfContentStrings = (const char*)&contents[ranlibArrayLen+16]; + if ( ((uint8_t*)(&_tableOfContents[_tableOfContentCount]) > &fileContent[fileLength]) + || ((uint8_t*)_tableOfContentStrings > &fileContent[fileLength]) ) + throw "malformed archive, perhaps wrong architecture"; + this->buildHashTable64(); + } +#endif else throw "archive has no table of contents"; - } } template <> @@ -438,15 +467,20 @@ bool File::forEachAtom(ld::File::AtomHandler& handler) const p->getName(memberName, sizeof(memberName)); if ( (p==start) && ((strcmp(memberName, SYMDEF_SORTED) == 0) || (strcmp(memberName, SYMDEF) == 0)) ) continue; +#ifdef SYMDEF_64 + if ( (p==start) && ((strcmp(memberName, SYMDEF_64_SORTED) == 0) || (strcmp(memberName, SYMDEF_64) == 0)) ) + continue; +#endif MemberState& state = this->makeObjectFileForMember(p); didSome |= loadMember(state, handler, "%s forced load of %s(%s)\n", _forceLoadThis ? "-force_load" : "-all_load", this->path(), memberName); } + _alreadyLoadedAll = true; } else if ( _forceLoadObjC ) { // call handler on all .o files in this archive containing objc classes - for(typename NameToEntryMap::const_iterator it = _hashTable.begin(); it != _hashTable.end(); ++it) { - if ( (strncmp(it->first, ".objc_c", 7) == 0) || (strncmp(it->first, "_OBJC_CLASS_$_", 14) == 0) ) { - const Entry* member = (Entry*)&_archiveFileContent[E::get32(it->second->ran_off)]; + for (const auto& entry : _hashTable) { + if ( (strncmp(entry.first, ".objc_c", 7) == 0) || (strncmp(entry.first, "_OBJC_CLASS_$_", 14) == 0) ) { + const Entry* member = (Entry*)&_archiveFileContent[entry.second]; MemberState& state = this->makeObjectFileForMember(member); char memberName[256]; member->getName(memberName, sizeof(memberName)); @@ -462,16 +496,35 @@ bool File::forEachAtom(ld::File::AtomHandler& handler) const // skip table-of-content member if ( (member==start) && ((strcmp(mname, SYMDEF_SORTED) == 0) || (strcmp(mname, SYMDEF) == 0)) ) continue; - MemberState& state = this->makeObjectFileForMember(member); - // only look at files not already loaded - if ( ! state.loaded ) { - if ( this->memberHasObjCCategories(member) ) { - MemberState& state = this->makeObjectFileForMember(member); - char memberName[256]; - member->getName(memberName, sizeof(memberName)); - didSome |= loadMember(state, handler, "-ObjC forced load of %s(%s)\n", this->path(), memberName); +#ifdef SYMDEF_64 + if ( (member==start) && ((strcmp(mname, SYMDEF_64_SORTED) == 0) || (strcmp(mname, SYMDEF_64) == 0)) ) + continue; +#endif + if ( validMachOFile(member->content(), member->contentSize(), _objOpts) ) { + MemberState& state = this->makeObjectFileForMember(member); + // only look at files not already loaded + if ( ! state.loaded ) { + if ( this->memberHasObjCCategories(member) ) { + MemberState& state = this->makeObjectFileForMember(member); + char memberName[256]; + member->getName(memberName, sizeof(memberName)); + didSome |= loadMember(state, handler, "-ObjC forced load of %s(%s)\n", this->path(), memberName); + } } } +#ifdef LTO_SUPPORT // ld64-port + else if ( validLTOFile(member->content(), member->contentSize(), _objOpts) ) { + if ( lto::hasObjCCategory(member->content(), member->contentSize()) ) { + MemberState& state = this->makeObjectFileForMember(member); + // only look at files not already loaded + if ( ! state.loaded ) { + char memberName[256]; + member->getName(memberName, sizeof(memberName)); + didSome |= loadMember(state, handler, "-ObjC forced load of %s(%s)\n", this->path(), memberName); + } + } + } +#endif } } return didSome; @@ -481,20 +534,20 @@ template bool File::justInTimeforEachAtom(const char* name, ld::File::AtomHandler& handler) const { // in force load case, all members already loaded - if ( _forceLoadAll || _forceLoadThis ) + if ( _alreadyLoadedAll ) return false; // do a hash search of table of contents looking for requested symbol - const struct ranlib* result = ranlibHashSearch(name); - if ( result != NULL ) { - const Entry* member = (Entry*)&_archiveFileContent[E::get32(result->ran_off)]; - MemberState& state = this->makeObjectFileForMember(member); - char memberName[256]; - member->getName(memberName, sizeof(memberName)); - return loadMember(state, handler, "%s forced load of %s(%s)\n", name, this->path(), memberName); - } - //fprintf(stderr, "%s NOT found in archive %s\n", name, this->path()); - return false; + const auto& pos = _hashTable.find(name); + if ( pos == _hashTable.end() ) + return false; + + // do a hash search of table of contents looking for requested symbol + const Entry* member = (Entry*)&_archiveFileContent[pos->second]; + MemberState& state = this->makeObjectFileForMember(member); + char memberName[256]; + member->getName(memberName, sizeof(memberName)); + return loadMember(state, handler, "%s forced load of %s(%s)\n", name, this->path(), memberName); } class CheckIsDataSymbolHandler : public ld::File::AtomHandler @@ -520,42 +573,31 @@ template bool File::justInTimeDataOnlyforEachAtom(const char* name, ld::File::AtomHandler& handler) const { // in force load case, all members already loaded - if ( _forceLoadAll || _forceLoadThis ) + if ( _alreadyLoadedAll ) return false; // do a hash search of table of contents looking for requested symbol - const struct ranlib* result = ranlibHashSearch(name); - if ( result != NULL ) { - const Entry* member = (Entry*)&_archiveFileContent[E::get32(result->ran_off)]; - MemberState& state = this->makeObjectFileForMember(member); - // only call handler for each member once - if ( ! state.loaded ) { - CheckIsDataSymbolHandler checker(name); - state.file->forEachAtom(checker); - if ( checker.symbolIsDataDefinition() ) { - char memberName[256]; - member->getName(memberName, sizeof(memberName)); - return loadMember(state, handler, "%s forced load of %s(%s)\n", name, this->path(), memberName); - } + const auto& pos = _hashTable.find(name); + if ( pos == _hashTable.end() ) + return false; + + const Entry* member = (Entry*)&_archiveFileContent[pos->second]; + MemberState& state = this->makeObjectFileForMember(member); + // only call handler for each member once + if ( ! state.loaded ) { + CheckIsDataSymbolHandler checker(name); + state.file->forEachAtom(checker); + if ( checker.symbolIsDataDefinition() ) { + char memberName[256]; + member->getName(memberName, sizeof(memberName)); + return loadMember(state, handler, "%s forced load of %s(%s)\n", name, this->path(), memberName); } } + //fprintf(stderr, "%s NOT found in archive %s\n", name, this->path()); return false; } - -typedef const struct ranlib* ConstRanLibPtr; - -template -ConstRanLibPtr File::ranlibHashSearch(const char* name) const -{ - typename NameToEntryMap::const_iterator pos = _hashTable.find(name); - if ( pos != _hashTable.end() ) - return pos->second; - else - return NULL; -} - template void File::buildHashTable() { @@ -564,17 +606,39 @@ void File::buildHashTable() for (int i = _tableOfContentCount-1; i >= 0; --i) { const struct ranlib* entry = &_tableOfContents[i]; const char* entryName = &_tableOfContentStrings[E::get32(entry->ran_un.ran_strx)]; - if ( E::get32(entry->ran_off) > _archiveFilelength ) { + uint64_t offset = E::get32(entry->ran_off); + if ( offset > _archiveFilelength ) { throwf("malformed archive TOC entry for %s, offset %d is beyond end of file %lld\n", entryName, entry->ran_off, _archiveFilelength); } //const Entry* member = (Entry*)&_archiveFileContent[E::get32(entry->ran_off)]; //fprintf(stderr, "adding hash %d, %s -> %p\n", i, entryName, entry); - _hashTable[entryName] = entry; + _hashTable[entryName] = offset; } } +#ifdef SYMDEF_64 +template +void File::buildHashTable64() +{ + // walk through list backwards, adding/overwriting entries + // this assures that with duplicates those earliest in the list will be found + for (int i = _tableOfContentCount-1; i >= 0; --i) { + const struct ranlib_64* entry = &_tableOfContents64[i]; + const char* entryName = &_tableOfContentStrings[E::get64(entry->ran_un.ran_strx)]; + uint64_t offset = E::get64(entry->ran_off); + if ( offset > _archiveFilelength ) { + throwf("malformed archive TOC entry for %s, offset %lld is beyond end of file %lld\n", + entryName, entry->ran_off, _archiveFilelength); + } + + //fprintf(stderr, "adding hash %d: %s -> 0x%0llX\n", i, entryName, offset); + _hashTable[entryName] = offset; + } +} +#endif + template void File::dumpTableOfContents() { @@ -621,6 +685,38 @@ ld::archive::File* parse(const uint8_t* fileContent, uint64_t fileLength, } +bool isArchiveFile(const uint8_t* fileContent, uint64_t fileLength, ld::Platform* platform, const char** archiveArchName) +{ + if ( strncmp((const char*)fileContent, "!\n", 8) != 0 ) + return false; + + // peak at first recognizable .o file and extract its platform and archName + // note: the template type does not matter here + const File::Entry* const start = (File::Entry*)&fileContent[8]; + const File::Entry* const end = (File::Entry*)&fileContent[fileLength]; + for (const File::Entry* p=start; p < end; p = p->next()) { + char memberName[256]; + p->getName(memberName, sizeof(memberName)); + // skip optional table-of-content member + if ( (p==start) && ((strcmp(memberName, SYMDEF_SORTED) == 0) || (strcmp(memberName, SYMDEF) == 0)) ) + continue; +#ifdef SYMDEF_64 + if ( (p==start) && ((strcmp(memberName, SYMDEF_64_SORTED) == 0) || (strcmp(memberName, SYMDEF_64) == 0)) ) + continue; +#endif + *archiveArchName = mach_o::relocatable::archName(p->content()); + if ( *archiveArchName != NULL ) { + cpu_type_t type; + cpu_subtype_t subtype; + uint32_t ignore; + if ( mach_o::relocatable::isObjectFile(p->content(), p->contentSize(), &type, &subtype, platform, &ignore) ) + return true; + } + } + return false; +} + + }; // namespace archive diff --git a/cctools/ld64/src/ld/parsers/archive_file.h b/cctools/ld64/src/ld/parsers/archive_file.h index 1ed411a..05b937c 100644 --- a/cctools/ld64/src/ld/parsers/archive_file.h +++ b/cctools/ld64/src/ld/parsers/archive_file.h @@ -43,6 +43,9 @@ struct ParserOptions { extern ld::archive::File* parse(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t modTime, ld::File::Ordinal ordinal, const ParserOptions& opts); +extern bool isArchiveFile(const uint8_t* fileContent, uint64_t fileLength, ld::Platform* platform, const char** archiveArchName); + + } // namespace archive diff --git a/cctools/ld64/src/ld/parsers/generic_dylib_file.hpp b/cctools/ld64/src/ld/parsers/generic_dylib_file.hpp index 26c094e..c0b78b9 100644 --- a/cctools/ld64/src/ld/parsers/generic_dylib_file.hpp +++ b/cctools/ld64/src/ld/parsers/generic_dylib_file.hpp @@ -123,36 +123,34 @@ template class File : public ld::dylib::File { public: - File(const char* path, time_t mTime, ld::File::Ordinal ordinal, Options::Platform platform, - uint32_t linkMinOSVersion, bool linkingFlatNamespace, bool hoistImplicitPublicDylibs, + File(const char* path, time_t mTime, ld::File::Ordinal ordinal, const ld::VersionSet& platforms, + bool allowWeakImports, bool linkingFlatNamespace, bool hoistImplicitPublicDylibs, bool allowSimToMacOSX, bool addVers); // overrides of ld::File virtual bool forEachAtom(ld::File::AtomHandler&) const override final; virtual bool justInTimeforEachAtom(const char* name, ld::File::AtomHandler&) const override final; - virtual ld::File::ObjcConstraint objCConstraint() const override final { return _objcConstraint; } virtual uint8_t swiftVersion() const override final { return _swiftVersion; } - virtual uint32_t minOSVersion() const override final { return _minVersionInDylib; } - virtual uint32_t platformLoadCommand() const override final { return _platformInDylib; } virtual ld::Bitcode* getBitcode() const override final { return _bitcode.get(); } // overrides of ld::dylib::File - virtual void processIndirectLibraries(ld::dylib::File::DylibHandler*, bool addImplicitDylibs) override final; + virtual void processIndirectLibraries(ld::dylib::File::DylibHandler*, bool addImplicitDylibs) override; virtual bool providedExportAtom() const override final { return _providedAtom; } virtual const char* parentUmbrella() const override final { return _parentUmbrella; } virtual const std::vector* allowableClients() const override final { return _allowableClients.empty() ? nullptr : &_allowableClients; } + virtual const std::vector& rpaths() const override final { return _rpaths; } virtual bool hasWeakExternals() const override final { return _hasWeakExports; } virtual bool deadStrippable() const override final { return _deadStrippable; } virtual bool hasWeakDefinition(const char* name) const override final; + virtual bool hasDefinition(const char* name) const override final; virtual bool hasPublicInstallName() const override final { return _hasPublicInstallName; } virtual bool allSymbolsAreWeakImported() const override final; virtual bool installPathVersionSpecific() const override final { return _installPathOverride; } virtual bool appExtensionSafe() const override final { return _appExtensionSafe; }; + virtual void forEachExportedSymbol(void (^handler)(const char* symbolName, bool weakDef)) const override; - bool wrongOS() const { return _wrongOS; } - private: using pint_t = typename A::P::uint_t; @@ -185,12 +183,12 @@ private: using NameSet = std::unordered_set; std::pair hasWeakDefinitionImpl(const char* name) const; + bool hasDefinitionImpl(const char* name) const; bool containsOrReExports(const char* name, bool& weakDef, bool& tlv, pint_t& addr) const; void assertNoReExportCycles(ReExportChain*) const; protected: bool isPublicLocation(const char* path) const; - void addSymbol(const char* name, bool weak = false, bool tlv = false, pint_t address = 0); private: ld::Section _importProxySection; @@ -204,15 +202,11 @@ protected: std::vector _dependentDylibs; ImportAtom* _importAtom; std::vector _allowableClients; + std::vector _rpaths; const char* _parentUmbrella; std::unique_ptr _bitcode; - const Options::Platform _platform; - ld::File::ObjcConstraint _objcConstraint; - const uint32_t _linkMinOSVersion; - uint32_t _minVersionInDylib; - uint32_t _platformInDylib; + ld::VersionSet _platforms; uint8_t _swiftVersion; - bool _wrongOS; bool _linkingFlat; bool _noRexports; bool _explictReExportFound; @@ -222,7 +216,7 @@ protected: bool _deadStrippable; bool _hasPublicInstallName; bool _appExtensionSafe; - + const bool _allowWeakImports; const bool _allowSimToMacOSXLinking; const bool _addVersionLoadCommand; @@ -233,8 +227,8 @@ template bool File::_s_logHashtable = false; template -File::File(const char* path, time_t mTime, ld::File::Ordinal ord, Options::Platform platform, - uint32_t linkMinOSVersion, bool linkingFlatNamespace, +File::File(const char* path, time_t mTime, ld::File::Ordinal ord, const ld::VersionSet& platforms, + bool allowWeakImports, bool linkingFlatNamespace, bool hoistImplicitPublicDylibs, bool allowSimToMacOSX, bool addVers) : ld::dylib::File(path, mTime, ord), @@ -244,13 +238,8 @@ File::File(const char* path, time_t mTime, ld::File::Ordinal ord, Options::P _indirectDylibsProcessed(false), _importAtom(nullptr), _parentUmbrella(nullptr), - _platform(platform), - _objcConstraint(ld::File::objcConstraintNone), - _linkMinOSVersion(linkMinOSVersion), - _minVersionInDylib(0), - _platformInDylib(Options::kPlatformUnknown), + _platforms(platforms), _swiftVersion(0), - _wrongOS(false), _linkingFlat(linkingFlatNamespace), _noRexports(false), _explictReExportFound(false), @@ -260,6 +249,7 @@ File::File(const char* path, time_t mTime, ld::File::Ordinal ord, Options::P _deadStrippable(false), _hasPublicInstallName(false), _appExtensionSafe(false), + _allowWeakImports(allowWeakImports), _allowSimToMacOSXLinking(allowSimToMacOSX), _addVersionLoadCommand(addVers) { @@ -283,6 +273,23 @@ std::pair File::hasWeakDefinitionImpl(const char* name) const return std::make_pair(false, false); } +template +bool File::hasDefinitionImpl(const char* name) const +{ + const auto pos = _atoms.find(name); + if ( pos != this->_atoms.end() ) + return true; + + // look in re-exported libraries. + for (const auto &dep : _dependentDylibs) { + if ( dep.reExport ) { + if ( dep.dylib->hasDefinitionImpl(name) ) + return true; + } + } + return false; +} + template bool File::hasWeakDefinition(const char* name) const { @@ -293,6 +300,16 @@ bool File::hasWeakDefinition(const char* name) const return hasWeakDefinitionImpl(name).second; } +template +bool File::hasDefinition(const char* name) const +{ + // If we are supposed to ignore this export, then pretend we don't have it. + if ( _ignoreExports.count(name) != 0 ) + return false; + + return hasDefinitionImpl(name); +} + template bool File::containsOrReExports(const char* name, bool& weakDef, bool& tlv, pint_t& addr) const { @@ -356,6 +373,14 @@ bool File::justInTimeforEachAtom(const char* name, ld::File::AtomHandler& han return false; } +template +void File::forEachExportedSymbol(void (^handler)(const char* symbolName, bool weakDef)) const +{ + for (const auto& entry : _atoms) { + handler(entry.first, entry.second.weakDef); + } +} + template void File::assertNoReExportCycles(ReExportChain* prev) const { @@ -388,7 +413,7 @@ void File::processIndirectLibraries(ld::dylib::File::DylibHandler* handler, b fprintf(stderr, "processIndirectLibraries(%s)\n", this->installPath()); if ( _linkingFlat ) { for (auto &dep : _dependentDylibs) - dep.dylib = (File*)handler->findDylib(dep.path, this->path()); + dep.dylib = (File*)handler->findDylib(dep.path, this, false); } else if ( _noRexports ) { // MH_NO_REEXPORTED_DYLIBS bit set, then nothing to do @@ -400,8 +425,8 @@ void File::processIndirectLibraries(ld::dylib::File::DylibHandler* handler, b if ( log ) fprintf(stderr, "processIndirectLibraries() parent=%s, child=%s\n", this->installPath(), dep.path); // a LC_REEXPORT_DYLIB, LC_SUB_UMBRELLA or LC_SUB_LIBRARY says we re-export this child - dep.dylib = (File*)handler->findDylib(dep.path, this->path()); - if ( dep.dylib->hasPublicInstallName() && !dep.dylib->wrongOS() ) { + dep.dylib = (File*)handler->findDylib(dep.path, this, this->speculativelyLoaded()); + if ( dep.dylib->hasPublicInstallName() ) { // promote this child to be automatically added as a direct dependent if this already is if ( (this->explicitlyLinked() || this->implicitlyLinked()) && (strcmp(dep.path, dep.dylib->installPath()) == 0) ) { if ( log ) @@ -425,7 +450,7 @@ void File::processIndirectLibraries(ld::dylib::File::DylibHandler* handler, b } else if ( !_explictReExportFound ) { // see if child contains LC_SUB_FRAMEWORK with my name - dep.dylib = (File*)handler->findDylib(dep.path, this->path()); + dep.dylib = (File*)handler->findDylib(dep.path, this, this->speculativelyLoaded()); const char* parentUmbrellaName = dep.dylib->parentUmbrella(); if ( parentUmbrellaName != nullptr ) { const char* parentName = this->path(); @@ -477,64 +502,6 @@ bool File::isPublicLocation(const char* path) const return false; } -template -void File::addSymbol(const char* name, bool weakDef, bool tlv, pint_t address) -{ - // symbols that start with $ld$ are meta-data to the static linker - // need way for ld and dyld to see different exported symbols in a dylib - if ( strncmp(name, "$ld$", 4) == 0 ) { - // $ld$ $ $ - const char* symAction = &name[4]; - const char* symCond = strchr(symAction, '$'); - if ( symCond != nullptr ) { - char curOSVers[16]; - sprintf(curOSVers, "$os%d.%d$", (_linkMinOSVersion >> 16), ((_linkMinOSVersion >> 8) & 0xFF)); - if ( strncmp(symCond, curOSVers, strlen(curOSVers)) == 0 ) { - const char* symName = strchr(&symCond[1], '$'); - if ( symName != nullptr ) { - ++symName; - if ( strncmp(symAction, "hide$", 5) == 0 ) { - if ( _s_logHashtable ) - fprintf(stderr, " adding %s to ignore set for %s\n", symName, this->path()); - _ignoreExports.insert(strdup(symName)); - return; - } - else if ( strncmp(symAction, "add$", 4) == 0 ) { - this->addSymbol(symName, weakDef); - return; - } - else if ( strncmp(symAction, "install_name$", 13) == 0 ) { - _dylibInstallPath = strdup(symName); - _installPathOverride = true; - // CoreGraphics redirects to ApplicationServices, but with wrong compat version - if ( strcmp(_dylibInstallPath, "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices") == 0 ) - _dylibCompatibilityVersion = Options::parseVersionNumber32("1.0"); - return; - } - else if ( strncmp(symAction, "compatibility_version$", 22) == 0 ) { - _dylibCompatibilityVersion = Options::parseVersionNumber32(symName); - return; - } - else { - warning("bad symbol action: %s in dylib %s", name, this->path()); - } - } - } - } - else { - warning("bad symbol condition: %s in dylib %s", name, this->path()); - } - } - - // add symbol as possible export if we are not supposed to ignore it - if ( _ignoreExports.count(name) == 0 ) { - AtomAndWeak bucket = { nullptr, weakDef, tlv, address }; - if ( this->_s_logHashtable ) - fprintf(stderr, " adding %s to hash table for %s\n", name, this->path()); - _atoms[strdup(name)] = bucket; - } -} - // If only weak_import symbols are used, linker should use LD_LOAD_WEAK_DYLIB template bool File::allSymbolsAreWeakImported() const diff --git a/cctools/ld64/src/ld/parsers/libunwind/AddressSpace.hpp b/cctools/ld64/src/ld/parsers/libunwind/AddressSpace.hpp index 2b0e186..88e1987 100644 --- a/cctools/ld64/src/ld/parsers/libunwind/AddressSpace.hpp +++ b/cctools/ld64/src/ld/parsers/libunwind/AddressSpace.hpp @@ -36,6 +36,7 @@ #include #include #include +#include #if defined(__arm__) || defined(__arm64__) // ld64-port #undef THREAD_STATE_NONE @@ -44,9 +45,6 @@ #undef MACHINE_THREAD_STATE_COUNT #endif -#include -#include - #include "FileAbstraction.hpp" #include "libunwind.h" #include "InternalMacros.h" diff --git a/cctools/ld64/src/ld/parsers/libunwind/DwarfInstructions.hpp b/cctools/ld64/src/ld/parsers/libunwind/DwarfInstructions.hpp index c14c38f..711def8 100644 --- a/cctools/ld64/src/ld/parsers/libunwind/DwarfInstructions.hpp +++ b/cctools/ld64/src/ld/parsers/libunwind/DwarfInstructions.hpp @@ -275,6 +275,10 @@ const char* DwarfInstructions::parseCFIs(A& addressSpace, pint_t ehSectionS break; } } + if ( pcRange == 0 ) { + warn(ref, pcStart, "FDE found for zero size function"); + break; + } //fprintf(stderr, "FDE for func at 0x%08X, alreadyHaveCU=%d\n", (uint32_t)entry->u.fdeInfo.function.targetAddress, alreadyHaveCU); if ( alreadyHaveCU && !forceDwarfConversion ) { if ( keepDwarfWhichHasCU ) diff --git a/cctools/ld64/src/ld/parsers/libunwind/Registers.hpp b/cctools/ld64/src/ld/parsers/libunwind/Registers.hpp index 283074a..22bae6e 100644 --- a/cctools/ld64/src/ld/parsers/libunwind/Registers.hpp +++ b/cctools/ld64/src/ld/parsers/libunwind/Registers.hpp @@ -43,13 +43,29 @@ #undef MACHINE_THREAD_STATE_COUNT #endif -#include - #include "libunwind.h" #include "InternalMacros.h" namespace libunwind { +typedef struct { + unsigned int __eax; + unsigned int __ebx; + unsigned int __ecx; + unsigned int __edx; + unsigned int __edi; + unsigned int __esi; + unsigned int __ebp; + unsigned int __esp; + unsigned int __ss; + unsigned int __eflags; + unsigned int __eip; + unsigned int __cs; + unsigned int __ds; + unsigned int __es; + unsigned int __fs; + unsigned int __gs; +} i386_thread_state_t; /// /// Registers_x86 holds the register state of a thread in a 32-bit intel process. @@ -231,6 +247,29 @@ inline void Registers_x86::setVectorRegister(int num, v128 value) } +typedef struct { + __uint64_t __rax; + __uint64_t __rbx; + __uint64_t __rcx; + __uint64_t __rdx; + __uint64_t __rdi; + __uint64_t __rsi; + __uint64_t __rbp; + __uint64_t __rsp; + __uint64_t __r8; + __uint64_t __r9; + __uint64_t __r10; + __uint64_t __r11; + __uint64_t __r12; + __uint64_t __r13; + __uint64_t __r14; + __uint64_t __r15; + __uint64_t __rip; + __uint64_t __rflags; + __uint64_t __cs; + __uint64_t __fs; + __uint64_t __gs; +} x86_thread_state64_t; /// diff --git a/cctools/ld64/src/ld/parsers/lto_file.cpp b/cctools/ld64/src/ld/parsers/lto_file.cpp index c0fd564..0a33cbe 100644 --- a/cctools/ld64/src/ld/parsers/lto_file.cpp +++ b/cctools/ld64/src/ld/parsers/lto_file.cpp @@ -31,14 +31,19 @@ #include #include #include +#include #include #include #include // ld64-port #include +#include +#include #include #include #include #include +#include +#include #include "MachOFileAbstraction.hpp" #include "Architectures.hpp" @@ -46,15 +51,20 @@ #include "macho_relocatable_file.h" #include "lto_file.h" +// ld64-port: We keep this even though it has been removed upstream +// as I am not sure if it won't break anything on all supported +// platforms. + // #defines are a work around for #undef __STDC_LIMIT_MACROS // ld64-port #undef __STDC_CONSTANT_MACROS // ld64-port #define __STDC_LIMIT_MACROS 1 #define __STDC_CONSTANT_MACROS 1 + #include "llvm-c/lto.h" + namespace lto { - // // ld64 only tracks non-internal symbols from an llvm bitcode file. @@ -68,14 +78,13 @@ class InternalAtom : public ld::Atom public: InternalAtom(class File& f); // overrides of ld::Atom - virtual ld::File* file() const { return &_file; } - virtual const char* name() const { return "import-atom"; } - virtual uint64_t size() const { return 0; } - virtual uint64_t objectAddress() const { return 0; } - virtual void copyRawContent(uint8_t buffer[]) const { } - virtual void setScope(Scope) { } - virtual ld::Fixup::iterator fixupsBegin() const { return &_undefs[0]; } - virtual ld::Fixup::iterator fixupsEnd() const { return &_undefs[_undefs.size()]; } + ld::File* file() const override { return &_file; } + const char* name() const override { return "import-atom"; } + uint64_t size() const override { return 0; } + uint64_t objectAddress() const override { return 0; } + void copyRawContent(uint8_t buffer[]) const override { } + ld::Fixup::iterator fixupsBegin() const override { return &_undefs[0]; } + ld::Fixup::iterator fixupsEnd() const override { return &_undefs[_undefs.size()]; } // for adding references to symbols outside bitcode file void addReference(const char* nm) @@ -96,24 +105,26 @@ class File : public ld::relocatable::File public: File(const char* path, time_t mTime, ld::File::Ordinal ordinal, const uint8_t* content, uint32_t contentLength, cpu_type_t arch); - virtual ~File(); + ~File() override; // overrides of ld::File - virtual bool forEachAtom(ld::File::AtomHandler&) const; - virtual bool justInTimeforEachAtom(const char* name, ld::File::AtomHandler&) const + bool forEachAtom(ld::File::AtomHandler&) const override; + bool justInTimeforEachAtom(const char* name, ld::File::AtomHandler&) const override { return false; } - virtual uint32_t cpuSubType() const { return _cpuSubType; } + uint32_t cpuSubType() const override { return _cpuSubType; } // overrides of ld::relocatable::File - virtual DebugInfoKind debugInfo() const { return _debugInfo; } - virtual const char* debugInfoPath() const { return _debugInfoPath; } - virtual time_t debugInfoModificationTime() const + DebugInfoKind debugInfo() const override { return _debugInfo; } + const char* debugInfoPath() const override { return _debugInfoPath; } + time_t debugInfoModificationTime() const override { return _debugInfoModTime; } - virtual const std::vector* stabs() const { return NULL; } - virtual bool canScatterAtoms() const { return true; } - virtual LinkerOptionsList* linkerOptions() const { return NULL; } - - + const std::vector* stabs() const override { return NULL; } + bool canScatterAtoms() const override { return true; } + LinkerOptionsList* linkerOptions() const override { return NULL; } + const ToolVersionList& toolVersions() const override { return _toolVersions; } + bool isThinLTO() const { return _isThinLTO; } + void setIsThinLTO(bool ThinLTO) { _isThinLTO = ThinLTO; } + // fixme rdar://24734472 objCConstraint() and objcHasCategoryClassProperties() void release(); lto_module_t module() { return _module; } class InternalAtom& internalAtom() { return _internalAtom; } @@ -127,11 +138,15 @@ public: static bool sSupportsLocalContext; static bool sHasTriedLocalContext; bool mergeIntoGenerator(lto_code_gen_t generator, bool useSetModule); +#if LTO_API_VERSION >= 18 + void addToThinGenerator(thinlto_code_gen_t generator, int id); +#endif private: friend class Atom; friend class InternalAtom; friend class Parser; - + + bool _isThinLTO; cpu_type_t _architecture; class InternalAtom _internalAtom; class Atom* _atomArray; @@ -146,6 +161,7 @@ private: ld::Fixup _fixupToInternal; ld::relocatable::File::DebugInfoKind _debugInfo; uint32_t _cpuSubType; + ToolVersionList _toolVersions; // unused, may some day contain version of clang the created bitcode }; // @@ -162,31 +178,32 @@ public: ld::Atom::Definition d, ld::Atom::Combine c, ld::Atom::Alignment a, bool ah); // overrides of ld::Atom - virtual ld::File* file() const { return &_file; } - virtual const char* translationUnitSource() const + const ld::File* file() const override { return (_compiledAtom ? _compiledAtom->file() : &_file ); } + const ld::File* originalFile() const override { return &_file; } + const char* translationUnitSource() const override { return (_compiledAtom ? _compiledAtom->translationUnitSource() : NULL); } - virtual const char* name() const { return _name; } - virtual uint64_t size() const { return (_compiledAtom ? _compiledAtom->size() : 0); } - virtual uint64_t objectAddress() const { return (_compiledAtom ? _compiledAtom->objectAddress() : 0); } - virtual void copyRawContent(uint8_t buffer[]) const + const char* name() const override { return _name; } + uint64_t size() const override { return (_compiledAtom ? _compiledAtom->size() : 0); } + uint64_t objectAddress() const override { return (_compiledAtom ? _compiledAtom->objectAddress() : 0); } + void copyRawContent(uint8_t buffer[]) const override { if (_compiledAtom) _compiledAtom->copyRawContent(buffer); } - virtual const uint8_t* rawContentPointer() const + const uint8_t* rawContentPointer() const override { return (_compiledAtom ? _compiledAtom->rawContentPointer() : NULL); } - virtual unsigned long contentHash(const class ld::IndirectBindingTable& ibt) const + unsigned long contentHash(const class ld::IndirectBindingTable& ibt) const override { return (_compiledAtom ? _compiledAtom->contentHash(ibt) : 0); } - virtual bool canCoalesceWith(const ld::Atom& rhs, const class ld::IndirectBindingTable& ibt) const + bool canCoalesceWith(const ld::Atom& rhs, const class ld::IndirectBindingTable& ibt) const override { return (_compiledAtom ? _compiledAtom->canCoalesceWith(rhs,ibt) : false); } - virtual ld::Fixup::iterator fixupsBegin() const + ld::Fixup::iterator fixupsBegin() const override { return (_compiledAtom ? _compiledAtom->fixupsBegin() : (ld::Fixup*)&_file._fixupToInternal); } - virtual ld::Fixup::iterator fixupsEnd() const + ld::Fixup::iterator fixupsEnd() const override { return (_compiledAtom ? _compiledAtom->fixupsEnd() : &((ld::Fixup*)&_file._fixupToInternal)[1]); } - virtual ld::Atom::UnwindInfo::iterator beginUnwind() const + ld::Atom::UnwindInfo::iterator beginUnwind() const override { return (_compiledAtom ? _compiledAtom->beginUnwind() : NULL); } - virtual ld::Atom::UnwindInfo::iterator endUnwind() const + ld::Atom::UnwindInfo::iterator endUnwind() const override { return (_compiledAtom ? _compiledAtom->endUnwind() : NULL); } - virtual ld::Atom::LineInfo::iterator beginLineInfo() const + ld::Atom::LineInfo::iterator beginLineInfo() const override { return (_compiledAtom ? _compiledAtom->beginLineInfo() : NULL); } - virtual ld::Atom::LineInfo::iterator endLineInfo() const + ld::Atom::LineInfo::iterator endLineInfo() const override { return (_compiledAtom ? _compiledAtom->endLineInfo() : NULL); } const ld::Atom* compiledAtom() { return _compiledAtom; } @@ -221,11 +238,13 @@ public: std::vector& newAtoms, std::vector& additionalUndefines); - static const char* ltoVersion() { return ::lto_get_version(); } + static const char* ltoVersion() { return ::lto_get_version(); } private: + static const char* tripletPrefixForArch(cpu_type_t arch); - static ld::relocatable::File* parseMachOFile(const uint8_t* p, size_t len, const OptimizeOptions& options); + static ld::relocatable::File* parseMachOFile(const uint8_t* p, size_t len, const std::string &path, const OptimizeOptions& options, + ld::File::Ordinal ordinal); #if LTO_API_VERSION >= 7 static void ltoDiagnosticHandler(lto_codegen_diagnostic_severity_t, const char*, void*); #endif @@ -236,23 +255,72 @@ private: class AtomSyncer : public ld::File::AtomHandler { public: AtomSyncer(std::vector& a, std::vector&na, - CStringToAtom la, CStringToAtom dla, const OptimizeOptions& options) : - _options(options), _additionalUndefines(a), _newAtoms(na), _llvmAtoms(la), _deadllvmAtoms(dla) { } - virtual void doAtom(const class ld::Atom&); - virtual void doFile(const class ld::File&) { } + const CStringToAtom &la, const CStringToAtom &dla, const OptimizeOptions& options) : + _options(options), _additionalUndefines(a), _newAtoms(na), _llvmAtoms(la), _deadllvmAtoms(dla), _lastProxiedAtom(NULL), _lastProxiedFile(NULL) {} + void doAtom(const class ld::Atom&) override; + void doFile(const class ld::File&) override { } - const OptimizeOptions& _options; std::vector& _additionalUndefines; std::vector& _newAtoms; - CStringToAtom _llvmAtoms; - CStringToAtom _deadllvmAtoms; + const CStringToAtom &_llvmAtoms; + const CStringToAtom &_deadllvmAtoms; + const ld::Atom* _lastProxiedAtom; + const ld::File* _lastProxiedFile; }; + static void setPreservedSymbols(const std::vector& allAtoms, + ld::Internal& state, + const OptimizeOptions& options, + CStringToAtom &deadllvmAtoms, + CStringToAtom &llvmAtoms, + lto_code_gen_t generator); + + static std::tuple codegen(const OptimizeOptions& options, + ld::Internal& state, + lto_code_gen_t generator, + std::string& object_path); + + + static void loadMachO(ld::relocatable::File* machoFile, + const OptimizeOptions& options, + ld::File::AtomHandler& handler, + std::vector& newAtoms, + std::vector& additionalUndefines, + CStringToAtom &llvmAtoms, + CStringToAtom &deadllvmAtoms); + + static bool optimizeLTO(const std::vector files, + const std::vector& allAtoms, + ld::Internal& state, + const OptimizeOptions& options, + ld::File::AtomHandler& handler, + std::vector& newAtoms, + std::vector& additionalUndefines); + + static bool optimizeThinLTO(const std::vector& Files, + const std::vector& allAtoms, + ld::Internal& state, + const OptimizeOptions& options, + ld::File::AtomHandler& handler, + std::vector& newAtoms, + std::vector& additionalUndefines); + +#if LTO_API_VERSION >= 18 + static thinlto_code_gen_t init_thinlto_codegen(const std::vector& files, + const std::vector& allAtoms, + ld::Internal& state, + const OptimizeOptions& options, + CStringToAtom& deadllvmAtoms, + CStringToAtom& llvmAtoms); +#endif + static std::vector _s_files; + static bool _s_llvmOptionsProcessed; }; std::vector Parser::_s_files; +bool Parser::_s_llvmOptionsProcessed = false; bool Parser::validFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t architecture, cpu_subtype_t subarch) @@ -303,7 +371,8 @@ File* Parser::parse(const uint8_t* fileContent, uint64_t fileLength, const char* } -ld::relocatable::File* Parser::parseMachOFile(const uint8_t* p, size_t len, const OptimizeOptions& options) +ld::relocatable::File* Parser::parseMachOFile(const uint8_t* p, size_t len, const std::string &path, const OptimizeOptions& options, + ld::File::Ordinal ordinal) { mach_o::relocatable::ParserOptions objOpts; objOpts.architecture = options.arch; @@ -315,27 +384,26 @@ ld::relocatable::File* Parser::parseMachOFile(const uint8_t* p, size_t len, cons objOpts.neverConvertDwarf = false; objOpts.verboseOptimizationHints = options.verboseOptimizationHints; objOpts.armUsesZeroCostExceptions = options.armUsesZeroCostExceptions; - objOpts.simulator = options.simulator; - objOpts.ignoreMismatchPlatform = options.ignoreMismatchPlatform; - objOpts.platform = options.platform; +#if SUPPORT_ARCH_arm64e + objOpts.supportsAuthenticatedPointers = options.supportsAuthenticatedPointers; +#endif + objOpts.platforms = options.platforms; objOpts.subType = 0; - objOpts.minOSVersion = 0; // ld64-port: https://gist.github.com/tpoechtrager/2efafec8ac996509b9d6 objOpts.srcKind = ld::relocatable::File::kSourceLTO; objOpts.treateBitcodeAsData = false; objOpts.usingBitcode = options.bitcodeBundle; objOpts.maxDefaultCommonAlignment = options.maxDefaultCommonAlignment; - // mach-o parsing is done in-memory, but need path for debug notes - const char* path = "/tmp/lto.o"; + const char *object_path = path.c_str(); + if (path.empty()) + object_path = "/tmp/lto.o"; + time_t modTime = 0; - if ( options.tmpObjectFilePath != NULL ) { - path = options.tmpObjectFilePath; - struct stat statBuffer; - if ( stat(options.tmpObjectFilePath, &statBuffer) == 0 ) - modTime = statBuffer.st_mtime; - } - - ld::relocatable::File* result = mach_o::relocatable::parse(p, len, path, modTime, ld::File::Ordinal::LTOOrdinal(), objOpts); + struct stat statBuffer; + if ( stat(object_path, &statBuffer) == 0 ) + modTime = statBuffer.st_mtime; + + ld::relocatable::File* result = mach_o::relocatable::parse(p, len, strdup(object_path), modTime, ordinal, objOpts); if ( result != NULL ) return result; throw "LLVM LTO, file is not of required architecture"; @@ -344,7 +412,7 @@ ld::relocatable::File* Parser::parseMachOFile(const uint8_t* p, size_t len, cons File::File(const char* pth, time_t mTime, ld::File::Ordinal ordinal, const uint8_t* content, uint32_t contentLength, cpu_type_t arch) - : ld::relocatable::File(pth,mTime,ordinal), _architecture(arch), _internalAtom(*this), + : ld::relocatable::File(pth,mTime,ordinal), _isThinLTO(false), _architecture(arch), _internalAtom(*this), _atomArray(NULL), _atomArrayCount(0), _module(NULL), _path(pth), _content(content), _contentLength(contentLength), _debugInfoPath(pth), _section("__TEXT_", "__tmp_lto", ld::Section::typeTempLTO), @@ -373,7 +441,11 @@ File::File(const char* pth, time_t mTime, ld::File::Ordinal ordinal, const uint8 throwf("could not parse object file %s: '%s', using libLTO version '%s'", pth, ::lto_get_error_message(), ::lto_get_version()); if ( log ) fprintf(stderr, "bitcode file: %s\n", pth); - + +#if LTO_API_VERSION >= 18 + _isThinLTO = ::lto_module_is_thinlto(_module); +#endif + // create atom for each global symbol in module uint32_t count = ::lto_module_get_num_symbols(_module); _atomArray = (Atom*)malloc(sizeof(Atom)*count); @@ -487,6 +559,15 @@ bool File::mergeIntoGenerator(lto_code_gen_t generator, bool useSetModule) { return false; } +#if LTO_API_VERSION >= 18 +void File::addToThinGenerator(thinlto_code_gen_t generator, int id) { + assert(!_module && "Expected module to be disposed"); + std::string pathWithID = _path; + pathWithID += std::to_string(id); + ::thinlto_codegen_add_module(generator, strdup(pathWithID.c_str()), (const char *)_content, _contentLength); +} +#endif + void File::release() { if ( _module != NULL ) @@ -568,79 +649,27 @@ void Parser::ltoDiagnosticHandler(lto_codegen_diagnostic_severity_t severity, co } #endif -bool Parser::optimize( const std::vector& allAtoms, - ld::Internal& state, - const OptimizeOptions& options, - ld::File::AtomHandler& handler, - std::vector& newAtoms, - std::vector& additionalUndefines) -{ + +/// Instruct libLTO about the list of symbols to preserve, compute deadllvmAtoms and llvmAtoms +void Parser::setPreservedSymbols( const std::vector& allAtoms, + ld::Internal& state, + const OptimizeOptions& options, + CStringToAtom &deadllvmAtoms, + CStringToAtom &llvmAtoms, + lto_code_gen_t generator) { const bool logMustPreserve = false; - const bool logExtraOptions = false; - const bool logBitcodeFiles = false; - const bool logAtomsBeforeSync = false; - // exit quickly if nothing to do - if ( _s_files.size() == 0 ) - return false; - - // print out LTO version string if -v was used - if ( options.verbose ) - fprintf(stderr, "%s\n", ::lto_get_version()); - - // create optimizer and add each Reader - lto_code_gen_t generator = NULL; -#if LTO_API_VERSION >= 11 - if ( File::sSupportsLocalContext ) - generator = ::lto_codegen_create_in_local_context(); - else -#endif - generator = ::lto_codegen_create(); -#if LTO_API_VERSION >= 7 - lto_codegen_set_diagnostic_handler(generator, ltoDiagnosticHandler, NULL); -#endif - - // The order that files are merged must match command line order - std::sort(_s_files.begin(), _s_files.end(), CommandLineOrderFileSorter()); - ld::File::Ordinal lastOrdinal; - - // When flto_codegen_only is on and we have a single .bc file, use lto_codegen_set_module instead of - // lto_codegen_add_module, to make sure the the destination module will be the same as the input .bc file. - bool useSetModule = false; -#if LTO_API_VERSION >= 13 - useSetModule = (_s_files.size() == 1) && options.ltoCodegenOnly && (::lto_api_version() >= 13); -#endif - for (std::vector::iterator it=_s_files.begin(); it != _s_files.end(); ++it) { - File* f = *it; - assert(f->ordinal() > lastOrdinal); - if ( logBitcodeFiles && !useSetModule) fprintf(stderr, "lto_codegen_add_module(%s)\n", f->path()); - if ( logBitcodeFiles && useSetModule) fprintf(stderr, "lto_codegen_set_module(%s)\n", f->path()); - if ( f->mergeIntoGenerator(generator, useSetModule) ) - throwf("lto: could not merge in %s because '%s', using libLTO version '%s'", f->path(), ::lto_get_error_message(), ::lto_get_version()); - lastOrdinal = f->ordinal(); - } - - // add any -mllvm command line options - for (std::vector::const_iterator it=options.llvmOptions->begin(); it != options.llvmOptions->end(); ++it) { - if ( logExtraOptions ) fprintf(stderr, "passing option to llvm: %s\n", *it); - ::lto_codegen_debug_options(generator, *it); - } - - // Need a way for LTO to get cpu variants (until that info is in bitcode) - if ( options.mcpu != NULL ) - ::lto_codegen_set_cpu(generator, options.mcpu); - - // The atom graph uses directed edges (references). Collect all references where - // originating atom is not part of any LTO Reader. This allows optimizer to optimize an - // external (i.e. not originated from same .o file) reference if all originating atoms are also + // The atom graph uses directed edges (references). Collect all references where + // originating atom is not part of any LTO Reader. This allows optimizer to optimize an + // external (i.e. not originated from same .o file) reference if all originating atoms are also // defined in llvm bitcode file. CStringSet nonLLVMRefs; - CStringToAtom llvmAtoms; - bool hasNonllvmAtoms = false; + bool hasNonllvmAtoms = false; for (std::vector::const_iterator it = allAtoms.begin(); it != allAtoms.end(); ++it) { const ld::Atom* atom = *it; - // only look at references that come from an atom that is not an llvm atom - if ( atom->contentType() != ld::Atom::typeLTOtemporary ) { + // only look at references that come from an atom that is not an LTO atom + if (atom->contentType() != ld::Atom::typeLTOtemporary || + ((lto::File *)atom->file())->isThinLTO()) { if ( (atom->section().type() != ld::Section::typeMachHeader) && (atom->definition() != ld::Atom::definitionProxy) ) { hasNonllvmAtoms = true; } @@ -649,7 +678,7 @@ bool Parser::optimize( const std::vector& allAtoms, switch ( fit->binding ) { case ld::Fixup::bindingDirectlyBound: // that reference an llvm atom - if ( fit->u.target->contentType() == ld::Atom::typeLTOtemporary ) + if ( fit->u.target->contentType() == ld::Atom::typeLTOtemporary ) nonLLVMRefs.insert(fit->u.target->name()); break; case ld::Fixup::bindingsIndirectlyBound: @@ -667,15 +696,14 @@ bool Parser::optimize( const std::vector& allAtoms, } // if entry point is in a llvm bitcode file, it must be preserved by LTO if ( state.entryPoint!= NULL ) { - if ( state.entryPoint->contentType() == ld::Atom::typeLTOtemporary ) + if ( state.entryPoint->contentType() == ld::Atom::typeLTOtemporary ) nonLLVMRefs.insert(state.entryPoint->name()); } - + // deadAtoms are the atoms that the linker coalesced. For instance weak or tentative definitions // overriden by another atom. If any of these deadAtoms are llvm atoms and they were replaced - // with a mach-o atom, we need to tell the lto engine to preserve (not optimize away) its dead + // with a mach-o atom, we need to tell the lto engine to preserve (not optimize away) its dead // atom so that the linker can replace it with the mach-o one later. - CStringToAtom deadllvmAtoms; for (std::vector::const_iterator it = allAtoms.begin(); it != allAtoms.end(); ++it) { const ld::Atom* atom = *it; if ( atom->coalescedAway() && (atom->contentType() == ld::Atom::typeLTOtemporary) ) { @@ -692,7 +720,7 @@ bool Parser::optimize( const std::vector& allAtoms, if ( llvmAtom->coalescedAway() ) { const char* name = llvmAtom->name(); if ( deadllvmAtoms.find(name) == deadllvmAtoms.end() ) { - if ( logMustPreserve ) + if ( logMustPreserve ) fprintf(stderr, "lto_codegen_add_must_preserve_symbol(%s) because linker coalesce away and replace with a mach-o atom\n", name); ::lto_codegen_add_must_preserve_symbol(generator, name); deadllvmAtoms[name] = (Atom*)llvmAtom; @@ -704,7 +732,7 @@ bool Parser::optimize( const std::vector& allAtoms, } } } - + // tell code generator about symbols that must be preserved for (CStringToAtom::iterator it = llvmAtoms.begin(); it != llvmAtoms.end(); ++it) { const char* name = it->first; @@ -713,7 +741,7 @@ bool Parser::optimize( const std::vector& allAtoms, // 1 - atom scope is global (and not linkage unit). // 2 - included in nonLLVMRefs set. // If a symbol is not listed in exportList then LTO is free to optimize it away. - if ( (atom->scope() == ld::Atom::scopeGlobal) && options.preserveAllGlobals ) { + if ( (atom->scope() == ld::Atom::scopeGlobal) && options.preserveAllGlobals ) { if ( logMustPreserve ) fprintf(stderr, "lto_codegen_add_must_preserve_symbol(%s) because global symbol\n", name); ::lto_codegen_add_must_preserve_symbol(generator, name); } @@ -727,16 +755,16 @@ bool Parser::optimize( const std::vector& allAtoms, ::lto_codegen_add_must_preserve_symbol(generator, name); } } - + // tell code generator to preserve initial undefines for( std::vector::const_iterator it=options.initialUndefines->begin(); it != options.initialUndefines->end(); ++it) { if ( logMustPreserve ) fprintf(stderr, "lto_codegen_add_must_preserve_symbol(%s) because it is an initial undefine\n", *it); ::lto_codegen_add_must_preserve_symbol(generator, *it); } - // special case running ld -r on all bitcode files to produce another bitcode file (instead of mach-o) - if ( options.relocatable && !hasNonllvmAtoms ) { -#if LTO_API_VERSION >= 15 + // special case running ld -r on all bitcode files to produce another bitcode file (instead of mach-o) + if ( options.relocatable && !hasNonllvmAtoms ) { +#if LTO_API_VERSION >= 17 ::lto_codegen_set_should_embed_uselists(generator, false); #endif if ( ! ::lto_codegen_write_merged_modules(generator, options.outputFilePath) ) { @@ -744,44 +772,62 @@ bool Parser::optimize( const std::vector& allAtoms, exit(0); } warning("could not produce merged bitcode file"); - } - - // set code-gen model - lto_codegen_model model = LTO_CODEGEN_PIC_MODEL_DYNAMIC; + } + +} + +// Retrieve the codegen model from the options +static lto_codegen_model getCodeModel(const OptimizeOptions& options) { if ( options.mainExecutable ) { if ( options.staticExecutable ) { // x86_64 "static" or any "-static -pie" is really dynamic code model if ( (options.arch == CPU_TYPE_X86_64) || options.pie ) - model = LTO_CODEGEN_PIC_MODEL_DYNAMIC; + return LTO_CODEGEN_PIC_MODEL_DYNAMIC; else - model = LTO_CODEGEN_PIC_MODEL_STATIC; + return LTO_CODEGEN_PIC_MODEL_STATIC; + } + else if ( options.preload ) { + if ( options.pie ) + return LTO_CODEGEN_PIC_MODEL_DYNAMIC; + else + return LTO_CODEGEN_PIC_MODEL_STATIC; } else { if ( options.pie ) - model = LTO_CODEGEN_PIC_MODEL_DYNAMIC; + return LTO_CODEGEN_PIC_MODEL_DYNAMIC; else - model = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC; + return LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC; } } else { if ( options.allowTextRelocs ) - model = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC; + return LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC; else - model = LTO_CODEGEN_PIC_MODEL_DYNAMIC; + return LTO_CODEGEN_PIC_MODEL_DYNAMIC; } - if ( ::lto_codegen_set_pic_model(generator, model) ) + +} + +std::tuple Parser::codegen(const OptimizeOptions& options, + ld::Internal& state, + lto_code_gen_t generator, + std::string& object_path) { + uint8_t *machOFile = NULL; // ld64-port: = NULL + size_t machOFileLen; + + if ( ::lto_codegen_set_pic_model(generator, getCodeModel(options)) ) throwf("could not create set codegen model: %s", lto_get_error_message()); - // if requested, save off merged bitcode file - if ( options.saveTemps ) { - char tempBitcodePath[MAXPATHLEN]; - strcpy(tempBitcodePath, options.outputFilePath); - strcat(tempBitcodePath, ".lto.bc"); -#if LTO_API_VERSION >= 15 - ::lto_codegen_set_should_embed_uselists(generator, true); + // if requested, save off merged bitcode file + if ( options.saveTemps ) { + char tempBitcodePath[MAXPATHLEN]; + strcpy(tempBitcodePath, options.outputFilePath); + strcat(tempBitcodePath, ".lto.bc"); +#if LTO_API_VERSION >= 17 + ::lto_codegen_set_should_embed_uselists(generator, true); #endif - ::lto_codegen_write_merged_modules(generator, tempBitcodePath); - } + ::lto_codegen_write_merged_modules(generator, tempBitcodePath); + } #if LTO_API_VERSION >= 3 // find assembler next to linker @@ -810,22 +856,21 @@ bool Parser::optimize( const std::vector& allAtoms, } #endif - // When lto API version is greater than or equal to 12, we use lto_codegen_optimize and lto_codegen_compile_optimized + // When lto API version is greater than or equal to 17, we use lto_codegen_optimize and lto_codegen_compile_optimized // instead of lto_codegen_compile, and we save the merged bitcode file in between. bool useSplitAPI = false; -#if LTO_API_VERSION >= 12 +#if LTO_API_VERSION >= 17 if ( ::lto_api_version() >= 12) useSplitAPI = true; #endif - size_t machOFileLen = 0; - const uint8_t* machOFile = NULL; if ( useSplitAPI) { -#if LTO_API_VERSION >= 12 -#if LTO_API_VERSION >= 14 - if ( ::lto_api_version() >= 14 && options.ltoCodegenOnly) - lto_codegen_set_should_internalize(generator, false); -#endif +// ld64-port: Fixed wrong if conditions +#if LTO_API_VERSION >= 17 +//#if LTO_API_VERSION >= 14 + if ( ::lto_api_version() >= 17 && options.ltoCodegenOnly) + lto_codegen_set_should_internalize(generator, false); +//#endif // run optimizer if ( !options.ltoCodegenOnly && ::lto_codegen_optimize(generator) ) throwf("could not do LTO optimization: '%s', using libLTO version '%s'", ::lto_get_error_message(), ::lto_get_version()); @@ -835,12 +880,12 @@ bool Parser::optimize( const std::vector& allAtoms, char tempOptBitcodePath[MAXPATHLEN]; strcpy(tempOptBitcodePath, options.outputFilePath); strcat(tempOptBitcodePath, ".lto.opt.bc"); -#if LTO_API_VERSION >= 15 +//#if LTO_API_VERSION >= 15 ::lto_codegen_set_should_embed_uselists(generator, true); -#endif +//#endif ::lto_codegen_write_merged_modules(generator, tempOptBitcodePath); if ( options.bitcodeBundle ) - state.ltoBitcodePath = tempOptBitcodePath; + state.ltoBitcodePath.push_back(tempOptBitcodePath); } // run code generator @@ -859,19 +904,19 @@ bool Parser::optimize( const std::vector& allAtoms, char tempOptBitcodePath[MAXPATHLEN]; strcpy(tempOptBitcodePath, options.outputFilePath); strcat(tempOptBitcodePath, ".lto.opt.bc"); -#if LTO_API_VERSION >= 15 +#if LTO_API_VERSION >= 17 ::lto_codegen_set_should_embed_uselists(generator, true); #endif ::lto_codegen_write_merged_modules(generator, tempOptBitcodePath); } } - - // if requested, save off temp mach-o file - if ( options.saveTemps ) { - char tempMachoPath[MAXPATHLEN]; - strcpy(tempMachoPath, options.outputFilePath); - strcat(tempMachoPath, ".lto.o"); - int fd = ::open(tempMachoPath, O_CREAT | O_WRONLY | O_TRUNC, 0666); + + // if requested, save off temp mach-o file + if ( options.saveTemps ) { + char tempMachoPath[MAXPATHLEN]; + strcpy(tempMachoPath, options.outputFilePath); + strcat(tempMachoPath, ".lto.o"); + int fd = ::open(tempMachoPath, O_CREAT | O_WRONLY | O_TRUNC, 0666); if ( fd != -1) { ::write(fd, machOFile, machOFileLen); ::close(fd); @@ -879,20 +924,30 @@ bool Parser::optimize( const std::vector& allAtoms, } // if needed, save temp mach-o file to specific location - if ( options.tmpObjectFilePath != NULL ) { - int fd = ::open(options.tmpObjectFilePath, O_CREAT | O_WRONLY | O_TRUNC, 0666); + if ( !object_path.empty() ) { + int fd = ::open(object_path.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666); if ( fd != -1) { ::write(fd, machOFile, machOFileLen); ::close(fd); } else { - warning("could not write LTO temp file '%s', errno=%d", options.tmpObjectFilePath, errno); + warning("could not write LTO temp file '%s', errno=%d", object_path.c_str(), errno); } } - - // parse generated mach-o file into a MachOReader - ld::relocatable::File* machoFile = parseMachOFile(machOFile, machOFileLen, options); - + return std::make_tuple(machOFile, machOFileLen); +} + +/// Load the MachO located in buffer \p machOFile with size \p machOFileLen. +/// The loaded atoms are sync'ed using all the supplied lists. +void Parser::loadMachO(ld::relocatable::File* machoFile, + const OptimizeOptions& options, + ld::File::AtomHandler& handler, + std::vector& newAtoms, + std::vector& additionalUndefines, + CStringToAtom &llvmAtoms, + CStringToAtom &deadllvmAtoms) { + const bool logAtomsBeforeSync = false; + // sync generated mach-o atoms with existing atoms ld knows about if ( logAtomsBeforeSync ) { fprintf(stderr, "llvmAtoms:\n"); @@ -910,11 +965,96 @@ bool Parser::optimize( const std::vector& allAtoms, } AtomSyncer syncer(additionalUndefines, newAtoms, llvmAtoms, deadllvmAtoms, options); machoFile->forEachAtom(syncer); - - // Remove InternalAtoms from ld - for (std::vector::iterator it=_s_files.begin(); it != _s_files.end(); ++it) { - (*it)->internalAtom().setCoalescedAway(); + + // notify about file level attributes + handler.doFile(*machoFile); +} + +// Full LTO processing +bool Parser::optimizeLTO(const std::vector files, + const std::vector& allAtoms, + ld::Internal& state, + const OptimizeOptions& options, + ld::File::AtomHandler& handler, + std::vector& newAtoms, + std::vector& additionalUndefines) { + const bool logExtraOptions = false; + const bool logBitcodeFiles = false; + + if (files.empty()) + return true; + + // create optimizer and add each Reader + lto_code_gen_t generator = NULL; +#if LTO_API_VERSION >= 11 + if ( File::sSupportsLocalContext ) + generator = ::lto_codegen_create_in_local_context(); + else +#endif + generator = ::lto_codegen_create(); +#if LTO_API_VERSION >= 7 + lto_codegen_set_diagnostic_handler(generator, ltoDiagnosticHandler, NULL); +#endif + + ld::File::Ordinal lastOrdinal; + + // When flto_codegen_only is on and we have a single .bc file, use lto_codegen_set_module instead of + // lto_codegen_add_module, to make sure the the destination module will be the same as the input .bc file. + bool useSetModule = false; +#if LTO_API_VERSION >= 13 + useSetModule = (files.size() == 1) && options.ltoCodegenOnly && (::lto_api_version() >= 13); +#endif + for (auto *f : files) { + assert(f->ordinal() > lastOrdinal); + if ( logBitcodeFiles && !useSetModule ) fprintf(stderr, "lto_codegen_add_module(%s)\n", f->path()); + if ( logBitcodeFiles && useSetModule ) fprintf(stderr, "lto_codegen_set_module(%s)\n", f->path()); + if ( f->mergeIntoGenerator(generator, useSetModule) ) + throwf("lto: could not merge in %s because '%s', using libLTO version '%s'", f->path(), ::lto_get_error_message(), ::lto_get_version()); + lastOrdinal = f->ordinal(); } + + // add any -mllvm command line options + if ( !_s_llvmOptionsProcessed ) { + for (const char* opt : *options.llvmOptions) { + if ( logExtraOptions ) fprintf(stderr, "passing option to llvm: %s\n", opt); + ::lto_codegen_debug_options(generator, opt); + } + _s_llvmOptionsProcessed = true; + } + + // Need a way for LTO to get cpu variants (until that info is in bitcode) + if ( options.mcpu != NULL ) + ::lto_codegen_set_cpu(generator, options.mcpu); + + // Compute the preserved symbols + CStringToAtom deadllvmAtoms, llvmAtoms; + setPreservedSymbols(allAtoms, state, options, deadllvmAtoms, llvmAtoms, generator); + + size_t machOFileLen = 0; + const uint8_t* machOFile = NULL; + + // mach-o parsing is done in-memory, but need path for debug notes + std::string object_path; + if ( options.tmpObjectFilePath != NULL ) { + object_path = options.tmpObjectFilePath; + // If the path exists and is a directory (for instance if some files + // were processed with ThinLTO before), we create the LTO file inside + // the directory. + struct stat statBuffer; + if( stat(object_path.c_str(), &statBuffer) == 0 && S_ISDIR(statBuffer.st_mode) ) { + object_path += "/lto.o"; + } + } + + // Codegen Now + std::tie(machOFile, machOFileLen) = codegen(options, state, generator, object_path); + + // parse generated mach-o file into a MachOReader + ld::relocatable::File* machoFile = parseMachOFile(machOFile, machOFileLen, object_path, options, ld::File::Ordinal::LTOOrdinal()); + + // Load the generated MachO file + loadMachO(machoFile, options, handler, newAtoms, additionalUndefines, llvmAtoms, deadllvmAtoms); + // Remove Atoms from ld if code generator optimized them away for (CStringToAtom::iterator li = llvmAtoms.begin(), le = llvmAtoms.end(); li != le; ++li) { // check if setRealAtom() called on this Atom @@ -923,49 +1063,502 @@ bool Parser::optimize( const std::vector& allAtoms, li->second->setCoalescedAway(); } } - - // notify about file level attributes - handler.doFile(*machoFile); - + // if final mach-o file has debug info, update original bitcode files to match - for (std::vector::iterator it=_s_files.begin(); it != _s_files.end(); ++it) { - (*it)->setDebugInfo(machoFile->debugInfo(), machoFile->path(), - machoFile->modificationTime(), machoFile->cpuSubType()); + for (auto *f : files) { + f->setDebugInfo(machoFile->debugInfo(), machoFile->path(), machoFile->modificationTime(), machoFile->cpuSubType()); } - + return true; } +#if LTO_API_VERSION >= 18 +// Create the ThinLTO codegenerator +thinlto_code_gen_t Parser::init_thinlto_codegen(const std::vector& files, + const std::vector& allAtoms, + ld::Internal& state, + const OptimizeOptions& options, + CStringToAtom& deadllvmAtoms, + CStringToAtom& llvmAtoms) { + const bool logMustPreserve = false; + + thinlto_code_gen_t thingenerator = ::thinlto_create_codegen(); + + // Caching control + if (options.ltoCachePath && !options.bitcodeBundle) { + struct stat statBuffer; + if( stat(options.ltoCachePath, &statBuffer) != 0 || !S_ISDIR(statBuffer.st_mode) ) { + if ( mkdir(options.ltoCachePath, 0700) !=0 ) { + warning("unable to create ThinLTO cache directory: %s", options.ltoCachePath); + } + } + thinlto_codegen_set_cache_dir(thingenerator, options.ltoCachePath); + if (options.ltoPruneIntervalOverwrite) + thinlto_codegen_set_cache_pruning_interval(thingenerator, options.ltoPruneInterval); + thinlto_codegen_set_cache_entry_expiration(thingenerator, options.ltoPruneAfter); + thinlto_codegen_set_final_cache_size_relative_to_available_space(thingenerator, options.ltoMaxCacheSize); + } + + // if requested, ask the code generator to save off intermediate bitcode files + if ( options.saveTemps ) { + std::string tempPath = options.outputFilePath; + tempPath += ".thinlto.bcs/"; + struct stat statBuffer; + if( stat(tempPath.c_str(), &statBuffer) != 0 || !S_ISDIR(statBuffer.st_mode) ) { + if ( mkdir(tempPath.c_str(), 0700) !=0 ) { + warning("unable to create ThinLTO output directory for temporary bitcode files: %s", tempPath.c_str()); + } + } + thinlto_codegen_set_savetemps_dir(thingenerator, tempPath.c_str()); + } + + // Set some codegen options + if ( thinlto_codegen_set_pic_model(thingenerator, getCodeModel(options)) ) + throwf("could not create set codegen model: %s", lto_get_error_message()); + + // Expose reachability informations for internalization in LTO + + // The atom graph uses directed edges (references). Collect all references where + // originating atom is not part of any LTO Reader. This allows optimizer to optimize an + // external (i.e. not originated from same .o file) reference if all originating atoms are also + // defined in llvm bitcode file. + CStringSet nonLLVMRefs; + CStringSet LLVMRefs; + for (std::vector::const_iterator it = allAtoms.begin(); it != allAtoms.end(); ++it) { + const ld::Atom* atom = *it; + const ld::Atom* target; + for (ld::Fixup::iterator fit=atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) { + switch ( fit->binding ) { + case ld::Fixup::bindingDirectlyBound: + // that reference a ThinLTO llvm atom + target = fit->u.target; + if ( target->contentType() == ld::Atom::typeLTOtemporary && + ((lto::File *)target->file())->isThinLTO() && + atom->file() != target->file() + ) { + if (atom->contentType() != ld::Atom::typeLTOtemporary || + !((lto::File *)atom->file())->isThinLTO()) + nonLLVMRefs.insert(target->name()); + else + LLVMRefs.insert(target->name()); + if ( logMustPreserve ) + fprintf(stderr, "Found a reference from %s -> %s\n", atom->name(), target->name()); + } + break; + case ld::Fixup::bindingsIndirectlyBound: + target = state.indirectBindingTable[fit->u.bindingIndex]; + if ( (target != NULL) && (target->contentType() == ld::Atom::typeLTOtemporary) && + ((lto::File *)target->file())->isThinLTO() && + atom->file() != target->file() + ) { + if (atom->contentType() != ld::Atom::typeLTOtemporary || + !((lto::File *)atom->file())->isThinLTO()) + nonLLVMRefs.insert(target->name()); + else + LLVMRefs.insert(target->name()); + if ( logMustPreserve ) + fprintf(stderr, "Found a reference from %s -> %s\n", atom->name(), target->name()); + } + default: + break; + } + } + if (atom->contentType() == ld::Atom::typeLTOtemporary && + ((lto::File *)atom->file())->isThinLTO() && + atom != &((lto::File *)atom->file())->internalAtom()) { + assert(atom->scope() != ld::Atom::scopeTranslationUnit && "LTO should not expose static atoms"); + assert(llvmAtoms.find(atom->name()) == llvmAtoms.end() && "Unexpected llvmAtom with duplicate name"); + llvmAtoms[atom->name()] = (Atom*)atom; + } + } + // if entry point is in a llvm bitcode file, it must be preserved by LTO + if ( state.entryPoint != NULL ) { + if ( state.entryPoint->contentType() == ld::Atom::typeLTOtemporary ) + nonLLVMRefs.insert(state.entryPoint->name()); + } + for (auto file : files) { + for(uint32_t i=0; i < file->_atomArrayCount; ++i) { + Atom* llvmAtom = &file->_atomArray[i]; + if ( llvmAtom->coalescedAway() ) { + const char* name = llvmAtom->name(); + if ( deadllvmAtoms.find(name) == deadllvmAtoms.end() ) { + if ( logMustPreserve ) + fprintf(stderr, "thinlto_codegen_add_must_preserve_symbol(%s) because linker coalesce away and replace with a mach-o atom\n", name); + ::thinlto_codegen_add_must_preserve_symbol(thingenerator, name, strlen(name)); + deadllvmAtoms[name] = (Atom*)llvmAtom; + } + } + else if ( options.linkerDeadStripping && !llvmAtom->live() ) { + const char* name = llvmAtom->name(); + deadllvmAtoms[name] = (Atom*)llvmAtom; + } + } + } + + // tell code generator about symbols that must be preserved + for (CStringToAtom::iterator it = llvmAtoms.begin(); it != llvmAtoms.end(); ++it) { + const char* name = it->first; + Atom* atom = it->second; + // Include llvm Symbol in export list if it meets one of following two conditions + // 1 - atom scope is global (and not linkage unit). + // 2 - included in nonLLVMRefs set. + // If a symbol is not listed in exportList then LTO is free to optimize it away. + if ( (atom->scope() == ld::Atom::scopeGlobal) && options.preserveAllGlobals ) { + if ( logMustPreserve ) fprintf(stderr, "thinlto_codegen_add_must_preserve_symbol(%s) because global symbol\n", name); + ::thinlto_codegen_add_must_preserve_symbol(thingenerator, name, strlen(name)); + } + else if ( nonLLVMRefs.find(name) != nonLLVMRefs.end() ) { + if ( logMustPreserve ) fprintf(stderr, "thinlto_codegen_add_must_preserve_symbol(%s) because referenced from outside of ThinLTO\n", name); + ::thinlto_codegen_add_must_preserve_symbol(thingenerator, name, strlen(name)); + } + else if ( LLVMRefs.find(name) != LLVMRefs.end() ) { + if ( logMustPreserve ) fprintf(stderr, "thinlto_codegen_add_cross_referenced_symbol(%s) because referenced from another file\n", name); + ::thinlto_codegen_add_cross_referenced_symbol(thingenerator, name, strlen(name)); + } else { + if ( logMustPreserve ) fprintf(stderr, "NOT preserving(%s)\n", name); + } + + // tell code generator to preserve initial undefines + for (const char* undefName : *options.initialUndefines) { + if ( logMustPreserve ) fprintf(stderr, "thinlto_codegen_add_cross_referenced_symbol(%s) because it is an initial undefine\n", undefName); + ::thinlto_codegen_add_cross_referenced_symbol(thingenerator, undefName, strlen(undefName)); + } + +// FIXME: to be implemented +// else if ( options.relocatable && hasNonllvmAtoms ) { +// // ld -r mode but merging in some mach-o files, so need to keep libLTO from optimizing away anything +// if ( logMustPreserve ) fprintf(stderr, "lto_codegen_add_must_preserve_symbol(%s) because -r mode disable LTO dead stripping\n", name); +// ::thinlto_codegen_add_must_preserve_symbol(thingenerator, name, strlen(name)); +// } + } + + return thingenerator; +} +#endif + +// Full LTO processing +bool Parser::optimizeThinLTO(const std::vector& files, + const std::vector& allAtoms, + ld::Internal& state, + const OptimizeOptions& options, + ld::File::AtomHandler& handler, + std::vector& newAtoms, + std::vector& additionalUndefines) { + const bool logBitcodeFiles = false; + + if (files.empty()) + return true; + +#if LTO_API_VERSION >= 18 + + if (::lto_api_version() < 18) + throwf("lto: could not use -thinlto because libLTO is too old (version '%d', >=18 is required)", ::lto_api_version()); + + // Handle -mllvm options + if ( !_s_llvmOptionsProcessed ) { + thinlto_debug_options(options.llvmOptions->data(), options.llvmOptions->size()); + _s_llvmOptionsProcessed = true; + } + + // Create the ThinLTO codegenerator + CStringToAtom deadllvmAtoms; + CStringToAtom llvmAtoms; + thinlto_code_gen_t thingenerator = init_thinlto_codegen(files, allAtoms, state, options, deadllvmAtoms, llvmAtoms); + + + ld::File::Ordinal lastOrdinal; + int FileId = 0; + for (auto *f : files) { + if ( logBitcodeFiles) fprintf(stderr, "thinlto_codegen_add_module(%s)\n", f->path()); + f->addToThinGenerator(thingenerator, FileId++); + lastOrdinal = f->ordinal(); + } + +#if LTO_API_VERSION >= 19 + // In the bitcode bundle case, we first run the generator with codegen disabled + // and get the bitcode output. These files are added for later bundling, and a + // new codegenerator is setup with these as input, and the optimizer disabled. + if (options.bitcodeBundle) { + // Bitcode Bundle case + thinlto_codegen_disable_codegen(thingenerator, true); + // Process the optimizer only + thinlto_codegen_process(thingenerator); + auto numObjects = thinlto_module_get_num_objects(thingenerator); + // Save the codegenerator + thinlto_code_gen_t bitcode_generator = thingenerator; + // Create a new codegen generator for the codegen part. + // Clear out the stored atoms so we can recompute them. + deadllvmAtoms.clear(); + llvmAtoms.clear(); + thingenerator = init_thinlto_codegen(files, allAtoms, state, options, deadllvmAtoms, llvmAtoms); + // Disable the optimizer + thinlto_codegen_set_codegen_only(thingenerator, true); + + // Save bitcode files for later, and add them to the codegen generator. + for (unsigned bufID = 0; bufID < numObjects; ++bufID) { + auto machOFile = thinlto_module_get_object(bitcode_generator, bufID); + std::string tempMachoPath = options.outputFilePath; + tempMachoPath += "."; + tempMachoPath += std::to_string(bufID); + tempMachoPath += ".thinlto.o.bc"; + state.ltoBitcodePath.push_back(tempMachoPath); + int fd = ::open(tempMachoPath.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666); + if ( fd != -1 ) { + ::write(fd, machOFile.Buffer, machOFile.Size); + ::close(fd); + } else { + throwf("unable to write temporary ThinLTO output: %s", tempMachoPath.c_str()); + } + + // Add the optimized bitcode to the codegen generator now. + ::thinlto_codegen_add_module(thingenerator, strdup(tempMachoPath.c_str()), (const char *)machOFile.Buffer, machOFile.Size); + } + } + + if (options.ltoCodegenOnly) + // Disable the optimizer + thinlto_codegen_set_codegen_only(thingenerator, true); +#endif + + // If object_path_lto is used, we switch to a file-based API: libLTO will + // generate the files on disk and we'll map them on-demand. + +#if LTO_API_VERSION >= 21 + bool useFileBasedAPI = (options.tmpObjectFilePath && ::lto_api_version() >= 21); + if ( useFileBasedAPI ) + thinlto_set_generated_objects_dir(thingenerator, options.tmpObjectFilePath); +#endif + + // run code generator + thinlto_codegen_process(thingenerator); + + unsigned numObjects; +#if LTO_API_VERSION >= 21 + if ( useFileBasedAPI ) + numObjects = thinlto_module_get_num_object_files(thingenerator); + else +#endif + numObjects = thinlto_module_get_num_objects(thingenerator); + if ( numObjects == 0 ) + throwf("could not do ThinLTO codegen (thinlto_codegen_process didn't produce any object): '%s', using libLTO version '%s'", ::lto_get_error_message(), ::lto_get_version()); + + auto get_thinlto_buffer_or_load_file = [&] (unsigned ID) { +#if LTO_API_VERSION >= 21 + if ( useFileBasedAPI ) { + const char* path = thinlto_module_get_object_file(thingenerator, ID); + // map in whole file + struct stat stat_buf; + int fd = ::open(path, O_RDONLY, 0); + if ( fd == -1 ) + throwf("can't open thinlto file '%s', errno=%d", path, errno); + if ( ::fstat(fd, &stat_buf) != 0 ) + throwf("fstat thinlto file '%s' failed, errno=%d\n", path, errno); + size_t len = stat_buf.st_size; + if ( len < 20 ) + throwf("ThinLTO file '%s' too small (length=%zu)", path, len); + const char* p = (const char*)::mmap(NULL, len, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0); + if ( p == (const char*)(-1) ) + throwf("can't map file, errno=%d", errno); + ::close(fd); + return LTOObjectBuffer{ p, len }; + } +#endif + return thinlto_module_get_object(thingenerator, ID); + }; + + // if requested, save off objects files + if ( options.saveTemps ) { + for (unsigned bufID = 0; bufID < numObjects; ++bufID) { + auto machOFile = get_thinlto_buffer_or_load_file(bufID); + std::string tempMachoPath = options.outputFilePath; + tempMachoPath += "."; + tempMachoPath += std::to_string(bufID); + tempMachoPath += ".thinlto.o"; + int fd = ::open(tempMachoPath.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666); + if ( fd != -1 ) { + ::write(fd, machOFile.Buffer, machOFile.Size); + ::close(fd); + } + else { + warning("unable to write temporary ThinLTO output: %s", tempMachoPath.c_str()); + } + } + } + + // mach-o parsing is done in-memory, but need path for debug notes + std::string macho_dirpath = "/tmp/thinlto.o"; + if ( options.tmpObjectFilePath != NULL ) { + macho_dirpath = options.tmpObjectFilePath; + struct stat statBuffer; + if( stat(macho_dirpath.c_str(), &statBuffer) != 0 || !S_ISDIR(statBuffer.st_mode) ) { + unlink(macho_dirpath.c_str()); + if ( mkdir(macho_dirpath.c_str(), 0700) !=0 ) { + warning("unable to create ThinLTO output directory for temporary object files: %s", macho_dirpath.c_str()); + } + } + } + + auto ordinal = ld::File::Ordinal::LTOOrdinal().nextFileListOrdinal(); + for (unsigned bufID = 0; bufID < numObjects; ++bufID) { + auto machOFile = get_thinlto_buffer_or_load_file(bufID); + if (!machOFile.Size) { + warning("Ignoring empty buffer generated by ThinLTO"); + continue; + } + + // mach-o parsing is done in-memory, but need path for debug notes + std::string tmp_path; +#if LTO_API_VERSION >= 21 + if ( useFileBasedAPI ) { + tmp_path = thinlto_module_get_object_file(thingenerator, bufID); + } + else +#endif + if ( options.tmpObjectFilePath != NULL) { + tmp_path = macho_dirpath + "/" + std::to_string(bufID) + ".o"; + // if needed, save temp mach-o file to specific location + int fd = ::open(tmp_path.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666); + if ( fd != -1) { + ::write(fd, (const uint8_t *)machOFile.Buffer, machOFile.Size); + ::close(fd); + } + else { + warning("could not write ThinLTO temp file '%s', errno=%d", tmp_path.c_str(), errno); + } + } + + // parse generated mach-o file into a MachOReader + ld::relocatable::File* machoFile = parseMachOFile((const uint8_t *)machOFile.Buffer, machOFile.Size, tmp_path, options, ordinal); + ordinal = ordinal.nextFileListOrdinal(); + + // Load the generated MachO file + loadMachO(machoFile, options, handler, newAtoms, additionalUndefines, llvmAtoms, deadllvmAtoms); + } + + // Remove Atoms from ld if code generator optimized them away + for (CStringToAtom::iterator li = llvmAtoms.begin(), le = llvmAtoms.end(); li != le; ++li) { + // check if setRealAtom() called on this Atom + if ( li->second->compiledAtom() == NULL ) { + //fprintf(stderr, "llvm optimized away %p %s\n", li->second, li->second->name()); + li->second->setCoalescedAway(); + } + } + + return true; +#else // ! (LTO_API_VERSION >= 18) + throwf("lto: could not use -thinlto because ld was built against a version of libLTO too old (version '%d', >=18 is required)", LTO_API_VERSION); +#endif +} + +bool Parser::optimize( const std::vector& allAtoms, + ld::Internal& state, + const OptimizeOptions& options, + ld::File::AtomHandler& handler, + std::vector& newAtoms, + std::vector& additionalUndefines) +{ + + // exit quickly if nothing to do + if ( _s_files.size() == 0 ) + return false; + + // print out LTO version string if -v was used + if ( options.verbose ) + fprintf(stderr, "%s\n", ::lto_get_version()); + + // The order that files are merged must match command line order + std::sort(_s_files.begin(), _s_files.end(), CommandLineOrderFileSorter()); + +#if LTO_API_VERSION >= 19 + // If ltoCodegenOnly is set, we don't want to merge any bitcode files and perform FullLTO + // we just take the ThinLTO path (optimization will be disabled anyway). + if (options.ltoCodegenOnly) { + for (auto *file : _s_files) { + file->setIsThinLTO(true); + } + } +#endif + + std::vector theLTOFiles; + std::vector theThinLTOFiles; + for (auto *file : _s_files) { + if (file->isThinLTO()) { + theThinLTOFiles.push_back(file); + } else { + theLTOFiles.push_back(file); + } + } + + auto result = optimizeThinLTO(theThinLTOFiles, allAtoms, state, options, handler, newAtoms, additionalUndefines) && + optimizeLTO(theLTOFiles, allAtoms, state, options, handler, newAtoms, additionalUndefines); + + // Remove InternalAtoms from ld + for (std::vector::iterator it=_s_files.begin(); it != _s_files.end(); ++it) { + (*it)->internalAtom().setCoalescedAway(); + } + + return result; +} + void Parser::AtomSyncer::doAtom(const ld::Atom& machoAtom) { static const bool log = false; - static const ld::Atom* lastProxiedAtom = NULL; - static const ld::File* lastProxiedFile = NULL; // update proxy atoms to point to real atoms and find new atoms const char* name = machoAtom.name(); - CStringToAtom::iterator pos = _llvmAtoms.find(name); - if ( pos != _llvmAtoms.end() ) { + CStringToAtom::const_iterator pos = _llvmAtoms.find(name); + if ( (pos != _llvmAtoms.end()) && (machoAtom.scope() != ld::Atom::scopeTranslationUnit) ) { // turn Atom into a proxy for this mach-o atom + if (pos->second->scope() == ld::Atom::scopeLinkageUnit) { + if (log) fprintf(stderr, "demote %s to hidden after LTO\n", name); + (const_cast(&machoAtom))->setScope(ld::Atom::scopeLinkageUnit); + } + // If both llvmAtom and machoAtom has the same scope and combine, but machoAtom loses auto hide, add it back. + // rdar://problem/38646854 + if (pos->second->scope() == machoAtom.scope() && + pos->second->combine() == machoAtom.combine() && + pos->second->autoHide() && !machoAtom.autoHide()) { + if (log) fprintf(stderr, "set %s to auto hide after LTO\n", name); + (const_cast(&machoAtom))->setAutoHide(); + } pos->second->setCompiledAtom(machoAtom); - lastProxiedAtom = &machoAtom; - lastProxiedFile = pos->second->file(); + _lastProxiedAtom = &machoAtom; + _lastProxiedFile = pos->second->file(); if (log) fprintf(stderr, "AtomSyncer, mach-o atom %p synced to lto atom %p (name=%s)\n", &machoAtom, pos->second, machoAtom.name()); } else { // an atom of this name was not in the allAtoms list the linker gave us - if ( _deadllvmAtoms.find(name) != _deadllvmAtoms.end() ) { + auto llvmAtom = _deadllvmAtoms.find(name); + if ( llvmAtom != _deadllvmAtoms.end() ) { // this corresponding to an atom that the linker coalesced away or marked not-live if ( _options.linkerDeadStripping ) { // llvm seems to want this atom and -dead_strip is enabled, so it will be deleted if not needed, so add back - Atom* llvmAtom = _deadllvmAtoms[name]; - llvmAtom->setCompiledAtom(machoAtom); + llvmAtom->second->setCompiledAtom(machoAtom); _newAtoms.push_back(&machoAtom); - if (log) fprintf(stderr, "AtomSyncer, mach-o atom %p matches dead lto atom %p but adding back (name=%s)\n", &machoAtom, llvmAtom, machoAtom.name()); + if (log) fprintf(stderr, "AtomSyncer, mach-o atom %p matches dead lto atom %p but adding back (name=%s)\n", &machoAtom, llvmAtom->second, machoAtom.name()); } else { // Don't pass it back as a new atom - if (log) fprintf(stderr, "AtomSyncer, mach-o atom %p matches dead lto atom %p (name=%s)\n", &machoAtom, _deadllvmAtoms[name], machoAtom.name()); + if (log) fprintf(stderr, "AtomSyncer, mach-o atom %p matches dead lto atom %p (name=%s)\n", &machoAtom, llvmAtom->second, machoAtom.name()); + if ( llvmAtom->second->coalescedAway() ) { + if (log) fprintf(stderr, "AtomSyncer: dead coalesced atom %s\n", machoAtom.name()); + // + // We told libLTO to keep a weak atom that will replaced by an native mach-o atom. + // We also need to remove any atoms directly dependent on this (FDE, LSDA). + for (ld::Fixup::iterator fit=machoAtom.fixupsBegin(), fend=machoAtom.fixupsEnd(); fit != fend; ++fit) { + switch ( fit->kind ) { + case ld::Fixup::kindNoneGroupSubordinate: + case ld::Fixup::kindNoneGroupSubordinateFDE: + case ld::Fixup::kindNoneGroupSubordinateLSDA: + assert(fit->binding == ld::Fixup::bindingDirectlyBound); + (const_cast(fit->u.target))->setCoalescedAway(); + if (log) fprintf(stderr, "AtomSyncer: mark coalesced-away subordinate atom %s\n", fit->u.target->name()); + break; + default: + break; + } + } + } } } else @@ -973,9 +1566,10 @@ void Parser::AtomSyncer::doAtom(const ld::Atom& machoAtom) // this is something new that lto conjured up, tell ld its new _newAtoms.push_back(&machoAtom); // if new static atom in same section as previous non-static atom, assign to same file as previous - if ( (lastProxiedAtom != NULL) && (lastProxiedAtom->section() == machoAtom.section()) ) { + if ( (_lastProxiedAtom != NULL) && (_lastProxiedAtom->section() == machoAtom.section()) ) { ld::Atom* ma = const_cast(&machoAtom); - ma->setFile(lastProxiedFile); + ma->setFile(_lastProxiedFile); + if (log) fprintf(stderr, "AtomSyncer, mach-o atom %s is static and being assigned to %s\n", machoAtom.name(), _lastProxiedFile->path()); } if (log) fprintf(stderr, "AtomSyncer, mach-o atom %p is totally new (name=%s)\n", &machoAtom, machoAtom.name()); } @@ -997,9 +1591,10 @@ void Parser::AtomSyncer::doAtom(const ld::Atom& machoAtom) // If mach-o atom is referencing another mach-o atom then // reference is not going through Atom proxy. Fix it here to ensure that all // llvm symbol references always go through Atom proxy. + if ( fit->u.target->scope() != ld::Atom::scopeTranslationUnit ) { - const char* targetName = fit->u.target->name(); - CStringToAtom::iterator post = _llvmAtoms.find(targetName); + const char* targetName = fit->u.target->name(); + CStringToAtom::const_iterator post = _llvmAtoms.find(targetName); if ( post != _llvmAtoms.end() ) { const ld::Atom* t = post->second; if (log) fprintf(stderr, " updating direct reference to %p to be ref to %p: %s\n", fit->u.target, t, targetName); @@ -1007,7 +1602,8 @@ void Parser::AtomSyncer::doAtom(const ld::Atom& machoAtom) } else { // Don't unbind follow-on reference into by-name reference - if ( (_deadllvmAtoms.find(targetName) != _deadllvmAtoms.end()) && (fit->kind != ld::Fixup::kindNoneFollowOn) && (fit->u.target->scope() != ld::Atom::scopeTranslationUnit) ) { + auto llvmAtom = _deadllvmAtoms.find(targetName); + if ( (llvmAtom != _deadllvmAtoms.end()) && (fit->kind != ld::Fixup::kindNoneFollowOn) && (fit->u.target->scope() != ld::Atom::scopeTranslationUnit) ) { // target was coalesed away and replace by mach-o atom from a non llvm .o file fit->binding = ld::Fixup::bindingByNameUnbound; fit->u.name = targetName; @@ -1047,6 +1643,21 @@ bool isObjectFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t ar return Parser::validFile(fileContent, fileLength, architecture, subarch); } +// +// Used by archive reader to see if member defines a Category (for -ObjC semantics) +// +bool hasObjCCategory(const uint8_t* fileContent, uint64_t fileLength) +{ +#if LTO_API_VERSION >= 20 + // note: if run with older libLTO.dylib that does not implement + // lto_module_has_objc_category, the call will return 0 which is "false" + return lto_module_has_objc_category(fileContent, fileLength); +#else + return false; +#endif +} + + static ld::relocatable::File *parseImpl( const uint8_t *fileContent, uint64_t fileLength, const char *path, time_t modTime, ld::File::Ordinal ordinal, cpu_type_t architecture, @@ -1090,6 +1701,27 @@ const char* version() return ::lto_get_version(); } +// +// used by "ld -v" to report static version of libLTO.dylib API being compiled +// +unsigned int static_api_version() +{ + return LTO_API_VERSION; +} + +// +// used by "ld -v" to report version of libLTO.dylib being used +// + +unsigned int runtime_api_version() +{ +// ld64-port: Added #if +#if LTO_API_VERSION >= 17 + return ::lto_api_version(); +#else + return -1; +#endif +} // // used by ld for error reporting @@ -1127,6 +1759,212 @@ bool optimize( const std::vector& allAtoms, }; // namespace lto +static const char *sLTODylib = "@rpath/libLTO.dylib"; +static std::atomic sLTOIsLoaded(false); + +static void *getHandle() { + auto impl = [&]() -> void* { +#ifndef __APPLE__ // ld64-port + static char lib[PATH_MAX] = ""; + if (char *p = getenv("LIBLTO")) { + strlcpy(lib, p, sizeof(lib)); + } else { + strlcpy(lib, sLTODylib, sizeof(lib)); + } + if (!strncmp(lib, "@rpath/", strlen("@rpath/"))) + memmove(lib, lib + strlen("@rpath/"), strlen(lib) - strlen("@rpath/") + 1); + char *ext = strrchr(lib, '.'); + if (ext && !strcmp(ext, ".dylib")) + strcpy(ext, ".so"); + sLTODylib = lib; +#endif + void *handle = ::dlopen(sLTODylib, RTLD_LAZY); +#ifndef __APPLE__ // ld64-port + if (!handle) + handle = ::dlopen("libLTO.so", RTLD_LAZY); +#endif + if (handle) + sLTOIsLoaded.store(true); + return handle; + }; + + // Memoize. + static void *handle = impl(); + return handle; +} + +namespace lto { +void set_library(const char *dylib) { + assert(!sLTOIsLoaded); + sLTODylib = dylib; +} +} // end namespace lto + +namespace { +template struct LTOSymbol; +template struct LTOSymbol { + R (*call)(Args...) = nullptr; + +public: + LTOSymbol() = delete; + LTOSymbol(const char *name) { + if (void *handle = getHandle()) + call = reinterpret_cast(::dlsym(handle, name)); + + if (!call) + call = [](Args...) -> R { return R{}; }; + } +}; +template struct LTOSymbol { + void (*call)(Args...) = nullptr; + +public: + LTOSymbol() = delete; + LTOSymbol(const char *name) { + if (void *handle = getHandle()) + call = reinterpret_cast(::dlsym(handle, name)); + + if (!call) + call = [](Args...) -> void {}; + } +}; +} // end namespace + +extern "C" { + +// ld64-port: Added LTO_API_VERSION checks + +#define WRAP_LTO_SYMBOL(RET, NAME, PARAMS, ARGS) \ + RET NAME PARAMS { \ + static LTOSymbol x(#NAME); \ + return (x.call)ARGS; \ + } + +WRAP_LTO_SYMBOL(const char *, lto_get_version, (), ()) +WRAP_LTO_SYMBOL(lto_bool_t, lto_module_has_objc_category, + (const void *mem, size_t length), (mem, length)) +WRAP_LTO_SYMBOL(lto_module_t, lto_module_create_from_memory_with_path, + (const void *mem, size_t length, const char *path), + (mem, length, path)) +WRAP_LTO_SYMBOL(lto_module_t, lto_module_create_in_local_context, + (const void *mem, size_t length, const char *path), + (mem, length, path)) +WRAP_LTO_SYMBOL(lto_module_t, lto_module_create_from_memory, + (const void *mem, size_t length), (mem, length)) +WRAP_LTO_SYMBOL(void, lto_module_dispose, (lto_module_t mod), (mod)) +WRAP_LTO_SYMBOL(unsigned int, lto_module_get_num_symbols, (lto_module_t mod), + (mod)) +WRAP_LTO_SYMBOL(const char *, lto_module_get_symbol_name, + (lto_module_t mod, unsigned int index), (mod, index)) +WRAP_LTO_SYMBOL(lto_symbol_attributes, lto_module_get_symbol_attribute, + (lto_module_t mod, unsigned int index), (mod, index)) +WRAP_LTO_SYMBOL(lto_bool_t, lto_codegen_add_module, + (lto_code_gen_t cg, lto_module_t mod), (cg, mod)) +#if LTO_API_VERSION >= 18 +WRAP_LTO_SYMBOL(lto_bool_t, lto_module_is_thinlto, (lto_module_t mod), (mod)) +#endif + +WRAP_LTO_SYMBOL(void, lto_codegen_set_module, + (lto_code_gen_t cg, lto_module_t mod), (cg, mod)) +#if LTO_API_VERSION >= 18 +WRAP_LTO_SYMBOL(void, thinlto_codegen_add_module, + (thinlto_code_gen_t cg, const char *identifier, + const char *data, int length), + (cg, identifier, data, length)) + +WRAP_LTO_SYMBOL(void, thinlto_codegen_add_must_preserve_symbol, + (thinlto_code_gen_t cg, const char *name, int length), + (cg, name, length)) +WRAP_LTO_SYMBOL(void, thinlto_codegen_add_cross_referenced_symbol, + (thinlto_code_gen_t cg, const char *name, int length), + (cg, name, length)) +WRAP_LTO_SYMBOL(void, thinlto_codegen_set_cache_dir, + (thinlto_code_gen_t cg, const char *cache_dir), (cg, cache_dir)) +WRAP_LTO_SYMBOL(void, thinlto_codegen_set_cache_pruning_interval, + (thinlto_code_gen_t cg, int interval), (cg, interval)) +WRAP_LTO_SYMBOL( + void, thinlto_codegen_set_final_cache_size_relative_to_available_space, + (thinlto_code_gen_t cg, unsigned percentage), (cg, percentage)) +WRAP_LTO_SYMBOL(void, thinlto_codegen_set_cache_entry_expiration, + (thinlto_code_gen_t cg, unsigned expiration), (cg, expiration)) + +WRAP_LTO_SYMBOL(void, thinlto_codegen_process, (thinlto_code_gen_t cg), (cg)) +WRAP_LTO_SYMBOL(unsigned int, thinlto_module_get_num_objects, + (thinlto_code_gen_t cg), (cg)) +WRAP_LTO_SYMBOL(LTOObjectBuffer, thinlto_module_get_object, + (thinlto_code_gen_t cg, unsigned int index), (cg, index)) +WRAP_LTO_SYMBOL(unsigned int, thinlto_module_get_num_object_files, + (thinlto_code_gen_t cg), (cg)) +WRAP_LTO_SYMBOL(const char *, thinlto_module_get_object_file, + (thinlto_code_gen_t cg, unsigned int index), (cg, index)) +WRAP_LTO_SYMBOL(lto_bool_t, thinlto_codegen_set_pic_model, + (thinlto_code_gen_t cg, lto_codegen_model m), (cg, m)) +WRAP_LTO_SYMBOL(void, thinlto_codegen_set_savetemps_dir, + (thinlto_code_gen_t cg, const char *save_temps_dir), + (cg, save_temps_dir)) +WRAP_LTO_SYMBOL(void, thinlto_set_generated_objects_dir, + (thinlto_code_gen_t cg, const char *save_temps_dir), + (cg, save_temps_dir)) +WRAP_LTO_SYMBOL(void, thinlto_codegen_set_cpu, + (thinlto_code_gen_t cg, const char *cpu), (cg, cpu)) +WRAP_LTO_SYMBOL(void, thinlto_codegen_disable_codegen, + (thinlto_code_gen_t cg, lto_bool_t disable), (cg, disable)) +WRAP_LTO_SYMBOL(void, thinlto_codegen_set_codegen_only, + (thinlto_code_gen_t cg, lto_bool_t codegen_only), + (cg, codegen_only)) +WRAP_LTO_SYMBOL(void, thinlto_debug_options, + (const char *const *options, int number), (options, number)) +#endif // LTO_API_VERSION >= 18 + +WRAP_LTO_SYMBOL(lto_code_gen_t, lto_codegen_create_in_local_context, (void), ()) +#if LTO_API_VERSION >= 7 +WRAP_LTO_SYMBOL(void, lto_codegen_set_diagnostic_handler, + (lto_code_gen_t cg, lto_diagnostic_handler_t handler, + void *context), + (cg, handler, context)) +#endif // LTO_API_VERSION >= 7 +WRAP_LTO_SYMBOL(lto_code_gen_t, lto_codegen_create, (void), ()) +WRAP_LTO_SYMBOL(void, lto_codegen_debug_options, + (lto_code_gen_t cg, const char *options), (cg, options)) +WRAP_LTO_SYMBOL(void, lto_codegen_dispose, (lto_code_gen_t cg), (cg)) +WRAP_LTO_SYMBOL(void, lto_codegen_set_assembler_path, + (lto_code_gen_t cg, const char *path), (cg, path)) +#if LTO_API_VERSION >= 18 +WRAP_LTO_SYMBOL(thinlto_code_gen_t, thinlto_create_codegen, (void), ()) +#endif // LTO_API_VERSION >= 18 +WRAP_LTO_SYMBOL(unsigned int, lto_api_version, (void), ()) +WRAP_LTO_SYMBOL(const void *, lto_codegen_compile_optimized, + (lto_code_gen_t cg, size_t *length), (cg, length)) +WRAP_LTO_SYMBOL(lto_bool_t, lto_module_is_object_file_in_memory_for_target, + (const void *mem, size_t length, + const char *target_triple_prefix), + (mem, length, target_triple_prefix)) +WRAP_LTO_SYMBOL(void, lto_codegen_set_should_embed_uselists, + (lto_code_gen_t cg, lto_bool_t ShouldEmbedUselists), + (cg, ShouldEmbedUselists)) +WRAP_LTO_SYMBOL(const void *, lto_codegen_compile, + (lto_code_gen_t cg, size_t *length), (cg, length)) +WRAP_LTO_SYMBOL(const char *, lto_get_error_message, (void), ()) +WRAP_LTO_SYMBOL(lto_module_t, lto_module_create_in_codegen_context, + (const void *mem, size_t length, const char *path, + lto_code_gen_t cg), + (mem, length, path, cg)) +WRAP_LTO_SYMBOL(lto_bool_t, lto_codegen_optimize, (lto_code_gen_t cg), (cg)) +WRAP_LTO_SYMBOL(lto_bool_t, lto_codegen_write_merged_modules, + (lto_code_gen_t cg, const char *path), (cg, path)) +WRAP_LTO_SYMBOL(void, lto_codegen_set_should_internalize, + (lto_code_gen_t cg, lto_bool_t ShouldInternalize), + (cg, ShouldInternalize)) +WRAP_LTO_SYMBOL(void, lto_codegen_set_cpu, (lto_code_gen_t cg, const char *cpu), + (cg, cpu)) +WRAP_LTO_SYMBOL(lto_bool_t, lto_codegen_set_pic_model, + (lto_code_gen_t cg, lto_codegen_model model), (cg, model)) +WRAP_LTO_SYMBOL(void, lto_codegen_add_must_preserve_symbol, + (lto_code_gen_t cg, const char *symbol), (cg, symbol)) + +#undef WRAP_LTO_SYMBOL + +} // end extern "C" #endif diff --git a/cctools/ld64/src/ld/parsers/lto_file.h b/cctools/ld64/src/ld/parsers/lto_file.h index 38cfcd1..6470888 100644 --- a/cctools/ld64/src/ld/parsers/lto_file.h +++ b/cctools/ld64/src/ld/parsers/lto_file.h @@ -31,12 +31,20 @@ namespace lto { extern const char* version(); +extern unsigned int runtime_api_version(); + +extern unsigned int static_api_version(); + +void set_library(const char *dylib); + extern bool libLTOisLoaded(); extern const char* archName(const uint8_t* fileContent, uint64_t fileLength); extern bool isObjectFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t architecture, cpu_subtype_t subarch); +extern bool hasObjCCategory(const uint8_t* fileContent, uint64_t fileLength); + extern ld::relocatable::File* parse(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t modTime, ld::File::Ordinal ordinal, cpu_type_t architecture, cpu_subtype_t subarch, bool logAllFiles, @@ -45,6 +53,11 @@ extern ld::relocatable::File* parse(const uint8_t* fileContent, uint64_t fileLen struct OptimizeOptions { const char* outputFilePath; const char* tmpObjectFilePath; + const char* ltoCachePath; + int ltoPruneInterval; + int ltoPruneAfter; + unsigned ltoMaxCacheSize; + bool ltoPruneIntervalOverwrite; bool preserveAllGlobals; bool verbose; bool saveTemps; @@ -52,6 +65,7 @@ struct OptimizeOptions { bool pie; bool mainExecutable; bool staticExecutable; + bool preload; bool relocatable; bool allowTextRelocs; bool linkerDeadStripping; @@ -60,12 +74,14 @@ struct OptimizeOptions { bool verboseOptimizationHints; bool armUsesZeroCostExceptions; bool simulator; - bool ignoreMismatchPlatform; +#if SUPPORT_ARCH_arm64e + bool supportsAuthenticatedPointers; +#endif bool bitcodeBundle; uint8_t maxDefaultCommonAlignment; cpu_type_t arch; const char* mcpu; - Options::Platform platform; + ld::VersionSet platforms; const std::vector* llvmOptions; const std::vector* initialUndefines; }; diff --git a/cctools/ld64/src/ld/parsers/macho_dylib_file.cpp b/cctools/ld64/src/ld/parsers/macho_dylib_file.cpp index 63be722..50cf577 100644 --- a/cctools/ld64/src/ld/parsers/macho_dylib_file.cpp +++ b/cctools/ld64/src/ld/parsers/macho_dylib_file.cpp @@ -42,6 +42,7 @@ #include "MachOTrie.hpp" #include "generic_dylib_file.hpp" #include "macho_dylib_file.h" +#include "PlatformSupport.h" #include "../code-sign-blobs/superblob.h" namespace mach_o { @@ -62,22 +63,25 @@ public: File(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t mTime, ld::File::Ordinal ordinal, bool linkingFlatNamespace, bool linkingMainExecutable, bool hoistImplicitPublicDylibs, - Options::Platform platform, uint32_t linkMinOSVersion, bool allowSimToMacOSX, - bool addVers, bool buildingForSimulator, + const ld::VersionSet& platforms, bool allowWeakImports, + bool allowSimToMacOSX, bool addVers, bool buildingForSimulator, bool logAllFiles, const char* installPath, - bool indirectDylib, bool ignoreMismatchPlatform, bool usingBitcode); + bool indirectDylib, bool usingBitcode, bool internalSDK); virtual ~File() noexcept {} + virtual const ld::VersionSet& platforms() const { return this->_platforms; } private: using P = typename A::P; using E = typename A::P::E; + using pint_t = typename A::P::uint_t; void addDyldFastStub(); - void buildExportHashTableFromExportInfo(const macho_dyld_info_command

* dyldInfo, - const uint8_t* fileContent); + void buildExportHashTableFromExportInfo(uint32_t exportsOffset, uint32_t exportsSize, + const uint8_t* fileContent); void buildExportHashTableFromSymbolTable(const macho_dysymtab_command

* dynamicInfo, const macho_nlist

* symbolTable, const char* strings, const uint8_t* fileContent); + void addSymbol(const char* name, bool weakDef = false, bool tlv = false, pint_t address = 0); static const char* objCInfoSegmentName(); static const char* objCInfoSectionName(); @@ -98,16 +102,17 @@ template const char* File::objCInfoSectionName() { return "__ima template File::File(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t mTime, ld::File::Ordinal ord, bool linkingFlatNamespace, bool linkingMainExecutable, - bool hoistImplicitPublicDylibs, Options::Platform platform, uint32_t linkMinOSVersion, + bool hoistImplicitPublicDylibs, const ld::VersionSet& cmdLinePlatforms, bool allowWeakImports, bool allowSimToMacOSX, bool addVers, bool buildingForSimulator, bool logAllFiles, - const char* targetInstallPath, bool indirectDylib, bool ignoreMismatchPlatform, bool usingBitcode) - : Base(strdup(path), mTime, ord, platform, linkMinOSVersion, linkingFlatNamespace, - hoistImplicitPublicDylibs, allowSimToMacOSX, addVers), _fileLength(fileLength), _linkeditStartOffset(0) + const char* targetInstallPath, bool indirectDylib, bool usingBitcode, bool internalSDK) + : Base(strdup(path), mTime, ord, cmdLinePlatforms, allowWeakImports, linkingFlatNamespace, + hoistImplicitPublicDylibs, allowSimToMacOSX, addVers), _fileLength(fileLength), _linkeditStartOffset(0) { const macho_header

* header = (const macho_header

*)fileContent; const uint32_t cmd_count = header->ncmds(); const macho_load_command

* const cmds = (macho_load_command

*)((char*)header + sizeof(macho_header

)); const macho_load_command

* const cmdsEnd = (macho_load_command

*)((char*)header + sizeof(macho_header

) + header->sizeofcmds()); + const uint8_t* const endOfFile = fileContent + fileLength; // write out path for -t option if ( logAllFiles ) @@ -132,16 +137,24 @@ File::File(const uint8_t* fileContent, uint64_t fileLength, const char* path, // pass 1: get pointers, and see if this dylib uses compressed LINKEDIT format const macho_dysymtab_command

* dynamicInfo = nullptr; const macho_dyld_info_command

* dyldInfo = nullptr; + const macho_linkedit_data_command

* exportsTrie = nullptr; const macho_nlist

* symbolTable = nullptr; const macho_symtab_command

* symtab = nullptr; const char* strings = nullptr; bool compressedLinkEdit = false; uint32_t dependentLibCount = 0; - Options::Platform lcPlatform = Options::kPlatformUnknown; + ld::VersionSet lcPlatforms; const macho_load_command

* cmd = cmds; for (uint32_t i = 0; i < cmd_count; ++i) { macho_dylib_command

* dylibID; uint32_t cmdLength = cmd->cmdsize(); + if ( (cmdLength & 3) != 0 ) + throwf("load command #%d has a unaligned size", i); + const uint8_t* endOfCmd = ((uint8_t*)cmd)+cmd->cmdsize(); + if ( endOfCmd > (uint8_t*)cmdsEnd ) + throwf("load command #%d extends beyond the end of the load commands", i); + if ( endOfCmd > endOfFile ) + throwf("load command #%d extends beyond the end of the file", i); switch (cmd->cmd()) { case LC_SYMTAB: symtab = (macho_symtab_command

*)cmd; @@ -158,6 +171,10 @@ File::File(const uint8_t* fileContent, uint64_t fileLength, const char* path, dyldInfo = (macho_dyld_info_command

*)cmd; compressedLinkEdit = true; break; + case LC_DYLD_EXPORTS_TRIE: + exportsTrie = (macho_linkedit_data_command

*)cmd; + compressedLinkEdit = true; + break; case LC_ID_DYLIB: dylibID = (macho_dylib_command

*)cmd; if ( dylibID->name_offset() > cmdLength ) @@ -186,15 +203,20 @@ File::File(const uint8_t* fileContent, uint64_t fileLength, const char* path, // Don't hoist "public" (in /usr/lib/) dylibs that should not be directly linked this->_hasPublicInstallName = false; break; + case LC_RPATH: + this->_rpaths.push_back(strdup(((macho_rpath_command

*)cmd)->path())); + break; case LC_VERSION_MIN_MACOSX: case LC_VERSION_MIN_IPHONEOS: case LC_VERSION_MIN_WATCHOS: - #if SUPPORT_APPLE_TV case LC_VERSION_MIN_TVOS: - #endif - this->_minVersionInDylib = (ld::MacVersionMin)((macho_version_min_command

*)cmd)->version(); - this->_platformInDylib = cmd->cmd(); - lcPlatform = Options::platformForLoadCommand(this->_platformInDylib); + lcPlatforms.insert(ld::PlatformVersion(ld::platformForLoadCommand(cmd->cmd(), (mach_header*)header), ((macho_version_min_command

*)cmd)->version())); + break; + case LC_BUILD_VERSION: + { + const macho_build_version_command

* buildVersCmd = (macho_build_version_command

*)cmd; + lcPlatforms.insert(ld::PlatformVersion((ld::Platform)buildVersCmd->platform(), buildVersCmd->minos())); + } break; case LC_CODE_SIGNATURE: break; @@ -217,14 +239,6 @@ File::File(const uint8_t* fileContent, uint64_t fileLength, const char* path, const uint32_t* contents = (uint32_t*)(&fileContent[sect->offset()]); if ( (sect->size() >= 8) && (contents[0] == 0) ) { uint32_t flags = E::get32(contents[1]); - if ( (flags & 4) == 4 ) - this->_objcConstraint = ld::File::objcConstraintGC; - else if ( (flags & 2) == 2 ) - this->_objcConstraint = ld::File::objcConstraintRetainReleaseOrGC; - else if ( (flags & 32) == 32 ) - this->_objcConstraint = ld::File::objcConstraintRetainReleaseForSimulator; - else - this->_objcConstraint = ld::File::objcConstraintRetainRelease; this->_swiftVersion = ((flags >> 8) & 0xFF); } else if ( sect->size() > 0 ) { @@ -248,96 +262,9 @@ File::File(const uint8_t* fileContent, uint64_t fileLength, const char* path, if ( cmd > cmdsEnd ) throwf("malformed dylb, load command #%d is outside size of load commands in %s", i, path); } - // arm/arm64 objects are default to ios platform if not set. - // rdar://problem/21746314 - if (lcPlatform == Options::kPlatformUnknown && - (std::is_same::value || std::is_same::value)) - lcPlatform = Options::kPlatformiOS; // check cross-linking - if ( lcPlatform != platform ) { - this->_wrongOS = true; - if ( this->_addVersionLoadCommand && !indirectDylib && !ignoreMismatchPlatform ) { - if ( buildingForSimulator ) { - if ( !this->_allowSimToMacOSXLinking ) { - switch (platform) { - case Options::kPlatformOSX: - case Options::kPlatformiOS: - if ( lcPlatform == Options::kPlatformUnknown ) - break; - // fall through if the Platform is not Unknown - case Options::kPlatformWatchOS: - // WatchOS errors on cross-linking when building for bitcode - if ( usingBitcode ) - throwf("building for %s simulator, but linking against dylib built for %s,", - Options::platformName(platform), - Options::platformName(lcPlatform)); - else - warning("URGENT: building for %s simulator, but linking against dylib (%s) built for %s. " - "Note: This will be an error in the future.", - Options::platformName(platform), path, - Options::platformName(lcPlatform)); - break; - #if SUPPORT_APPLE_TV - case Options::kPlatform_tvOS: - // tvOS is a warning temporarily. rdar://problem/21746965 - if ( usingBitcode ) - throwf("building for %s simulator, but linking against dylib built for %s,", - Options::platformName(platform), - Options::platformName(lcPlatform)); - else - warning("URGENT: building for %s simulator, but linking against dylib (%s) built for %s. " - "Note: This will be an error in the future.", - Options::platformName(platform), path, - Options::platformName(lcPlatform)); - break; - #endif - case Options::kPlatformUnknown: - // skip if the target platform is unknown - break; - } - } - } - else { - switch (platform) { - case Options::kPlatformOSX: - case Options::kPlatformiOS: - if ( lcPlatform == Options::kPlatformUnknown ) - break; - // fall through if the Platform is not Unknown - case Options::kPlatformWatchOS: - // WatchOS errors on cross-linking when building for bitcode - if ( usingBitcode ) - throwf("building for %s, but linking against dylib built for %s,", - Options::platformName(platform), - Options::platformName(lcPlatform)); - else - warning("URGENT: building for %s, but linking against dylib (%s) built for %s. " - "Note: This will be an error in the future.", - Options::platformName(platform), path, - Options::platformName(lcPlatform)); - break; - #if SUPPORT_APPLE_TV - case Options::kPlatform_tvOS: - // tvOS is a warning temporarily. rdar://problem/21746965 - if ( usingBitcode ) - throwf("building for %s, but linking against dylib built for %s,", - Options::platformName(platform), - Options::platformName(lcPlatform)); - else - warning("URGENT: building for %s, but linking against dylib (%s) built for %s. " - "Note: This will be an error in the future.", - Options::platformName(platform), path, - Options::platformName(lcPlatform)); - break; - #endif - case Options::kPlatformUnknown: - // skip if the target platform is unknown - break; - } - } - } - } + cmdLinePlatforms.checkDylibCrosslink(lcPlatforms, path, "dylib", internalSDK, indirectDylib, usingBitcode); // figure out if we need to examine dependent dylibs // with compressed LINKEDIT format, MH_NO_REEXPORTED_DYLIBS can be trusted @@ -459,7 +386,9 @@ File::File(const uint8_t* fileContent, uint64_t fileLength, const char* path, // build hash table if ( dyldInfo != nullptr ) - buildExportHashTableFromExportInfo(dyldInfo, fileContent); + buildExportHashTableFromExportInfo(dyldInfo->export_off(), dyldInfo->export_size(), fileContent); + else if ( exportsTrie != nullptr ) + buildExportHashTableFromExportInfo(exportsTrie->dataoff(), exportsTrie->datasize(), fileContent); else buildExportHashTableFromSymbolTable(dynamicInfo, symbolTable, strings, fileContent); @@ -502,16 +431,16 @@ void File::buildExportHashTableFromSymbolTable(const macho_dysymtab_command

-void File::buildExportHashTableFromExportInfo(const macho_dyld_info_command

* dyldInfo, +void File::buildExportHashTableFromExportInfo(uint32_t exportsOffset, uint32_t exportsSize, const uint8_t* fileContent) { if ( this->_s_logHashtable ) - fprintf(stderr, "ld: building hashtable from export info in %s\n", this->path()); - if ( dyldInfo->export_size() > 0 ) { - const uint8_t* start = fileContent + dyldInfo->export_off(); - const uint8_t* end = &start[dyldInfo->export_size()]; - if ( (dyldInfo->export_off() + dyldInfo->export_size()) > _fileLength ) - throwf("malformed mach-o dylib, exports trie extends beyond end of file, "); + fprintf(stderr, "ld: building hashtable from export trie in %s\n", this->path()); + if ( exportsSize > 0 ) { + const uint8_t* start = fileContent + exportsOffset; + const uint8_t* end = &start[exportsSize]; + if ( (exportsOffset + exportsSize) > _fileLength ) + throwf("malformed mach-o dylib, exports trie extends beyond end of file"); std::vector list; parseTrie(start, end, list); for (const auto &entry : list) @@ -522,6 +451,78 @@ void File::buildExportHashTableFromExportInfo(const macho_dyld_info_command

+void File::addSymbol(const char* name, bool weakDef, bool tlv, pint_t address) +{ + __block uint32_t linkMinOSVersion = 0; + + this->platforms().forEach(^(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop) { + //FIXME hack to handle symbol versioning in a zippered world. + //This will need to be rethought + if (linkMinOSVersion == 0) + linkMinOSVersion = minVersion; + if (platform == ld::Platform::macOS) + linkMinOSVersion = minVersion; + }); + + // symbols that start with $ld$ are meta-data to the static linker + // need way for ld and dyld to see different exported symbols in a dylib + if ( strncmp(name, "$ld$", 4) == 0 ) { + // $ld$ $ $ + const char* symAction = &name[4]; + const char* symCond = strchr(symAction, '$'); + if ( symCond != nullptr ) { + char curOSVers[16]; + sprintf(curOSVers, "$os%d.%d$", (linkMinOSVersion >> 16), ((linkMinOSVersion >> 8) & 0xFF)); + if ( strncmp(symCond, curOSVers, strlen(curOSVers)) == 0 ) { + const char* symName = strchr(&symCond[1], '$'); + if ( symName != nullptr ) { + ++symName; + if ( strncmp(symAction, "hide$", 5) == 0 ) { + if ( this->_s_logHashtable ) + fprintf(stderr, " adding %s to ignore set for %s\n", symName, this->path()); + this->_ignoreExports.insert(strdup(symName)); + return; + } + else if ( strncmp(symAction, "add$", 4) == 0 ) { + this->addSymbol(symName, weakDef); + return; + } + else if ( strncmp(symAction, "weak$", 5) == 0 ) { + if ( !this->_allowWeakImports ) + this->_ignoreExports.insert(strdup(symName)); + } + else if ( strncmp(symAction, "install_name$", 13) == 0 ) { + this->_dylibInstallPath = strdup(symName); + this->_installPathOverride = true; + // CoreGraphics redirects to ApplicationServices, but with wrong compat version + if ( strcmp(this->_dylibInstallPath, "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices") == 0 ) + this->_dylibCompatibilityVersion = Options::parseVersionNumber32("1.0"); + return; + } + else if ( strncmp(symAction, "compatibility_version$", 22) == 0 ) { + this->_dylibCompatibilityVersion = Options::parseVersionNumber32(symName); + return; + } + else { + warning("bad symbol action: %s in dylib %s", name, this->path()); + } + } + } + } + else { + warning("bad symbol condition: %s in dylib %s", name, this->path()); + } + } + + // add symbol as possible export if we are not supposed to ignore it + if ( this->_ignoreExports.count(name) == 0 ) { + typename Base::AtomAndWeak bucket = { nullptr, weakDef, tlv, address }; + if ( this->_s_logHashtable ) + fprintf(stderr, " adding %s to hash table for %s\n", name, this->path()); + this->_atoms[strdup(name)] = bucket; + } +} template <> void File::addDyldFastStub() @@ -549,21 +550,66 @@ public: static bool validFile(const uint8_t* fileContent, bool executableOrDyliborBundle, bool subTypeMustMatch=false, uint32_t subType=0); static const char* fileKind(const uint8_t* fileContent); + static ld::Platform findPlatform(const macho_header

* header, uint64_t fileLength, uint32_t* minOsVers); + static uint8_t loadCommandSizeMask(); static ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t mTime, ld::File::Ordinal ordinal, const Options& opts, bool indirectDylib) { return new File(fileContent, fileLength, path, mTime, ordinal, opts.flatNamespace(), opts.linkingMainExecutable(), opts.implicitlyLinkIndirectPublicDylibs(), - opts.platform(), opts.minOSversion(), + opts.platforms(), opts.allowWeakImports(), opts.allowSimulatorToLinkWithMacOSX(), opts.addVersionLoadCommand(), opts.targetIOSSimulator(), opts.logAllFiles(), opts.installPath(), - indirectDylib, opts.outputKind() == Options::kPreload, opts.bundleBitcode()); + indirectDylib, opts.bundleBitcode(), opts.internalSDK()); } }; +template <> uint8_t Parser::loadCommandSizeMask() { return 0x03; } +template <> uint8_t Parser::loadCommandSizeMask() { return 0x07; } +template <> uint8_t Parser::loadCommandSizeMask() { return 0x03; } +template <> uint8_t Parser::loadCommandSizeMask() { return 0x07; } +template +ld::Platform Parser::findPlatform(const macho_header

* header, uint64_t fileLength, uint32_t* minOsVers) +{ + const uint32_t cmd_count = header->ncmds(); + if ( cmd_count == 0 ) + return ld::Platform::unknown; + const uint8_t* const endOfFile = (uint8_t*)header + fileLength; + const macho_load_command

* const cmds = (macho_load_command

*)((char*)header + sizeof(macho_header

)); + const macho_load_command

* const cmdsEnd = (macho_load_command

*)((char*)header + sizeof(macho_header

) + header->sizeofcmds()); + const macho_load_command

* cmd = cmds; + for (uint32_t i = 0; i < cmd_count; ++i) { + uint32_t size = cmd->cmdsize(); + if ( (size & loadCommandSizeMask()) != 0 ) + throwf("load command #%d has a unaligned size", i); + const uint8_t* endOfCmd = ((uint8_t*)cmd)+cmd->cmdsize(); + if ( endOfCmd > (uint8_t*)cmdsEnd ) + throwf("load command #%d extends beyond the end of the load commands", i); + if ( endOfCmd > endOfFile ) + throwf("load command #%d extends beyond the end of the file", i); + const macho_version_min_command

* versCmd = (macho_version_min_command

*)cmd; + const macho_build_version_command

* buildVersCmd = (macho_build_version_command

*)cmd; + switch (cmd->cmd()) { + case LC_VERSION_MIN_MACOSX: + case LC_VERSION_MIN_IPHONEOS: + case LC_VERSION_MIN_WATCHOS: + case LC_VERSION_MIN_TVOS: + *minOsVers = versCmd->version(); + return ld::platformForLoadCommand(cmd->cmd(), (mach_header*)header); + case LC_BUILD_VERSION: + *minOsVers = buildVersCmd->minos(); + return ld::platformFromBuildVersion(buildVersCmd->platform(), (mach_header*)header); + } + cmd = (const macho_load_command

*)(((char*)cmd)+cmd->cmdsize()); + if ( cmd > cmdsEnd ) + throwf("malformed mach-o file, load command #%d is outside size of load commands", i); + } + *minOsVers = 0; + return ld::Platform::unknown; +} template <> bool Parser::validFile(const uint8_t* fileContent, bool executableOrDyliborBundle, bool subTypeMustMatch, uint32_t subType) @@ -678,28 +724,34 @@ bool Parser::validFile(const uint8_t* fileContent, bool executableOrDylib } -bool isDylibFile(const uint8_t* fileContent, cpu_type_t* result, cpu_subtype_t* subResult) +bool isDylibFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t* result, cpu_subtype_t* subResult, ld::Platform* platform, uint32_t* minOsVers) { if ( Parser::validFile(fileContent, false) ) { *result = CPU_TYPE_X86_64; const auto* header = reinterpret_cast>*>(fileContent); *subResult = header->cpusubtype(); + *platform = Parser::findPlatform(header, fileLength, minOsVers); return true; } if ( Parser::validFile(fileContent, false) ) { *result = CPU_TYPE_I386; *subResult = CPU_SUBTYPE_X86_ALL; + const auto* header = reinterpret_cast>*>(fileContent); + *platform = Parser::findPlatform(header, fileLength, minOsVers); return true; } if ( Parser::validFile(fileContent, false) ) { *result = CPU_TYPE_ARM; const auto* header = reinterpret_cast>*>(fileContent); *subResult = header->cpusubtype(); + *platform = Parser::findPlatform(header, fileLength, minOsVers); return true; } if ( Parser::validFile(fileContent, false) ) { *result = CPU_TYPE_ARM64; - *subResult = CPU_SUBTYPE_ARM64_ALL; + const auto* header = reinterpret_cast>*>(fileContent); + *subResult = header->cpusubtype(); + *platform = Parser::findPlatform(header, fileLength, minOsVers); return true; } return false; @@ -756,6 +808,7 @@ const char* Parser::fileKind(const uint8_t* fileContent) } #endif + // // used by linker is error messages to describe mismatched files // @@ -771,7 +824,7 @@ const char* archName(const uint8_t* fileContent) return Parser::fileKind(fileContent); } #if SUPPORT_ARCH_arm64 - if ( Parser::validFile(fileContent, false) ) { + if ( Parser::validFile(fileContent, true) ) { return Parser::fileKind(fileContent); } #endif @@ -779,43 +832,64 @@ const char* archName(const uint8_t* fileContent) } -// -// main function used by linker to instantiate ld::Files -// -ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength, const char* path, - time_t modTime, const Options& opts, ld::File::Ordinal ordinal, - bool bundleLoader, bool indirectDylib) +static ld::dylib::File* parseAsArchitecture(const uint8_t* fileContent, uint64_t fileLength, const char* path, + time_t modTime, const Options& opts, ld::File::Ordinal ordinal, + bool bundleLoader, bool indirectDylib, + cpu_type_t architecture, cpu_subtype_t subArchitecture) { bool subTypeMustMatch = opts.enforceDylibSubtypesMatch(); - switch ( opts.architecture() ) { + switch ( architecture) { #if SUPPORT_ARCH_x86_64 case CPU_TYPE_X86_64: - if ( Parser::validFile(fileContent, bundleLoader, subTypeMustMatch, opts.subArchitecture()) ) + if ( Parser::validFile(fileContent, bundleLoader, subTypeMustMatch, subArchitecture) ) return Parser::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib); - break; + break; #endif #if SUPPORT_ARCH_i386 case CPU_TYPE_I386: - if ( Parser::validFile(fileContent, bundleLoader, subTypeMustMatch, opts.subArchitecture()) ) + if ( Parser::validFile(fileContent, bundleLoader, subTypeMustMatch, subArchitecture) ) return Parser::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib); - break; + break; #endif #if SUPPORT_ARCH_arm_any case CPU_TYPE_ARM: - if ( Parser::validFile(fileContent, bundleLoader, subTypeMustMatch, opts.subArchitecture()) ) + if ( Parser::validFile(fileContent, bundleLoader, subTypeMustMatch, subArchitecture) ) return Parser::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib); - break; + break; #endif #if SUPPORT_ARCH_arm64 case CPU_TYPE_ARM64: - if ( Parser::validFile(fileContent, bundleLoader, subTypeMustMatch, opts.subArchitecture()) ) + if ( Parser::validFile(fileContent, bundleLoader, subTypeMustMatch, subArchitecture) ) return Parser::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib); - break; + break; #endif } return nullptr; } +// +// main function used by linker to instantiate ld::Files +// +ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength, const char* path, + time_t modtime, const Options& opts, ld::File::Ordinal ordinal, + bool bundleLoader, bool indirectDylib) +{ + // First make sure we are even a dylib with a known arch. If we aren't then there's no point in continuing. + if (!archName(fileContent)) + return nullptr; + + auto file = parseAsArchitecture(fileContent, fileLength, path, modtime, opts, ordinal, bundleLoader, indirectDylib, opts.architecture(), opts.subArchitecture()); + + // If we've been provided with an architecture we can fall back to, try to parse the dylib as that instead. + if (!file && opts.fallbackArchitecture()) { + warning("architecture %s not present in dylib file %s, attempting fallback", opts.architectureName(), path); + file = parseAsArchitecture(fileContent, fileLength, path, modtime, opts, ordinal, bundleLoader, indirectDylib, opts.fallbackArchitecture(), opts.fallbackSubArchitecture()); + } + + return file; +} + + }; // namespace dylib }; // namespace mach_o diff --git a/cctools/ld64/src/ld/parsers/macho_dylib_file.h b/cctools/ld64/src/ld/parsers/macho_dylib_file.h index ba7b8ff..0439e09 100644 --- a/cctools/ld64/src/ld/parsers/macho_dylib_file.h +++ b/cctools/ld64/src/ld/parsers/macho_dylib_file.h @@ -32,7 +32,7 @@ namespace mach_o { namespace dylib { -extern bool isDylibFile(const uint8_t* fileContent, cpu_type_t* result, cpu_subtype_t* subResult); +extern bool isDylibFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t* result, cpu_subtype_t* subResult, ld::Platform* platform, uint32_t* minOsVers); extern const char* archName(const uint8_t* fileContent); diff --git a/cctools/ld64/src/ld/parsers/macho_relocatable_file.cpp b/cctools/ld64/src/ld/parsers/macho_relocatable_file.cpp index 1a561f7..a998ead 100644 --- a/cctools/ld64/src/ld/parsers/macho_relocatable_file.cpp +++ b/cctools/ld64/src/ld/parsers/macho_relocatable_file.cpp @@ -81,41 +81,50 @@ public: _dwarfTranslationUnitPath(NULL), _dwarfDebugInfoSect(NULL), _dwarfDebugAbbrevSect(NULL), _dwarfDebugLineSect(NULL), _dwarfDebugStringSect(NULL), - _objConstraint(ld::File::objcConstraintNone), + _hasObjC(false), _swiftVersion(0), + _swiftLanguageVersion(0), _cpuSubType(0), _minOSVersion(0), - _platform(0), _canScatterAtoms(false), - _srcKind(kSourceUnknown) {} + _hasllvmProfiling(false), + _objcHasCategoryClassPropertiesField(false), + _srcKind(kSourceUnknown) { } virtual ~File(); // overrides of ld::File virtual bool forEachAtom(ld::File::AtomHandler&) const; virtual bool justInTimeforEachAtom(const char* name, ld::File::AtomHandler&) const { return false; } - virtual uint32_t minOSVersion() const { return _minOSVersion; } - virtual uint32_t platformLoadCommand() const { return _platform; } + virtual const ld::VersionSet& platforms() const { return _platforms; } // overrides of ld::relocatable::File - virtual ObjcConstraint objCConstraint() const { return _objConstraint; } + virtual bool hasObjC() const { return _hasObjC; } + virtual bool objcHasCategoryClassPropertiesField() const + { return _objcHasCategoryClassPropertiesField; } virtual uint32_t cpuSubType() const { return _cpuSubType; } virtual DebugInfoKind debugInfo() const { return _debugInfoKind; } virtual const std::vector* stabs() const { return &_stabs; } virtual bool canScatterAtoms() const { return _canScatterAtoms; } + virtual bool hasllvmProfiling() const { return _hasllvmProfiling; } virtual const char* translationUnitSource() const; virtual LinkerOptionsList* linkerOptions() const { return &_linkerOptions; } + virtual const ToolVersionList& toolVersions() const { return _toolVersions; } virtual uint8_t swiftVersion() const { return _swiftVersion; } + virtual uint16_t swiftLanguageVersion() const { return _swiftLanguageVersion; } virtual ld::Bitcode* getBitcode() const { return _bitcode.get(); } virtual SourceKind sourceKind() const { return _srcKind; } - const uint8_t* fileContent() { return _fileContent; } + virtual const uint8_t* fileContent() const { return _fileContent; } + virtual const std::vector* astFiles() const { return &_astFiles; } + + void setHasllvmProfiling() { _hasllvmProfiling = true; } private: friend class Atom; friend class Section; friend class Parser; friend class CFISection::OAS; - + typedef typename A::P P; const uint8_t* _fileContent; @@ -129,21 +138,26 @@ private: std::vector _unwindInfos; std::vector _lineInfos; std::vector_stabs; + std::vector _astFiles; ld::relocatable::File::DebugInfoKind _debugInfoKind; const char* _dwarfTranslationUnitPath; const macho_section

* _dwarfDebugInfoSect; const macho_section

* _dwarfDebugAbbrevSect; const macho_section

* _dwarfDebugLineSect; const macho_section

* _dwarfDebugStringSect; - ld::File::ObjcConstraint _objConstraint; + bool _hasObjC; uint8_t _swiftVersion; + uint16_t _swiftLanguageVersion; uint32_t _cpuSubType; uint32_t _minOSVersion; - uint32_t _platform; + ld::VersionSet _platforms; bool _canScatterAtoms; + bool _hasllvmProfiling; + bool _objcHasCategoryClassPropertiesField; std::vector > _linkerOptions; std::unique_ptr _bitcode; SourceKind _srcKind; + ToolVersionList _toolVersions; }; @@ -386,6 +400,10 @@ public: TLVDefsSection(Parser& parser, File& f, const macho_section* s) : SymboledSection(parser, f, s) { } + typedef typename A::P::uint_t pint_t; + + virtual ld::Atom::Alignment alignmentForAddress(pint_t addr) { return ld::Atom::Alignment(log2(sizeof(pint_t))); } + private: }; @@ -531,6 +549,7 @@ protected: typedef typename A::P::uint_t pint_t; typedef typename A::P P; + virtual void makeFixups(class Parser& parser, const struct Parser::CFI_CU_InfoArrays&); virtual ld::Atom::ContentType contentType() { return ld::Atom::typeTLVPointer; } virtual ld::Atom::Alignment alignmentForAddress(pint_t addr) { return ld::Atom::Alignment(log2(sizeof(pint_t))); } virtual const char* unlabeledAtomName(Parser&, pint_t) { return "tlv_lazy_ptr"; } @@ -793,7 +812,8 @@ public: parser.inclusionFromSymbol(sym), (parser.dontDeadStripFromSymbol(sym) && !sct.dontDeadStripIfReferencesLive()) || sct.dontDeadStrip(), parser.isThumbFromSymbol(sym), alias, - sct.alignmentForAddress(sym.n_value())), + sct.alignmentForAddress(sym.n_value()), + parser.coldFromSymbol(sym)), _size(sz), _objAddress(sym.n_value()), _name(parser.nameFromSymbol(sym)), _hash(0), _fixupsStartIndex(0), _lineInfoStartIndex(0), @@ -931,6 +951,7 @@ void Atom::verifyAlignment(const macho_section

& sect) const } #endif + template void Atom::verifyAlignment(const macho_section

&) const { @@ -977,7 +998,7 @@ public: static bool validFile(const uint8_t* fileContent, bool subtypeMustMatch=false, cpu_subtype_t subtype=0); static const char* fileKind(const uint8_t* fileContent); - static Options::Platform findPlatform(const macho_header* header); + static ld::Platform findPlatform(const macho_header* header, uint64_t fileLength, uint32_t* minOsVers); static bool hasObjC2Categories(const uint8_t* fileContent); static bool hasObjC1Categories(const uint8_t* fileContent); static bool getNonLocalSymbols(const uint8_t* fileContnet, std::vector &syms); @@ -987,8 +1008,7 @@ public: Parser p(fileContent, fileLength, path, modTime, ordinal, opts.warnUnwindConversionProblems, opts.keepDwarfUnwind, opts.forceDwarfConversion, - opts.neverConvertDwarf, opts.verboseOptimizationHints, - opts.ignoreMismatchPlatform); + opts.neverConvertDwarf, opts.verboseOptimizationHints); return p.parse(opts); } @@ -1008,6 +1028,9 @@ public: const char* name; // only used if targetAtom is NULL int64_t addend; bool weakImport; // only used if targetAtom is NULL +#if SUPPORT_ARCH_arm64e + ld::Fixup::AuthData authData; // only used for authenticated pointers +#endif }; struct FixupInAtom { @@ -1026,6 +1049,11 @@ public: FixupInAtom(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k, uint64_t addend) : fixup(src.offsetInAtom, c, k, addend), atom(src.atom) { src.atom->incrementFixupCount(); } +#if SUPPORT_ARCH_arm64e + FixupInAtom(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k, ld::Fixup::AuthData authData) : + fixup(src.offsetInAtom, c, k, authData), atom(src.atom) { src.atom->incrementFixupCount(); } +#endif + FixupInAtom(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k) : fixup(src.offsetInAtom, c, k, (uint64_t)0), atom(src.atom) { src.atom->incrementFixupCount(); } @@ -1053,6 +1081,12 @@ public: _allFixups.push_back(FixupInAtom(src, c, k, addend)); } +#if SUPPORT_ARCH_arm64e + void addFixup(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k, ld::Fixup::AuthData authData) { + _allFixups.push_back(FixupInAtom(src, c, k, authData)); + } +#endif + void addFixup(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k) { _allFixups.push_back(FixupInAtom(src, c, k)); } @@ -1071,6 +1105,7 @@ public: static bool weakImportFromSymbol(const macho_nlist

& sym); static bool resolverFromSymbol(const macho_nlist

& sym); static bool altEntryFromSymbol(const macho_nlist

& sym); + static bool coldFromSymbol(const macho_nlist

& sym); uint32_t symbolIndexFromIndirectSectionAddress(pint_t,const macho_section

*); const macho_section

* firstMachOSection() { return _sectionsStart; } const macho_section

* machOSectionFromSectionIndex(uint32_t index); @@ -1189,10 +1224,10 @@ private: const char* path, time_t modTime, ld::File::Ordinal ordinal, bool warnUnwindConversionProblems, bool keepDwarfUnwind, bool forceDwarfConversion, bool neverConvertDwarf, - bool verboseOptimizationHints, bool ignoreMismatchPlatform); + bool verboseOptimizationHints); ld::relocatable::File* parse(const ParserOptions& opts); static uint8_t loadCommandSizeMask(); - bool parseLoadCommands(Options::Platform platform, uint32_t minOSVersion, bool simulator, bool ignoreMismatchPlatform); + bool parseLoadCommands(const ld::VersionSet& platforms, bool internalSDK); void makeSections(); void prescanSymbolTable(); void makeSortedSymbolsArray(uint32_t symArray[], const uint32_t sectionArray[]); @@ -1203,6 +1238,7 @@ private: void parseDebugInfo(); void parseStabs(); + void addAstFiles(); void appendAliasAtoms(uint8_t* atomBuffer); static bool isConstFunStabs(const char *stabStr); bool read_comp_unit(const char ** name, const char ** comp_dir, @@ -1257,7 +1293,6 @@ private: bool _neverConvertDwarf; bool _verboseOptimizationHints; bool _armUsesZeroCostExceptions; - bool _ignoreMismatchPlatform; bool _treateBitcodeAsData; bool _usingBitcode; uint8_t _maxDefaultCommonAlignment; @@ -1265,6 +1300,9 @@ private: const macho_section

* _stubsMachOSection; std::vector _dtraceProviderInfo; std::vector _allFixups; +#if SUPPORT_ARCH_arm64e + bool _supportsAuthenticatedPointers; +#endif }; @@ -1272,7 +1310,7 @@ private: template Parser::Parser(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t modTime, ld::File::Ordinal ordinal, bool convertDUI, bool keepDwarfUnwind, bool forceDwarfConversion, - bool neverConvertDwarf, bool verboseOptimizationHints, bool ignoreMismatchPlatform) + bool neverConvertDwarf, bool verboseOptimizationHints) : _fileContent(fileContent), _fileLength(fileLength), _path(path), _modTime(modTime), _ordinal(ordinal), _file(NULL), _symbols(NULL), _symbolCount(0), _indirectSymbolCount(0), _strings(NULL), _stringsSize(0), @@ -1288,7 +1326,6 @@ Parser::Parser(const uint8_t* fileContent, uint64_t fileLength, const char* p _keepDwarfUnwind(keepDwarfUnwind), _forceDwarfConversion(forceDwarfConversion), _neverConvertDwarf(neverConvertDwarf), _verboseOptimizationHints(verboseOptimizationHints), - _ignoreMismatchPlatform(ignoreMismatchPlatform), _stubsSectionNum(0), _stubsMachOSection(NULL) { } @@ -1352,6 +1389,8 @@ bool Parser::validFile(const uint8_t* fileContent, bool subtypeMustMatch, return false; if ( header->filetype() != MH_OBJECT ) return false; + if ( subtypeMustMatch && (header->cpusubtype() != (uint32_t)subtype) ) + return false; return true; } @@ -1403,10 +1442,16 @@ const char* Parser::fileKind(const uint8_t* fileContent) return NULL; if ( header->cputype() != CPU_TYPE_ARM64 ) return NULL; + for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) { + if ( (t->cpuType == CPU_TYPE_ARM) && ((cpu_subtype_t)header->cpusubtype() == t->cpuSubType) ) { + return t->archName; + } + } return "arm64"; } #endif + template bool Parser::hasObjC2Categories(const uint8_t* fileContent) { @@ -1426,6 +1471,12 @@ bool Parser::hasObjC2Categories(const uint8_t* fileContent) && (strcmp(sect->segname(), "__DATA") == 0) ) { return true; } + // -ObjC option should cause all swift code in static libraries to be loaded + if ( (sect->size() > 0) + && (strncmp(sect->sectname(), "__swift", 7) == 0) + && (strcmp(sect->segname(), "__TEXT") == 0) ) { + return true; + } } } cmd = (const macho_load_command

*)(((char*)cmd)+cmd->cmdsize()); @@ -1542,16 +1593,27 @@ template bool Parser::LabelAndCFIBreakIterator::next(Parser& parser, const Section& sect, uint32_t sectNum, pint_t startAddr, pint_t endAddr, pint_t* addr, pint_t* size, const macho_nlist

** symbol) { + bool cfiApplicable = (sect.machoSection()->flags() & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS)); // may not be a label on start of section, but need atom demarcation there if ( newSection ) { newSection = false; // advance symIndex until we get to the first label at or past the start of this section while ( symIndex < sortedSymbolCount ) { - const macho_nlist

& sym = parser.symbolFromIndex(sortedSymbolIndexes[symIndex]); - if ( ! sect.ignoreLabel(parser.nameFromSymbol(sym)) ) { - pint_t nextSymbolAddr = sym.n_value(); + const macho_nlist

* sym = &parser.symbolFromIndex(sortedSymbolIndexes[symIndex]); + // if compile threw in "ltmp*" symbol at start of section and there is another real label at same location, ignore ltmp one + if ( symIndex+1 < sortedSymbolCount ) { + const macho_nlist

* sym2 = &parser.symbolFromIndex(sortedSymbolIndexes[symIndex+1]); + if ( (sym->n_sect() == sym2->n_sect()) && (sym->n_value() == sym2->n_value()) ) { + if ( strncmp(parser.nameFromSymbol(*sym), "ltmp", 4) == 0 ) { + ++symIndex; + sym = sym2; + } + } + } + if ( ! sect.ignoreLabel(parser.nameFromSymbol(*sym)) ) { + pint_t nextSymbolAddr = sym->n_value(); //fprintf(stderr, "sectNum=%d, nextSymbolAddr=0x%08llX, name=%s\n", sectNum, (uint64_t)nextSymbolAddr, parser.nameFromSymbol(sym)); - if ( (nextSymbolAddr > startAddr) || ((nextSymbolAddr == startAddr) && (sym.n_sect() == sectNum)) ) + if ( (nextSymbolAddr > startAddr) || ((nextSymbolAddr == startAddr) && (sym->n_sect() == sectNum)) ) break; } ++symIndex; @@ -1601,7 +1663,7 @@ bool Parser::LabelAndCFIBreakIterator::next(Parser& parser, const Section< return true; } // no symbols in section, check CFI - if ( cfiIndex < cfiStartsCount ) { + if ( cfiApplicable && (cfiIndex < cfiStartsCount) ) { pint_t nextCfiAddr = cfiStartsArray[cfiIndex]; if ( nextCfiAddr < endAddr ) { // use cfi @@ -1702,14 +1764,31 @@ typename A::P::uint_t Parser::realAddr(typename A::P::uint_t addr) return addr; } +#if !__has_builtin(__builtin_mul_overflow) // ld64-port (clang < 3.8) +template +bool __builtin_mul_overflow(uint32_t a, uint32_t b, T *r) +{ + static_assert(sizeof(T) == sizeof(uint32_t), ""); + uint64_t lr = a * b; + *r = (T)lr; + return lr > (uint64_t)uint32_t(-1); +} +#endif + #define STACK_ALLOC_IF_SMALL(_type, _name, _actual_count, _maxCount) \ _type* _name = NULL; \ uint32_t _name##_count = 1; \ - if ( _actual_count > _maxCount ) \ - _name = (_type*)malloc(sizeof(_type) * _actual_count); \ + uint32_t _name##_stack_count = _actual_count ? _actual_count : 1; \ + if ( _actual_count > _maxCount ) { \ + uint32_t allocSize; \ + if ( __builtin_mul_overflow(_actual_count, sizeof(_type), &allocSize) ) \ + throw "STACK_ALLOC_IF_SMALL allocation overflow"; \ + _name = (_type*)malloc(allocSize); \ + _name##_stack_count = 1; \ + } \ else \ _name##_count = _actual_count; \ - _type _name##_buffer[_name##_count]; \ + _type _name##_buffer[_name##_stack_count]; \ if ( _name == NULL ) \ _name = _name##_buffer; @@ -1726,6 +1805,10 @@ ld::relocatable::File* Parser::parse(const ParserOptions& opts) _treateBitcodeAsData = opts.treateBitcodeAsData; _usingBitcode = opts.usingBitcode; +#if SUPPORT_ARCH_arm64e + _supportsAuthenticatedPointers = opts.supportsAuthenticatedPointers; +#endif + // respond to -t option if ( opts.logAllFiles ) printf("%s\n", _path); @@ -1734,7 +1817,7 @@ ld::relocatable::File* Parser::parse(const ParserOptions& opts) _maxDefaultCommonAlignment = opts.maxDefaultCommonAlignment; // parse start of mach-o file - if ( ! parseLoadCommands(opts.platform, opts.minOSVersion, opts.simulator, opts.ignoreMismatchPlatform) ) + if ( ! parseLoadCommands(opts.platforms, opts.internalSDK) ) return _file; // make array of @@ -1760,7 +1843,7 @@ ld::relocatable::File* Parser::parse(const ParserOptions& opts) // create lists of address that already have compact unwind and thus don't need the dwarf parsed unsigned cuLsdaCount = 0; - pint_t cuStarts[countOfCUs]; + STACK_ALLOC_IF_SMALL(pint_t, cuStarts, countOfCUs, 1024); for (uint32_t i=0; i < countOfCUs; ++i) { if ( CUSection::encodingMeansUseDwarf(cuInfoArray[i].compactUnwindInfo) ) cuStarts[i] = -1; @@ -1964,21 +2047,13 @@ ld::relocatable::File* Parser::parse(const ParserOptions& opts) return _file; } -static void versionToString(uint32_t value, char buffer[32]) -{ - if ( value & 0xFF ) - sprintf(buffer, "%d.%d.%d", value >> 16, (value >> 8) & 0xFF, value & 0xFF); - else - sprintf(buffer, "%d.%d", value >> 16, (value >> 8) & 0xFF); -} - template <> uint8_t Parser::loadCommandSizeMask() { return 0x03; } template <> uint8_t Parser::loadCommandSizeMask() { return 0x07; } template <> uint8_t Parser::loadCommandSizeMask() { return 0x03; } template <> uint8_t Parser::loadCommandSizeMask() { return 0x07; } template -bool Parser::parseLoadCommands(Options::Platform platform, uint32_t linkMinOSVersion, bool simulator, bool ignoreMismatchPlatform) +bool Parser::parseLoadCommands(const ld::VersionSet& cmdLinePlatforms, bool internalSDK) { const macho_header

* header = (const macho_header

*)_fileContent; @@ -1992,7 +2067,7 @@ bool Parser::parseLoadCommands(Options::Platform platform, uint32_t linkMinOS // an empty .o file with zero load commands will crash linker if ( cmd_count == 0 ) return false; - Options::Platform lcPlatform = Options::kPlatformUnknown; + ld::VersionSet lcPlatforms; const macho_load_command

* const cmds = (macho_load_command

*)((char*)header + sizeof(macho_header

)); const macho_load_command

* const cmdsEnd = (macho_load_command

*)((char*)header + sizeof(macho_header

) + header->sizeofcmds()); const macho_load_command

* cmd = cmds; @@ -2074,14 +2149,25 @@ bool Parser::parseLoadCommands(Options::Platform platform, uint32_t linkMinOS case LC_VERSION_MIN_MACOSX: case LC_VERSION_MIN_IPHONEOS: case LC_VERSION_MIN_WATCHOS: - #if SUPPORT_APPLE_TV case LC_VERSION_MIN_TVOS: - #endif - if ( ignoreMismatchPlatform ) - break; - _file->_platform = cmd->cmd(); - lcPlatform = Options::platformForLoadCommand(cmd->cmd()); - _file->_minOSVersion = ((macho_version_min_command

*)cmd)->version(); + { + ld::Platform filePlatform = ld::platformForLoadCommand(cmd->cmd(), (mach_header*)header); + lcPlatforms.insert(ld::PlatformVersion(filePlatform, ((macho_version_min_command

*)cmd)->version())); + _file->_platforms.insert(ld::PlatformVersion(filePlatform, ((macho_version_min_command

*)cmd)->version())); + } + break; + case LC_BUILD_VERSION: + { + const macho_build_version_command

* buildVersCmd = (macho_build_version_command

*)cmd; + ld::Platform plat = ld::platformFromBuildVersion(buildVersCmd->platform(), (mach_header*)header); + lcPlatforms.insert(ld::PlatformVersion(plat, buildVersCmd->minos())); + _file->_platforms.insert(ld::PlatformVersion(plat, buildVersCmd->minos())); + const macho_build_tool_version

* entry = (macho_build_tool_version

*)((uint8_t*)cmd + sizeof(macho_build_version_command

)); + for (uint32_t t=0; t < buildVersCmd->ntools(); ++t) { + _file->_toolVersions.push_back(std::make_pair(entry->tool(), entry->version())); + ++entry; + } + } break; case macho_segment_command

::CMD: if ( segment != NULL ) @@ -2096,79 +2182,32 @@ bool Parser::parseLoadCommands(Options::Platform platform, uint32_t linkMinOS if ( cmd > cmdsEnd ) throwf("malformed mach-o file, load command #%d is outside size of load commands", i); } - // arm/arm64 objects are default to ios platform if not set. - // rdar://problem/21746314 - if (lcPlatform == Options::kPlatformUnknown && - (std::is_same::value || std::is_same::value)) - lcPlatform = Options::kPlatformiOS; // Check platform cross-linking. - if ( !ignoreMismatchPlatform ) { - if ( lcPlatform != platform ) { - switch (platform) { - case Options::kPlatformOSX: - case Options::kPlatformiOS: - if ( lcPlatform == Options::kPlatformUnknown ) - break; - // fall through if the Platform is not Unknown - case Options::kPlatformWatchOS: - // Error when using bitcocde, warning otherwise. - if (_usingBitcode) - throwf("building for %s%s, but linking in object file built for %s,", - Options::platformName(platform), (simulator ? " simulator" : ""), - Options::platformName(lcPlatform)); - else - warning("URGENT: building for %s%s, but linking in object file (%s) built for %s. " - "Note: This will be an error in the future.", - Options::platformName(platform), (simulator ? " simulator" : ""), path(), - Options::platformName(lcPlatform)); - break; - #if SUPPORT_APPLE_TV - case Options::kPlatform_tvOS: - // Error when using bitcocde, warning otherwise. - if (_usingBitcode) - throwf("building for %s%s, but linking in object file built for %s,", - Options::platformName(platform), (simulator ? " simulator" : ""), - Options::platformName(lcPlatform)); - else - warning("URGENT: building for %s%s, but linking in object file (%s) built for %s. " - "Note: This will be an error in the future.", - Options::platformName(platform), (simulator ? " simulator" : ""), path(), - Options::platformName(lcPlatform)); - break; - #endif - case Options::kPlatformUnknown: - // skip if the target platform is unknown - break; - } - } - if ( linkMinOSVersion && (_file->_minOSVersion > linkMinOSVersion) ) { - char t1[32]; - char t2[32]; - versionToString(_file->_minOSVersion, t1); - versionToString(linkMinOSVersion, t2); - warning("object file (%s) was built for newer %s version (%s) than being linked (%s)", - _path, Options::platformName(lcPlatform), t1, t2); - } - } + cmdLinePlatforms.checkObjectCrosslink(lcPlatforms, path(), internalSDK, _usingBitcode); - - // record range of sections + // validate just one segment if ( segment == NULL ) throw "missing LC_SEGMENT"; + if ( segment->filesize() > _fileLength ) + throw "LC_SEGMENT filesize too large"; + + // record and validate sections _sectionsStart = (macho_section

*)((char*)segment + sizeof(macho_segment_command

)); _machOSectionsCount = segment->nsects(); if ( (sizeof(macho_segment_command

) + _machOSectionsCount * sizeof(macho_section

)) > segment->cmdsize() ) throw "too many sections for size of LC_SEGMENT command"; + return true; } template -Options::Platform Parser::findPlatform(const macho_header

* header) +ld::Platform Parser::findPlatform(const macho_header

* header, uint64_t fileLength, uint32_t* minOsVers) { const uint32_t cmd_count = header->ncmds(); if ( cmd_count == 0 ) - return Options::kPlatformUnknown; + return ld::Platform::unknown; + const uint8_t* const endOfFile = (uint8_t*)header + fileLength; const macho_load_command

* const cmds = (macho_load_command

*)((char*)header + sizeof(macho_header

)); const macho_load_command

* const cmdsEnd = (macho_load_command

*)((char*)header + sizeof(macho_header

) + header->sizeofcmds()); const macho_load_command

* cmd = cmds; @@ -2179,17 +2218,27 @@ Options::Platform Parser::findPlatform(const macho_header

* header) const uint8_t* endOfCmd = ((uint8_t*)cmd)+cmd->cmdsize(); if ( endOfCmd > (uint8_t*)cmdsEnd ) throwf("load command #%d extends beyond the end of the load commands", i); + if ( endOfCmd > endOfFile ) + throwf("load command #%d extends beyond the end of the file", i); + const macho_version_min_command

* versCmd = (macho_version_min_command

*)cmd; + const macho_build_version_command

* buildVersCmd = (macho_build_version_command

*)cmd; switch (cmd->cmd()) { case LC_VERSION_MIN_MACOSX: - return Options::kPlatformOSX; case LC_VERSION_MIN_IPHONEOS: - return Options::kPlatformiOS; + case LC_VERSION_MIN_WATCHOS: + case LC_VERSION_MIN_TVOS: + *minOsVers = versCmd->version(); + return ld::platformForLoadCommand(cmd->cmd(), (mach_header*)header); + case LC_BUILD_VERSION: + *minOsVers = buildVersCmd->minos(); + return ld::platformFromBuildVersion(buildVersCmd->platform(), (mach_header*)header); } cmd = (const macho_load_command

*)(((char*)cmd)+cmd->cmdsize()); if ( cmd > cmdsEnd ) throwf("malformed mach-o file, load command #%d is outside size of load commands", i); } - return Options::kPlatformUnknown; + *minOsVers = 0; + return ld::Platform::unknown; } @@ -2526,19 +2575,15 @@ void Parser::makeSections() // #define OBJC_IMAGE_SUPPORTS_GC 2 // #define OBJC_IMAGE_GC_ONLY 4 // #define OBJC_IMAGE_IS_SIMULATED 32 + // #define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES 64 // const uint32_t* contents = (uint32_t*)(_file->fileContent()+sect->offset()); if ( (sect->size() >= 8) && (contents[0] == 0) ) { uint32_t flags = E::get32(contents[1]); - if ( (flags & 4) == 4 ) - _file->_objConstraint = ld::File::objcConstraintGC; - else if ( (flags & 2) == 2 ) - _file->_objConstraint = ld::File::objcConstraintRetainReleaseOrGC; - else if ( (flags & 32) == 32 ) - _file->_objConstraint = ld::File::objcConstraintRetainReleaseForSimulator; - else - _file->_objConstraint = ld::File::objcConstraintRetainRelease; + _file->_hasObjC = true; _file->_swiftVersion = ((flags >> 8) & 0xFF); + _file->_swiftLanguageVersion = ((flags >> 16) & 0xFFFF); + _file->_objcHasCategoryClassPropertiesField = (flags & 64); if ( sect->size() > 8 ) { warning("section %s/%s has unexpectedly large size %llu in %s", sect->segname(), Section::makeSectionName(sect), sect->size(), _file->path()); @@ -3006,6 +3051,13 @@ void Parser::addFixups(const SourceLocation& src, ld::Fixup::Kind setKind, co ld::Fixup::Cluster cl = ld::Fixup::k1of3; ld::Fixup::Kind firstKind = ld::Fixup::kindSetTargetAddress; bool combined = false; + +#if SUPPORT_ARCH_arm64e + bool isAuthenticated = setKind == ld::Fixup::kindStoreLittleEndianAuth64; + // Authenticated pointers need an extra fixup for the auth data. + if (isAuthenticated) + cl = ld::Fixup::k2of4; +#endif if ( target.addend == 0 ) { cl = ld::Fixup::k1of1; combined = true; @@ -3065,6 +3117,12 @@ void Parser::addFixups(const SourceLocation& src, ld::Fixup::Kind setKind, co case ld::Fixup::kindStoreARM64TLVPLoadPageOff12: firstKind = ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12; break; +#endif +#if SUPPORT_ARCH_arm64e + case ld::Fixup::kindStoreLittleEndianAuth64: + firstKind = ld::Fixup::kindStoreTargetAddressLittleEndianAuth64; + cl = ld::Fixup::k2of2; + break; #endif default: combined = false; @@ -3073,6 +3131,19 @@ void Parser::addFixups(const SourceLocation& src, ld::Fixup::Kind setKind, co } } +#if SUPPORT_ARCH_arm64e + // As the auth data is independent of the addend and target, we can just always + // put it first. + if (isAuthenticated) { + if (cl == ld::Fixup::k2of2) { + addFixup(src, ld::Fixup::k1of2, ld::Fixup::kindSetAuthData, target.authData); + } else { + assert(cl == ld::Fixup::k2of4); + addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetAuthData, target.authData); + } + } +#endif + if ( target.atom != NULL ) { if ( target.atom->scope() == ld::Atom::scopeTranslationUnit ) { addFixup(src, cl, firstKind, target.atom); @@ -3097,12 +3168,24 @@ void Parser::addFixups(const SourceLocation& src, ld::Fixup::Kind setKind, co addFixup(src, cl, firstKind, target.weakImport, target.name); } if ( target.addend == 0 ) { +#if SUPPORT_ARCH_arm64e + if (isAuthenticated) + assert(combined); +#endif if ( ! combined ) addFixup(src, ld::Fixup::k2of2, setKind); } else { - addFixup(src, ld::Fixup::k2of3, ld::Fixup::kindAddAddend, target.addend); - addFixup(src, ld::Fixup::k3of3, setKind); +#if SUPPORT_ARCH_arm64e + if (isAuthenticated) { + addFixup(src, ld::Fixup::k3of4, ld::Fixup::kindAddAddend, target.addend); + addFixup(src, ld::Fixup::k4of4, setKind); + } else +#endif + { + addFixup(src, ld::Fixup::k2of3, ld::Fixup::kindAddAddend, target.addend); + addFixup(src, ld::Fixup::k3of3, setKind); + } } } @@ -3168,10 +3251,10 @@ uint32_t TentativeDefinitionSection::appendAtoms(class Parser& parser, uin alignP2 = 63 - (uint8_t)__builtin_clzll(size); if ( size != (1ULL << alignP2) ) ++alignP2; + // limit default alignment of large commons + if ( alignP2 > parser.maxDefaultCommonAlignment() ) + alignP2 = parser.maxDefaultCommonAlignment(); } - // limit alignment of extremely large commons to 2^15 bytes (8-page) - if ( alignP2 > parser.maxDefaultCommonAlignment() ) - alignP2 = parser.maxDefaultCommonAlignment(); Atom* allocatedSpace = (Atom*)p; new (allocatedSpace) Atom(*this, parser.nameFromSymbol(sym), (pint_t)ULLONG_MAX, size, ld::Atom::definitionTentative, ld::Atom::combineByName, @@ -3271,10 +3354,11 @@ uint32_t Parser::symbolIndexFromIndirectSectionAddress(pint_t addr, const mac break; case S_LAZY_SYMBOL_POINTERS: case S_NON_LAZY_SYMBOL_POINTERS: + case S_THREAD_LOCAL_VARIABLE_POINTERS: elementSize = sizeof(pint_t); break; default: - throw "section does not use inirect symbol table"; + throw "section does not use indirect symbol table"; } uint32_t indexInSection = (addr - sect->addr()) / elementSize; uint32_t indexIntoIndirectTable = sect->reserved1() + indexInSection; @@ -3286,7 +3370,10 @@ uint32_t Parser::symbolIndexFromIndirectSectionAddress(pint_t addr, const mac template const char* Parser::nameFromSymbol(const macho_nlist

& sym) { - return &_strings[sym.n_strx()]; + uint32_t strOffset = sym.n_strx(); + if ( strOffset >= _stringsSize ) + throw "malformed nlist string offset"; + return &_strings[strOffset]; } template @@ -3373,6 +3460,12 @@ bool Parser::altEntryFromSymbol(const macho_nlist

& sym) return ( sym.n_desc() & N_ALT_ENTRY ); } +template +bool Parser::coldFromSymbol(const macho_nlist

& sym) +{ + return ( sym.n_desc() & N_COLD_FUNC ); +} + /* Skip over a LEB128 value (signed or unsigned). */ static void @@ -3582,6 +3675,8 @@ bool Parser::isConstFunStabs(const char *stabStr) template void Parser::parseDebugInfo() { + addAstFiles(); + // check for dwarf __debug_info section if ( _file->_dwarfDebugInfoSect == NULL ) { // if no DWARF debug info, look for stabs @@ -3748,6 +3843,18 @@ void Parser::parseDebugInfo() template void Parser::parseStabs() { + typedef std::unordered_map*, ld::CStringHash, ld::CStringEquals> CStringToAtom; + CStringToAtom atomMap; + + { + uint8_t* p = _file->_atomsArray; + for(int i=_file->_atomsArrayCount; i > 0; --i) { + Atom* atom = (Atom*)p; + atomMap.insert({ atom->name(), atom }); + p += sizeof(Atom); + } + } + // scan symbol table for stabs entries Atom* currentAtom = NULL; pint_t currentAtomAddress = 0; @@ -3800,7 +3907,7 @@ void Parser::parseStabs() { // n_value field is NOT atom address ;-( // need to find atom by name match - const char* colon = strchr(symString, ':'); + const char* colon = strstr(symString, ":G"); if ( colon != NULL ) { // build underscore leading name int nameLen = colon - symString; @@ -3808,7 +3915,12 @@ void Parser::parseStabs() strlcpy(&symName[1], symString, nameLen+1); symName[0] = '_'; symName[nameLen+1] = '\0'; - currentAtom = this->findAtomByName(symName); + auto atomIt = atomMap.find(symName); + if (atomIt != atomMap.end()) { + currentAtom = atomIt->second; + } else { + currentAtom = NULL; + } if ( currentAtom != NULL ) { stab.atom = currentAtom; stab.string = symString; @@ -3816,7 +3928,12 @@ void Parser::parseStabs() } else { // might be a debug-note without trailing :G() - currentAtom = this->findAtomByName(symString); + auto atomIt = atomMap.find(symString); + if (atomIt != atomMap.end()) { + currentAtom = atomIt->second; + } else { + currentAtom = NULL; + } if ( currentAtom != NULL ) { stab.atom = currentAtom; stab.string = symString; @@ -3952,6 +4069,22 @@ void Parser::parseStabs() } +template +void Parser::addAstFiles() +{ + // scan symbol table for N_AST entries + for (uint32_t symbolIndex = 0; symbolIndex < _symbolCount; ++symbolIndex ) { + const macho_nlist

& sym = this->symbolFromIndex(symbolIndex); + if ( (sym.n_type() == N_AST) && (sym.n_strx() != 0) ) { + const char* symString = this->nameFromSymbol(sym); + ld::relocatable::File::AstTimeAndPath entry; + entry.time = sym.n_value(); + entry.path = symString; + _file->_astFiles.push_back(entry); + } + } +} + // Look at the compilation unit DIE and determine // its NAME, compilation directory (in COMP_DIR) and its @@ -4388,6 +4521,7 @@ bool CFISection::needsRelocating() return true; } + template bool CFISection::needsRelocating() { @@ -4396,7 +4530,7 @@ bool CFISection::needsRelocating() template <> void CFISection::cfiParse(class Parser& parser, uint8_t* buffer, - libunwind::CFI_Atom_Info::OAS> cfiArray[], // ld64-port: removed superfluous ::CFI_Atom_Info + libunwind::CFI_Atom_Info::OAS> cfiArray[], uint32_t& count, const pint_t cuStarts[], uint32_t cuCount) { const uint32_t sectionSize = this->_machOSection->size(); @@ -4461,7 +4595,7 @@ void CFISection::cfiParse(class Parser& parser, uint8_t* buffer, template <> void CFISection::cfiParse(class Parser& parser, uint8_t* buffer, - libunwind::CFI_Atom_Info::OAS> cfiArray[], // ld64-port: removed superfluous ::CFI_Atom_Info + libunwind::CFI_Atom_Info::OAS> cfiArray[], uint32_t& count, const pint_t cuStarts[], uint32_t cuCount) { // create ObjectAddressSpace object for use by libunwind @@ -4482,7 +4616,7 @@ void CFISection::cfiParse(class Parser& parser, uint8_t* buffer, template <> void CFISection::cfiParse(class Parser& parser, uint8_t* buffer, - libunwind::CFI_Atom_Info::OAS> cfiArray[], // ld64-port: removed superfluous ::CFI_Atom_Info + libunwind::CFI_Atom_Info::OAS> cfiArray[], uint32_t& count, const pint_t cuStarts[], uint32_t cuCount) { if ( !parser.armUsesZeroCostExceptions() ) { @@ -4505,10 +4639,9 @@ void CFISection::cfiParse(class Parser& parser, uint8_t* buffer, - template <> void CFISection::cfiParse(class Parser& parser, uint8_t* buffer, - libunwind::CFI_Atom_Info::OAS> cfiArray[], // ld64-port: removed superfluous ::CFI_Atom_Info + libunwind::CFI_Atom_Info::OAS> cfiArray[], uint32_t& count, const pint_t cuStarts[], uint32_t cuCount) { // copy __eh_frame data to buffer @@ -4575,6 +4708,7 @@ void CFISection::cfiParse(class Parser& parser, uint8_t* buffer, } + template uint32_t CFISection::computeAtomCount(class Parser& parser, struct Parser::LabelAndCFIBreakIterator& it, @@ -4612,7 +4746,6 @@ template <> bool CFISection::bigEndian() { return false; } template <> bool CFISection::bigEndian() { return false; } template <> bool CFISection::bigEndian() { return false; } - template <> void CFISection::addCiePersonalityFixups(class Parser& parser, const CFI_Atom_Info* cieInfo) { @@ -4684,6 +4817,7 @@ void CFISection::addCiePersonalityFixups(class Parser& parser, con } #endif + template <> void CFISection::addCiePersonalityFixups(class Parser& parser, const CFI_Atom_Info* cieInfo) { @@ -5009,6 +5143,7 @@ const char* CUSection::personalityName(class Parser& parser, const } #endif + #if SUPPORT_ARCH_arm_any template <> const char* CUSection::personalityName(class Parser& parser, const macho_relocation_info* reloc) @@ -5073,6 +5208,7 @@ bool CUSection::encodingMeansUseDwarf(compact_unwind_encoding_t enc) } #endif + template int CUSection::infoSorter(const void* l, const void* r) { @@ -5110,6 +5246,10 @@ void CUSection::parse(class Parser& parser, uint32_t cnt, Info array[]) // scan relocs, extern relocs are needed for personality references (possibly for function/lsda refs??) const uint32_t sectionSize = this->_machOSection->size(); + if ( this->_machOSection->reloff() > parser.fileLength() ) + throw "relocations beyond end of file"; + if ( this->_machOSection->reloff()+this->_machOSection->nreloc()*sizeof(macho_relocation_info

) > parser.fileLength() ) + throw "relocations beyond end of file"; const macho_relocation_info

* relocs = (macho_relocation_info

*)(this->file().fileContent() + this->_machOSection->reloff()); const macho_relocation_info

* relocsEnd = &relocs[this->_machOSection->nreloc()]; for (const macho_relocation_info

* reloc = relocs; reloc < relocsEnd; ++reloc) { @@ -5217,6 +5357,9 @@ SymboledSection::SymboledSection(Parser& parser, File& f, const macho_s _type = ld::Atom::typeLSDA; else if ( this->type() == ld::Section::typeInitializerPointers ) _type = ld::Atom::typeInitializerPointers; + // don't warn about static initializers in dylibs built for profiling + if ( strncmp(s->sectname(), "__llvm_prf_", 11) == 0 ) + this->_file.setHasllvmProfiling(); break; } } @@ -5314,6 +5457,7 @@ ld::Atom::SymbolTableInclusion ImplicitSizeSection::symbolTableInclusion( return ld::Atom::symbolTableInWithRandomAutoStripLabel; } + template ld::Atom::SymbolTableInclusion ImplicitSizeSection::symbolTableInclusion() { @@ -5395,7 +5539,7 @@ uint32_t ImplicitSizeSection::appendAtoms(class Parser& parser, uint8_t* p } else { // make named atom for label - //fprintf(stderr, " 0x%08llX make labeled\n", (uint64_t)foundAddr); + //fprintf(stderr, " 0x%08llX make labeled: %s\n", (uint64_t)foundAddr, parser.nameFromSymbol(*foundLabel)); new (allocatedSpace) Atom(*this, parser, *foundLabel, labeledAtomSize); } if ( !skip ) { @@ -5754,6 +5898,47 @@ ld::Atom::Combine TLVPointerSection::combine(Parser& parser, pint_t addr) return ld::Atom::combineByNameAndReferences; } +template <> +void TLVPointerSection::makeFixups(class Parser& parser, const struct Parser::CFI_CU_InfoArrays&) +{ + // add references for each thread local pointer atom based on indirect symbol table + const macho_section

* sect = this->machoSection(); + const pint_t endAddr = sect->addr() + sect->size(); + for (pint_t addr = sect->addr(); addr < endAddr; addr += sizeof(pint_t)) { + typename Parser::SourceLocation src; + typename Parser::TargetDesc target; + src.atom = this->findAtomByAddress(addr); + src.offsetInAtom = 0; + uint32_t symIndex = parser.symbolIndexFromIndirectSectionAddress(addr, sect); + target.atom = NULL; + target.name = NULL; + target.weakImport = false; + target.addend = 0; + if ( symIndex == INDIRECT_SYMBOL_LOCAL ) { + throwf("unexpected INDIRECT_SYMBOL_LOCAL in section %s", this->sectionName()); + } + else { + const macho_nlist

& sym = parser.symbolFromIndex(symIndex); + // use direct reference for local symbols + if ( ((sym.n_type() & N_TYPE) == N_SECT) && ((sym.n_type() & N_EXT) == 0) ) { + throwf("unexpected pointer to local symbol in section %s", this->sectionName()); + } + else { + target.name = parser.nameFromSymbol(sym); + target.weakImport = parser.weakImportFromSymbol(sym); + assert(src.atom->combine() == ld::Atom::combineByNameAndReferences); + } + } + parser.addFixups(src, ld::Fixup::kindStoreLittleEndian32, target); + } +} + +template +void TLVPointerSection::makeFixups(class Parser& parser, const struct Parser::CFI_CU_InfoArrays&) +{ + assert(0 && "should not have thread-local-pointer sections in .o files"); +} + template const char* TLVPointerSection::targetName(const class Atom* atom, const ld::IndirectBindingTable& ind, bool* isStatic) @@ -6183,11 +6368,17 @@ template <> bool Section::addRelocFixup(class Parser& parser, const macho_relocation_info

* reloc) { const macho_section

* sect = this->machoSection(); + if ( sect == NULL ) { + warning("malformed mach-o, relocations not supported on section %s", this->sectionName()); + return false; + } uint64_t srcAddr = sect->addr() + reloc->r_address(); Parser::SourceLocation src; Parser::TargetDesc target; Parser::TargetDesc toTarget; src.atom = this->findAtomByAddress(srcAddr); + if ( src.atom == NULL ) + throwf("malformed mach-o, reloc addr 0x%llX not in any atom", srcAddr); src.offsetInAtom = srcAddr - src.atom->_objAddress; const uint8_t* fixUpPtr = file().fileContent() + sect->offset() + reloc->r_address(); uint64_t contentValue = 0; @@ -6883,7 +7074,7 @@ bool Section::addRelocFixup(class Parser& parser, const macho_relocati if ( target.atom == NULL ) throwf("bad r_value (0x%08X) for ARM_RELOC_VANILLA\n", sreloc->r_value()); contentValue = LittleEndian::get32(*fixUpPtr); - target.addend = contentValue - target.atom->_objAddress; + target.addend = (int64_t)contentValue - (int64_t)(target.atom->_objAddress); if ( target.atom->isThumb() ) target.addend &= -2; // remove thumb bit parser.addFixups(src, ld::Fixup::kindStoreLittleEndian32, target); @@ -7319,7 +7510,7 @@ bool Section::addRelocFixup(class Parser& parser, const macho_relo instruction = contentValue; target.addend = ((instruction & 0x60000000) >> 29) | ((instruction & 0x01FFFFE0) >> 3); if ( target.addend != 0 ) - throw "non-zero addend with ARM64_RELOC_GOT_LOAD_PAGE21 is not supported"; + throw "non-zero addend with ARM64_RELOC_TLVP_LOAD_PAGE21 is not supported"; parser.addFixups(src, ld::Fixup::kindStoreARM64TLVPLoadPage21, target); break; case ARM64_RELOC_TLVP_LOAD_PAGEOFF12: @@ -7370,8 +7561,12 @@ bool Section::addRelocFixup(class Parser& parser, const macho_relo parser.findTargetFromAddressAndSectionNum(contentValue, nextReloc->r_symbolnum(), toTarget); useDirectBinding = (toTarget.atom->scope() == ld::Atom::scopeTranslationUnit); } - if ( useDirectBinding ) - parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, toTarget.atom); + if ( useDirectBinding ) { + if ( (toTarget.atom->combine() == ld::Atom::combineByNameAndContent) || (toTarget.atom->combine() == ld::Atom::combineByNameAndReferences) ) + parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, ld::Fixup::bindingByContentBound, toTarget.atom); + else + parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, toTarget.atom); + } else parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, toTarget.weakImport, toTarget.name); parser.addFixup(src, ld::Fixup::k2of4, ld::Fixup::kindAddAddend, toTarget.addend); @@ -7400,6 +7595,52 @@ bool Section::addRelocFixup(class Parser& parser, const macho_relo parser.addFixups(src, ld::Fixup::kindStoreARM64PointerToGOT, target); } break; +#if SUPPORT_ARCH_arm64e + case ARM64_RELOC_AUTHENTICATED_POINTER: { + if ( reloc->r_pcrel() ) + throw "pcrel and ARM64_RELOC_AUTHENTICATED_POINTER not supported"; + if ( ! reloc->r_extern() ) + throw "r_extern == 0 and ARM64_RELOC_AUTHENTICATED_POINTER not supported"; + // An authenticated pointer is: + // { + // int32_t addend; + // uint16_t diversityData; + // uint16_t hasAddressDiversity : 1; + // uint16_t key : 2; + // uint16_t zeroes : 11; + // uint16_t zero : 1; + // uint16_t authenticated : 1; + // } + target.addend = (int32_t)(contentValue & 0xFFFFFFFF); + if (parser._supportsAuthenticatedPointers) { + target.authData.discriminator = (uint16_t)(contentValue >> 32); + target.authData.hasAddressDiversity = (contentValue & (1ULL << 48)) != 0; + target.authData.key = (ld::Fixup::AuthData::ptrauth_key)((contentValue >> 49) & 0x3); + } else { + static bool emittedWarning = false; + if (!emittedWarning) { + emittedWarning = true; + warning("stripping authenticated relocation as image uses -preload or -static"); + } + } + bool isAuthenticated = (contentValue & (1ULL << 63)) != 0; + if (!isAuthenticated) + throw "ARM64_RELOC_AUTHENTICATED_POINTER value must have authenticated bit set"; + switch ( reloc->r_length() ) { + case 0: + case 1: + case 2: + throw "length < 3 and ARM64_RELOC_AUTHENTICATED_POINTER not supported"; + case 3: + if (parser._supportsAuthenticatedPointers) + parser.addFixups(src, ld::Fixup::kindStoreLittleEndianAuth64, target); + else + parser.addFixups(src, ld::Fixup::kindStoreLittleEndian64, target); + break; + } + break; + } +#endif default: throwf("unknown relocation type %d", reloc->r_type()); } @@ -7407,6 +7648,7 @@ bool Section::addRelocFixup(class Parser& parser, const macho_relo } #endif + template bool ObjC1ClassSection::addRelocFixup(class Parser& parser, const macho_relocation_info

* reloc) { @@ -7558,6 +7800,7 @@ void Section::addLOH(class Parser& parser, int kind, int count, co } #endif + template void Section::addLOH(class Parser& parser, int kind, int count, const uint64_t addrs[]) { @@ -7804,34 +8047,34 @@ bool isObjectFile(const uint8_t* fileContent, uint64_t fileLength, const ParserO // // used by linker to infer architecture when no -arch is on command line // -bool isObjectFile(const uint8_t* fileContent, cpu_type_t* result, cpu_subtype_t* subResult, Options::Platform* platform) +bool isObjectFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t* result, cpu_subtype_t* subResult, ld::Platform* platform, uint32_t* minOsVers) { if ( mach_o::relocatable::Parser::validFile(fileContent) ) { *result = CPU_TYPE_X86_64; const macho_header >* header = (const macho_header >*)fileContent; *subResult = header->cpusubtype(); - *platform = Parser::findPlatform(header); + *platform = Parser::findPlatform(header, fileLength, minOsVers); return true; } if ( mach_o::relocatable::Parser::validFile(fileContent) ) { const macho_header >* header = (const macho_header >*)fileContent; *result = CPU_TYPE_I386; *subResult = CPU_SUBTYPE_X86_ALL; - *platform = Parser::findPlatform(header); + *platform = Parser::findPlatform(header, fileLength, minOsVers); return true; } if ( mach_o::relocatable::Parser::validFile(fileContent, false, 0) ) { const macho_header >* header = (const macho_header >*)fileContent; *result = CPU_TYPE_ARM; *subResult = header->cpusubtype(); - *platform = Parser::findPlatform(header); + *platform = Parser::findPlatform(header, fileLength, minOsVers); return true; } if ( mach_o::relocatable::Parser::validFile(fileContent, false, 0) ) { const macho_header >* header = (const macho_header >*)fileContent; *result = CPU_TYPE_ARM64; - *subResult = CPU_SUBTYPE_ARM64_ALL; - *platform = Parser::findPlatform(header); + *subResult = header->cpusubtype(); + *platform = Parser::findPlatform(header, fileLength, minOsVers); return true; } return false; @@ -7851,6 +8094,11 @@ const char* archName(const uint8_t* fileContent) if ( mach_o::relocatable::Parser::validFile(fileContent, false, 0) ) { return mach_o::relocatable::Parser::fileKind(fileContent); } +#if SUPPORT_ARCH_arm64 + if ( mach_o::relocatable::Parser::validFile(fileContent, false, 0) ) { + return mach_o::relocatable::Parser::fileKind(fileContent); + } +#endif return NULL; } @@ -7901,9 +8149,11 @@ bool getNonLocalSymbols(const uint8_t* fileContent, std::vector &sy else if ( mach_o::relocatable::Parser::validFile(fileContent, false, 0) ) { return mach_o::relocatable::Parser::getNonLocalSymbols(fileContent, syms); } +#if SUPPORT_ARCH_arm64 else if ( mach_o::relocatable::Parser::validFile(fileContent, false, 0) ) { return mach_o::relocatable::Parser::getNonLocalSymbols(fileContent, syms); } +#endif return false; } diff --git a/cctools/ld64/src/ld/parsers/macho_relocatable_file.h b/cctools/ld64/src/ld/parsers/macho_relocatable_file.h index e31f7f9..ccb44bf 100644 --- a/cctools/ld64/src/ld/parsers/macho_relocatable_file.h +++ b/cctools/ld64/src/ld/parsers/macho_relocatable_file.h @@ -41,15 +41,16 @@ struct ParserOptions { bool neverConvertDwarf; bool verboseOptimizationHints; bool armUsesZeroCostExceptions; - bool simulator; - bool ignoreMismatchPlatform; +#if SUPPORT_ARCH_arm64e + bool supportsAuthenticatedPointers; +#endif uint32_t subType; - Options::Platform platform; - uint32_t minOSVersion; + ld::VersionSet platforms; ld::relocatable::File::SourceKind srcKind; bool treateBitcodeAsData; bool usingBitcode; uint8_t maxDefaultCommonAlignment; + bool internalSDK; }; extern ld::relocatable::File* parse(const uint8_t* fileContent, uint64_t fileLength, @@ -58,7 +59,7 @@ extern ld::relocatable::File* parse(const uint8_t* fileContent, uint64_t fileLen extern bool isObjectFile(const uint8_t* fileContent, uint64_t fileLength, const ParserOptions& opts); -extern bool isObjectFile(const uint8_t* fileContent, cpu_type_t* result, cpu_subtype_t* subResult, Options::Platform* platform); +extern bool isObjectFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t* result, cpu_subtype_t* subResult, ld::Platform* platform, uint32_t* minOsVers); extern bool hasObjC2Categories(const uint8_t* fileContent); diff --git a/cctools/ld64/src/ld/parsers/textstub_dylib_file.cpp b/cctools/ld64/src/ld/parsers/textstub_dylib_file.cpp index 09c0e12..226ce55 100644 --- a/cctools/ld64/src/ld/parsers/textstub_dylib_file.cpp +++ b/cctools/ld64/src/ld/parsers/textstub_dylib_file.cpp @@ -22,484 +22,22 @@ * @APPLE_LICENSE_HEADER_END@ */ +#ifdef TAPI_SUPPORT #include #include - +#include #include #include // ld64-port #include // ld64-port #include "Architectures.hpp" -#include "Bitcode.hpp" // ld64-port: "bitcode.hpp" -> "Bitcode.hpp" +#include "Bitcode.hpp" #include "MachOFileAbstraction.hpp" #include "MachOTrie.hpp" #include "generic_dylib_file.hpp" #include "textstub_dylib_file.hpp" -namespace { - -/// -/// A token is a light-weight reference to the content of an nmap'ed file. It -/// doesn't own the data and it doesn't make a copy of it. The referenced data -/// is only valid as long as the file is mapped in. -/// -class Token { - const char* _p; - size_t _size; - - int compareMemory(const char* lhs, const char* rhs, size_t size) const { - if (size == 0) - return 0; - return ::memcmp(lhs, rhs, size); - } - -public: - Token() : _p(nullptr), _size(0) {} - - Token(const char* p) : _p(p), _size(0) { - if (p) - _size = ::strlen(p); - } - - Token(const char* p, size_t s) : _p(p), _size(s) {} - - const char* data() const { return _p; } - - size_t size() const { return _size; } - - std::string str() const { return std::string(_p, _size); } - - bool empty() const { return _size == 0; } - - bool operator==(Token other) const { - if (_size != other._size) - return false; - return compareMemory(_p, other._p, _size) == 0; - } - - bool operator!=(Token other) const { - return !(*this == other); - } -}; - -/// -/// Simple text-based dynamic library file tokenizer. -/// -class Tokenizer { - const char* _start; - const char* _current; - const char* _end; - Token _currentToken; - - void fetchNextToken(); - void scanToNextToken(); - void skip(unsigned distance) { - _current += distance; - assert(_current <= _end && "Skipped past the end"); - } - - const char* skipLineBreak(const char* pos) const; - bool isDelimiter(const char* pos) const; - -public: - Tokenizer(const char* data, uint64_t size) : _start(data), _current(data), _end(data + size) {} - - void reset() { - _current = _start; - fetchNextToken(); - } - - Token peek() { return _currentToken; } - Token next() { - Token token = peek(); - fetchNextToken(); - return token; - } -}; - -const char* Tokenizer::skipLineBreak(const char* pos) const -{ - if ( pos == _end ) - return pos; - - // Carriage return. - if ( *pos == 0x0D ) { - // line feed. - if ( pos + 1 != _end && *(pos + 1) == 0x0A) - return pos + 2; - return pos + 1; - } - - // line feed. - if ( *pos == 0x0A ) - return pos + 1; - - return pos; -} - -void Tokenizer::scanToNextToken() { - while (true) { - while ( isDelimiter(_current) ) - skip(1); - - const char* i = skipLineBreak(_current); - if ( i == _current ) - break; - - _current = i; - } -} - - -bool Tokenizer::isDelimiter(const char* pos) const { - if ( pos == _end ) - return false; - if ( *pos == ' ' || *pos == '\t' || *pos == '\r' || *pos == '\n' || *pos == ',' || *pos == ':' || *pos == '\'' || *pos == '\"' ) - return true; - return false; -} - -void Tokenizer::fetchNextToken() { - scanToNextToken(); - - if (_current == _end) { - _currentToken = Token(); - return; - } - - auto start = _current; - while ( !isDelimiter(_current) ) { - ++_current; - } - - _currentToken = Token(start, _current - start); -} - -/// -/// Representation of a parsed text-based dynamic library file. -/// -struct DynamicLibrary { - Token _installName; - uint32_t _currentVersion; - uint32_t _compatibilityVersion; - uint8_t _swiftVersion; - ld::File::ObjcConstraint _objcConstraint; - Options::Platform _platform; - std::vector _allowedClients; - std::vector _reexportedLibraries; - std::vector _symbols; - std::vector _classes; - std::vector _ivars; - std::vector _weakDefSymbols; - std::vector _tlvSymbols; - - DynamicLibrary() : _currentVersion(0x10000), _compatibilityVersion(0x10000), _swiftVersion(0), - _objcConstraint(ld::File::objcConstraintNone) {} -}; - -/// -/// A simple text-based dynamic library file parser. -/// -class TBDFile { - Tokenizer _tokenizer; - - Token peek() { return _tokenizer.peek(); } - Token next() { return _tokenizer.next(); } - - void expectToken(Token str) { - Token token = next(); - if (token != str) - throwf("unexpected token: %s", token.str().c_str()); - } - - bool hasOptionalToken(Token str) { - auto token = peek(); - if ( token == str ) { - next(); - return true; - } - return false; - } - - - void parseFlowSequence(std::function func) { - expectToken("["); - - while ( true ) { - auto token = peek(); - if ( token == "]" ) - break; - - token = next(); - func(token); - } - - expectToken("]"); - } - - void parseAllowedClients(DynamicLibrary& lib) { - if ( !hasOptionalToken("allowed-clients") ) - return; - parseFlowSequence([&](Token name) { - lib._allowedClients.emplace_back(name); - }); - } - - void parseReexportedDylibs(DynamicLibrary& lib) { - if ( !hasOptionalToken("re-exports") ) - return; - parseFlowSequence([&](Token name) { - lib._reexportedLibraries.emplace_back(name); - }); - } - - void parseSymbols(DynamicLibrary& lib) { - if ( hasOptionalToken("symbols") ) { - parseFlowSequence([&](Token name) { - lib._symbols.emplace_back(name); - }); - } - - if ( hasOptionalToken("objc-classes") ) { - parseFlowSequence([&](Token name) { - lib._classes.emplace_back(name); - }); - } - - if ( hasOptionalToken("objc-ivars") ) { - parseFlowSequence([&](Token name) { - lib._ivars.emplace_back(name); - }); - } - - if ( hasOptionalToken("weak-def-symbols") ) { - parseFlowSequence([&](Token name) { - lib._weakDefSymbols.emplace_back(name); - }); - } - - if ( hasOptionalToken("thread-local-symbols") ) { - parseFlowSequence([&](Token name) { - lib._tlvSymbols.emplace_back(name); - }); - } - } - - std::vector parseArchFlowSequence() { - std::vector availabledArchitectures; - expectToken("archs"); - parseFlowSequence([&](Token name) { - availabledArchitectures.emplace_back(name.str()); - }); - return availabledArchitectures; - } - - bool parseArchFlowSequence(std::string &selectedArchName) { - auto availabledArchitectures = parseArchFlowSequence(); - - for (const auto &archName : availabledArchitectures) { - if (archName == selectedArchName) - return true; - } - - return false; - } - - void parsePlatform(DynamicLibrary& lib) { - expectToken("platform"); - - auto token = next(); - if (token == "macosx") - lib._platform = Options::kPlatformOSX; - else if (token == "ios") - lib._platform = Options::kPlatformiOS; - else if (token == "watchos") - lib._platform = Options::kPlatformWatchOS; -#if SUPPORT_APPLE_TV - else if (token == "tvos") - lib._platform = Options::kPlatform_tvOS; -#endif - else - lib._platform = Options::kPlatformUnknown; - } - - void parseInstallName(DynamicLibrary& lib) { - expectToken("install-name"); - - lib._installName = next(); - if ( lib._installName.empty() ) - throwf("no install name specified"); - } - - uint32_t parseVersionNumber32(Token token) { - if ( token.size() >= 128 ) - throwf("malformed version number"); - - // Make a null-terminated string. - char buffer[128]; - ::memcpy(buffer, token.data(), token.size()); - buffer[token.size()] = '\0'; - - return Options::parseVersionNumber32(buffer); - } - - void parseCurrentVersion(DynamicLibrary& lib) { - if ( !hasOptionalToken("current-version") ) - return; - lib._currentVersion = parseVersionNumber32(next()); - } - - void parseCompatibilityVersion(DynamicLibrary& lib) { - if ( !hasOptionalToken("compatibility-version") ) - return; - lib._compatibilityVersion = parseVersionNumber32(next()); - } - - void parseSwiftVersion(DynamicLibrary& lib) { - if ( !hasOptionalToken("swift-version") ) - return; - auto token = next(); - if ( token == "1.0" ) - lib._swiftVersion = 1; - else if ( token == "1.1" ) - lib._swiftVersion = 2; - else if ( token == "2.0" ) - lib._swiftVersion = 3; - else - throwf("unsupported Swift ABI version: %s", token.str().c_str()); - } - - void parseObjCConstraint(DynamicLibrary& lib) { - if ( !hasOptionalToken("objc-constraint") ) - return; - auto token = next(); - if ( token == "none" ) - lib._objcConstraint = ld::File::objcConstraintNone; - else if ( token == "retain_release" ) - lib._objcConstraint = ld::File::objcConstraintRetainRelease; - else if ( token == "retain_release_for_simulator" ) - lib._objcConstraint = ld::File::objcConstraintRetainReleaseForSimulator; - else if ( token == "retain_release_or_gc" ) - lib._objcConstraint = ld::File::objcConstraintRetainReleaseOrGC; - else if ( token == "gc" ) - lib._objcConstraint = ld::File::objcConstraintGC; - else - throwf("unexpected token: %s", token.str().c_str()); - } - void parseExportsBlock(DynamicLibrary& lib, std::string &selectedArchName) { - if ( !hasOptionalToken("exports") ) - return; - - if ( !hasOptionalToken("-") ) - return; - - while ( true ) { - if ( !parseArchFlowSequence(selectedArchName) ) { - Token token; - while ( true ) { - token = peek(); - if ( token == "archs" || token == "..." || token.empty() ) - break; - next(); - } - if (token == "..." || token.empty() ) - break; - - continue; - } - - parseAllowedClients(lib); - parseReexportedDylibs(lib); - parseSymbols(lib); - if ( !hasOptionalToken("-") ) - break; - } - } - - std::vector getCompatibleArchList(std::string &requestedArchName) { - if (requestedArchName == "i386") - return {"i386"}; - else if (requestedArchName == "x86_64" || requestedArchName == "x86_64h") - return {"x86_64", "x86_64h"}; - else if (requestedArchName == "armv7" || requestedArchName == "armv7s") - return {"armv7", "armv7s"}; - else if (requestedArchName == "armv7k") - return {"armv7k"}; - else if (requestedArchName == "arm64") - return {"arm64"}; - else - return {}; - } - - std::string parseAndSelectArchitecture(std::string &requestedArchName) { - auto availabledArchitectures = parseArchFlowSequence(); - - // First try to find an exact match (cpu type and sub-cpu type). - if (std::find(availabledArchitectures.begin(), availabledArchitectures.end(), requestedArchName) - != availabledArchitectures.end()) - return requestedArchName; - - // If there is no exact match, then try to find an ABI compatible slice. - auto compatibleArchitectures = getCompatibleArchList(requestedArchName); - std::vector result; - std::sort(availabledArchitectures.begin(), availabledArchitectures.end()); - std::sort(compatibleArchitectures.begin(), compatibleArchitectures.end()); - std::set_intersection(availabledArchitectures.begin(), availabledArchitectures.end(), - compatibleArchitectures.begin(), compatibleArchitectures.end(), - std::back_inserter(result)); - - if (result.empty()) - return std::string(); - else - return result.front(); - } - - void parseDocument(DynamicLibrary& lib, std::string &requestedArchName) { - auto selectedArchName = parseAndSelectArchitecture(requestedArchName); - if (selectedArchName.empty()) - throwf("invalid arch"); - - parsePlatform(lib); - parseInstallName(lib); - parseCurrentVersion(lib); - parseCompatibilityVersion(lib); - parseSwiftVersion(lib); - parseObjCConstraint(lib); - parseExportsBlock(lib, selectedArchName); - } - -public: - TBDFile(const char* data, uint64_t size) : _tokenizer(data, size) {} - - DynamicLibrary parseFileForArch(std::string requestedArchName) { - _tokenizer.reset(); - DynamicLibrary lib; - expectToken("---"); - parseDocument(lib, requestedArchName); - expectToken("..."); - return lib; - } - - bool validForArch(std::string requestedArchName) { - _tokenizer.reset(); - auto token = next(); - if ( token != "---" ) - return false; - return !parseAndSelectArchitecture(requestedArchName).empty(); - } - - void dumpTokens() { - _tokenizer.reset(); - Token token; - do { - token = next(); - printf("token: %s\n", token.str().c_str()); - } while ( !token.empty() ); - } -}; - -} // end anonymous namespace namespace textstub { namespace dylib { @@ -515,51 +53,183 @@ class File final : public generic::dylib::File using Base = generic::dylib::File; public: - static bool validFile(const uint8_t* fileContent, bool executableOrDylib); - File(const uint8_t* fileContent, uint64_t fileLength, const char* path, + File(const char* path, const uint8_t* fileContent, uint64_t fileLength, const Options *opts, time_t mTime, ld::File::Ordinal ordinal, bool linkingFlatNamespace, - bool hoistImplicitPublicDylibs, Options::Platform platform, - cpu_type_t cpuType, const char* archName, uint32_t linkMinOSVersion, + bool linkingMainExecutable, bool hoistImplicitPublicDylibs, + const ld::VersionSet& platforms, bool allowWeakImports, + cpu_type_t cpuType, cpu_subtype_t cpuSubType, bool enforceDylibSubtypesMatch, bool allowSimToMacOSX, bool addVers, bool buildingForSimulator, - bool logAllFiles, const char* installPath, bool indirectDylib); + bool logAllFiles, const char* installPath, bool indirectDylib, + bool usingBitcode, bool internalSDK); + File(tapi::LinkerInterfaceFile* file, const char *path, const Options *opts, + time_t mTime, ld::File::Ordinal ordinal, bool linkingFlatNamespace, + bool linkingMainExecutable, bool hoistImplicitPublicDylibs, + const ld::VersionSet& platforms, bool allowWeakImports, + cpu_type_t cpuType, cpu_subtype_t cpuSubType, bool enforceDylibSubtypesMatch, + bool allowSimToMacOSX, bool addVers, bool buildingForSimulator, + bool logAllFiles, const char* installPath, bool indirectDylib, + bool usingBitcode, bool internalSDK); virtual ~File() noexcept {} + + // overrides of generic::dylib::File + virtual void processIndirectLibraries(ld::dylib::File::DylibHandler*, bool addImplicitDylibs) override final; private: - void buildExportHashTable(const DynamicLibrary &lib); - - cpu_type_t _cpuType; + void init(tapi::LinkerInterfaceFile* file, const Options *opts, bool buildingForSimulator, + bool indirectDylib, bool linkingFlatNamespace, bool linkingMainExecutable, + const char *path, const ld::VersionSet& platforms, const char *targetInstallPath, + bool usingBitcode, bool internalSDK); + void buildExportHashTable(const tapi::LinkerInterfaceFile* file); + static bool useSimulatorVariant(); + + const Options* _opts; + tapi::LinkerInterfaceFile* _interface; }; +template <> bool File::useSimulatorVariant() { return true; } +template <> bool File::useSimulatorVariant() { return true; } +template bool File::useSimulatorVariant() { return false; } + + +static ld::VersionSet mapPlatform(tapi::Platform platform, bool useSimulatorVariant) { + ld::VersionSet platforms; + switch (platform) { + case tapi::Platform::Unknown: + break; + case tapi::Platform::OSX: + platforms.insert(ld::Platform::macOS); + break; + case tapi::Platform::iOS: + if (useSimulatorVariant) + platforms.insert(ld::Platform::iOS_simulator); + else + platforms.insert(ld::Platform::iOS); + break; + case tapi::Platform::watchOS: + if (useSimulatorVariant) + platforms.insert(ld::Platform::watchOS_simulator); + else + platforms.insert(ld::Platform::watchOS); + break; + case tapi::Platform::tvOS: + if (useSimulatorVariant) + platforms.insert(ld::Platform::tvOS_simulator); + else + platforms.insert(ld::Platform::tvOS); + break; + #if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 2) || (TAPI_API_VERSION_MAJOR > 1)) + case tapi::Platform::bridgeOS: + platforms.insert(ld::Platform::bridgeOS); + break; + #endif + #if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 4) || (TAPI_API_VERSION_MAJOR > 1)) + case tapi::Platform::iOSMac: + platforms.insert(ld::Platform::iOSMac); + break; + case tapi::Platform::zippered: + platforms.insert(ld::Platform::macOS); + platforms.insert(ld::Platform::iOSMac); + break; + #endif + #if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 5) || (TAPI_API_VERSION_MAJOR > 1)) + case tapi::Platform::DriverKit: + platforms.insert(ld::Platform::driverKit); + break; + #endif + } + + return platforms; +} + template -File::File(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t mTime, - ld::File::Ordinal ord, bool linkingFlatNamespace, bool hoistImplicitPublicDylibs, - Options::Platform platform, cpu_type_t cpuType, const char* archName, - uint32_t linkMinOSVersion, bool allowSimToMacOSX, bool addVers, - bool buildingForSimulator, bool logAllFiles, const char* targetInstallPath, - bool indirectDylib) - : Base(strdup(path), mTime, ord, platform, linkMinOSVersion, linkingFlatNamespace, - hoistImplicitPublicDylibs, allowSimToMacOSX, addVers), - _cpuType(cpuType) +File::File(const char* path, const uint8_t* fileContent, uint64_t fileLength, const Options *opts, + time_t mTime, ld::File::Ordinal ord, bool linkingFlatNamespace, + bool linkingMainExecutable, bool hoistImplicitPublicDylibs, const ld::VersionSet& platforms, + bool allowWeakImports, cpu_type_t cpuType, cpu_subtype_t cpuSubType, + bool enforceDylibSubtypesMatch, bool allowSimToMacOSX, bool addVers, + bool buildingForSimulator, bool logAllFiles, const char* targetInstallPath, + bool indirectDylib, bool usingBitcode, bool internalSDK) +: Base(strdup(path), mTime, ord, platforms, allowWeakImports, linkingFlatNamespace, + hoistImplicitPublicDylibs, allowSimToMacOSX, addVers) { - this->_bitcode = std::unique_ptr(new ld::Bitcode(nullptr, 0)); - // Text stubs are implicit app extension safe. - this->_appExtensionSafe = true; + std::unique_ptr file; + std::string errorMessage; + __block uint32_t linkMinOSVersion = 0; + //FIXME handle this correctly once we have multi-platfrom TAPI + platforms.forEach(^(ld::Platform platform, uint32_t minVersion, uint32_t sdkVersion, bool &stop) { + if (linkMinOSVersion == 0) + linkMinOSVersion = minVersion; + if (platform == ld::Platform::macOS) + linkMinOSVersion = minVersion; + }); + +// Support $ld$weak symbols in .tbd files +#if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 3) || (TAPI_API_VERSION_MAJOR > 1)) + // Check if the library supports the new create API. + if (tapi::APIVersion::isAtLeast(1, 3)) { + tapi::ParsingFlags flags = tapi::ParsingFlags::None; + if (enforceDylibSubtypesMatch) + flags |= tapi::ParsingFlags::ExactCpuSubType; + + if (!allowWeakImports) + flags |= tapi::ParsingFlags::DisallowWeakImports; + + _interface = tapi::LinkerInterfaceFile::create( + path, cpuType, cpuSubType, flags, + tapi::PackedVersion32(linkMinOSVersion), errorMessage); + } else { + throwf("unsupported libtapi API version '%i.%i'", tapi::APIVersion::getMajor(), tapi::APIVersion::getMinor()); + } +#else + #error "unsupported libtapi API version" +#endif + + if (!_interface) + throw strdup(errorMessage.c_str()); + + // unmap file - it is no longer needed. + munmap((void *)fileContent, fileLength); // write out path for -t option if ( logAllFiles ) printf("%s\n", path); - TBDFile stub((const char*)fileContent, fileLength); - auto lib = stub.parseFileForArch(archName); + init(_interface, opts, buildingForSimulator, indirectDylib, linkingFlatNamespace, + linkingMainExecutable, path, platforms, targetInstallPath, usingBitcode, internalSDK); +} - this->_noRexports = lib._reexportedLibraries.empty(); - this->_hasWeakExports = !lib._weakDefSymbols.empty(); - this->_dylibInstallPath = strdup(lib._installName.str().c_str()); - this->_dylibCurrentVersion = lib._currentVersion; - this->_dylibCompatibilityVersion = lib._compatibilityVersion; - this->_swiftVersion = lib._swiftVersion; - this->_objcConstraint = lib._objcConstraint; - this->_hasPublicInstallName = this->isPublicLocation(this->_dylibInstallPath); + template + File::File(tapi::LinkerInterfaceFile* file, const char* path, const Options *opts, + time_t mTime, ld::File::Ordinal ordinal, bool linkingFlatNamespace, + bool linkingMainExecutable, bool hoistImplicitPublicDylibs, + const ld::VersionSet& platforms, bool allowWeakImports, + cpu_type_t cpuType, cpu_subtype_t cpuSubType, bool enforceDylibSubtypesMatch, + bool allowSimToMacOSX, bool addVers, bool buildingForSimulator, + bool logAllFiles, const char* installPath, bool indirectDylib, + bool usingBitcode, bool internalSDK) + : Base(strdup(path), mTime, ordinal, platforms, allowWeakImports, linkingFlatNamespace, + hoistImplicitPublicDylibs, allowSimToMacOSX, addVers), _interface(file) +{ + init(_interface, opts, buildingForSimulator, indirectDylib, linkingFlatNamespace, + linkingMainExecutable, path, platforms, installPath, usingBitcode, internalSDK); +} + +template +void File::init(tapi::LinkerInterfaceFile* file, const Options *opts, bool buildingForSimulator, + bool indirectDylib, bool linkingFlatNamespace, bool linkingMainExecutable, + const char *path, const ld::VersionSet& cmdLinePlatforms, const char *targetInstallPath, + bool usingBitcode, bool internalSDK) { + _opts = opts; + this->_bitcode = std::unique_ptr(new ld::Bitcode(nullptr, 0)); + this->_noRexports = !file->hasReexportedLibraries(); + this->_hasWeakExports = file->hasWeakDefinedExports(); + this->_dylibInstallPath = strdup(file->getInstallName().c_str()); + this->_installPathOverride = file->isInstallNameVersionSpecific(); + this->_dylibCurrentVersion = file->getCurrentVersion(); + this->_dylibCompatibilityVersion = file->getCompatibilityVersion(); + this->_swiftVersion = file->getSwiftVersion(); + this->_parentUmbrella = file->getParentFrameworkName().empty() ? nullptr : strdup(file->getParentFrameworkName().c_str()); + this->_appExtensionSafe = file->isApplicationExtensionSafe(); // if framework, capture framework name const char* lastSlash = strrchr(this->_dylibInstallPath, '/'); @@ -572,101 +242,77 @@ File::File(const uint8_t* fileContent, uint64_t fileLength, const char* path, if ( strstr(this->_dylibInstallPath, frname) != NULL ) this->_frameworkName = leafName; } - - // TEMPORARY HACK BEGIN: Support ancient re-export command LC_SUB_FRAMEWORK. - // [TAPI] Support LC_SUB_FRAMEWORK as re-export indicator. - auto installName = std::string(this->_dylibInstallPath); - - // All sub-frameworks of ApplicationServices use LC_SUB_FRAMEWORK. - if (installName.find("/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/") == 0 && - installName.find(".dylib") == std::string::npos) { - this->_parentUmbrella = "ApplicationServices"; - } else if (installName.find("/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/") == 0) { - this->_parentUmbrella = "Carbon"; - } else if (installName.find("/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/") == 0 && - installName.find(".dylib") == std::string::npos) { - this->_parentUmbrella = "CoreServices"; - } else if (installName.find("/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLinearAlgebra.dylib") == 0 || - installName.find("/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libQuadrature.dylib") == 0 || - installName.find("System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libSparseBLAS.dylib") == 0) { - this->_parentUmbrella = "vecLib"; - } else if (installName.find("/System/Library/Frameworks/WebKit.framework/Versions/A/Frameworks/WebCore.framework/Versions/A/WebCore") == 0) { - this->_parentUmbrella = "WebKit"; - } else if (installName.find("/usr/lib/system/") == 0 && - installName != "/usr/lib/system/libkxld.dylib") { - this->_parentUmbrella = "System"; - } - // TEMPORARY HACK END - - for (auto &client : lib._allowedClients) { - if ((this->_parentUmbrella != nullptr) && (client.str() != this->_parentUmbrella)) - this->_allowableClients.push_back(strdup(client.str().c_str())); - } - + + for (auto &client : file->allowableClients()) + this->_allowableClients.push_back(strdup(client.c_str())); + // [TAPI] Don't hoist "public" (in /usr/lib/) dylibs that should not be directly linked - if ( !this->_allowableClients.empty() ) - this->_hasPublicInstallName = false; + this->_hasPublicInstallName = file->hasAllowableClients() ? false : this->isPublicLocation(file->getInstallName().c_str()); + + for (const auto &client : file->allowableClients()) + this->_allowableClients.emplace_back(strdup(client.c_str())); - if ( (lib._platform != platform) && (platform != Options::kPlatformUnknown) ) { - this->_wrongOS = true; - if ( this->_addVersionLoadCommand && !indirectDylib ) { - if ( buildingForSimulator ) { - if ( !this->_allowSimToMacOSXLinking ) - throwf("building for %s simulator, but linking against dylib built for %s (%s).", - Options::platformName(platform), Options::platformName(lib._platform), path); - } else { - throwf("building for %s, but linking against dylib built for %s (%s).", - Options::platformName(platform), Options::platformName(lib._platform), path); - } - } + ld::VersionSet lcPlatforms; +#if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 6) || (TAPI_API_VERSION_MAJOR > 1)) + if (tapi::APIVersion::isAtLeast(1, 6)) { + for (const auto &platform : file->getPlatformSet()) + lcPlatforms.insert((ld::Platform)platform); + } else +#endif + { + lcPlatforms = mapPlatform(file->getPlatform(), useSimulatorVariant()); } + this->_platforms = lcPlatforms; - this->_dependentDylibs.reserve(lib._reexportedLibraries.size()); - for ( const auto& reexport : lib._reexportedLibraries ) { - const char *path = strdup(reexport.str().c_str()); + // check cross-linking + cmdLinePlatforms.checkDylibCrosslink(lcPlatforms, path, ".tbd", internalSDK, indirectDylib, usingBitcode); + + for (const auto& reexport : file->reexportedLibraries()) { + const char *path = strdup(reexport.c_str()); if ( (targetInstallPath == nullptr) || (strcmp(targetInstallPath, path) != 0) ) this->_dependentDylibs.emplace_back(path, true); } - + + for (const auto& symbol : file->ignoreExports()) + this->_ignoreExports.insert(strdup(symbol.c_str())); + + // if linking flat and this is a flat dylib, create one atom that references all imported symbols. + if ( linkingFlatNamespace && linkingMainExecutable && (file->hasTwoLevelNamespace() == false) ) { + std::vector importNames; + importNames.reserve(file->undefineds().size()); + // We do not need to strdup the name, because that will be done by the + // ImportAtom constructor. + for (const auto &sym : file->undefineds()) + importNames.emplace_back(sym.getName().c_str()); + this->_importAtom = new generic::dylib::ImportAtom(*this, importNames); + } + // build hash table - buildExportHashTable(lib); - - munmap((caddr_t)fileContent, fileLength); + buildExportHashTable(file); } template -void File::buildExportHashTable(const DynamicLibrary& lib) { +void File::buildExportHashTable(const tapi::LinkerInterfaceFile* file) { if (this->_s_logHashtable ) fprintf(stderr, "ld: building hashtable from text-stub info in %s\n", this->path()); - for (auto &sym : lib._symbols) - this->addSymbol(sym.str().c_str()); + for (const auto &sym : file->exports()) { + const char* name = sym.getName().c_str(); + bool weakDef = sym.isWeakDefined(); + bool tlv = sym.isThreadLocalValue(); -#if SUPPORT_ARCH_i386 - if (this->_platform == Options::kPlatformOSX && _cpuType == CPU_TYPE_I386) { - for (auto &sym : lib._classes) - this->addSymbol((".objc_class_name" + sym.str()).c_str()); - } else { - for (auto &sym : lib._classes) { - this->addSymbol(("_OBJC_CLASS_$" + sym.str()).c_str()); - this->addSymbol(("_OBJC_METACLASS_$" + sym.str()).c_str()); - } + typename Base::AtomAndWeak bucket = { nullptr, weakDef, tlv, 0 }; + if ( this->_s_logHashtable ) + fprintf(stderr, " adding %s to hash table for %s\n", name, this->path()); + this->_atoms[strdup(name)] = bucket; } -#else - for (auto &sym : lib._classes) { - this->addSymbol(("_OBJC_CLASS_$" + sym.str()).c_str()); - this->addSymbol(("_OBJC_METACLASS_$" + sym.str()).c_str()); - } -#endif +} - for (auto &sym : lib._ivars) - this->addSymbol(("_OBJC_IVAR_$" + sym.str()).c_str()); - - for (auto &sym : lib._weakDefSymbols) - this->addSymbol(sym.str().c_str(), /*weak=*/true); - - for (auto &sym : lib._tlvSymbols) - this->addSymbol(sym.str().c_str(), /*weak=*/false, /*tlv=*/true); +template +void File::processIndirectLibraries(ld::dylib::File::DylibHandler* handler, bool addImplicitDylibs) { + if (_interface) + _opts->addTAPIInterface(_interface, this->path()); + Base::processIndirectLibraries(handler, addImplicitDylibs); } template @@ -675,78 +321,163 @@ class Parser public: using P = typename A::P; - static bool validFile(const uint8_t* fileContent, uint64_t fileLength, - const std::string &path, const char* archName); - static ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength, const char* path, - time_t mTime, ld::File::Ordinal ordinal, const Options& opts, - bool indirectDylib) + static ld::dylib::File* parse(const char* path, const uint8_t* fileContent, + uint64_t fileLength, time_t mTime, + ld::File::Ordinal ordinal, const Options& opts, + bool indirectDylib, cpu_type_t architecture, cpu_subtype_t subArchitecture) { - return new File(fileContent, fileLength, path, mTime, ordinal, + return new File(path, fileContent, fileLength, &opts, mTime, ordinal, opts.flatNamespace(), + opts.linkingMainExecutable(), opts.implicitlyLinkIndirectPublicDylibs(), - opts.platform(), - opts.architecture(), - opts.architectureName(), - opts.minOSversion(), + opts.platforms(), + opts.allowWeakImports(), + architecture, + subArchitecture, + opts.enforceDylibSubtypesMatch(), opts.allowSimulatorToLinkWithMacOSX(), opts.addVersionLoadCommand(), opts.targetIOSSimulator(), opts.logAllFiles(), opts.installPath(), - indirectDylib); + indirectDylib, + opts.bundleBitcode(), + opts.internalSDK()); } + + static ld::dylib::File* parse(const char* path, tapi::LinkerInterfaceFile* file, time_t mTime, + ld::File::Ordinal ordinal, const Options& opts, + bool indirectDylib, cpu_type_t architecture, cpu_subtype_t subArchitecture) + { + return new File(file, path, &opts, mTime, ordinal, + opts.flatNamespace(), + opts.linkingMainExecutable(), + opts.implicitlyLinkIndirectPublicDylibs(), + opts.platforms(), + opts.allowWeakImports(), + architecture, + subArchitecture, + opts.enforceDylibSubtypesMatch(), + opts.allowSimulatorToLinkWithMacOSX(), + opts.addVersionLoadCommand(), + opts.targetIOSSimulator(), + opts.logAllFiles(), + opts.installPath(), + indirectDylib, + opts.bundleBitcode(), + opts.internalSDK()); + } + }; -template -bool Parser::validFile(const uint8_t* fileContent, uint64_t fileLength, const std::string &path, - const char* archName) + +static ld::dylib::File* parseAsArchitecture(const uint8_t* fileContent, uint64_t fileLength, const char* path, + time_t modTime, ld::File::Ordinal ordinal, const Options& opts, + bool bundleLoader, bool indirectDylib, + cpu_type_t architecture, cpu_subtype_t subArchitecture) { - if ( path.find(".tbd", path.size()-4) == std::string::npos ) - return false; - - TBDFile stub((const char*)fileContent, fileLength); - if ( !stub.validForArch(archName) ) - throwf("missing required architecture %s in file %s", archName, path.c_str()); - - return true; + switch ( architecture ) { +#if SUPPORT_ARCH_x86_64 + case CPU_TYPE_X86_64: + return Parser::parse(path, fileContent, fileLength, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); +#endif +#if SUPPORT_ARCH_i386 + case CPU_TYPE_I386: + return Parser::parse(path, fileContent, fileLength, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); +#endif +#if SUPPORT_ARCH_arm_any + case CPU_TYPE_ARM: + return Parser::parse(path, fileContent, fileLength, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); +#endif +#if SUPPORT_ARCH_arm64 + case CPU_TYPE_ARM64: + return Parser::parse(path, fileContent, fileLength, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); +#endif +#if SUPPORT_ARCH_arm64_32 + case CPU_TYPE_ARM64_32: + return Parser::parse(path, fileContent, fileLength, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); +#endif + default: + throwf("unsupported architecture for tbd file"); + } + assert(0 && "function should return valid pointer or throw"); } + +static ld::dylib::File *parseAsArchitecture(const char *path, tapi::LinkerInterfaceFile* file, time_t modTime, + ld::File::Ordinal ordinal, const Options& opts, bool indirectDylib, + cpu_type_t architecture, cpu_subtype_t subArchitecture) +{ + switch ( architecture ) { +#if SUPPORT_ARCH_x86_64 + case CPU_TYPE_X86_64: + return Parser::parse(path, file, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); +#endif +#if SUPPORT_ARCH_i386 + case CPU_TYPE_I386: + return Parser::parse(path, file, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); +#endif +#if SUPPORT_ARCH_arm_any + case CPU_TYPE_ARM: + return Parser::parse(path, file, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); +#endif +#if SUPPORT_ARCH_arm64 + case CPU_TYPE_ARM64: + return Parser::parse(path, file, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); +#endif +#if SUPPORT_ARCH_arm64_32 + case CPU_TYPE_ARM64_32: + return Parser::parse(path, file, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); +#endif + default: + throwf("unsupported architecture for tbd file"); + } + assert(0 && "function should return valid pointer or throw"); +} + + // // main function used by linker to instantiate ld::Files // ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength, const char* path, - time_t modTime, const Options& opts, ld::File::Ordinal ordinal, + time_t modtime, const Options& opts, ld::File::Ordinal ordinal, bool bundleLoader, bool indirectDylib) { - switch ( opts.architecture() ) { -#if SUPPORT_ARCH_x86_64 - case CPU_TYPE_X86_64: - if ( Parser::validFile(fileContent, fileLength, path, opts.architectureName()) ) - return Parser::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib); - break; -#endif -#if SUPPORT_ARCH_i386 - case CPU_TYPE_I386: - if ( Parser::validFile(fileContent, fileLength, path, opts.architectureName()) ) - return Parser::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib); - break; -#endif -#if SUPPORT_ARCH_arm_any - case CPU_TYPE_ARM: - if ( Parser::validFile(fileContent, fileLength, path, opts.architectureName()) ) - return Parser::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib); - break; -#endif -#if SUPPORT_ARCH_arm64 - case CPU_TYPE_ARM64: - if ( Parser::validFile(fileContent, fileLength, path, opts.architectureName()) ) - return Parser::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib); - break; -#endif + if (!tapi::LinkerInterfaceFile::isSupported(path, fileContent, fileLength)) + return nullptr; + + try { + return parseAsArchitecture(fileContent, fileLength, path, modtime, ordinal, opts, bundleLoader, indirectDylib, opts.architecture(), opts.subArchitecture()); + } catch (...) { + if (!opts.fallbackArchitecture()) + throw; } - return nullptr; + + warning("architecture %s not present in TBD %s, attempting fallback", opts.architectureName(), path); + return parseAsArchitecture(fileContent, fileLength, path, modtime, ordinal, opts, bundleLoader, indirectDylib, opts.fallbackArchitecture(), opts.fallbackSubArchitecture()); } - - + +ld::dylib::File *parse(const char *path, tapi::LinkerInterfaceFile* file, time_t modTime, + ld::File::Ordinal ordinal, const Options& opts, bool indirectDylib) { + try { + return parseAsArchitecture(path, file, modTime, ordinal, opts, indirectDylib, opts.architecture(), opts.subArchitecture()); + } catch (...) { + if (!opts.fallbackArchitecture()) + throw; + } + + warning("architecture %s not present in TBD %s, attempting fallback", opts.architectureName(), path); + return parseAsArchitecture(path, file, modTime, ordinal, opts, indirectDylib, opts.fallbackArchitecture(), opts.fallbackSubArchitecture()); +} + + +bool isTextStubFile(const uint8_t* fileContent, uint64_t fileLength, const char* path) { + return tapi::LinkerInterfaceFile::isSupported(path, fileContent, fileLength); +} + + + } // namespace dylib } // namespace textstub + +#endif /* TAPI_SUPPORT */ diff --git a/cctools/ld64/src/ld/parsers/textstub_dylib_file.hpp b/cctools/ld64/src/ld/parsers/textstub_dylib_file.hpp index e0a75f6..287b034 100644 --- a/cctools/ld64/src/ld/parsers/textstub_dylib_file.hpp +++ b/cctools/ld64/src/ld/parsers/textstub_dylib_file.hpp @@ -25,6 +25,8 @@ #ifndef __TEXTSTUB_DYLIB_FILE_H__ #define __TEXTSTUB_DYLIB_FILE_H__ +#ifdef TAPI_SUPPORT + #include "ld.hpp" #include "Options.h" @@ -36,8 +38,14 @@ extern ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength, c time_t modTime, const Options& opts, ld::File::Ordinal ordinal, bool bundleLoader, bool indirectDylib); +extern ld::dylib::File *parse(const char *path, tapi::LinkerInterfaceFile* file, time_t modTime, + ld::File::Ordinal ordinal, const Options& opts, bool indirectDylib); + +extern bool isTextStubFile(const uint8_t* fileContent, uint64_t fileLength, const char* path); + } // namespace dylib } // namespace textstub +#endif /* TAPI_SUPPORT */ #endif // __TEXTSTUB_DYLIB_FILE_H__ diff --git a/cctools/ld64/src/ld/passes/Makefile.am b/cctools/ld64/src/ld/passes/Makefile.am index 7f4e43e..b261381 100644 --- a/cctools/ld64/src/ld/passes/Makefile.am +++ b/cctools/ld64/src/ld/passes/Makefile.am @@ -40,5 +40,7 @@ libPasses_la_SOURCES = \ tlvp.cpp \ stubs/stubs.cpp \ bitcode_bundle.cpp \ - code_dedup.cpp + code_dedup.cpp \ + thread_starts.cpp \ + inits.cpp diff --git a/cctools/ld64/src/ld/passes/Makefile.in b/cctools/ld64/src/ld/passes/Makefile.in new file mode 100644 index 0000000..a50a113 --- /dev/null +++ b/cctools/ld64/src/ld/passes/Makefile.in @@ -0,0 +1,713 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = ld64/src/ld/passes +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libPasses_la_LIBADD = +am__dirstamp = $(am__leading_dot)dirstamp +am_libPasses_la_OBJECTS = libPasses_la-branch_island.lo \ + libPasses_la-branch_shim.lo libPasses_la-compact_unwind.lo \ + libPasses_la-dtrace_dof.lo libPasses_la-dylibs.lo \ + libPasses_la-got.lo libPasses_la-huge.lo libPasses_la-objc.lo \ + libPasses_la-order.lo libPasses_la-tlvp.lo \ + stubs/libPasses_la-stubs.lo libPasses_la-bitcode_bundle.lo \ + libPasses_la-code_dedup.lo libPasses_la-thread_starts.lo \ + libPasses_la-inits.lo +libPasses_la_OBJECTS = $(am_libPasses_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libPasses_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libPasses_la_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(libPasses_la_SOURCES) +DIST_SOURCES = $(libPasses_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libPasses.la +noinst_HEADERS = \ + branch_island.h \ + branch_shim.h \ + compact_unwind.h \ + dtrace_dof.h \ + dylibs.h \ + got.h \ + huge.h \ + objc.h \ + order.h \ + tlvp.h \ + bitcode_bundle.h \ + code_dedup.h + +libPasses_la_CXXFLAGS = \ + -D__DARWIN_UNIX03 \ + $(WARNINGS) \ + $(LTO_DEF) \ + $(ENDIAN_FLAG) \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/include/foreign \ + -I$(top_srcdir)/ld64/src/abstraction \ + -I$(top_srcdir)/ld64/src/ld \ + -I$(top_srcdir)/ld64/src/ld/parsers \ + -I$(top_srcdir)/ld64/src/3rd \ + -I$(top_srcdir)/ld64/src + +libPasses_la_SOURCES = \ + branch_island.cpp \ + branch_shim.cpp \ + compact_unwind.cpp \ + dtrace_dof.cpp \ + dylibs.cpp \ + got.cpp \ + huge.cpp \ + objc.cpp \ + order.cpp \ + tlvp.cpp \ + stubs/stubs.cpp \ + bitcode_bundle.cpp \ + code_dedup.cpp \ + thread_starts.cpp \ + inits.cpp + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps ld64/src/ld/passes/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps ld64/src/ld/passes/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +stubs/$(am__dirstamp): + @$(MKDIR_P) stubs + @: > stubs/$(am__dirstamp) +stubs/libPasses_la-stubs.lo: stubs/$(am__dirstamp) + +libPasses.la: $(libPasses_la_OBJECTS) $(libPasses_la_DEPENDENCIES) $(EXTRA_libPasses_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libPasses_la_LINK) $(libPasses_la_OBJECTS) $(libPasses_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f stubs/*.$(OBJEXT) + -rm -f stubs/*.lo + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + $(AM_V_CXX)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(AM_V_CXX)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: + $(AM_V_CXX)$(LTCXXCOMPILE) -c -o $@ $< + +libPasses_la-branch_island.lo: branch_island.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPasses_la_CXXFLAGS) $(CXXFLAGS) -c -o libPasses_la-branch_island.lo `test -f 'branch_island.cpp' || echo '$(srcdir)/'`branch_island.cpp + +libPasses_la-branch_shim.lo: branch_shim.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPasses_la_CXXFLAGS) $(CXXFLAGS) -c -o libPasses_la-branch_shim.lo `test -f 'branch_shim.cpp' || echo '$(srcdir)/'`branch_shim.cpp + +libPasses_la-compact_unwind.lo: compact_unwind.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPasses_la_CXXFLAGS) $(CXXFLAGS) -c -o libPasses_la-compact_unwind.lo `test -f 'compact_unwind.cpp' || echo '$(srcdir)/'`compact_unwind.cpp + +libPasses_la-dtrace_dof.lo: dtrace_dof.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPasses_la_CXXFLAGS) $(CXXFLAGS) -c -o libPasses_la-dtrace_dof.lo `test -f 'dtrace_dof.cpp' || echo '$(srcdir)/'`dtrace_dof.cpp + +libPasses_la-dylibs.lo: dylibs.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPasses_la_CXXFLAGS) $(CXXFLAGS) -c -o libPasses_la-dylibs.lo `test -f 'dylibs.cpp' || echo '$(srcdir)/'`dylibs.cpp + +libPasses_la-got.lo: got.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPasses_la_CXXFLAGS) $(CXXFLAGS) -c -o libPasses_la-got.lo `test -f 'got.cpp' || echo '$(srcdir)/'`got.cpp + +libPasses_la-huge.lo: huge.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPasses_la_CXXFLAGS) $(CXXFLAGS) -c -o libPasses_la-huge.lo `test -f 'huge.cpp' || echo '$(srcdir)/'`huge.cpp + +libPasses_la-objc.lo: objc.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPasses_la_CXXFLAGS) $(CXXFLAGS) -c -o libPasses_la-objc.lo `test -f 'objc.cpp' || echo '$(srcdir)/'`objc.cpp + +libPasses_la-order.lo: order.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPasses_la_CXXFLAGS) $(CXXFLAGS) -c -o libPasses_la-order.lo `test -f 'order.cpp' || echo '$(srcdir)/'`order.cpp + +libPasses_la-tlvp.lo: tlvp.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPasses_la_CXXFLAGS) $(CXXFLAGS) -c -o libPasses_la-tlvp.lo `test -f 'tlvp.cpp' || echo '$(srcdir)/'`tlvp.cpp + +stubs/libPasses_la-stubs.lo: stubs/stubs.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPasses_la_CXXFLAGS) $(CXXFLAGS) -c -o stubs/libPasses_la-stubs.lo `test -f 'stubs/stubs.cpp' || echo '$(srcdir)/'`stubs/stubs.cpp + +libPasses_la-bitcode_bundle.lo: bitcode_bundle.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPasses_la_CXXFLAGS) $(CXXFLAGS) -c -o libPasses_la-bitcode_bundle.lo `test -f 'bitcode_bundle.cpp' || echo '$(srcdir)/'`bitcode_bundle.cpp + +libPasses_la-code_dedup.lo: code_dedup.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPasses_la_CXXFLAGS) $(CXXFLAGS) -c -o libPasses_la-code_dedup.lo `test -f 'code_dedup.cpp' || echo '$(srcdir)/'`code_dedup.cpp + +libPasses_la-thread_starts.lo: thread_starts.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPasses_la_CXXFLAGS) $(CXXFLAGS) -c -o libPasses_la-thread_starts.lo `test -f 'thread_starts.cpp' || echo '$(srcdir)/'`thread_starts.cpp + +libPasses_la-inits.lo: inits.cpp + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPasses_la_CXXFLAGS) $(CXXFLAGS) -c -o libPasses_la-inits.lo `test -f 'inits.cpp' || echo '$(srcdir)/'`inits.cpp + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm -rf stubs/.libs stubs/_libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f stubs/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/ld64/src/ld/passes/bitcode_bundle.cpp b/cctools/ld64/src/ld/passes/bitcode_bundle.cpp index d4d7509..c7e153a 100644 --- a/cctools/ld64/src/ld/passes/bitcode_bundle.cpp +++ b/cctools/ld64/src/ld/passes/bitcode_bundle.cpp @@ -227,6 +227,25 @@ private: ld::Internal& _state; }; +#if LTO_API_VERSION >= 7 +static void ltoDiagnosticHandler(lto_codegen_diagnostic_severity_t severity, const char* message, void*) +{ + switch ( severity ) { +#if LTO_API_VERSION >= 10 + case LTO_DS_REMARK: +#endif + case LTO_DS_NOTE: + break; // ignore remarks and notes + case LTO_DS_WARNING: + warning("%s", message); + break; + case LTO_DS_ERROR: + throwf("%s", message); + } +} +#endif + + BitcodeAtom::BitcodeAtom() : ld::Atom(bitcodeBundleSection, ld::Atom::definitionRegular, ld::Atom::combineNever, @@ -294,6 +313,11 @@ BitcodeObfuscator::BitcodeObfuscator() _lto_get_asm_symbol_num == NULL || _lto_get_asm_symbol_name == NULL || ::lto_api_version() < 14 ) throwf("loaded libLTO doesn't support -bitcode_hide_symbols: %s", ::lto_get_version()); _obfuscator = ::lto_codegen_create_in_local_context(); + +#if LTO_API_VERSION >= 7 + lto_codegen_set_diagnostic_handler(_obfuscator, ltoDiagnosticHandler, NULL); +#endif + #if LTO_API_VERSION >= 14 lto_codegen_set_should_internalize(_obfuscator, false); #endif @@ -464,6 +488,7 @@ void BundleHandler::copyXARProp(xar_file_t src, xar_file_t dst) strcmp(key, "hide-symbols") == 0 || strcmp(key, "platform") == 0 || strcmp(key, "sdkversion") == 0 || + strcmp(key, "swift-version") == 0 || strcmp(key, "dylibs/lib") == 0 || strcmp(key, "link-options/option") == 0 ) { xar_prop_create(dst, key, val); @@ -666,10 +691,25 @@ void BitcodeBundle::doPass() bh->populateMustPreserveSymbols(obfuscator); handlerMap.emplace(std::string(f->path()), bh); } else if ( ld::LLVMBitcode* bitcode = dynamic_cast(f->getBitcode()) ) { - BitcodeHandler* bitcodeHandler = new BitcodeHandler((char*)bitcode->getContent(), bitcode->getSize()); - bitcodeHandler->populateMustPreserveSymbols(obfuscator); + BitcodeHandler bitcodeHandler((char*)bitcode->getContent(), bitcode->getSize()); + bitcodeHandler.populateMustPreserveSymbols(obfuscator); } } + // add must preserve symbols from lto input. + for ( auto &f : _state.ltoBitcodePath ) { + BitcodeTempFile ltoTemp(f.c_str(), false); // Keep the temp file because it needs to be read in later in the pass. + BitcodeHandler bitcodeHandler((char*)ltoTemp.getContent(), ltoTemp.getSize()); + bitcodeHandler.populateMustPreserveSymbols(obfuscator); + } + // add must preserve symbols from compiler_rt input. + for ( auto &f : _state.filesFromCompilerRT ) { + std::vector symbols; + if ( f->fileContent() && mach_o::relocatable::getNonLocalSymbols(f->fileContent(), symbols) ) { + for ( auto &sym : symbols) + obfuscator->addMustPreserveSymbols(sym); + } + } + // special symbols supplied by linker obfuscator->addMustPreserveSymbols("___dso_handle"); obfuscator->addMustPreserveSymbols("__mh_execute_header"); @@ -771,26 +811,30 @@ void BitcodeBundle::doPass() } } - // Write merged LTO bitcode + // Write merged LTO bitcode files if ( !_state.ltoBitcodePath.empty() ) { - xar_file_t ltoFile = NULL; - BitcodeTempFile* ltoTemp = new BitcodeTempFile(_state.ltoBitcodePath.c_str(), !_options.saveTempFiles()); - if ( _options.hideSymbols() ) { + int count = 0; + for (auto &path : _state.ltoBitcodePath) { + std::string xar_name = "lto.o." + std::to_string(count++); + xar_file_t ltoFile = NULL; + BitcodeTempFile* ltoTemp = new BitcodeTempFile(path.c_str(), !_options.saveTempFiles()); + if ( _options.hideSymbols() ) { ld::Bitcode ltoBitcode(ltoTemp->getContent(), ltoTemp->getSize()); char ltoTempFile[PATH_MAX]; sprintf(ltoTempFile, "%s/lto.bc", tempdir); - obfuscator->bitcodeHideSymbols(<oBitcode, _state.ltoBitcodePath.c_str(), ltoTempFile); + obfuscator->bitcodeHideSymbols(<oBitcode, path.c_str(), ltoTempFile); BitcodeTempFile* ltoStrip = new BitcodeTempFile(ltoTempFile, !_options.saveTempFiles()); - ltoFile = xar_add_frombuffer(x, NULL, "lto.o", (char*)ltoStrip->getContent(), ltoStrip->getSize()); + ltoFile = xar_add_frombuffer(x, NULL, xar_name.c_str(), (char*)ltoStrip->getContent(), ltoStrip->getSize()); delete ltoStrip; - } else { - ltoFile = xar_add_frombuffer(x, NULL, "lto.o", (char*)ltoTemp->getContent(), ltoTemp->getSize()); + } else { + ltoFile = xar_add_frombuffer(x, NULL, xar_name.c_str(), (char*)ltoTemp->getContent(), ltoTemp->getSize()); + } + if ( ltoFile == NULL ) + throwf("could not add lto file %s to bitcode bundle", path.c_str()); + if ( xar_prop_set(ltoFile, "file-type", "LTO") != 0 ) + throwf("could not set bitcode property for %s in bitcode bundle", path.c_str()); + delete ltoTemp; } - if ( ltoFile == NULL ) - throwf("could not add lto file %s to bitcode bundle", _state.ltoBitcodePath.c_str()); - if ( xar_prop_set(ltoFile, "file-type", "LTO") != 0 ) - throwf("could not set bitcode property for %s in bitcode bundle", _state.ltoBitcodePath.c_str()); - delete ltoTemp; } // Common LinkOptions @@ -951,11 +995,19 @@ void BitcodeBundle::doPass() // Write SDK version if ( _options.sdkPaths().size() > 1 ) throwf("only one -syslibroot is accepted for bitcode bundle"); - if ( xar_prop_create((xar_file_t)linkXML, "platform", _options.getPlatformStr().c_str()) != 0 ) + if ( xar_prop_create((xar_file_t)linkXML, "platform", _options.platforms().to_str().c_str()) != 0 ) throwf("could not add platform name to bitcode bundle"); if ( xar_prop_create((xar_file_t)linkXML, "sdkversion", _options.getSDKVersionStr().c_str()) != 0 ) throwf("could not add SDK version to bitcode bundle"); + // Write swift version into header + if (_state.swiftVersion != 0) { + char swiftVersion[64]; + Options::userReadableSwiftVersion(_state.swiftVersion, swiftVersion); + if ( xar_prop_create((xar_file_t)linkXML, "swift-version", swiftVersion) ) + throwf("could not add swift version to bitcode bundle"); + } + // Write dylibs char sdkRoot[PATH_MAX]; if ( _options.sdkPaths().empty() || (realpath(_options.sdkPaths().front(), sdkRoot) == NULL) ) @@ -991,6 +1043,12 @@ void BitcodeBundle::doPass() } } + // Write if compiler_rt is force loaded + if (_state.forceLoadCompilerRT) { + if ( xar_prop_create((xar_file_t)linkXML, "rt-forceload", "1") != 0 ) + throwf("could not add compiler_rt force_load info to bitcode bundle"); + } + // Write link-line into archive for ( auto &it : linkCmd ) { if (xar_prop_create((xar_file_t)linkXML, "link-options/option", it.c_str()) != 0) diff --git a/cctools/ld64/src/ld/passes/branch_shim.cpp b/cctools/ld64/src/ld/passes/branch_shim.cpp index 7be33d2..d5f81eb 100644 --- a/cctools/ld64/src/ld/passes/branch_shim.cpp +++ b/cctools/ld64/src/ld/passes/branch_shim.cpp @@ -348,7 +348,7 @@ void doPass(const Options& opts, ld::Internal& state) break; fixUpLocation += fit->offsetInAtom; uint32_t instruction = *((uint32_t*)fixUpLocation); - bool is_b = ((instruction & 0x0F000000) == 0x0A000000) && ((instruction & 0xF0000000) != 0xF0000000); + bool is_b = ((instruction & 0x0E000000) == 0x0A000000) && ((instruction & 0xF0000000) != 0xF0000000); // need shim for branch from arm to thumb, or for call to function outside kext if ( is_b || (targetIsProxy && makingKextBundle) ) { if ( _s_log ) fprintf(stderr, "need to add arm->thumb instr=0x%08X shim to %s for %s\n", instruction, target->name(), atom->name()); diff --git a/cctools/ld64/src/ld/passes/code_dedup.cpp b/cctools/ld64/src/ld/passes/code_dedup.cpp index e067acf..af761c1 100644 --- a/cctools/ld64/src/ld/passes/code_dedup.cpp +++ b/cctools/ld64/src/ld/passes/code_dedup.cpp @@ -49,7 +49,7 @@ public: DeDupAliasAtom(const ld::Atom* dupOf, const ld::Atom* replacement) : ld::Atom(dupOf->section(), ld::Atom::definitionRegular, ld::Atom::combineNever, dupOf->scope(), dupOf->contentType(), ld::Atom::symbolTableIn, - false, false, true, 0), + false, false, true, replacement->alignment()), _dedupOf(dupOf), _fixup(0, ld::Fixup::k1of1, ld::Fixup::kindNoneFollowOn, ld::Fixup::bindingDirectlyBound, replacement) { if ( dupOf->autoHide() ) @@ -142,12 +142,21 @@ struct atom_hashing { // A helper for std::unordered_map<> that compares functions struct atom_equal { - struct VisitedSet { - std::unordered_set atoms1; - std::unordered_set atoms2; + struct BackChain { + BackChain* prev; + const Atom* inCallChain1; + const Atom* inCallChain2; + + bool inCallChain(const Atom* target) { + for (BackChain* p = this; p->prev != NULL; p = p->prev) { + if ( (p->inCallChain1 == target) || (p->inCallChain2 == target) ) + return true; + } + return false; + } }; - static bool sameFixups(const ld::Atom* atom1, const ld::Atom* atom2, VisitedSet& visited) { + static bool sameFixups(const ld::Atom* atom1, const ld::Atom* atom2, BackChain& backChain) { ++sFixupCompareCount; //fprintf(stderr, "sameFixups(%s,%s)\n", atom1->name(), atom2->name()); Fixup::iterator f1 = atom1->fixupsBegin(); @@ -198,10 +207,16 @@ struct atom_equal { return false; if ( target1->section().type() != ld::Section::typeCode ) return false; - // to support co-recursive functions, don't call equals() on targets we've already visited - if ( ((visited.atoms1.count(target1) == 0) || (visited.atoms2.count(target2) == 0)) && !equal(target1, target2, visited) ) - return false; - } + // to support co-recursive functions, don't recurse into equals() for targets already in the back chain + if ( !backChain.inCallChain(target1) || !backChain.inCallChain(target2) ) { + BackChain nextBackChain; + nextBackChain.prev = &backChain; + nextBackChain.inCallChain1 = target1; + nextBackChain.inCallChain2 = target2; + if ( !equal(target1, target2, nextBackChain) ) + return false; + } + } ++f1; ++f2; @@ -210,17 +225,21 @@ struct atom_equal { return true; } - static bool equal(const ld::Atom* atom1, const ld::Atom* atom2, VisitedSet& visited) { + static bool equal(const ld::Atom* atom1, const ld::Atom* atom2, BackChain& backChain) { + if ( atom1->size() != atom2->size() ) + return false; if ( atom_hashing::hash(atom1) != atom_hashing::hash(atom2) ) return false; - visited.atoms1.insert(atom1); - visited.atoms2.insert(atom2); - return sameFixups(atom1, atom2, visited); + if ( memcmp(atom1->rawContentPointer(), atom2->rawContentPointer(), atom1->size()) != 0 ) + return false; + bool result = sameFixups(atom1, atom2, backChain); + //fprintf(stderr, "sameFixups(%s,%s) = %d\n", atom1->name(), atom2->name(), result); + return result; } bool operator()(const ld::Atom* atom1, const ld::Atom* atom2) const { - VisitedSet visited; - return equal(atom1, atom2, visited); + BackChain backChain = { NULL, atom1, atom2 }; + return equal(atom1, atom2, backChain); } }; @@ -309,6 +328,7 @@ void doPass(const Options& opts, ld::Internal& state) textAtoms.insert(pos, aliasAtom); state.atomToSection[aliasAtom] = textSection; replacementMap[dupAtom] = aliasAtom; + (const_cast(dupAtom))->setCoalescedAway(); } } } @@ -348,7 +368,7 @@ void doPass(const Options& opts, ld::Internal& state) if ( log ) { fprintf(stderr, "atoms before pruning:\n"); for (const ld::Atom* atom : textSection->atoms) - fprintf(stderr, " %p (size=%llu) %sp\n", atom, atom->size(), atom->name()); + fprintf(stderr, " %p (size=%llu) %s\n", atom, atom->size(), atom->name()); } // remove replaced atoms from section textSection->atoms.erase(std::remove_if(textSection->atoms.begin(), textSection->atoms.end(), @@ -363,7 +383,7 @@ void doPass(const Options& opts, ld::Internal& state) if ( log ) { fprintf(stderr, "atoms after pruning:\n"); for (const ld::Atom* atom : textSection->atoms) - fprintf(stderr, " %p (size=%llu) %sp\n", atom, atom->size(), atom->name()); + fprintf(stderr, " %p (size=%llu) %s\n", atom, atom->size(), atom->name()); } //fprintf(stderr, "hash-count=%lu, fixup-compares=%lu, atom-count=%u\n", sHashCount, sFixupCompareCount, atomsBeingComparedCount); diff --git a/cctools/ld64/src/ld/passes/compact_unwind.cpp b/cctools/ld64/src/ld/passes/compact_unwind.cpp index d2847bb..cacfb87 100644 --- a/cctools/ld64/src/ld/passes/compact_unwind.cpp +++ b/cctools/ld64/src/ld/passes/compact_unwind.cpp @@ -87,7 +87,8 @@ private: typedef macho_unwind_info_compressed_second_level_page_header

CSLP; bool encodingMeansUseDwarf(compact_unwind_encoding_t enc); - void compressDuplicates(const std::vector& entries, + bool encodingCannotBeMerged(compact_unwind_encoding_t enc); + void compressDuplicates(const std::vector& entries, std::vector& uniqueEntries); void makePersonalityIndexes(std::vector& entries, std::map& personalityIndexMap); @@ -303,6 +304,7 @@ bool UnwindInfoAtom::encodingMeansUseDwarf(compact_unwind_encoding_t enc) return ((enc & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF); } + template <> bool UnwindInfoAtom::encodingMeansUseDwarf(compact_unwind_encoding_t enc) { @@ -310,6 +312,27 @@ bool UnwindInfoAtom::encodingMeansUseDwarf(compact_unwind_encoding_t enc) } + + +template <> +bool UnwindInfoAtom::encodingCannotBeMerged(compact_unwind_encoding_t enc) +{ + return ((enc & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_STACK_IND); +} + +template <> +bool UnwindInfoAtom::encodingCannotBeMerged(compact_unwind_encoding_t enc) +{ + return ((enc & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_STACK_IND); +} + +template +bool UnwindInfoAtom::encodingCannotBeMerged(compact_unwind_encoding_t enc) +{ + return false; +} + + template void UnwindInfoAtom::compressDuplicates(const std::vector& entries, std::vector& uniqueEntries) { @@ -319,9 +342,10 @@ void UnwindInfoAtom::compressDuplicates(const std::vector& entri for(std::vector::const_iterator it=entries.begin(); it != entries.end(); ++it) { const UnwindEntry& next = *it; bool newNeedsDwarf = encodingMeansUseDwarf(next.encoding); + bool cannotBeMerged = encodingCannotBeMerged(next.encoding); // remove entries which have same encoding and personalityPointer as last one if ( newNeedsDwarf || (next.encoding != last.encoding) || (next.personalityPointer != last.personalityPointer) - || (next.lsda != NULL) || (last.lsda != NULL) ) { + || cannotBeMerged || (next.lsda != NULL) || (last.lsda != NULL) ) { uniqueEntries.push_back(next); } last = next; @@ -424,6 +448,7 @@ void UnwindInfoAtom::addCompressedAddressOffsetFixup(uint32_t offset, con _fixups.push_back(ld::Fixup(offset, ld::Fixup::k3of3, ld::Fixup::kindStoreLittleEndianLow24of32)); } + template <> void UnwindInfoAtom::addCompressedAddressOffsetFixup(uint32_t offset, const ld::Atom* func, const ld::Atom* fromFunc) { @@ -461,6 +486,7 @@ void UnwindInfoAtom::addCompressedEncodingFixup(uint32_t offset, const ld _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndianLow24of32)); } + template <> void UnwindInfoAtom::addCompressedEncodingFixup(uint32_t offset, const ld::Atom* fde) { @@ -489,6 +515,7 @@ void UnwindInfoAtom::addRegularAddressFixup(uint32_t offset, const ld::At _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32)); } + template <> void UnwindInfoAtom::addRegularAddressFixup(uint32_t offset, const ld::Atom* func) { @@ -517,6 +544,7 @@ void UnwindInfoAtom::addRegularFDEOffsetFixup(uint32_t offset, const ld:: _fixups.push_back(ld::Fixup(offset+4, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndianLow24of32)); } + template <> void UnwindInfoAtom::addRegularFDEOffsetFixup(uint32_t offset, const ld::Atom* fde) { @@ -545,6 +573,7 @@ void UnwindInfoAtom::addImageOffsetFixup(uint32_t offset, const ld::Atom* _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32)); } + template <> void UnwindInfoAtom::addImageOffsetFixup(uint32_t offset, const ld::Atom* targ) { @@ -576,6 +605,7 @@ void UnwindInfoAtom::addImageOffsetFixupPlusAddend(uint32_t offset, const _fixups.push_back(ld::Fixup(offset, ld::Fixup::k3of3, ld::Fixup::kindStoreLittleEndian32)); } + template <> void UnwindInfoAtom::addImageOffsetFixupPlusAddend(uint32_t offset, const ld::Atom* targ, uint32_t addend) { diff --git a/cctools/ld64/src/ld/passes/dylibs.cpp b/cctools/ld64/src/ld/passes/dylibs.cpp index f77f5cd..7edc85c 100644 --- a/cctools/ld64/src/ld/passes/dylibs.cpp +++ b/cctools/ld64/src/ld/passes/dylibs.cpp @@ -94,9 +94,11 @@ void doPass(const Options& opts, ld::Internal& state) targetIsWeakImport = fit->weakImport; break; default: - break; + break; } if ( (target != NULL) && (target->definition() == ld::Atom::definitionProxy) ) { + if ( targetIsWeakImport && !opts.allowWeakImports() ) + throwf("weak import of symbol '%s' not supported because of option: -no_weak_imports", target->name()); ld::Atom::WeakImportState curWI = target->weakImportState(); if ( curWI == ld::Atom::weakImportUnset ) { // first use of this proxy, set weak-import based on this usage diff --git a/cctools/ld64/src/ld/passes/got.cpp b/cctools/ld64/src/ld/passes/got.cpp index 01c2e30..d11a057 100644 --- a/cctools/ld64/src/ld/passes/got.cpp +++ b/cctools/ld64/src/ld/passes/got.cpp @@ -74,10 +74,48 @@ private: ld::Section GOTEntryAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); ld::Section GOTEntryAtom::_s_sectionWeak("__DATA", "__got_weak", ld::Section::typeNonLazyPointer); +#if SUPPORT_ARCH_arm64e -static bool gotFixup(const Options& opts, ld::Internal& internal, const ld::Atom* targetOfGOT, const ld::Fixup* fixup, bool* optimizable, bool* targetIsExternalWeakDef) +class GOTAuthEntryAtom : public ld::Atom { +public: + GOTAuthEntryAtom(ld::Internal& internal, const ld::Atom* target, bool weakImport, bool weakDef) + : ld::Atom(weakDef ? _s_sectionWeak : _s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), + _fixup1(0, ld::Fixup::k1of2, ld::Fixup::kindSetAuthData, (ld::Fixup::AuthData){ 0, true, ld::Fixup::AuthData::ptrauth_key_asia }), + _fixup2(0, ld::Fixup::k2of2, ld::Fixup::kindStoreTargetAddressLittleEndianAuth64, target), + _target(target) + { _fixup2.weakImport = weakImport; internal.addAtom(*this); } + + virtual const ld::File* file() const { return NULL; } + virtual const char* name() const { return _target->name(); } + virtual uint64_t size() const { return 8; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; } + +private: + mutable ld::Fixup _fixup1; + mutable ld::Fixup _fixup2; + const ld::Atom* _target; + + static ld::Section _s_section; + static ld::Section _s_sectionWeak; +}; + +ld::Section GOTAuthEntryAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); +ld::Section GOTAuthEntryAtom::_s_sectionWeak("__DATA", "__got_weak", ld::Section::typeNonLazyPointer); + +#endif + + +static bool gotFixup(const Options& opts, ld::Internal& internal, const ld::Atom* targetOfGOT, const ld::Atom* fixupAtom, + const ld::Fixup* fixup, bool* optimizable, bool* targetIsExternalWeakDef, bool* targetIsPersonalityFn) { *targetIsExternalWeakDef = false; + *targetIsPersonalityFn = false; switch (fixup->kind) { case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad: #if SUPPORT_ARCH_arm64 @@ -136,11 +174,23 @@ static bool gotFixup(const Options& opts, ld::Internal& internal, const ld::Atom case ld::Fixup::kindStoreX86PCRel32GOT: #if SUPPORT_ARCH_arm64 case ld::Fixup::kindStoreARM64PCRelToGOT: +#endif +#if SUPPORT_ARCH_arm64e + // Note, this handles identifying DWARF unwind info personality functions + if (opts.supportsAuthenticatedPointers()) { + if (fixupAtom->section().type() == ld::Section::typeCFI) + *targetIsPersonalityFn = true; + } #endif *optimizable = false; return true; case ld::Fixup::kindNoneGroupSubordinatePersonality: *optimizable = false; +#if SUPPORT_ARCH_arm64e + // Note, this is a compact unwind info personality function + if (opts.supportsAuthenticatedPointers()) + *targetIsPersonalityFn = true; +#endif return true; default: break; @@ -157,6 +207,17 @@ struct AtomByNameSorter } }; +struct GotMapEntry { + const ld::Atom* atom; + bool isPersonalityFn; + + bool operator<(const GotMapEntry& other) const { + if (atom != other.atom) + return atom < other.atom; + return (int)isPersonalityFn < (int)other.isPersonalityFn; + } +}; + void doPass(const Options& opts, ld::Internal& internal) { const bool log = false; @@ -166,7 +227,7 @@ void doPass(const Options& opts, ld::Internal& internal) return; // pre-fill gotMap with existing non-lazy pointers - std::map gotMap; + std::map gotMap; for (ld::Internal::FinalSection* sect : internal.sections) { if ( sect->type() != ld::Section::typeNonLazyPointer ) continue; @@ -194,7 +255,7 @@ void doPass(const Options& opts, ld::Internal& internal) } if ( target != NULL ) { if (log) fprintf(stderr, "found existing got entry to %s\n", target->name()); - gotMap[target] = atom; + gotMap[{ target, false }] = atom; } } } @@ -229,7 +290,8 @@ void doPass(const Options& opts, ld::Internal& internal) } bool optimizable; bool targetIsExternalWeakDef; - if ( !gotFixup(opts, internal, targetOfGOT, fit, &optimizable, &targetIsExternalWeakDef) ) + bool targetIsPersonalityFn; + if ( !gotFixup(opts, internal, targetOfGOT, atom, fit, &optimizable, &targetIsExternalWeakDef, &targetIsPersonalityFn) ) continue; if ( optimizable ) { // change from load of GOT entry to lea of target @@ -268,8 +330,8 @@ void doPass(const Options& opts, ld::Internal& internal) atomsReferencingGOT.push_back(atom); atomUsesGOT = true; } - if ( gotMap.count(targetOfGOT) == 0 ) - gotMap[targetOfGOT] = NULL; + if ( gotMap.count({ targetOfGOT, targetIsPersonalityFn }) == 0 ) + gotMap[{ targetOfGOT, targetIsPersonalityFn }] = NULL; // record if target is weak def weakDefMap[targetOfGOT] = targetIsExternalWeakDef; // record weak_import attribute @@ -327,8 +389,16 @@ void doPass(const Options& opts, ld::Internal& internal) // make GOT entries for (auto& entry : gotMap) { if ( entry.second == NULL ) { - entry.second = new GOTEntryAtom(internal, entry.first, weakImportMap[entry.first], opts.useDataConstSegment() && weakDefMap[entry.first], is64); - if (log) fprintf(stderr, "making new GOT slot for %s, gotMap[%p] = %p\n", entry.first->name(), entry.first, entry.second); + bool weakDef = opts.useDataConstSegment() && opts.sharedRegionEligible() && weakDefMap[entry.first.atom]; +#if SUPPORT_ARCH_arm64e + if ( entry.first.isPersonalityFn && (opts.supportsAuthenticatedPointers()) ) { + entry.second = new GOTAuthEntryAtom(internal, entry.first.atom, weakImportMap[entry.first.atom], weakDef); + if (log) fprintf(stderr, "making new GOT slot for %s, gotMap[%p] = %p\n", entry.first.atom->name(), entry.first.atom, entry.second); + continue; + } +#endif + entry.second = new GOTEntryAtom(internal, entry.first.atom, weakImportMap[entry.first.atom], weakDef, is64); + if (log) fprintf(stderr, "making new GOT slot for %s, gotMap[%p] = %p\n", entry.first.atom->name(), entry.first.atom, entry.second); } } @@ -357,7 +427,9 @@ void doPass(const Options& opts, ld::Internal& internal) } bool optimizable; bool targetIsExternalWeakDef; - if ( (targetOfGOT == NULL) || !gotFixup(opts, internal, targetOfGOT, fit, &optimizable, &targetIsExternalWeakDef) ) + bool targetIsPersonalityFn; + if ( (targetOfGOT == NULL) || !gotFixup(opts, internal, targetOfGOT, atom, fit, + &optimizable, &targetIsExternalWeakDef, &targetIsPersonalityFn) ) continue; if ( !optimizable ) { // GOT use not optimized away, update to bind to GOT entry @@ -367,7 +439,7 @@ void doPass(const Options& opts, ld::Internal& internal) case ld::Fixup::bindingDirectlyBound: if ( log ) fprintf(stderr, "updating GOT use in %s to %s\n", atom->name(), targetOfGOT->name()); fitThatSetTarget->binding = ld::Fixup::bindingDirectlyBound; - fitThatSetTarget->u.target = gotMap[targetOfGOT]; + fitThatSetTarget->u.target = gotMap[{ targetOfGOT, targetIsPersonalityFn }]; break; default: assert(0 && "unsupported GOT reference"); diff --git a/cctools/ld64/src/ld/passes/huge.cpp b/cctools/ld64/src/ld/passes/huge.cpp index 693976c..3797a23 100644 --- a/cctools/ld64/src/ld/passes/huge.cpp +++ b/cctools/ld64/src/ld/passes/huge.cpp @@ -47,10 +47,53 @@ public: } }; +class DataPadAtom : public ld::Atom { +public: + DataPadAtom(ld::Internal& state) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)) + { state.addAtom(*this); } + + + virtual const ld::File* file() const { return NULL; } + virtual const char* name() const { return "padding"; } + virtual uint64_t size() const { return 8; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + +protected: + virtual ~DataPadAtom() {} + + static ld::Section _s_section; +}; + +ld::Section DataPadAtom::_s_section("__DATA", "__data", ld::Section::typeUnclassified); + + void doPass(const Options& opts, ld::Internal& state) { const bool log = false; - + + // add __data section if __DATA segment was gutted by dirty data removal + if ( (opts.outputKind() == Options::kDynamicLibrary) && opts.useDataConstSegment() && opts.hasDataSymbolMoves() ) { + uint64_t dataAtomsSize = 0; + bool foundSegmentDATA_DIRTY = false; + for (ld::Internal::FinalSection* sect : state.sections) { + if ( strcmp(sect->segmentName(), "__DATA") == 0 ) { + for (const ld::Atom* atom : sect->atoms) { + dataAtomsSize += atom->size(); + } + } + else if ( strcmp(sect->segmentName(), "__DATA_DIRTY") == 0 ) { + foundSegmentDATA_DIRTY = true; + } + } + if ( foundSegmentDATA_DIRTY && (dataAtomsSize == 0) ) { + new DataPadAtom(state); + } + } + // only make make __huge section in final linked images if ( opts.outputKind() == Options::kObjectFile ) return; diff --git a/cctools/ld64/src/ld/passes/inits.cpp b/cctools/ld64/src/ld/passes/inits.cpp new file mode 100644 index 0000000..2d066d0 --- /dev/null +++ b/cctools/ld64/src/ld/passes/inits.cpp @@ -0,0 +1,148 @@ +/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- + * + * Copyright (c) 2017 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include +#include +#include + +#include +#include + +#include "ld.hpp" +#include "inits.h" + +namespace ld { +namespace passes { +namespace inits { + + + +class InitOffsetAtom : public ld::Atom { +public: + InitOffsetAtom(const ld::Atom* atom) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _fixup1(0, ld::Fixup::k1of2, ld::Fixup::kindSetTargetImageOffset, atom), + _fixup2(0, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32) + { } + + + virtual const ld::File* file() const { return NULL; } + virtual const char* name() const { return "init-offset"; } + virtual uint64_t size() const { return 4; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; } + +protected: + mutable ld::Fixup _fixup1; + ld::Fixup _fixup2; + + static ld::Section _s_section; +}; + +ld::Section InitOffsetAtom::_s_section("__TEXT", "__init_offsets", ld::Section::typeInitOffsets); + + + +void doPass(Options& opts, ld::Internal& state) +{ + //const bool log = false; + + // only transform initializers in final linked image + if ( opts.outputKind() == Options::kObjectFile ) + return; + + // only transform if targetting new enough OS + if ( !opts.makeInitializersIntoOffsets() ) + return; + + // transform -init function + std::vector initFunctions; + if ( (opts.initFunctionName() != NULL) && (state.entryPoint != NULL) ) { + InitOffsetAtom* initOffsetAtom = new InitOffsetAtom(state.entryPoint); + initFunctions.push_back(initOffsetAtom); + state.addAtom(*initOffsetAtom); + state.entryPoint = NULL; // this prevents LC_ROUTINES from being generated + } + + // only needed if there is a __mod_init_funcs section + for (ld::Internal::FinalSection* sect : state.sections) { + if ( sect->type() != ld::Section::typeInitializerPointers ) + continue; + const uint64_t pointerSize = (opts.architecture() & CPU_ARCH_ABI64) ? 8 : 4; + std::vector orderedAtoms; + for (const ld::Atom* atom : sect->atoms) { + for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) { + if ( fit->firstInCluster() ) + orderedAtoms.push_back(NULL); + } + } + for (const ld::Atom* atom : sect->atoms) { + for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) { + const Atom* initFunc = NULL; + switch ( fit->binding ) { + case ld::Fixup::bindingDirectlyBound: + initFunc = fit->u.target; + break; + case ld::Fixup::bindingsIndirectlyBound: + initFunc = state.indirectBindingTable[fit->u.bindingIndex]; + break; + default: + assert(0 && "fixup binding kind unsupported for initializer section"); + break; + } + unsigned index = fit->offsetInAtom / pointerSize; + assert(index < orderedAtoms.size()); + orderedAtoms[index] = new InitOffsetAtom(initFunc); + } + } + // relocations in .o files may be in random order, so fixups are in random order, + // but we need initializers to run in order the pointers were in the __mod_init_func section. + for (InitOffsetAtom* atom : orderedAtoms) { + initFunctions.push_back(atom); + state.addAtom(*atom); + } + } + if ( initFunctions.empty() ) + return; + + + + // remove any old style __mod_init_funcs sections + state.sections.erase(std::remove_if(state.sections.begin(), state.sections.end(), + [&](ld::Internal::FinalSection*& sect) { + return (sect->type() == ld::Section::typeInitializerPointers); + }), state.sections.end()); +} + + +} // namespace inits +} // namespace passes +} // namespace ld diff --git a/cctools/ld64/src/ld/passes/inits.h b/cctools/ld64/src/ld/passes/inits.h new file mode 100644 index 0000000..e86fd4b --- /dev/null +++ b/cctools/ld64/src/ld/passes/inits.h @@ -0,0 +1,45 @@ +/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- + * + * Copyright (c) 2009 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef __INITS_H__ +#define __INITS_H__ + +#include "Options.h" +#include "ld.hpp" + + +namespace ld { +namespace passes { +namespace inits { + +// called by linker to transform __mod_init_funs to __init_offsets +extern void doPass(Options& opts, ld::Internal& internal); + + +} // namespace huge +} // namespace passes +} // namespace ld + +#endif // __INITS_H__ diff --git a/cctools/ld64/src/ld/passes/objc.cpp b/cctools/ld64/src/ld/passes/objc.cpp index c65ca21..c24038d 100644 --- a/cctools/ld64/src/ld/passes/objc.cpp +++ b/cctools/ld64/src/ld/passes/objc.cpp @@ -50,11 +50,12 @@ struct objc_image_info { uint32_t flags; }; -#define OBJC_IMAGE_SUPPORTS_GC (1<<1) -#define OBJC_IMAGE_REQUIRES_GC (1<<2) -#define OBJC_IMAGE_OPTIMIZED_BY_DYLD (1<<3) -#define OBJC_IMAGE_SUPPORTS_COMPACTION (1<<4) -#define OBJC_IMAGE_IS_SIMULATED (1<<5) +#define OBJC_IMAGE_SUPPORTS_GC (1<<1) +#define OBJC_IMAGE_REQUIRES_GC (1<<2) +#define OBJC_IMAGE_OPTIMIZED_BY_DYLD (1<<3) +#define OBJC_IMAGE_SUPPORTS_COMPACTION (1<<4) +#define OBJC_IMAGE_IS_SIMULATED (1<<5) +#define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1<<6) @@ -64,8 +65,7 @@ struct objc_image_info { template class ObjCImageInfoAtom : public ld::Atom { public: - ObjCImageInfoAtom(ld::File::ObjcConstraint objcConstraint, - bool compaction, bool abi2, uint8_t swiftVersion); + ObjCImageInfoAtom(bool abi2, bool hasCategoryClassProperties, uint8_t swiftVersion, uint16_t swiftLanguageVersion); virtual const ld::File* file() const { return NULL; } virtual const char* name() const { return "objc image info"; } @@ -88,44 +88,61 @@ template ld::Section ObjCImageInfoAtom::_s_sectionABI2("__DATA", template -ObjCImageInfoAtom::ObjCImageInfoAtom(ld::File::ObjcConstraint objcConstraint, bool compaction, - bool abi2, uint8_t swiftVersion) +ObjCImageInfoAtom::ObjCImageInfoAtom(bool abi2, bool hasCategoryClassProperties, uint8_t swiftVersion, uint16_t swiftLanguageVersion) : ld::Atom(abi2 ? _s_sectionABI2 : _s_sectionABI1, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeUnclassified, symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)) { uint32_t value = 0; - switch ( objcConstraint ) { - case ld::File::objcConstraintNone: - case ld::File::objcConstraintRetainRelease: - if ( compaction ) - warning("ignoring -objc_gc_compaction because code not compiled for ObjC garbage collection"); - break; - case ld::File::objcConstraintRetainReleaseOrGC: - value |= OBJC_IMAGE_SUPPORTS_GC; - if ( compaction ) - value |= OBJC_IMAGE_SUPPORTS_COMPACTION; - break; - case ld::File::objcConstraintGC: - value |= OBJC_IMAGE_SUPPORTS_GC | OBJC_IMAGE_REQUIRES_GC; - if ( compaction ) - value |= OBJC_IMAGE_SUPPORTS_COMPACTION; - break; - case ld::File::objcConstraintRetainReleaseForSimulator: - value |= OBJC_IMAGE_IS_SIMULATED; - break; + if ( hasCategoryClassProperties ) { + value |= OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES; } - // provide swift language version in final binary for runtime to inspect + // provide swift ABI version in final binary for runtime to inspect value |= (swiftVersion << 8); + // provide swift language version in final binary for runtime to inspect + value |= (swiftLanguageVersion << 16); + _content.version = 0; A::P::E::set32(_content.flags, value); } +// +// This class is for a new Atom which is an ObjC category name created by merging names from categories +// +template +class CategoryNameAtom : public ld::Atom { +public: + CategoryNameAtom(ld::Internal& state, + const std::vector* categories); + + virtual const ld::File* file() const { return _file; } + virtual const char* name() const { return "objc merged category name"; } + virtual uint64_t size() const { return _categoryName.size() + 1; } + virtual uint64_t objectAddress() const { return 0; } + virtual void setScope(Scope) { } + virtual void copyRawContent(uint8_t buffer[]) const { + strcpy((char*)buffer, _categoryName.c_str()); + } + +private: + typedef typename A::P::uint_t pint_t; + + const ld::File* _file; + std::string _categoryName; + + static ld::Section _s_section; +}; + +template +ld::Section CategoryNameAtom::_s_section("__TEXT", "__objc_classname", ld::Section::typeCString); + + + // // This class is for a new Atom which is an ObjC method list created by merging method lists from categories // @@ -206,9 +223,12 @@ ld::Section ProtocolListAtom::_s_section("__DATA", "__objc_const", ld::Sectio template class PropertyListAtom : public ld::Atom { public: + enum class PropertyKind { ClassProperties, InstanceProperties }; + PropertyListAtom(ld::Internal& state, const ld::Atom* baseProtocolList, - const std::vector* categories, - std::set& deadAtoms); + const std::vector* categories, + std::set& deadAtoms, + PropertyKind kind); virtual const ld::File* file() const { return _file; } virtual const char* name() const { return "objc merged property list"; } @@ -241,36 +261,35 @@ ld::Section PropertyListAtom::_s_section("__DATA", "__objc_const", ld::Sectio // -// This class is used to create an Atom that replaces an atom from a .o file that holds a class_ro_t. +// This class is used to create an Atom that replaces an atom from a .o file that holds a class_ro_t or category_t. // It is needed because there is no way to add Fixups to an existing atom. // template -class ClassROOverlayAtom : public ld::Atom { +class ObjCOverlayAtom : public ld::Atom { public: - ClassROOverlayAtom(const ld::Atom* classROAtom); + ObjCOverlayAtom(const ld::Atom* classROAtom); // overrides of ld::Atom virtual const ld::File* file() const { return _atom->file(); } virtual const char* name() const { return _atom->name(); } virtual uint64_t size() const { return _atom->size(); } virtual uint64_t objectAddress() const { return _atom->objectAddress(); } - virtual void copyRawContent(uint8_t buffer[]) const + virtual void copyRawContent(uint8_t buffer[]) const { _atom->copyRawContent(buffer); } - virtual const uint8_t* rawContentPointer() const + virtual const uint8_t* rawContentPointer() const { return _atom->rawContentPointer(); } - virtual unsigned long contentHash(const class ld::IndirectBindingTable& ibt) const + virtual unsigned long contentHash(const class ld::IndirectBindingTable& ibt) const { return _atom->contentHash(ibt); } - virtual bool canCoalesceWith(const ld::Atom& rhs, const class ld::IndirectBindingTable& ibt) const + virtual bool canCoalesceWith(const ld::Atom& rhs, const class ld::IndirectBindingTable& ibt) const { return _atom->canCoalesceWith(rhs,ibt); } virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixups[0]; } virtual ld::Fixup::iterator fixupsEnd() const { return (ld::Fixup*)&_fixups[_fixups.size()]; } - void addProtocolListFixup(); - void addPropertyListFixup(); - void addMethodListFixup(); +protected: + void addFixupAtOffset(uint32_t offset); -private: +private: typedef typename A::P::uint_t pint_t; const ld::Atom* _atom; @@ -278,7 +297,30 @@ private: }; template -ClassROOverlayAtom::ClassROOverlayAtom(const ld::Atom* classROAtom) +class ClassROOverlayAtom : public ObjCOverlayAtom { +public: + ClassROOverlayAtom(const ld::Atom* contentAtom) : ObjCOverlayAtom(contentAtom) { } + + void addProtocolListFixup(); + void addPropertyListFixup(); + void addMethodListFixup(); +}; + +template +class CategoryOverlayAtom : public ObjCOverlayAtom { +public: + CategoryOverlayAtom(const ld::Atom* contentAtom) : ObjCOverlayAtom(contentAtom) { } + + void addNameFixup(); + void addInstanceMethodListFixup(); + void addClassMethodListFixup(); + void addProtocolListFixup(); + void addInstancePropertyListFixup(); + void addClassPropertyListFixup(); +}; + +template +ObjCOverlayAtom::ObjCOverlayAtom(const ld::Atom* classROAtom) : ld::Atom(classROAtom->section(), ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeUnclassified, classROAtom->symbolTableInclusion(), false, false, false, classROAtom->alignment()), @@ -314,7 +356,7 @@ const ld::Atom* ObjCData::getPointerInContent(ld::Internal& state, const ld:: if ( hasAddend != NULL ) *hasAddend = false; for (ld::Fixup::iterator fit=contentAtom->fixupsBegin(); fit != contentAtom->fixupsEnd(); ++fit) { - if ( fit->offsetInAtom == offset ) { + if ( (fit->offsetInAtom == offset) && (fit->kind != ld::Fixup::kindNoneFollowOn) ) { switch ( fit->binding ) { case ld::Fixup::bindingsIndirectlyBound: target = state.indirectBindingTable[fit->u.bindingIndex]; @@ -359,51 +401,216 @@ void ObjCData::setPointerInContent(ld::Internal& state, const ld::Atom* conte +#define GET_FIELD(state, classAtom, field) \ + ObjCData::getPointerInContent(state, classAtom, offsetof(Content, field)) +#define SET_FIELD(state, classAtom, field, valueAtom) \ + ObjCData::setPointerInContent(state, classAtom, offsetof(Content, field), valueAtom) + +#define GET_RO_FIELD(state, classAtom, field) \ + ObjCData::getPointerInContent(state, getROData(state, classAtom), offsetof(ROContent, field)) +#define SET_RO_FIELD(state, classROAtom, field, valueAtom) \ + ObjCData::setPointerInContent(state, getROData(state, classAtom), offsetof(ROContent, field), valueAtom) + // // Helper class for reading and updating existing ObjC category atoms from .o files // template class Category : public ObjCData { public: + // Getters + static const ld::Atom* getName(ld::Internal& state, const ld::Atom* contentAtom); static const ld::Atom* getClass(ld::Internal& state, const ld::Atom* contentAtom, bool& hasAddend); static const ld::Atom* getInstanceMethods(ld::Internal& state, const ld::Atom* contentAtom); static const ld::Atom* getClassMethods(ld::Internal& state, const ld::Atom* contentAtom); static const ld::Atom* getProtocols(ld::Internal& state, const ld::Atom* contentAtom); - static const ld::Atom* getProperties(ld::Internal& state, const ld::Atom* contentAtom); + static const ld::Atom* getInstanceProperties(ld::Internal& state, const ld::Atom* contentAtom); + static const ld::Atom* getClassProperties(ld::Internal& state, const ld::Atom* contentAtom); + // Setters + static const ld::Atom* setName(ld::Internal& state, const ld::Atom* categoryAtom, + const ld::Atom* categoryNameAtom, std::set& deadAtoms); + static const ld::Atom* setInstanceMethods(ld::Internal& state, const ld::Atom* categoryAtom, + const ld::Atom* methodListAtom, std::set& deadAtoms); + static const ld::Atom* setClassMethods(ld::Internal& state, const ld::Atom* categoryAtom, + const ld::Atom* methodListAtom, std::set& deadAtoms); + static const ld::Atom* setProtocols(ld::Internal& state, const ld::Atom* categoryAtom, + const ld::Atom* protocolListAtom, std::set& deadAtoms); + static const ld::Atom* setInstanceProperties(ld::Internal& state, const ld::Atom* categoryAtom, + const ld::Atom* propertyListAtom, std::set& deadAtoms); + static const ld::Atom* setClassProperties(ld::Internal& state, const ld::Atom* categoryAtom, + const ld::Atom* propertyListAtom, std::set& deadAtoms); static uint32_t size() { return 6*sizeof(pint_t); } + + static bool hasCategoryClassPropertiesField(const ld::Atom* categoryAtom); + private: typedef typename A::P::uint_t pint_t; + + friend class CategoryOverlayAtom; + + struct Content { + pint_t name; + pint_t cls; + pint_t instanceMethods; + pint_t classMethods; + pint_t protocols; + pint_t instanceProperties; + // Fields below this point are not always present on disk. + pint_t classProperties; + }; }; +template +const ld::Atom* Category::getName(ld::Internal& state, const ld::Atom* contentAtom) +{ + return GET_FIELD(state, contentAtom, name); +} + template const ld::Atom* Category::getClass(ld::Internal& state, const ld::Atom* contentAtom, bool& hasAddend) { - return ObjCData::getPointerInContent(state, contentAtom, sizeof(pint_t), &hasAddend); // category_t.cls + return ObjCData::getPointerInContent(state, contentAtom, offsetof(Content, cls), &hasAddend); // category_t.cls } template const ld::Atom* Category::getInstanceMethods(ld::Internal& state, const ld::Atom* contentAtom) { - return ObjCData::getPointerInContent(state, contentAtom, 2*sizeof(pint_t)); // category_t.instanceMethods + return GET_FIELD(state, contentAtom, instanceMethods); } template const ld::Atom* Category::getClassMethods(ld::Internal& state, const ld::Atom* contentAtom) { - return ObjCData::getPointerInContent(state, contentAtom, 3*sizeof(pint_t)); // category_t.classMethods + return GET_FIELD(state, contentAtom, classMethods); } template const ld::Atom* Category::getProtocols(ld::Internal& state, const ld::Atom* contentAtom) { - return ObjCData::getPointerInContent(state, contentAtom, 4*sizeof(pint_t)); // category_t.protocols + return GET_FIELD(state, contentAtom, protocols); } template -const ld::Atom* Category::getProperties(ld::Internal& state, const ld::Atom* contentAtom) +const ld::Atom* Category::getInstanceProperties(ld::Internal& state, const ld::Atom* contentAtom) { - return ObjCData::getPointerInContent(state, contentAtom, 5*sizeof(pint_t)); // category_t.instanceProperties + return GET_FIELD(state, contentAtom, instanceProperties); +} + +template +const ld::Atom* Category::getClassProperties(ld::Internal& state, const ld::Atom* contentAtom) +{ + // Only specially-marked files have this field. + if ( hasCategoryClassPropertiesField(contentAtom) ) + return GET_FIELD(state, contentAtom, classProperties); + return NULL; +} + +template +bool Category::hasCategoryClassPropertiesField(const ld::Atom* contentAtom) +{ + // Only specially-marked files have this field. + if ( const ld::relocatable::File* objFile = dynamic_cast(contentAtom->file()) ) { + return objFile->objcHasCategoryClassPropertiesField(); + } + return false; +} + + + +template +const ld::Atom* Category::setName(ld::Internal &state, const ld::Atom *categoryAtom, + const ld::Atom *categoryNameAtom, std::set &deadAtoms) +{ + // if the base category does not already have a method list, we need to create an overlay + if ( getName(state, categoryAtom) == NULL ) { + deadAtoms.insert(categoryAtom); + CategoryOverlayAtom* overlay = new CategoryOverlayAtom(categoryAtom); + overlay->addNameFixup(); + SET_FIELD(state, overlay, name, categoryNameAtom); + return overlay; + } + SET_FIELD(state, categoryAtom, name, categoryNameAtom); + return NULL; // means category atom was not replaced +} + +template +const ld::Atom* Category::setInstanceMethods(ld::Internal& state, const ld::Atom* categoryAtom, + const ld::Atom* methodListAtom, std::set& deadAtoms) +{ + // if the base category does not already have a method list, we need to create an overlay + if ( getInstanceMethods(state, categoryAtom) == NULL ) { + deadAtoms.insert(categoryAtom); + CategoryOverlayAtom* overlay = new CategoryOverlayAtom(categoryAtom); + overlay->addInstanceMethodListFixup(); + SET_FIELD(state, overlay, instanceMethods, methodListAtom); + return overlay; + } + SET_FIELD(state, categoryAtom, instanceMethods, methodListAtom); + return NULL; // means category atom was not replaced +} + +template +const ld::Atom* Category::setClassMethods(ld::Internal& state, const ld::Atom* categoryAtom, + const ld::Atom* methodListAtom, std::set& deadAtoms) +{ + // if the base category does not already have a method list, we need to create an overlay + if ( getClassMethods(state, categoryAtom) == NULL ) { + deadAtoms.insert(categoryAtom); + CategoryOverlayAtom* overlay = new CategoryOverlayAtom(categoryAtom); + overlay->addClassMethodListFixup(); + SET_FIELD(state, overlay, classMethods, methodListAtom); + return overlay; + } + SET_FIELD(state, categoryAtom, classMethods, methodListAtom); + return NULL; // means category atom was not replaced +} + +template +const ld::Atom* Category::setProtocols(ld::Internal& state, const ld::Atom* categoryAtom, + const ld::Atom* protocolListAtom, std::set& deadAtoms) +{ + // if the base category does not already have a protocol list, we need to create an overlay + if ( getProtocols(state, categoryAtom) == NULL ) { + deadAtoms.insert(categoryAtom); + CategoryOverlayAtom* overlay = new CategoryOverlayAtom(categoryAtom); + overlay->addProtocolListFixup(); + SET_FIELD(state, overlay, protocols, protocolListAtom); + return overlay; + } + SET_FIELD(state, categoryAtom, protocols, protocolListAtom); + return NULL; // means category atom was not replaced +} + +template +const ld::Atom* Category::setInstanceProperties(ld::Internal& state, const ld::Atom* categoryAtom, + const ld::Atom* methodListAtom, std::set& deadAtoms) +{ + // if the base category does not already have a property list, we need to create an overlay + if ( getInstanceProperties(state, categoryAtom) == NULL ) { + deadAtoms.insert(categoryAtom); + CategoryOverlayAtom* overlay = new CategoryOverlayAtom(categoryAtom); + overlay->addInstancePropertyListFixup(); + SET_FIELD(state, overlay, instanceProperties, methodListAtom); + return overlay; + } + SET_FIELD(state, categoryAtom, instanceProperties, methodListAtom); + return NULL; // means category atom was not replaced +} + +template +const ld::Atom* Category::setClassProperties(ld::Internal& state, const ld::Atom* categoryAtom, + const ld::Atom* methodListAtom, std::set& deadAtoms) +{ + // if the base category does not already have a property list, we need to create an overlay + if ( getClassProperties(state, categoryAtom) == NULL ) { + deadAtoms.insert(categoryAtom); + CategoryOverlayAtom* overlay = new CategoryOverlayAtom(categoryAtom); + overlay->addClassPropertyListFixup(); + SET_FIELD(state, overlay, classProperties, methodListAtom); + return overlay; + } + SET_FIELD(state, categoryAtom, classProperties, methodListAtom); + return NULL; // means category atom was not replaced } @@ -446,10 +653,12 @@ private: template class Class : public ObjCData { public: + static const ld::Atom* getMetaClass(ld::Internal& state, const ld::Atom* classAtom); static const ld::Atom* getInstanceMethodList(ld::Internal& state, const ld::Atom* classAtom); static const ld::Atom* getInstanceProtocolList(ld::Internal& state, const ld::Atom* classAtom); static const ld::Atom* getInstancePropertyList(ld::Internal& state, const ld::Atom* classAtom); static const ld::Atom* getClassMethodList(ld::Internal& state, const ld::Atom* classAtom); + static const ld::Atom* getClassPropertyList(ld::Internal& state, const ld::Atom* classAtom); static const ld::Atom* setInstanceMethodList(ld::Internal& state, const ld::Atom* classAtom, const ld::Atom* methodListAtom, std::set& deadAtoms); static const ld::Atom* setInstanceProtocolList(ld::Internal& state, const ld::Atom* classAtom, @@ -460,74 +669,107 @@ public: const ld::Atom* methodListAtom, std::set& deadAtoms); static const ld::Atom* setClassProtocolList(ld::Internal& state, const ld::Atom* classAtom, const ld::Atom* protocolListAtom, std::set& deadAtoms); - static uint32_t size() { return 5*sizeof(pint_t); } - static unsigned int class_ro_header_size(); + static const ld::Atom* setClassPropertyList(ld::Internal& state, const ld::Atom* classAtom, + const ld::Atom* propertyListAtom, std::set& deadAtoms); + static uint32_t size() { return sizeof(Content); } + private: + friend class ClassROOverlayAtom; + typedef typename A::P::uint_t pint_t; + static const ld::Atom* getROData(ld::Internal& state, const ld::Atom* classAtom); + + struct Content { + pint_t isa; + pint_t superclass; + pint_t method_cache; + pint_t vtable; + pint_t data; + }; + + struct ROContent { + uint32_t flags; + uint32_t instanceStart; + // Note there is 4-bytes of alignment padding between instanceSize + // and ivarLayout on 64-bit archs, but no padding on 32-bit archs. + // This union is a way to model that. + union { + uint32_t instanceSize; + pint_t pad; + } instanceSize; + pint_t ivarLayout; + pint_t name; + pint_t baseMethods; + pint_t baseProtocols; + pint_t ivars; + pint_t weakIvarLayout; + pint_t baseProperties; + }; }; -template <> unsigned int Class::class_ro_header_size() { return 16; } -template <> unsigned int Class::class_ro_header_size() { return 12;} -template <> unsigned int Class::class_ro_header_size() { return 12; } - +template +const ld::Atom* Class::getMetaClass(ld::Internal& state, const ld::Atom* classAtom) +{ + const ld::Atom* metaClassAtom = GET_FIELD(state, classAtom, isa); + assert(metaClassAtom != NULL); + return metaClassAtom; +} template const ld::Atom* Class::getROData(ld::Internal& state, const ld::Atom* classAtom) { - return ObjCData::getPointerInContent(state, classAtom, 4*sizeof(pint_t)); // class_t.data - + const ld::Atom* classROAtom = GET_FIELD(state, classAtom, data); + assert(classROAtom != NULL); + return classROAtom; } template const ld::Atom* Class::getInstanceMethodList(ld::Internal& state, const ld::Atom* classAtom) { - const ld::Atom* classROAtom = getROData(state, classAtom); // class_t.data - assert(classROAtom != NULL); - return ObjCData::getPointerInContent(state, classROAtom, class_ro_header_size() + 2*sizeof(pint_t)); // class_ro_t.baseMethods + return GET_RO_FIELD(state, classAtom, baseMethods); } template const ld::Atom* Class::getInstanceProtocolList(ld::Internal& state, const ld::Atom* classAtom) { - const ld::Atom* classROAtom = getROData(state, classAtom); // class_t.data - assert(classROAtom != NULL); - return ObjCData::getPointerInContent(state, classROAtom, class_ro_header_size() + 3*sizeof(pint_t)); // class_ro_t.baseProtocols + return GET_RO_FIELD(state, classAtom, baseProtocols); } template const ld::Atom* Class::getInstancePropertyList(ld::Internal& state, const ld::Atom* classAtom) { - const ld::Atom* classROAtom = getROData(state, classAtom); // class_t.data - assert(classROAtom != NULL); - return ObjCData::getPointerInContent(state, classROAtom, class_ro_header_size() + 6*sizeof(pint_t)); // class_ro_t.baseProperties + return GET_RO_FIELD(state, classAtom, baseProperties); } template const ld::Atom* Class::getClassMethodList(ld::Internal& state, const ld::Atom* classAtom) { - const ld::Atom* metaClassAtom = ObjCData::getPointerInContent(state, classAtom, 0); // class_t.isa - assert(metaClassAtom != NULL); - return Class::getInstanceMethodList(state, metaClassAtom); + return Class::getInstanceMethodList(state, getMetaClass(state, classAtom)); +} + +template +const ld::Atom* Class::getClassPropertyList(ld::Internal& state, const ld::Atom* classAtom) +{ + return Class::getInstancePropertyList(state, getMetaClass(state, classAtom)); } template const ld::Atom* Class::setInstanceMethodList(ld::Internal& state, const ld::Atom* classAtom, const ld::Atom* methodListAtom, std::set& deadAtoms) { - const ld::Atom* classROAtom = getROData(state, classAtom); // class_t.data - assert(classROAtom != NULL); // if the base class does not already have a method list, we need to create an overlay if ( getInstanceMethodList(state, classAtom) == NULL ) { - ClassROOverlayAtom* overlay = new ClassROOverlayAtom(classROAtom); + const ld::Atom* oldROAtom = getROData(state, classAtom); + deadAtoms.insert(oldROAtom); + ClassROOverlayAtom* overlay = new ClassROOverlayAtom(oldROAtom); //fprintf(stderr, "replace class RO atom %p with %p for method list in class atom %s\n", classROAtom, overlay, classAtom->name()); overlay->addMethodListFixup(); - ObjCData::setPointerInContent(state, classAtom, 4*sizeof(pint_t), overlay); // class_t.data - deadAtoms.insert(classROAtom); - ObjCData::setPointerInContent(state, overlay, class_ro_header_size() + 2*sizeof(pint_t), methodListAtom); // class_ro_t.baseMethods + SET_FIELD(state, classAtom, data, overlay); + SET_RO_FIELD(state, classAtom, baseMethods, methodListAtom); return overlay; } - ObjCData::setPointerInContent(state, classROAtom, class_ro_header_size() + 2*sizeof(pint_t), methodListAtom); // class_ro_t.baseMethods + SET_RO_FIELD(state, classAtom, baseMethods, methodListAtom); return NULL; // means classRO atom was not replaced } @@ -535,20 +777,19 @@ template const ld::Atom* Class::setInstanceProtocolList(ld::Internal& state, const ld::Atom* classAtom, const ld::Atom* protocolListAtom, std::set& deadAtoms) { - const ld::Atom* classROAtom = getROData(state, classAtom); // class_t.data - assert(classROAtom != NULL); // if the base class does not already have a protocol list, we need to create an overlay if ( getInstanceProtocolList(state, classAtom) == NULL ) { - ClassROOverlayAtom* overlay = new ClassROOverlayAtom(classROAtom); + const ld::Atom* oldROAtom = getROData(state, classAtom); + deadAtoms.insert(oldROAtom); + ClassROOverlayAtom* overlay = new ClassROOverlayAtom(oldROAtom); //fprintf(stderr, "replace class RO atom %p with %p for protocol list in class atom %s\n", classROAtom, overlay, classAtom->name()); overlay->addProtocolListFixup(); - ObjCData::setPointerInContent(state, classAtom, 4*sizeof(pint_t), overlay); // class_t.data - deadAtoms.insert(classROAtom); - ObjCData::setPointerInContent(state, overlay, class_ro_header_size() + 3*sizeof(pint_t), protocolListAtom); // class_ro_t.baseProtocols + SET_FIELD(state, classAtom, data, overlay); + SET_RO_FIELD(state, classAtom, baseProtocols, protocolListAtom); return overlay; } //fprintf(stderr, "set class RO atom %p protocol list in class atom %s\n", classROAtom, classAtom->name()); - ObjCData::setPointerInContent(state, classROAtom, class_ro_header_size() + 3*sizeof(pint_t), protocolListAtom); // class_ro_t.baseProtocols + SET_RO_FIELD(state, classAtom, baseProtocols, protocolListAtom); return NULL; // means classRO atom was not replaced } @@ -557,9 +798,8 @@ const ld::Atom* Class::setClassProtocolList(ld::Internal& state, const ld::At const ld::Atom* protocolListAtom, std::set& deadAtoms) { // meta class also points to same protocol list as class - const ld::Atom* metaClassAtom = ObjCData::getPointerInContent(state, classAtom, 0); // class_t.isa + const ld::Atom* metaClassAtom = getMetaClass(state, classAtom); //fprintf(stderr, "setClassProtocolList(), classAtom=%p %s, metaClass=%p %s\n", classAtom, classAtom->name(), metaClassAtom, metaClassAtom->name()); - assert(metaClassAtom != NULL); return setInstanceProtocolList(state, metaClassAtom, protocolListAtom, deadAtoms); } @@ -569,19 +809,18 @@ template const ld::Atom* Class::setInstancePropertyList(ld::Internal& state, const ld::Atom* classAtom, const ld::Atom* propertyListAtom, std::set& deadAtoms) { - const ld::Atom* classROAtom = getROData(state, classAtom); // class_t.data - assert(classROAtom != NULL); // if the base class does not already have a property list, we need to create an overlay if ( getInstancePropertyList(state, classAtom) == NULL ) { - ClassROOverlayAtom* overlay = new ClassROOverlayAtom(classROAtom); + const ld::Atom* oldROAtom = getROData(state, classAtom); + deadAtoms.insert(oldROAtom); + ClassROOverlayAtom* overlay = new ClassROOverlayAtom(oldROAtom); //fprintf(stderr, "replace class RO atom %p with %p for property list in class atom %s\n", classROAtom, overlay, classAtom->name()); overlay->addPropertyListFixup(); - ObjCData::setPointerInContent(state, classAtom, 4*sizeof(pint_t), overlay); // class_t.data - deadAtoms.insert(classROAtom); - ObjCData::setPointerInContent(state, overlay, class_ro_header_size() + 6*sizeof(pint_t), propertyListAtom); // class_ro_t.baseProperties + SET_FIELD(state, classAtom, data, overlay); + SET_RO_FIELD(state, classAtom, baseProperties, propertyListAtom); return overlay; } - ObjCData::setPointerInContent(state, classROAtom, class_ro_header_size() + 6*sizeof(pint_t), propertyListAtom); // class_ro_t.baseProperties + SET_RO_FIELD(state, classAtom, baseProperties, propertyListAtom); return NULL; // means classRO atom was not replaced } @@ -590,86 +829,103 @@ const ld::Atom* Class::setClassMethodList(ld::Internal& state, const ld::Atom const ld::Atom* methodListAtom, std::set& deadAtoms) { // class methods is just instance methods of metaClass - const ld::Atom* metaClassAtom = ObjCData::getPointerInContent(state, classAtom, 0); // class_t.isa - assert(metaClassAtom != NULL); - return setInstanceMethodList(state, metaClassAtom, methodListAtom, deadAtoms); + return setInstanceMethodList(state, getMetaClass(state, classAtom), methodListAtom, deadAtoms); +} + +template +const ld::Atom* Class::setClassPropertyList(ld::Internal& state, const ld::Atom* classAtom, + const ld::Atom* propertyListAtom, std::set& deadAtoms) +{ + // class properties is just instance properties of metaClass + return setInstancePropertyList(state, getMetaClass(state, classAtom), propertyListAtom, deadAtoms); +} + +#undef GET_FIELD +#undef SET_FIELD +#undef GET_RO_FIELD +#undef SET_RO_FIELD + + +template +ld::Fixup::Kind pointerFixupKind(); + +template <> +ld::Fixup::Kind pointerFixupKind>() { + return ld::Fixup::kindStoreTargetAddressBigEndian32; +} +template <> +ld::Fixup::Kind pointerFixupKind>() { + return ld::Fixup::kindStoreTargetAddressBigEndian64; +} +template <> +ld::Fixup::Kind pointerFixupKind>() { + return ld::Fixup::kindStoreTargetAddressLittleEndian32; +} +template <> +ld::Fixup::Kind pointerFixupKind>() { + return ld::Fixup::kindStoreTargetAddressLittleEndian64; +} + +template +void ObjCOverlayAtom::addFixupAtOffset(uint32_t offset) +{ + const ld::Atom* targetAtom = this; // temporary + _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of1, pointerFixupKind(), targetAtom)); } - -template <> -void ClassROOverlayAtom::addMethodListFixup() +template +void ClassROOverlayAtom::addMethodListFixup() { - const ld::Atom* targetAtom = this; // temporary - uint32_t offset = Class::class_ro_header_size() + 2*8; // class_ro_t.baseMethods - _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, targetAtom)); + this->addFixupAtOffset(offsetof(typename Class::ROContent, baseMethods)); } -template <> -void ClassROOverlayAtom::addMethodListFixup() +template +void ClassROOverlayAtom::addProtocolListFixup() { - const ld::Atom* targetAtom = this; // temporary - uint32_t offset = Class::class_ro_header_size() + 2*4; // class_ro_t.baseMethods - _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, targetAtom)); + this->addFixupAtOffset(offsetof(typename Class::ROContent, baseProtocols)); } -template <> -void ClassROOverlayAtom::addMethodListFixup() +template +void ClassROOverlayAtom::addPropertyListFixup() { - const ld::Atom* targetAtom = this; // temporary - uint32_t offset = Class::class_ro_header_size() + 2*4; // class_ro_t.baseMethods - _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, targetAtom)); + this->addFixupAtOffset(offsetof(typename Class::ROContent, baseProperties)); } - - -template <> -void ClassROOverlayAtom::addProtocolListFixup() +template +void CategoryOverlayAtom::addNameFixup() { - const ld::Atom* targetAtom = this; // temporary - uint32_t offset = Class::class_ro_header_size() + 3*8; // class_ro_t.baseProtocols - _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, targetAtom)); + this->addFixupAtOffset(offsetof(typename Category::Content, name)); } -template <> -void ClassROOverlayAtom::addProtocolListFixup() +template +void CategoryOverlayAtom::addInstanceMethodListFixup() { - const ld::Atom* targetAtom = this; // temporary - uint32_t offset = Class::class_ro_header_size() + 3*4; // class_ro_t.baseProtocols - _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, targetAtom)); + this->addFixupAtOffset(offsetof(typename Category::Content, instanceMethods)); } -template <> -void ClassROOverlayAtom::addProtocolListFixup() +template +void CategoryOverlayAtom::addClassMethodListFixup() { - const ld::Atom* targetAtom = this; // temporary - uint32_t offset = Class::class_ro_header_size() + 3*4; // class_ro_t.baseProtocols - _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, targetAtom)); + this->addFixupAtOffset(offsetof(typename Category::Content, classMethods)); } - -template <> -void ClassROOverlayAtom::addPropertyListFixup() +template +void CategoryOverlayAtom::addProtocolListFixup() { - const ld::Atom* targetAtom = this; // temporary - uint32_t offset = Class::class_ro_header_size() + 6*8; // class_ro_t.baseProperties - _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, targetAtom)); + this->addFixupAtOffset(offsetof(typename Category::Content, protocols)); } -template <> -void ClassROOverlayAtom::addPropertyListFixup() +template +void CategoryOverlayAtom::addInstancePropertyListFixup() { - const ld::Atom* targetAtom = this; // temporary - uint32_t offset = Class::class_ro_header_size() + 6*4; // class_ro_t.baseProperties - _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, targetAtom)); + this->addFixupAtOffset(offsetof(typename Category::Content, instanceProperties)); } -template <> -void ClassROOverlayAtom::addPropertyListFixup() +template +void CategoryOverlayAtom::addClassPropertyListFixup() { - const ld::Atom* targetAtom = this; // temporary - uint32_t offset = Class::class_ro_header_size() + 6*4; // class_ro_t.baseProperties - _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, targetAtom)); + this->addFixupAtOffset(offsetof(typename Category::Content, classProperties)); } @@ -681,12 +937,13 @@ void ClassROOverlayAtom::addPropertyListFixup() template class OptimizeCategories { public: - static void doit(const Options& opts, ld::Internal& state); + static void doit(const Options& opts, ld::Internal& state, bool haveCategoriesWithoutClassPropertyStorage); + static bool hasName(ld::Internal& state, const std::vector* categories); static bool hasInstanceMethods(ld::Internal& state, const std::vector* categories); static bool hasClassMethods(ld::Internal& state, const std::vector* categories); static bool hasProtocols(ld::Internal& state, const std::vector* categories); - static bool hasProperties(ld::Internal& state, const std::vector* categories); - + static bool hasInstanceProperties(ld::Internal& state, const std::vector* categories); + static bool hasClassProperties(ld::Internal& state, const std::vector* categories); static unsigned int class_ro_baseMethods_offset(); private: @@ -695,6 +952,19 @@ private: }; +template +bool OptimizeCategories::hasName(ld::Internal& state, const std::vector* categories) +{ + for (std::vector::const_iterator it=categories->begin(); it != categories->end(); ++it) { + const ld::Atom* categoryAtom = *it; + const ld::Atom* name = Category::getName(state, categoryAtom); + if ( name != NULL ) + return true; + } + return false; +} + + template bool OptimizeCategories::hasInstanceMethods(ld::Internal& state, const std::vector* categories) { @@ -741,11 +1011,26 @@ bool OptimizeCategories::hasProtocols(ld::Internal& state, const std::vector< template -bool OptimizeCategories::hasProperties(ld::Internal& state, const std::vector* categories) +bool OptimizeCategories::hasInstanceProperties(ld::Internal& state, const std::vector* categories) { for (std::vector::const_iterator it=categories->begin(); it != categories->end(); ++it) { const ld::Atom* categoryAtom = *it; - const ld::Atom* propertyListAtom = Category::getProperties(state, categoryAtom); + const ld::Atom* propertyListAtom = Category::getInstanceProperties(state, categoryAtom); + if ( propertyListAtom != NULL ) { + if ( PropertyList::count(state, propertyListAtom) > 0 ) + return true; + } + } + return false; +} + + +template +bool OptimizeCategories::hasClassProperties(ld::Internal& state, const std::vector* categories) +{ + for (std::vector::const_iterator it=categories->begin(); it != categories->end(); ++it) { + const ld::Atom* categoryAtom = *it; + const ld::Atom* propertyListAtom = Category::getClassProperties(state, categoryAtom); if ( propertyListAtom != NULL ) { if ( PropertyList::count(state, propertyListAtom) > 0 ) return true; @@ -805,6 +1090,11 @@ private: return strcmp(left->name(), right->name()); } } + // don't crash if objc atom does not have an owning file, just sort those to end + if ( leftf == nullptr ) + return false; + if ( rightf == nullptr ) + return true; return (leftf->ordinal() < rightf->ordinal()); } }; @@ -813,8 +1103,9 @@ private: std::sort(atoms.begin(), atoms.end(), AtomSorter()); } + template -void OptimizeCategories::doit(const Options& opts, ld::Internal& state) +void OptimizeCategories::doit(const Options& opts, ld::Internal& state, bool haveCategoriesWithoutClassPropertyStorage) { // first find all categories referenced by __objc_nlcatlist section std::set nlcatListAtoms; @@ -839,6 +1130,9 @@ void OptimizeCategories::doit(const Options& opts, ld::Internal& state) std::vector classOrder; std::set deadAtoms; ld::Internal::FinalSection* methodListSection = NULL; + typedef std::map*>> ExternalCatMap; + ExternalCatMap externalClassToCategories; + std::vector externalClassOrder; for (std::vector::iterator sit=state.sections.begin(); sit != state.sections.end(); ++sit) { ld::Internal::FinalSection* sect = *sit; if ( sect->type() == ld::Section::typeObjC2CategoryList ) { @@ -858,15 +1152,16 @@ void OptimizeCategories::doit(const Options& opts, ld::Internal& state) continue; const ld::Atom* categoryOnClassAtom = fixClassAliases(Category::getClass(state, categoryAtom, hasAddend)); assert(categoryOnClassAtom != NULL); + + // for now, back off optimization on new style classes + if ( hasAddend != 0 ) + continue; + // don't apply categories to swift classes + if ( categoryOnClassAtom->hasFixupsOfKind(ld::Fixup::kindNoneGroupSubordinate) ) + continue; + // only look at classes defined in this image if ( categoryOnClassAtom->definition() != ld::Atom::definitionProxy ) { - // for now, back off optimization on new style classes - if ( hasAddend != 0 ) - continue; - // don't apply categories to swift classes - if ( categoryOnClassAtom->hasFixupsOfKind(ld::Fixup::kindNoneGroupSubordinate) ) - continue; - CatMap::iterator pos = classToCategories.find(categoryOnClassAtom); if ( pos == classToCategories.end() ) { classToCategories[categoryOnClassAtom] = new std::vector(); @@ -876,6 +1171,19 @@ void OptimizeCategories::doit(const Options& opts, ld::Internal& state) // mark category atom and catlist atom as dead deadAtoms.insert(categoryAtom); deadAtoms.insert(categoryListElementAtom); + } else if ( !haveCategoriesWithoutClassPropertyStorage ) { + // Note, we only merge duplicate categories which handle the class properties field. Otherwise we may want to add + // the class properties from a .o which has it to a category which doesn't + ExternalCatMap::iterator pos = externalClassToCategories.find(categoryOnClassAtom); + if ( pos == externalClassToCategories.end() ) { + externalClassToCategories[categoryOnClassAtom] = { categoryListElementAtom, new std::vector() }; + externalClassOrder.push_back(categoryOnClassAtom); + } else { + // mark category atom and catlist atom as dead as this is not the first category for this class + deadAtoms.insert(categoryAtom); + deadAtoms.insert(categoryListElementAtom); + } + externalClassToCategories[categoryOnClassAtom].second->push_back(categoryAtom); } } } @@ -884,9 +1192,12 @@ void OptimizeCategories::doit(const Options& opts, ld::Internal& state) methodListSection = sect; } - // if found some categories + // Malformed binaries may not have methods lists in __objc_const. In that case just give up + if ( methodListSection == NULL ) + return; + + // if found some categories on classes defined in this image if ( classToCategories.size() != 0 ) { - assert(methodListSection != NULL); sortAtomVector(classOrder); // alter each class definition to have new method list which includes all category methods for (std::vector::iterator it = classOrder.begin(); it != classOrder.end(); it++) { @@ -941,10 +1252,10 @@ void OptimizeCategories::doit(const Options& opts, ld::Internal& state) state.atomToSection[newMetaClassRO] = methodListSection; } } - // if any category adds properties, generate new merged property list, and replace - if ( OptimizeCategories::hasProperties(state, categories) ) { + // if any category adds instance properties, generate new merged property list, and replace + if ( OptimizeCategories::hasInstanceProperties(state, categories) ) { const ld::Atom* basePropertyListAtom = Class::getInstancePropertyList(state, classAtom); - const ld::Atom* newPropertyListAtom = new PropertyListAtom(state, basePropertyListAtom, categories, deadAtoms); + const ld::Atom* newPropertyListAtom = new PropertyListAtom(state, basePropertyListAtom, categories, deadAtoms, PropertyListAtom::PropertyKind::InstanceProperties); const ld::Atom* newClassRO = Class::setInstancePropertyList(state, classAtom, newPropertyListAtom, deadAtoms); // add new property list to final sections methodListSection->atoms.push_back(newPropertyListAtom); @@ -955,9 +1266,138 @@ void OptimizeCategories::doit(const Options& opts, ld::Internal& state) state.atomToSection[newClassRO] = methodListSection; } } - + // if any category adds class properties, generate new merged property list, and replace + if ( OptimizeCategories::hasClassProperties(state, categories) ) { + const ld::Atom* basePropertyListAtom = Class::getClassPropertyList(state, classAtom); + const ld::Atom* newPropertyListAtom = new PropertyListAtom(state, basePropertyListAtom, categories, deadAtoms, PropertyListAtom::PropertyKind::ClassProperties); + const ld::Atom* newClassRO = Class::setClassPropertyList(state, classAtom, newPropertyListAtom, deadAtoms); + // add new property list to final sections + methodListSection->atoms.push_back(newPropertyListAtom); + state.atomToSection[newPropertyListAtom] = methodListSection; + if ( newClassRO != NULL ) { + assert(strcmp(newClassRO->section().sectionName(), "__objc_const") == 0); + methodListSection->atoms.push_back(newClassRO); + state.atomToSection[newClassRO] = methodListSection; + } + } } + } + // if found some duplicate categories on classes defined in another image + if ( externalClassToCategories.size() != 0 ) { + sortAtomVector(externalClassOrder); + // alter each class definition to have new method list which includes all category methods + for (std::vector::iterator it = externalClassOrder.begin(); it != externalClassOrder.end(); it++) { + const ld::Atom* categoryListElementAtom; + const std::vector* categories; + std::tie(categoryListElementAtom, categories) = externalClassToCategories[*it]; + assert(categories->size() != 0); + // Skip single categories. We only optimize duplicates + if (categories->size() == 1) + continue; + + const ld::Atom* categoryAtom = categories->front(); + + // The category name should reflect all the categories we just merged + // FIXME: Turn this back on once we know how to merge the category name without trashing the indirect symbol index and therefore + // all other users of this uniqued string +#if 0 + if ( OptimizeCategories::hasName(state, categories) ) { + ld::Internal::FinalSection* categoryNameSection = state.atomToSection[Category::getName(state, categoryAtom)]; + const ld::Atom* newCategoryNameAtom = new CategoryNameAtom(state, categories); + const ld::Atom* newCategory = Category::setName(state, categoryAtom, newCategoryNameAtom, deadAtoms); + // add new category name to final sections + categoryNameSection->atoms.push_back(newCategoryNameAtom); + state.atomToSection[newCategoryNameAtom] = categoryNameSection; + if ( newCategory != NULL ) { + assert(strcmp(newCategory->section().sectionName(), "__objc_const") == 0); + categoryNameSection->atoms.push_back(newCategory); + state.atomToSection[newCategory] = categoryNameSection; + categoryAtom = newCategory; + ObjCData::setPointerInContent(state, categoryListElementAtom, 0, newCategory); + } + } +#endif + + // if any category adds instance methods, generate new merged method list, and replace + if ( OptimizeCategories::hasInstanceMethods(state, categories) ) { + const ld::Atom* newInstanceMethodListAtom = new MethodListAtom(state, nullptr, false, categories, deadAtoms); + const ld::Atom* newCategory = Category::setInstanceMethods(state, categoryAtom, newInstanceMethodListAtom, deadAtoms); + // add new method list to final sections + methodListSection->atoms.push_back(newInstanceMethodListAtom); + state.atomToSection[newInstanceMethodListAtom] = methodListSection; + if ( newCategory != NULL ) { + assert(strcmp(newCategory->section().sectionName(), "__objc_const") == 0); + methodListSection->atoms.push_back(newCategory); + state.atomToSection[newCategory] = methodListSection; + categoryAtom = newCategory; + ObjCData::setPointerInContent(state, categoryListElementAtom, 0, newCategory); + } + } + // if any category adds class methods, generate new merged method list, and replace + if ( OptimizeCategories::hasClassMethods(state, categories) ) { + const ld::Atom* newClassMethodListAtom = new MethodListAtom(state, nullptr, true, categories, deadAtoms); + const ld::Atom* newCategory = Category::setClassMethods(state, categoryAtom, newClassMethodListAtom, deadAtoms); + // add new method list to final sections + methodListSection->atoms.push_back(newClassMethodListAtom); + state.atomToSection[newClassMethodListAtom] = methodListSection; + if ( newCategory != NULL ) { + assert(strcmp(newCategory->section().sectionName(), "__objc_const") == 0); + methodListSection->atoms.push_back(newCategory); + state.atomToSection[newCategory] = methodListSection; + categoryAtom = newCategory; + ObjCData::setPointerInContent(state, categoryListElementAtom, 0, newCategory); + } + } + // if any category adds protocols, generate new merged protocol list, and replace + if ( OptimizeCategories::hasProtocols(state, categories) ) { + const ld::Atom* newProtocolListAtom = new ProtocolListAtom(state, nullptr, categories, deadAtoms); + const ld::Atom* newCategory = Category::setProtocols(state, categoryAtom, newProtocolListAtom, deadAtoms); + // add new protocol list to final sections + methodListSection->atoms.push_back(newProtocolListAtom); + state.atomToSection[newProtocolListAtom] = methodListSection; + if ( newCategory != NULL ) { + assert(strcmp(newCategory->section().sectionName(), "__objc_const") == 0); + methodListSection->atoms.push_back(newCategory); + state.atomToSection[newCategory] = methodListSection; + categoryAtom = newCategory; + ObjCData::setPointerInContent(state, categoryListElementAtom, 0, newCategory); + } + } + // if any category adds instance properties, generate new merged property list, and replace + if ( OptimizeCategories::hasInstanceProperties(state, categories) ) { + const ld::Atom* newPropertyListAtom = new PropertyListAtom(state, nullptr, categories, deadAtoms, PropertyListAtom::PropertyKind::InstanceProperties); + const ld::Atom* newCategory = Category::setInstanceProperties(state, categoryAtom, newPropertyListAtom, deadAtoms); + // add new protocol list to final sections + methodListSection->atoms.push_back(newPropertyListAtom); + state.atomToSection[newPropertyListAtom] = methodListSection; + if ( newCategory != NULL ) { + assert(strcmp(newCategory->section().sectionName(), "__objc_const") == 0); + methodListSection->atoms.push_back(newCategory); + state.atomToSection[newCategory] = methodListSection; + categoryAtom = newCategory; + ObjCData::setPointerInContent(state, categoryListElementAtom, 0, newCategory); + } + } + // if any category adds class properties, generate new merged property list, and replace + if ( OptimizeCategories::hasClassProperties(state, categories) ) { + const ld::Atom* newPropertyListAtom = new PropertyListAtom(state, nullptr, categories, deadAtoms, PropertyListAtom::PropertyKind::ClassProperties); + const ld::Atom* newCategory = Category::setClassProperties(state, categoryAtom, newPropertyListAtom, deadAtoms); + // add new protocol list to final sections + methodListSection->atoms.push_back(newPropertyListAtom); + state.atomToSection[newPropertyListAtom] = methodListSection; + if ( newCategory != NULL ) { + assert(strcmp(newCategory->section().sectionName(), "__objc_const") == 0); + methodListSection->atoms.push_back(newCategory); + state.atomToSection[newCategory] = methodListSection; + categoryAtom = newCategory; + ObjCData::setPointerInContent(state, categoryListElementAtom, 0, newCategory); + } + } + } + } + + if ( !classToCategories.empty() || !externalClassToCategories.empty() ) { // remove dead atoms for (std::vector::iterator sit=state.sections.begin(); sit != state.sections.end(); ++sit) { ld::Internal::FinalSection* sect = *sit; @@ -967,6 +1407,25 @@ void OptimizeCategories::doit(const Options& opts, ld::Internal& state) } +template +CategoryNameAtom::CategoryNameAtom(ld::Internal& state, const std::vector* categories) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeUnclassified, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)), _file(categories->front()->file()) +{ + for (const ld::Atom* categoryAtom : *categories) { + const char* name = (const char*)Category::getName(state, categoryAtom)->rawContentPointer(); + if (!name) + continue; + if (_categoryName.empty()) { + _categoryName = name; + } else { + _categoryName = _categoryName + "," + name; + } + } +} + + template MethodListAtom::MethodListAtom(ld::Internal& state, const ld::Atom* baseMethodList, bool meta, const std::vector* categories, std::set& deadAtoms) @@ -1037,12 +1496,12 @@ MethodListAtom::MethodListAtom(ld::Internal& state, const ld::Atom* baseMetho if ( baseMethodListMethodNameAtoms.count(target) != 0 ) { warning("%s method '%s' in category from %s overrides method from class in %s", (meta ? "meta" : "instance"), target->rawContentPointer(), - categoryMethodListAtom->file()->path(), baseMethodList->file()->path() ); + categoryMethodListAtom->safeFilePath(), baseMethodList->safeFilePath() ); } if ( categoryMethodNameAtoms.count(target) != 0 ) { warning("%s method '%s' in category from %s conflicts with same method from another category", (meta ? "meta" : "instance"), target->rawContentPointer(), - categoryMethodListAtom->file()->path()); + categoryMethodListAtom->safeFilePath()); } categoryMethodNameAtoms.insert(target); } @@ -1120,7 +1579,7 @@ ProtocolListAtom::ProtocolListAtom(ld::Internal& state, const ld::Atom* baseP template PropertyListAtom::PropertyListAtom(ld::Internal& state, const ld::Atom* basePropertyList, - const std::vector* categories, std::set& deadAtoms) + const std::vector* categories, std::set& deadAtoms, PropertyKind kind) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeUnclassified, symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), _file(NULL), _propertyCount(0) @@ -1135,7 +1594,7 @@ PropertyListAtom::PropertyListAtom(ld::Internal& state, const ld::Atom* baseP fixupCount = basePropertyList->fixupsEnd() - basePropertyList->fixupsBegin(); } for (std::vector::const_iterator ait=categories->begin(); ait != categories->end(); ++ait) { - const ld::Atom* categoryPropertyListAtom = Category::getProperties(state, *ait); + const ld::Atom* categoryPropertyListAtom = kind == PropertyKind::ClassProperties ? Category::getClassProperties(state, *ait) : Category::getInstanceProperties(state, *ait); if ( categoryPropertyListAtom != NULL ) { _propertyCount += PropertyList::count(state, categoryPropertyListAtom); fixupCount += (categoryPropertyListAtom->fixupsEnd() - categoryPropertyListAtom->fixupsBegin()); @@ -1152,7 +1611,7 @@ PropertyListAtom::PropertyListAtom(ld::Internal& state, const ld::Atom* baseP _fixups.reserve(fixupCount); uint32_t slide = 0; for (std::vector::const_iterator it=categories->begin(); it != categories->end(); ++it) { - const ld::Atom* categoryPropertyListAtom = Category::getProperties(state, *it); + const ld::Atom* categoryPropertyListAtom = kind == PropertyKind::ClassProperties ? Category::getClassProperties(state, *it) : Category::getInstanceProperties(state, *it); if ( categoryPropertyListAtom != NULL ) { for (ld::Fixup::iterator fit=categoryPropertyListAtom->fixupsBegin(); fit != categoryPropertyListAtom->fixupsEnd(); ++fit) { ld::Fixup fixup = *fit; @@ -1179,85 +1638,106 @@ PropertyListAtom::PropertyListAtom(ld::Internal& state, const ld::Atom* baseP } +template +bool scanCategories(ld::Internal& state) +{ + bool warned = false; + bool haveCategoriesWithoutClassPropertyStorage = false; + for (std::vector::iterator sit=state.sections.begin(); sit != state.sections.end(); ++sit) { + ld::Internal::FinalSection* sect = *sit; + if ( sect->type() == ld::Section::typeObjC2CategoryList ) { + const char* aFileWithCategorysWithNonNullClassProperties = nullptr; + for (std::vector::iterator ait=sect->atoms.begin(); ait != sect->atoms.end(); ++ait) { + const ld::Atom* categoryListElementAtom = *ait; + bool hasAddend; + const ld::Atom* categoryAtom = ObjCData::getPointerInContent(state, categoryListElementAtom, 0, &hasAddend); + + if (Category::getClassProperties(state, categoryAtom)) { + aFileWithCategorysWithNonNullClassProperties = categoryAtom->safeFilePath(); + } -void doPass(const Options& opts, ld::Internal& state) -{ - // only make image info section if objc was used - if ( state.objcObjectConstraint != ld::File::objcConstraintNone ) { - - // verify dylibs are GC compatible with object files - if ( state.objcObjectConstraint != state.objcDylibConstraint ) { - if ( (state.objcDylibConstraint == ld::File::objcConstraintRetainRelease) - && (state.objcObjectConstraint == ld::File::objcConstraintGC) ) { - throw "Linked dylibs built for retain/release but object files built for GC-only"; - } - else if ( (state.objcDylibConstraint == ld::File::objcConstraintGC) - && (state.objcObjectConstraint == ld::File::objcConstraintRetainRelease) ) { - throw "Linked dylibs built for GC-only but object files built for retain/release"; + if ( const ld::relocatable::File* objFile = dynamic_cast(categoryAtom->file()) ) { + if ( !objFile->objcHasCategoryClassPropertiesField() ) { + haveCategoriesWithoutClassPropertyStorage = true; + if ( aFileWithCategorysWithNonNullClassProperties ) { + // Complain about mismatched category ABI. + // These can't be combined into a single linkage unit because there is only one size indicator for all categories in the file. + // If there is a mismatch then we don't set the HasCategoryClassProperties bit in the output file, + // which has at runtime causes any class property metadata that was present to be ignored. + if ( !warned ) { + warning("Incompatible Objective-C category definitions. Some category metadata may be lost. '%s' and '%s built with different compilers", + aFileWithCategorysWithNonNullClassProperties, categoryAtom->safeFilePath()); + warned = true; + } + } + } + } } } - - const bool compaction = opts.objcGcCompaction(); - - // add image info atom - switch ( opts.architecture() ) { -#if SUPPORT_ARCH_x86_64 - case CPU_TYPE_X86_64: - state.addAtom(*new ObjCImageInfoAtom(state.objcObjectConstraint, compaction, - true, state.swiftVersion)); - break; -#endif -#if SUPPORT_ARCH_i386 - case CPU_TYPE_I386: - state.addAtom(*new ObjCImageInfoAtom(state.objcObjectConstraint, compaction, - opts.objCABIVersion2POverride() ? true : false, state.swiftVersion)); - break; -#endif -#if SUPPORT_ARCH_arm_any - case CPU_TYPE_ARM: - state.addAtom(*new ObjCImageInfoAtom(state.objcObjectConstraint, compaction, - true, state.swiftVersion)); - break; -#endif -#if SUPPORT_ARCH_arm64 - case CPU_TYPE_ARM64: - state.addAtom(*new ObjCImageInfoAtom(state.objcObjectConstraint, compaction, - true, state.swiftVersion)); - break; -#endif - default: - assert(0 && "unknown objc arch"); - } } + return haveCategoriesWithoutClassPropertyStorage; +} + + +template +void doPass(const Options& opts, ld::Internal& state) +{ + // Do nothing if the output has no ObjC content. + if ( !state.hasObjC ) { + return; + } + + // Search for categories that have a non-null class properties field. + // Search for categories that do not have storage for the class properties field. + bool haveCategoriesWithoutClassPropertyStorage = scanCategories(state); if ( opts.objcCategoryMerging() ) { // optimize classes defined in this linkage unit by merging in categories also in this linkage unit - switch ( opts.architecture() ) { + OptimizeCategories::doit(opts, state, haveCategoriesWithoutClassPropertyStorage); + } + + // add image info atom + // The HasCategoryClassProperties bit is set as often as possible. + state.addAtom(*new ObjCImageInfoAtom(isObjC2, !haveCategoriesWithoutClassPropertyStorage, state.swiftVersion, state.swiftLanguageVersion)); +} + + +void doPass(const Options& opts, ld::Internal& state) +{ + switch ( opts.architecture() ) { #if SUPPORT_ARCH_x86_64 - case CPU_TYPE_X86_64: - OptimizeCategories::doit(opts, state); - break; + case CPU_TYPE_X86_64: + doPass(opts, state); + break; #endif #if SUPPORT_ARCH_i386 - case CPU_TYPE_I386: - if ( opts.objCABIVersion2POverride() ) - OptimizeCategories::doit(opts, state); - break; + case CPU_TYPE_I386: + if (opts.objCABIVersion2POverride()) { + doPass(opts, state); + } else { + doPass(opts, state); + } + break; #endif #if SUPPORT_ARCH_arm_any - case CPU_TYPE_ARM: - OptimizeCategories::doit(opts, state); - break; + case CPU_TYPE_ARM: + doPass(opts, state); + break; #endif #if SUPPORT_ARCH_arm64 - case CPU_TYPE_ARM64: - // disabled until tested + case CPU_TYPE_ARM64: +#if SUPPORT_ARCH_arm64e + if (opts.subArchitecture() == CPU_SUBTYPE_ARM64E) { + doPass(opts, state); break; + } #endif - default: - assert(0 && "unknown objc arch"); - } + doPass(opts, state); + break; +#endif + default: + assert(0 && "unknown objc arch"); } } diff --git a/cctools/ld64/src/ld/passes/order.cpp b/cctools/ld64/src/ld/passes/order.cpp index a7d31f3..5919fb8 100644 --- a/cctools/ld64/src/ld/passes/order.cpp +++ b/cctools/ld64/src/ld/passes/order.cpp @@ -234,6 +234,12 @@ bool Layout::Comparer::operator()(const ld::Atom* left, const ld::Atom* right) return rightLast; } #endif + + // sort cold functions to end + bool leftCold = left->cold(); + bool rightCold = right->cold(); + if ( leftCold != rightCold ) + return rightCold; // sort by .o order const ld::File* leftFile = left->file(); @@ -530,7 +536,7 @@ void Layout::buildOrdinalOverrideMap() AtomToOrdinal::iterator pos = _ordinalOverrideMap.find(nextAtom); if ( pos == _ordinalOverrideMap.end() ) { _ordinalOverrideMap[nextAtom] = index++; - if (_s_log ) fprintf(stderr, "override ordinal %u assigned to %s in cluster from %s\n", index, nextAtom->name(), nextAtom->file()->path()); + if (_s_log ) fprintf(stderr, "override ordinal %u assigned to %s in cluster from %s\n", index, nextAtom->name(), nextAtom->safeFilePath()); } else { if (_s_log ) fprintf(stderr, "could not order %s as %u because it was already laid out earlier by %s as %u\n", @@ -540,7 +546,7 @@ void Layout::buildOrdinalOverrideMap() } else { _ordinalOverrideMap[atom] = index; - if (_s_log ) fprintf(stderr, "override ordinal %u assigned to %s from %s\n", index, atom->name(), atom->file()->path()); + if (_s_log ) fprintf(stderr, "override ordinal %u assigned to %s from %s\n", index, atom->name(), atom->safeFilePath()); } ++matchCount; } @@ -617,10 +623,20 @@ void Layout::doPass() // sort atoms in each section for (std::vector::iterator sit=_state.sections.begin(); sit != _state.sections.end(); ++sit) { ld::Internal::FinalSection* sect = *sit; - if ( sect->type() == ld::Section::typeTempAlias ) - continue; - if ( log ) fprintf(stderr, "sorting section %s\n", sect->sectionName()); - std::sort(sect->atoms.begin(), sect->atoms.end(), _comparer); + switch ( sect->type() ) { + case ld::Section::typeTempAlias: + case ld::Section::typeStub: + case ld::Section::typeLazyPointer: + case ld::Section::typeLazyPointerClose: + case ld::Section::typeStubClose: + case ld::Section::typeNonLazyPointer: + // these sections are already sorted by pass that created them + break; + default: + if ( log ) fprintf(stderr, "sorting section %s\n", sect->sectionName()); + std::sort(sect->atoms.begin(), sect->atoms.end(), _comparer); + break; + } } if ( log ) { diff --git a/cctools/ld64/src/ld/passes/stubs/stub_arm.hpp b/cctools/ld64/src/ld/passes/stubs/stub_arm.hpp index 02ae454..7149eb2 100644 --- a/cctools/ld64/src/ld/passes/stubs/stub_arm.hpp +++ b/cctools/ld64/src/ld/passes/stubs/stub_arm.hpp @@ -57,22 +57,22 @@ class ImageCachePointerAtom : public ld::Atom { public: ImageCachePointerAtom(ld::passes::stubs::Pass& pass) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, - ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, - symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)) { pass.addAtom(*this); } + ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified, + symbolTableIn, false, false, false, ld::Atom::Alignment(2)) { pass.addAtom(*this); } virtual const ld::File* file() const { return NULL; } - virtual const char* name() const { return "non-lazy pointer"; } + virtual const char* name() const { return "__dyld_private"; } virtual uint64_t size() const { return 4; } virtual uint64_t objectAddress() const { return 0; } virtual void copyRawContent(uint8_t buffer[]) const { } virtual void setScope(Scope) { } private: - + static ld::Section _s_section; }; -ld::Section ImageCachePointerAtom::_s_section("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer); +ld::Section ImageCachePointerAtom::_s_section("__DATA", "__data", ld::Section::typeUnclassified); @@ -144,12 +144,12 @@ ld::Section StubHelperHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Sect class StubHelperAtom : public ld::Atom { public: StubHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, - const ld::Atom* lazyPointer) + const ld::Atom* lazyPointer, bool stubToResolver) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), _stubTo(stubTo), - _fixup1(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARMBranch24, helperHelper(pass)), + _fixup1(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARMBranch24, helperHelper(pass, *this, stubToResolver)), _fixup2(8, ld::Fixup::k1of2, ld::Fixup::kindSetLazyOffset, lazyPointer), _fixup3(8, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32) { } @@ -167,8 +167,11 @@ public: virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } private: - static ld::Atom* helperHelper(ld::passes::stubs::Pass& pass) { - if ( pass.compressedHelperHelper == NULL ) + static ld::Atom* helperHelper(ld::passes::stubs::Pass& pass, StubHelperAtom& stub, bool stubToResolver) { + // hack for resolvers in chained fixups. StubHelper is not used by needs to be constructed, so use dummy values + if ( stubToResolver ) + return &stub; + if ( pass.compressedHelperHelper == NULL ) pass.compressedHelperHelper = new StubHelperHelperAtom(pass); return pass.compressedHelperHelper; } @@ -240,7 +243,7 @@ public: ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeLazyPointer, symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), _stubTo(stubTo), - _helper(pass, stubTo, this), + _helper(pass, stubTo, this, stubToResolver), _resolverHelper(pass, stubTo, this), _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, stubToResolver ? &_resolverHelper : (stubToGlobalWeakDef ? &stubTo : &_helper)), @@ -293,12 +296,14 @@ ld::Section LazyPointerAtom::_s_sectionWeak("__DATA", "__la_weak_ptr", ld::Secti class NonLazyPointerAtom : public ld::Atom { public: - NonLazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo) + NonLazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool weakImport) : ld::Atom(_s_section, ld::Atom::definitionRegular, - ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeLazyPointer, + ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), _stubTo(stubTo), _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, &stubTo) { + _fixup1.weakImport = weakImport; pass.addAtom(*this); } @@ -324,12 +329,13 @@ ld::Section NonLazyPointerAtom::_s_section("__DATA", "__nl_symbol_ptr", ld::Sect class StubPICKextAtom : public ld::Atom { public: - StubPICKextAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo) + StubPICKextAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool weakImport) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, - symbolTableIn, false, true, false, ld::Atom::Alignment(2)), + symbolTableNotIn, false, true, false, ld::Atom::Alignment(2)), _stubTo(stubTo), - _nonLazyPointer(pass, stubTo), + _nonLazyPointer(pass, stubTo, weakImport), _fixup1(0, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, &_nonLazyPointer), _fixup2(0, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, this), _fixup3(0, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, 12), @@ -338,8 +344,8 @@ public: _fixup6(4, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, this), _fixup7(4, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, 12), _fixup8(4, ld::Fixup::k4of4, ld::Fixup::kindStoreThumbHigh16) { - pass.addAtom(*this); asprintf((char**)&_name, "%s.stub", _stubTo.name()); + pass.addAtom(*this); } virtual const ld::File* file() const { return _stubTo.file(); } @@ -493,6 +499,48 @@ private: ld::Section StubCloseAtom::_s_section("__TEXT", "__symbolstub1", ld::Section::typeStubClose); +class NonLazyStubPICAtom : public ld::Atom { +public: + NonLazyStubPICAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport, bool usingDataConst) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _stubTo(stubTo), + _nonlazyPointer(pass, stubTo, weakImport), + _fixup1(12, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, &_nonlazyPointer), + _fixup2(12, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, this), + _fixup3(12, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, 12), + _fixup4(12, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndian32) + { pass.addAtom(*this); } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _stubTo.name(); } + virtual uint64_t size() const { return 16; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + OSWriteLittleInt32(&buffer[ 0], 0, 0xe59fc004); // ldr ip, pc + 12 + OSWriteLittleInt32(&buffer[ 4], 0, 0xe08fc00c); // add ip, pc, ip + OSWriteLittleInt32(&buffer[ 8], 0, 0xe59cf000); // ldr pc, [ip] + OSWriteLittleInt32(&buffer[12], 0, 0x00000000); // .long L_foo$nonlazy_ptr - (L1$scv + 8) + } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup4)[1]; } + +private: + const ld::Atom& _stubTo; + NonLazyPointerAtom _nonlazyPointer; + ld::Fixup _fixup1; + ld::Fixup _fixup2; + ld::Fixup _fixup3; + ld::Fixup _fixup4; + + static ld::Section _s_section; +}; + +ld::Section NonLazyStubPICAtom::_s_section("__TEXT", "__picsymbolstub5", ld::Section::typeStub); + } // namespace arm diff --git a/cctools/ld64/src/ld/passes/stubs/stub_arm64.hpp b/cctools/ld64/src/ld/passes/stubs/stub_arm64.hpp index 09de1fa..9f84d5c 100644 --- a/cctools/ld64/src/ld/passes/stubs/stub_arm64.hpp +++ b/cctools/ld64/src/ld/passes/stubs/stub_arm64.hpp @@ -60,22 +60,22 @@ class ImageCachePointerAtom : public ld::Atom { public: ImageCachePointerAtom(ld::passes::stubs::Pass& pass) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, - ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, - symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)) { pass.addAtom(*this); } + ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified, + symbolTableIn, false, false, false, ld::Atom::Alignment(3)) { pass.addAtom(*this); } virtual const ld::File* file() const { return NULL; } - virtual const char* name() const { return "image cache pointer"; } + virtual const char* name() const { return "__dyld_private"; } virtual uint64_t size() const { return 8; } virtual uint64_t objectAddress() const { return 0; } virtual void copyRawContent(uint8_t buffer[]) const { } virtual void setScope(Scope) { } private: - + static ld::Section _s_section; }; -ld::Section ImageCachePointerAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); +ld::Section ImageCachePointerAtom::_s_section("__DATA", "__data", ld::Section::typeUnclassified); @@ -145,12 +145,12 @@ ld::Section StubHelperHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Sect class StubHelperAtom : public ld::Atom { public: StubHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom* lazyPointer, - const ld::Atom& stubTo) + const ld::Atom& stubTo, bool stubToResolver) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, - symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)), + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), _stubTo(stubTo), - _fixup1(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Branch26, helperHelper(pass)), + _fixup1(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Branch26, helperHelper(pass, *this, stubToResolver)), _fixup2(8, ld::Fixup::k1of2, ld::Fixup::kindSetLazyOffset, lazyPointer), _fixup3(8, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32) { } @@ -168,7 +168,10 @@ public: virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } private: - static ld::Atom* helperHelper(ld::passes::stubs::Pass& pass) { + static ld::Atom* helperHelper(ld::passes::stubs::Pass& pass, StubHelperAtom& stub, bool stubToResolver) { + // hack for resolvers in chained fixups. StubHelper is not used by needs to be constructed, so use dummy values + if ( stubToResolver ) + return &stub; if ( pass.compressedHelperHelper == NULL ) pass.compressedHelperHelper = new StubHelperHelperAtom(pass); return pass.compressedHelperHelper; @@ -191,7 +194,7 @@ public: const ld::Atom& stubTo) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, - symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)), + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), _stubTo(stubTo), _fixup1(24, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Branch26, &stubTo), _fixup2(28, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, lazyPointer), @@ -247,7 +250,7 @@ public: ld::Atom::scopeTranslationUnit, ld::Atom::typeLazyPointer, symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), _stubTo(stubTo), - _helper(pass, this, stubTo), + _helper(pass, this, stubTo, stubToResolver), _resolverHelper(pass, this, stubTo), _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, stubToResolver ? &_resolverHelper : @@ -301,7 +304,7 @@ public: bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport, bool dataConstUsed) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, - symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)), + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), _stubTo(stubTo), _lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport, dataConstUsed), _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_lazyPointer), @@ -338,12 +341,14 @@ ld::Section StubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub); class NonLazyPointerAtom : public ld::Atom { public: - NonLazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo) + NonLazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool weakImport) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), _stubTo(stubTo), _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, &stubTo) { + _fixup1.weakImport = weakImport; pass.addAtom(*this); } @@ -366,18 +371,19 @@ private: ld::Section NonLazyPointerAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); -class KextStubAtom : public ld::Atom { +class NonLazyStubAtom : public ld::Atom { public: - KextStubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo) + NonLazyStubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool weakImport) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, - symbolTableIn, false, false, false, ld::Atom::Alignment(1)), + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), _stubTo(stubTo), - _nonLazyPointer(pass, stubTo), + _nonLazyPointer(pass, stubTo, weakImport), _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_nonLazyPointer), - _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_nonLazyPointer) { - pass.addAtom(*this); + _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_nonLazyPointer) { asprintf((char**)&_name, "%s.stub", _stubTo.name()); + pass.addAtom(*this); } virtual const ld::File* file() const { return _stubTo.file(); } @@ -403,8 +409,8 @@ private: static ld::Section _s_section; }; -ld::Section KextStubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeCode); +ld::Section NonLazyStubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub); -} // namespace x86_64 +} // namespace arm64 diff --git a/cctools/ld64/src/ld/passes/stubs/stub_arm64_32.hpp b/cctools/ld64/src/ld/passes/stubs/stub_arm64_32.hpp new file mode 100644 index 0000000..6bd0647 --- /dev/null +++ b/cctools/ld64/src/ld/passes/stubs/stub_arm64_32.hpp @@ -0,0 +1,406 @@ +/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- + * + * Copyright (c) 2010-2013 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// already in ld::passes::stubs namespace + +#if SUPPORT_ARCH_arm64_32 + +// already in ld::passes::stubs namespace +namespace arm64_32 { + + + +class FastBindingPointerAtom : public ld::Atom { +public: + FastBindingPointerAtom(ld::passes::stubs::Pass& pass) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _fixup(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, + pass.internal()->compressedFastBinderProxy) + { pass.addAtom(*this); } + + virtual const ld::File* file() const { return NULL; } + virtual const char* name() const { return "fast binder pointer"; } + virtual uint64_t size() const { return 4; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup)[1]; } + +private: + mutable ld::Fixup _fixup; + + static ld::Section _s_section; +}; + +ld::Section FastBindingPointerAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); + + +class ImageCachePointerAtom : public ld::Atom { +public: + ImageCachePointerAtom(ld::passes::stubs::Pass& pass) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified, + symbolTableIn, false, false, false, ld::Atom::Alignment(2)) { pass.addAtom(*this); } + + virtual const ld::File* file() const { return NULL; } + virtual const char* name() const { return "__dyld_private"; } + virtual uint64_t size() const { return 4; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual void setScope(Scope) { } + +private: + + static ld::Section _s_section; +}; + +ld::Section ImageCachePointerAtom::_s_section("__DATA", "__data", ld::Section::typeUnclassified); + + + + + +// +// The stub-helper-helper is the common code factored out of each helper function. +// It is in the same section as the stub-helpers. +// Similar to the PLT0 entry in ELF. +// +class StubHelperHelperAtom : public ld::Atom { +public: + StubHelperHelperAtom(ld::passes::stubs::Pass& pass) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, compressedImageCache(pass)), + _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, compressedImageCache(pass)), + _fixup3(12, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, compressedFastBinder(pass)), + _fixup4(16, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, compressedFastBinder(pass)), + _fixup5(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_ADD, 0, 4), + _fixup6(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_LDR, 12, 16) + { pass.addAtom(*this); } + + virtual ld::File* file() const { return NULL; } + virtual const char* name() const { return "helper helper"; } + virtual uint64_t size() const { return 24; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + OSWriteLittleInt32(&buffer[ 0], 0, 0x90000011); // ADRP X17, dyld_mageLoaderCache@page + OSWriteLittleInt32(&buffer[ 4], 0, 0x91000231); // ADD X17, X17, dyld_mageLoaderCache@pageoff + OSWriteLittleInt32(&buffer[ 8], 0, 0xA9BF47F0); // STP X16/X17, [SP, #-16]! + OSWriteLittleInt32(&buffer[12], 0, 0x90000010); // ADRP X16, _fast_lazy_bind@page + OSWriteLittleInt32(&buffer[16], 0, 0xB9400210); // LDR W16, [X16,_fast_lazy_bind@pageoff] + OSWriteLittleInt32(&buffer[20], 0, 0xD61F0200); // BR X16 + } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup6)[1]; } + +private: + static ld::Atom* compressedImageCache(ld::passes::stubs::Pass& pass) { + if ( pass.compressedImageCache == NULL ) + pass.compressedImageCache = new ImageCachePointerAtom(pass); + return pass.compressedImageCache; + } + static ld::Atom* compressedFastBinder(ld::passes::stubs::Pass& pass) { + if ( pass.compressedFastBinderPointer == NULL ) + pass.compressedFastBinderPointer = new FastBindingPointerAtom(pass); + return pass.compressedFastBinderPointer; + } + + mutable ld::Fixup _fixup1; + ld::Fixup _fixup2; + ld::Fixup _fixup3; + ld::Fixup _fixup4; + ld::Fixup _fixup5; + ld::Fixup _fixup6; + + static ld::Section _s_section; +}; + +ld::Section StubHelperHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper); + + + +class StubHelperAtom : public ld::Atom { +public: + StubHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom* lazyPointer, + const ld::Atom& stubTo, bool stubToResolver) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _stubTo(stubTo), + _fixup1(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Branch26, helperHelper(pass, *this, stubToResolver)), + _fixup2(8, ld::Fixup::k1of2, ld::Fixup::kindSetLazyOffset, lazyPointer), + _fixup3(8, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32) { } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _stubTo.name(); } + virtual uint64_t size() const { return 12; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + OSWriteLittleInt32(&buffer[0], 0, 0x18000050); // LDR W16, L0 + OSWriteLittleInt32(&buffer[4], 0, 0x14000000); // B helperhelper + OSWriteLittleInt32(&buffer[8], 0, 0x00000000); // L0: .long 0 + } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } + +private: + static ld::Atom* helperHelper(ld::passes::stubs::Pass& pass, StubHelperAtom& stub, bool stubToResolver) { + // hack for resolvers in chained fixups. StubHelper is not used by needs to be constructed, so use dummy values + if ( stubToResolver ) + return &stub; + if ( pass.compressedHelperHelper == NULL ) + pass.compressedHelperHelper = new StubHelperHelperAtom(pass); + return pass.compressedHelperHelper; + } + + const ld::Atom& _stubTo; + mutable ld::Fixup _fixup1; + ld::Fixup _fixup2; + ld::Fixup _fixup3; + + static ld::Section _s_section; +}; + +ld::Section StubHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper); + + +class ResolverHelperAtom : public ld::Atom { +public: + ResolverHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom* lazyPointer, + const ld::Atom& stubTo) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _stubTo(stubTo), + _fixup1(24, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Branch26, &stubTo), + _fixup2(28, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, lazyPointer), + _fixup3(32, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, lazyPointer) { } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _stubTo.name(); } + virtual uint64_t size() const { return 68; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + OSWriteLittleInt32(&buffer[ 0], 0, 0xa9bf7bfd); // stp fp, lr, [sp, #-16]! + OSWriteLittleInt32(&buffer[ 4], 0, 0x910003fd); // mov fp, sp + OSWriteLittleInt32(&buffer[ 8], 0, 0xa9bf03e1); // stp x1, x0, [sp, #-16]! + OSWriteLittleInt32(&buffer[12], 0, 0xa9bf0be3); // stp x3, x2, [sp, #-16]! + OSWriteLittleInt32(&buffer[16], 0, 0xa9bf13e5); // stp x5, x4, [sp, #-16]! + OSWriteLittleInt32(&buffer[20], 0, 0xa9bf1be7); // stp x7, x6, [sp, #-16]! + OSWriteLittleInt32(&buffer[24], 0, 0x94000000); // bl _foo + OSWriteLittleInt32(&buffer[28], 0, 0x90000010); // adrp x16, lazy_pointer@PAGE + OSWriteLittleInt32(&buffer[32], 0, 0x91000210); // add x16, x16, lazy_pointer@PAGEOFF + OSWriteLittleInt32(&buffer[36], 0, 0xb9000200); // str w0, [x16] + OSWriteLittleInt32(&buffer[40], 0, 0xaa0003f0); // mov x16, x0 + OSWriteLittleInt32(&buffer[44], 0, 0xa8c11be7); // ldp x7, x6, [sp], #16 + OSWriteLittleInt32(&buffer[48], 0, 0xa8c113e5); // ldp x5, x4, [sp], #16 + OSWriteLittleInt32(&buffer[52], 0, 0xa8c10be3); // ldp x3, x2, [sp], #16 + OSWriteLittleInt32(&buffer[56], 0, 0xa8c103e1); // ldp x1, x0, [sp], #16 + OSWriteLittleInt32(&buffer[60], 0, 0xa8c17bfd); // ldp fp, lr, [sp], #16 + OSWriteLittleInt32(&buffer[64], 0, 0xd61f0200); // br x16 + } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } + +private: + + const ld::Atom& _stubTo; + mutable ld::Fixup _fixup1; + ld::Fixup _fixup2; + ld::Fixup _fixup3; + + static ld::Section _s_section; +}; + +ld::Section ResolverHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper); + + + +class LazyPointerAtom : public ld::Atom { +public: + LazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeTranslationUnit, ld::Atom::typeLazyPointer, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _stubTo(stubTo), + _helper(pass, this, stubTo, stubToResolver), + _resolverHelper(pass, this, stubTo), + _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, + stubToResolver ? &_resolverHelper : + (stubToGlobalWeakDef ? &stubTo : &_helper)), + _fixup2(0, ld::Fixup::k1of1, ld::Fixup::kindLazyTarget, &stubTo) { + _fixup2.weakImport = weakImport; pass.addAtom(*this); + if ( stubToResolver ) + pass.addAtom(_resolverHelper); + else if ( !stubToGlobalWeakDef ) + pass.addAtom(_helper); + } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _stubTo.name(); } + virtual uint64_t size() const { return 4; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; } + +private: + const ld::Atom& _stubTo; + StubHelperAtom _helper; + ResolverHelperAtom _resolverHelper; + mutable ld::Fixup _fixup1; + ld::Fixup _fixup2; + + static ld::Section _s_section; +}; + +ld::Section LazyPointerAtom::_s_section("__DATA", "__la_symbol_ptr", ld::Section::typeLazyPointer); + + +class StubAtom : public ld::Atom { +public: + StubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _stubTo(stubTo), + _lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport), + _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_lazyPointer), + _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_lazyPointer), + _fixup3(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_LDR, 0, 4) + { pass.addAtom(*this); } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _stubTo.name(); } + virtual uint64_t size() const { return 12; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + OSWriteLittleInt32(&buffer[0], 0, 0x90000010); // ADRP X16, lazy_pointer@page + OSWriteLittleInt32(&buffer[4], 0, 0xB9400210); // LDR W16, [X16, lazy_pointer@pageoff] + OSWriteLittleInt32(&buffer[8], 0, 0xD61F0200); // BR X16 + } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } + +private: + const ld::Atom& _stubTo; + LazyPointerAtom _lazyPointer; + mutable ld::Fixup _fixup1; + mutable ld::Fixup _fixup2; + mutable ld::Fixup _fixup3; + + static ld::Section _s_section; +}; + +ld::Section StubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub); + + + +class NonLazyPointerAtom : public ld::Atom { +public: + NonLazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool weakImport) + : ld::Atom(_s_section, ld::Atom::definitionRegular, + ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _stubTo(stubTo), + _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, &stubTo) { + _fixup1.weakImport = weakImport; + pass.addAtom(*this); + } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _stubTo.name(); } + virtual uint64_t size() const { return 4; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup1)[1]; } + +private: + const ld::Atom& _stubTo; + ld::Fixup _fixup1; + + static ld::Section _s_section; +}; + +ld::Section NonLazyPointerAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); + + +class NonLazyStubAtom : public ld::Atom { +public: + NonLazyStubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool weakImport) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _stubTo(stubTo), + _nonLazyPointer(pass, stubTo, weakImport), + _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_nonLazyPointer), + _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_nonLazyPointer) { + asprintf((char**)&_name, "%s.stub", _stubTo.name()); + pass.addAtom(*this); + } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _name; } + virtual uint64_t size() const { return 12; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + OSWriteLittleInt32(&buffer[0], 0, 0x90000010); // ADRP X16, non_lazy_pointer@page + OSWriteLittleInt32(&buffer[4], 0, 0xB9400210); // LDR W16, [X16, non_lazy_pointer@pageoff] + OSWriteLittleInt32(&buffer[8], 0, 0xD61F0200); // BR X16 + } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; } + +private: + const ld::Atom& _stubTo; + const char* _name; + NonLazyPointerAtom _nonLazyPointer; + mutable ld::Fixup _fixup1; + mutable ld::Fixup _fixup2; + + static ld::Section _s_section; +}; + +ld::Section NonLazyStubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub); + + +} // namespace arm64_32 +#endif diff --git a/cctools/ld64/src/ld/passes/stubs/stub_arm64e.hpp b/cctools/ld64/src/ld/passes/stubs/stub_arm64e.hpp new file mode 100644 index 0000000..57b2533 --- /dev/null +++ b/cctools/ld64/src/ld/passes/stubs/stub_arm64e.hpp @@ -0,0 +1,425 @@ +/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- + * + * Copyright (c) 2010-2013 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// already in ld::passes::stubs namespace + +#if SUPPORT_ARCH_arm64e + +// already in ld::passes::stubs namespace +namespace arm64e { + + + +class FastBindingPointerAtom : public ld::Atom { +public: + FastBindingPointerAtom(ld::passes::stubs::Pass& pass) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), + _fixup(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, + pass.internal()->compressedFastBinderProxy) + { pass.addAtom(*this); } + + virtual const ld::File* file() const { return NULL; } + virtual const char* name() const { return "fast binder pointer"; } + virtual uint64_t size() const { return 8; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup)[1]; } + +private: + mutable ld::Fixup _fixup; + + static ld::Section _s_section; +}; + +ld::Section FastBindingPointerAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); + + +class ImageCachePointerAtom : public ld::Atom { +public: + ImageCachePointerAtom(ld::passes::stubs::Pass& pass) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified, + symbolTableIn, false, false, false, ld::Atom::Alignment(3)) { pass.addAtom(*this); } + + virtual const ld::File* file() const { return NULL; } + virtual const char* name() const { return "__dyld_private"; } + virtual uint64_t size() const { return 8; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual void setScope(Scope) { } + +private: + + static ld::Section _s_section; +}; + +ld::Section ImageCachePointerAtom::_s_section("__DATA", "__data", ld::Section::typeUnclassified); + + + + + +// +// The stub-helper-helper is the common code factored out of each helper function. +// It is in the same section as the stub-helpers. +// Similar to the PLT0 entry in ELF. +// +class StubHelperHelperAtom : public ld::Atom { +public: + StubHelperHelperAtom(ld::passes::stubs::Pass& pass) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, compressedImageCache(pass)), + _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, compressedImageCache(pass)), + _fixup3(12, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, compressedFastBinder(pass)), + _fixup4(16, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, compressedFastBinder(pass)), + _fixup5(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_ADD, 0, 4), + _fixup6(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_LDR, 12, 16) + { pass.addAtom(*this); } + + virtual ld::File* file() const { return NULL; } + virtual const char* name() const { return "helper helper"; } + virtual uint64_t size() const { return 24; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + OSWriteLittleInt32(&buffer[ 0], 0, 0x90000011); // ADRP X17, dyld_mageLoaderCache@page + OSWriteLittleInt32(&buffer[ 4], 0, 0x91000231); // ADD X17, X17, dyld_mageLoaderCache@pageoff + OSWriteLittleInt32(&buffer[ 8], 0, 0xA9BF47F0); // STP X16/X17, [SP, #-16]! + OSWriteLittleInt32(&buffer[12], 0, 0x90000010); // ADRP X16, _fast_lazy_bind@page + OSWriteLittleInt32(&buffer[16], 0, 0xF9400210); // LDR X16, [X16,_fast_lazy_bind@pageoff] + OSWriteLittleInt32(&buffer[20], 0, 0xD61F0200); // BR X16 + } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup6)[1]; } + +private: + static ld::Atom* compressedImageCache(ld::passes::stubs::Pass& pass) { + if ( pass.compressedImageCache == NULL ) + pass.compressedImageCache = new ImageCachePointerAtom(pass); + return pass.compressedImageCache; + } + static ld::Atom* compressedFastBinder(ld::passes::stubs::Pass& pass) { + if ( pass.compressedFastBinderPointer == NULL ) + pass.compressedFastBinderPointer = new FastBindingPointerAtom(pass); + return pass.compressedFastBinderPointer; + } + + mutable ld::Fixup _fixup1; + ld::Fixup _fixup2; + ld::Fixup _fixup3; + ld::Fixup _fixup4; + ld::Fixup _fixup5; + ld::Fixup _fixup6; + + static ld::Section _s_section; +}; + +ld::Section StubHelperHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper); + + + +class StubHelperAtom : public ld::Atom { +public: + StubHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom* lazyPointer, + const ld::Atom& stubTo, bool stubToResolver) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _stubTo(stubTo), + _fixup1(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Branch26, helperHelper(pass, *this, stubToResolver)), + _fixup2(8, ld::Fixup::k1of2, ld::Fixup::kindSetLazyOffset, lazyPointer), + _fixup3(8, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32) { } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _stubTo.name(); } + virtual uint64_t size() const { return 12; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + OSWriteLittleInt32(&buffer[0], 0, 0x18000050); // LDR W16, L0 + OSWriteLittleInt32(&buffer[4], 0, 0x14000000); // B helperhelper + OSWriteLittleInt32(&buffer[8], 0, 0x00000000); // L0: .long 0 + } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } + +private: + static ld::Atom* helperHelper(ld::passes::stubs::Pass& pass, StubHelperAtom& stub, bool stubToResolver) { + // hack for resolvers in chained fixups. StubHelper is not used by needs to be constructed, so use dummy values + if ( stubToResolver ) + return &stub; + if ( pass.compressedHelperHelper == NULL ) + pass.compressedHelperHelper = new StubHelperHelperAtom(pass); + return pass.compressedHelperHelper; + } + + const ld::Atom& _stubTo; + mutable ld::Fixup _fixup1; + ld::Fixup _fixup2; + ld::Fixup _fixup3; + + static ld::Section _s_section; +}; + +ld::Section StubHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper); + + +class ResolverHelperAtom : public ld::Atom { +public: + ResolverHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom* lazyPointer, + const ld::Atom& stubTo) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _stubTo(stubTo), + _fixup1(24, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Branch26, &stubTo), + _fixup2(28, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, lazyPointer), + _fixup3(32, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, lazyPointer) { } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _stubTo.name(); } + virtual uint64_t size() const { return 68; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + OSWriteLittleInt32(&buffer[ 0], 0, 0xa9bf7bfd); // stp fp, lr, [sp, #-16]! + OSWriteLittleInt32(&buffer[ 4], 0, 0x910003fd); // mov fp, sp + OSWriteLittleInt32(&buffer[ 8], 0, 0xa9bf03e1); // stp x1, x0, [sp, #-16]! + OSWriteLittleInt32(&buffer[12], 0, 0xa9bf0be3); // stp x3, x2, [sp, #-16]! + OSWriteLittleInt32(&buffer[16], 0, 0xa9bf13e5); // stp x5, x4, [sp, #-16]! + OSWriteLittleInt32(&buffer[20], 0, 0xa9bf1be7); // stp x7, x6, [sp, #-16]! + OSWriteLittleInt32(&buffer[24], 0, 0x94000000); // bl _foo + OSWriteLittleInt32(&buffer[28], 0, 0x90000010); // adrp x16, lazy_pointer@PAGE + OSWriteLittleInt32(&buffer[32], 0, 0x91000210); // add x16, x16, lazy_pointer@PAGEOFF + OSWriteLittleInt32(&buffer[36], 0, 0xf9000200); // str x0, [x16] + OSWriteLittleInt32(&buffer[40], 0, 0xaa0003f0); // mov x16, x0 + OSWriteLittleInt32(&buffer[44], 0, 0xa8c11be7); // ldp x7, x6, [sp], #16 + OSWriteLittleInt32(&buffer[48], 0, 0xa8c113e5); // ldp x5, x4, [sp], #16 + OSWriteLittleInt32(&buffer[52], 0, 0xa8c10be3); // ldp x3, x2, [sp], #16 + OSWriteLittleInt32(&buffer[56], 0, 0xa8c103e1); // ldp x1, x0, [sp], #16 + OSWriteLittleInt32(&buffer[60], 0, 0xa8c17bfd); // ldp fp, lr, [sp], #16 + OSWriteLittleInt32(&buffer[64], 0, 0xD61F0A1F); // braaz x16 + } + + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } + +private: + + const ld::Atom& _stubTo; + mutable ld::Fixup _fixup1; + ld::Fixup _fixup2; + ld::Fixup _fixup3; + + static ld::Section _s_section; +}; + +ld::Section ResolverHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper); + + + +class LazyPointerAtom : public ld::Atom { +public: + LazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport, bool dataConstUsed) + : ld::Atom(selectSection(stubToGlobalWeakDef, stubToResolver, dataConstUsed), + ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeTranslationUnit, ld::Atom::typeLazyPointer, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), + _stubTo(stubTo), + _helper(pass, this, stubTo, stubToResolver), + _resolverHelper(pass, this, stubTo), + _fixup1(0, ld::Fixup::k1of2, ld::Fixup::kindSetAuthData, (ld::Fixup::AuthData){ 0, false, ld::Fixup::AuthData::ptrauth_key_asia }), + _fixup2(0, ld::Fixup::k2of2, ld::Fixup::kindStoreTargetAddressLittleEndianAuth64, + stubToResolver ? &_resolverHelper : (stubToGlobalWeakDef ? &stubTo : &_helper)), + _fixup3(0, ld::Fixup::k1of1, ld::Fixup::kindLazyTarget, &stubTo) { + _fixup2.weakImport = weakImport; pass.addAtom(*this); + if ( stubToResolver ) + pass.addAtom(_resolverHelper); + else if ( !stubToGlobalWeakDef ) + pass.addAtom(_helper); + } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _stubTo.name(); } + virtual uint64_t size() const { return 8; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } + +private: + static ld::Section& selectSection(bool stubToGlobalWeakDef, bool stubToResolver, bool dataConstUsed) { + if ( stubToGlobalWeakDef && dataConstUsed ) + return _s_sectionWeak; + else if ( stubToResolver && dataConstUsed ) + return _s_sectionResolver; + else + return _s_section; + } + + const ld::Atom& _stubTo; + StubHelperAtom _helper; + ResolverHelperAtom _resolverHelper; + mutable ld::Fixup _fixup1; + ld::Fixup _fixup2; + ld::Fixup _fixup3; + + static ld::Section _s_section; + static ld::Section _s_sectionResolver; + static ld::Section _s_sectionWeak; +}; + +ld::Section LazyPointerAtom::_s_section("__DATA", "__la_symbol_ptr", ld::Section::typeLazyPointer); +ld::Section LazyPointerAtom::_s_sectionResolver("__DATA_DIRTY", "__la_resolver", ld::Section::typeLazyPointer); +ld::Section LazyPointerAtom::_s_sectionWeak("__DATA", "__la_weak_ptr", ld::Section::typeLazyPointer); + + +class StubAtom : public ld::Atom { +public: + StubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport, bool dataConstUsed) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _stubTo(stubTo), + _lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport, dataConstUsed), + _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_lazyPointer), + _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_lazyPointer), + _fixup3(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_LDR, 0, 4) + { pass.addAtom(*this); } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _stubTo.name(); } + virtual uint64_t size() const { return 12; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + OSWriteLittleInt32(&buffer[0], 0, 0x90000010); // ADRP X16, lazy_pointer@page + OSWriteLittleInt32(&buffer[4], 0, 0xF9400210); // LDR X16, [X16, lazy_pointer@pageoff] + OSWriteLittleInt32(&buffer[8], 0, 0xD61F0A1F); // BRAAZ X16 + } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } + +private: + const ld::Atom& _stubTo; + LazyPointerAtom _lazyPointer; + mutable ld::Fixup _fixup1; + mutable ld::Fixup _fixup2; + mutable ld::Fixup _fixup3; + + static ld::Section _s_section; +}; + +ld::Section StubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub); + + + +class NonLazyPointerAtom : public ld::Atom { +public: + NonLazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool weakImport) + : ld::Atom(_s_section, ld::Atom::definitionRegular, + ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), + _stubTo(stubTo), + _fixup1(0, ld::Fixup::k1of2, ld::Fixup::kindSetAuthData, (ld::Fixup::AuthData){ 0, true, ld::Fixup::AuthData::ptrauth_key_asia }), + _fixup2(0, ld::Fixup::k2of2, ld::Fixup::kindStoreTargetAddressLittleEndianAuth64, &stubTo) { + _fixup2.weakImport = weakImport; + pass.addAtom(*this); + } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _stubTo.name(); } + virtual uint64_t size() const { return 8; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; } + +private: + const ld::Atom& _stubTo; + ld::Fixup _fixup1; + ld::Fixup _fixup2; + + static ld::Section _s_section; +}; + +ld::Section NonLazyPointerAtom::_s_section("__DATA", "__auth_got", ld::Section::typeNonLazyPointer); + + +class NonLazyStubAtom : public ld::Atom { +public: + NonLazyStubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool weakImport) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _stubTo(stubTo), + _nonLazyPointer(pass, stubTo, weakImport), + _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_nonLazyPointer), + _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_nonLazyPointer) { + asprintf((char**)&_name, "%s.stub", _stubTo.name()); + pass.addAtom(*this); + } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _name; } + virtual uint64_t size() const { return 16; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + OSWriteLittleInt32(&buffer[ 0], 0, 0x90000011); // ADRP X17, dyld_mageLoaderCache@page + OSWriteLittleInt32(&buffer[ 4], 0, 0x91000231); // ADD X17, X17, dyld_mageLoaderCache@pageoff + OSWriteLittleInt32(&buffer[ 8], 0, 0xF9400230); // LDR X16, [X17] + OSWriteLittleInt32(&buffer[12], 0, 0xD71F0A11); // BRAA X16, X17 + } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; } + +private: + const ld::Atom& _stubTo; + const char* _name; + NonLazyPointerAtom _nonLazyPointer; + mutable ld::Fixup _fixup1; + mutable ld::Fixup _fixup2; + + static ld::Section _s_section; +}; + +ld::Section NonLazyStubAtom::_s_section("__TEXT", "__auth_stubs", ld::Section::typeStub); + + +} // namespace arm64e +#endif diff --git a/cctools/ld64/src/ld/passes/stubs/stub_x86.hpp b/cctools/ld64/src/ld/passes/stubs/stub_x86.hpp index 08879c1..25fa26d 100644 --- a/cctools/ld64/src/ld/passes/stubs/stub_x86.hpp +++ b/cctools/ld64/src/ld/passes/stubs/stub_x86.hpp @@ -60,11 +60,11 @@ class ImageCachePointerAtom : public ld::Atom { public: ImageCachePointerAtom(ld::passes::stubs::Pass& pass) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, - ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, - symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)) { pass.addAtom(*this); } + ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified, + symbolTableIn, false, false, false, ld::Atom::Alignment(2)) { pass.addAtom(*this); } virtual const ld::File* file() const { return NULL; } - virtual const char* name() const { return "image cache pointer"; } + virtual const char* name() const { return "__dyld_private"; } virtual uint64_t size() const { return 4; } virtual uint64_t objectAddress() const { return 0; } virtual void copyRawContent(uint8_t buffer[]) const { } @@ -75,7 +75,7 @@ private: static ld::Section _s_section; }; -ld::Section ImageCachePointerAtom::_s_section("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer); +ld::Section ImageCachePointerAtom::_s_section("__DATA", "__data", ld::Section::typeUnclassified); @@ -328,6 +328,89 @@ private: ld::Section StubAtom::_s_section("__TEXT", "__symbol_stub", ld::Section::typeStub); +class NonLazyPointerAtom : public ld::Atom { +public: + NonLazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& target, + bool weakImport) + : ld::Atom(_s_section, ld::Atom::definitionRegular, + ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _target(target), + _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, &target) { + _fixup1.weakImport = weakImport; + pass.addAtom(*this); + } + + virtual const ld::File* file() const { return _target.file(); } + virtual const char* name() const { return _target.name(); } + virtual uint64_t size() const { return 4; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup1)[1]; } + +private: + const ld::Atom& _target; + ld::Fixup _fixup1; + + static ld::Section _s_section; +}; + +ld::Section NonLazyPointerAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); + + +class NonLazyStubAtom : public ld::Atom { +public: + NonLazyStubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& target, + bool weakImport) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)), + _target(target), + _nonlazyPointer(pass, target, weakImport), + _fixup1(8, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, &_nonlazyPointer), + _fixup2(8, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, this), + _fixup3(8, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, 5), + _fixup4(8, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndian32) { pass.addAtom(*this); } + + virtual const ld::File* file() const { return _target.file(); } + virtual const char* name() const { return _target.name(); } + virtual uint64_t size() const { return 14; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + buffer[0] = 0xE8; // call next instruction (picbase) + buffer[1] = 0x00; + buffer[2] = 0x00; + buffer[3] = 0x00; + buffer[4] = 0x00; + buffer[5] = 0x58; // pop eax + buffer[6] = 0x8D; // lea foo$nonlazy_pointer-picbase(eax),eax + buffer[7] = 0x80; + buffer[8] = 0x00; + buffer[9] = 0x00; + buffer[10] = 0x00; + buffer[11] = 0x00; + buffer[12] = 0xFF; // jmp *(eax) + buffer[13] = 0x20; + } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup4)[1]; } + +private: + const ld::Atom& _target; + NonLazyPointerAtom _nonlazyPointer; + mutable ld::Fixup _fixup1; + ld::Fixup _fixup2; + ld::Fixup _fixup3; + ld::Fixup _fixup4; + + static ld::Section _s_section; +}; + +ld::Section NonLazyStubAtom::_s_section("__TEXT", "__symbol_stub", ld::Section::typeStub); + } // namespace x86 diff --git a/cctools/ld64/src/ld/passes/stubs/stub_x86_64.hpp b/cctools/ld64/src/ld/passes/stubs/stub_x86_64.hpp index 5031dbc..5f4fd53 100644 --- a/cctools/ld64/src/ld/passes/stubs/stub_x86_64.hpp +++ b/cctools/ld64/src/ld/passes/stubs/stub_x86_64.hpp @@ -53,29 +53,34 @@ private: static ld::Section _s_section; }; -ld::Section FastBindingPointerAtom::_s_section("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer); +ld::Section FastBindingPointerAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); class ImageCachePointerAtom : public ld::Atom { public: ImageCachePointerAtom(ld::passes::stubs::Pass& pass) - : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, - ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, - symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)) { pass.addAtom(*this); } + : ld::Atom( (pass.usingDataConstSegment ? _s_section : _s_sectionOld), + ld::Atom::definitionRegular, ld::Atom::combineNever, + (pass.usingDataConstSegment ? ld::Atom::scopeTranslationUnit : ld::Atom::scopeLinkageUnit), + (pass.usingDataConstSegment ? ld::Atom::typeUnclassified : ld::Atom::typeNonLazyPointer), + (pass.usingDataConstSegment ? symbolTableIn : symbolTableNotIn), + false, false, false, ld::Atom::Alignment(3)) { pass.addAtom(*this); } virtual const ld::File* file() const { return NULL; } - virtual const char* name() const { return "image cache pointer"; } + virtual const char* name() const { return "__dyld_private"; } virtual uint64_t size() const { return 8; } virtual uint64_t objectAddress() const { return 0; } virtual void copyRawContent(uint8_t buffer[]) const { } virtual void setScope(Scope) { } private: - + static ld::Section _s_section; + static ld::Section _s_sectionOld; }; -ld::Section ImageCachePointerAtom::_s_section("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer); +ld::Section ImageCachePointerAtom::_s_section( "__DATA", "__data", ld::Section::typeUnclassified); +ld::Section ImageCachePointerAtom::_s_sectionOld("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer); @@ -147,14 +152,14 @@ ld::Section StubHelperHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Sect class StubHelperAtom : public ld::Atom { public: StubHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom* lazyPointer, - const ld::Atom& stubTo) + const ld::Atom& stubTo, bool stubToResolver) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)), _stubTo(stubTo), _fixup1(1, ld::Fixup::k1of2, ld::Fixup::kindSetLazyOffset, lazyPointer), _fixup2(1, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32), - _fixup3(6, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressX86BranchPCRel32, helperHelper(pass)) { } + _fixup3(6, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressX86BranchPCRel32, helperHelper(pass, *this, stubToResolver)) { } virtual const ld::File* file() const { return _stubTo.file(); } virtual const char* name() const { return _stubTo.name(); } @@ -177,8 +182,11 @@ public: virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } private: - static ld::Atom* helperHelper(ld::passes::stubs::Pass& pass) { - if ( pass.compressedHelperHelper == NULL ) + static ld::Atom* helperHelper(ld::passes::stubs::Pass& pass, StubHelperAtom& stub, bool stubToResolver) { + // hack for resolvers in chained fixups. StubHelper is not used by needs to be constructed, so use dummy values + if ( stubToResolver ) + return &stub; + if ( pass.compressedHelperHelper == NULL ) pass.compressedHelperHelper = new StubHelperHelperAtom(pass); return pass.compressedHelperHelper; } @@ -274,7 +282,7 @@ public: ld::Atom::scopeTranslationUnit, ld::Atom::typeLazyPointer, symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), _stubTo(stubTo), - _helper(pass, this, stubTo), + _helper(pass, this, stubTo, stubToResolver), _resolverHelper(pass, this, stubTo), _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, stubToResolver ? &_resolverHelper : @@ -351,12 +359,14 @@ ld::Section StubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub); class NonLazyPointerAtom : public ld::Atom { public: - NonLazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo) + NonLazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool weakImport) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), _stubTo(stubTo), _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, &stubTo) { + _fixup1.weakImport = weakImport; pass.addAtom(*this); } @@ -380,14 +390,15 @@ ld::Section NonLazyPointerAtom::_s_section("__DATA", "__got", ld::Section::typeN -class KextStubAtom : public ld::Atom { +class NonLazyStubAtom : public ld::Atom { public: - KextStubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo) + NonLazyStubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool weakImport) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)), _stubTo(stubTo), - _nonLazyPointer(pass, stubTo), + _nonLazyPointer(pass, stubTo, weakImport), _fixup(2, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressX86PCRel32, &_nonLazyPointer) { pass.addAtom(*this); } virtual const ld::File* file() const { return _stubTo.file(); } @@ -414,7 +425,7 @@ private: static ld::Section _s_section; }; -ld::Section KextStubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub); +ld::Section NonLazyStubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub); } // namespace x86_64 diff --git a/cctools/ld64/src/ld/passes/stubs/stubs.cpp b/cctools/ld64/src/ld/passes/stubs/stubs.cpp index abed7e3..16b2397 100644 --- a/cctools/ld64/src/ld/passes/stubs/stubs.cpp +++ b/cctools/ld64/src/ld/passes/stubs/stubs.cpp @@ -56,6 +56,7 @@ public: Atom* compressedHelperHelper; Atom* compressedImageCache; Atom* compressedFastBinderPointer; + const bool usingDataConstSegment; private: @@ -75,7 +76,6 @@ private: const cpu_type_t _architecture; const bool _lazyDylibsInUuse; const bool _compressedLINKEDIT; - const bool _prebind; const bool _mightBeInSharedRegion; const bool _pic; const bool _flatNamespace; @@ -93,16 +93,22 @@ private: #if SUPPORT_ARCH_arm64 #include "stub_arm64.hpp" #endif +#if SUPPORT_ARCH_arm64e +#include "stub_arm64e.hpp" +#endif +#if SUPPORT_ARCH_arm64_32 +#include "stub_arm64_32.hpp" +#endif Pass::Pass(const Options& opts) : compressedHelperHelper(NULL), compressedImageCache(NULL), compressedFastBinderPointer(NULL), + usingDataConstSegment(opts.useDataConstSegment()), _options(opts), _architecture(opts.architecture()), _lazyDylibsInUuse(opts.usingLazyDylibLinking()), _compressedLINKEDIT(opts.makeCompressedDyldInfo()), - _prebind(opts.prebind()), _mightBeInSharedRegion(opts.sharedRegionEligible()), _pic(opts.outputSlidable()), _flatNamespace(opts.nameSpace() != Options::kTwoLevelNameSpace), @@ -154,7 +160,7 @@ const ld::Atom* Pass::stubableFixup(const ld::Fixup* fixup, ld::Internal& state) } break; default: - if ( target->contentType() == ld::Atom::typeResolver ) { + if ( (target != NULL) && (target->contentType() == ld::Atom::typeResolver) ) { // any pointer to a resolver needs to change to pointer to stub return target; } @@ -178,8 +184,8 @@ ld::Atom* Pass::makeStub(const ld::Atom& target, bool weakImport) if ( (dylib != NULL) && dylib->willBeLazyLoadedDylib() ) forLazyDylib = true; bool stubToResolver = (target.contentType() == ld::Atom::typeResolver); -#if SUPPORT_ARCH_arm_any || SUPPORT_ARCH_arm64 - bool usingDataConst = _options.useDataConstSegment(); +#if SUPPORT_ARCH_arm_any || SUPPORT_ARCH_arm64 || SUPPORT_ARCH_arm64e + bool usingDataConst = _options.useDataConstSegment() && _options.sharedRegionEligible(); #endif if ( usingCompressedLINKEDIT() && !forLazyDylib ) { @@ -190,7 +196,11 @@ ld::Atom* Pass::makeStub(const ld::Atom& target, bool weakImport) switch ( _architecture ) { #if SUPPORT_ARCH_i386 case CPU_TYPE_I386: - if ( usingCompressedLINKEDIT() && !forLazyDylib ) + if ( usingCompressedLINKEDIT() && !forLazyDylib && _options.noLazyBinding() && !stubToResolver ) + return new ld::passes::stubs::x86::NonLazyStubAtom(*this, target, weakImport); + else if ( _options.makeChainedFixups() && !stubToResolver ) + return new ld::passes::stubs::x86::NonLazyStubAtom(*this, target, weakImport); + else if ( usingCompressedLINKEDIT() && !forLazyDylib ) return new ld::passes::stubs::x86::StubAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport); else return new ld::passes::stubs::x86::classic::StubAtom(*this, target, forLazyDylib, weakImport); @@ -198,23 +208,43 @@ ld::Atom* Pass::makeStub(const ld::Atom& target, bool weakImport) #endif #if SUPPORT_ARCH_x86_64 case CPU_TYPE_X86_64: - if ( (_options.outputKind() == Options::kKextBundle) && _options.kextsUseStubs() ) - return new ld::passes::stubs::x86_64::KextStubAtom(*this, target); - else if ( usingCompressedLINKEDIT() && !forLazyDylib ) - return new ld::passes::stubs::x86_64::StubAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport); + if ( (_options.outputKind() == Options::kKextBundle) && _options.kextsUseStubs() ) + return new ld::passes::stubs::x86_64::NonLazyStubAtom(*this, target, weakImport); + else if ( _options.makeChainedFixups() ) { + if ( stubToResolver ) + return new ld::passes::stubs::x86_64::StubAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport); + else + return new ld::passes::stubs::x86_64::NonLazyStubAtom(*this, target, weakImport); + } + else if ( usingCompressedLINKEDIT() ) { + if ( forLazyDylib ) + return new ld::passes::stubs::x86_64::classic::StubAtom(*this, target, stubToGlobalWeakDef, weakImport); + else if ( _options.noLazyBinding() && !stubToResolver ) + return new ld::passes::stubs::x86_64::NonLazyStubAtom(*this, target, weakImport); + else + return new ld::passes::stubs::x86_64::StubAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport); + } else - return new ld::passes::stubs::x86_64::classic::StubAtom(*this, target, forLazyDylib, weakImport); + return new ld::passes::stubs::x86_64::classic::StubAtom(*this, target, stubToGlobalWeakDef, weakImport); break; #endif #if SUPPORT_ARCH_arm_any case CPU_TYPE_ARM: if ( (_options.outputKind() == Options::kKextBundle) && _options.kextsUseStubs() ) { // if text relocs are not allows in kext bundles, then linker must create a stub - return new ld::passes::stubs::arm::StubPICKextAtom(*this, target); + return new ld::passes::stubs::arm::StubPICKextAtom(*this, target, weakImport); + } + else if ( _options.makeChainedFixups() ) { + if ( stubToResolver ) + return new ld::passes::stubs::arm::StubPICAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport, usingDataConst); + else + return new ld::passes::stubs::arm::NonLazyStubPICAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport, usingDataConst); } else if ( usingCompressedLINKEDIT() && !forLazyDylib ) { - if ( (_stubCount < 900) && !_mightBeInSharedRegion && !_largeText ) + if ( (_stubCount < 900) && !_mightBeInSharedRegion && !_largeText && !_options.makeEncryptable() ) return new ld::passes::stubs::arm::StubCloseAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport); + else if ( usingCompressedLINKEDIT() && !forLazyDylib && _options.noLazyBinding() && !stubToResolver) + return new ld::passes::stubs::arm::StubPICKextAtom(*this, target, weakImport); else if ( _pic ) return new ld::passes::stubs::arm::StubPICAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport, usingDataConst); else @@ -230,8 +260,25 @@ ld::Atom* Pass::makeStub(const ld::Atom& target, bool weakImport) #endif #if SUPPORT_ARCH_arm64 case CPU_TYPE_ARM64: - if ( (_options.outputKind() == Options::kKextBundle) && _options.kextsUseStubs() ) - return new ld::passes::stubs::arm64::KextStubAtom(*this, target); +#if SUPPORT_ARCH_arm64e + if ( (_options.subArchitecture() == CPU_SUBTYPE_ARM64E) && _options.useAuthenticatedStubs() ) { + if ( (_options.outputKind() == Options::kKextBundle) && _options.kextsUseStubs() ) + return new ld::passes::stubs::arm64e::NonLazyStubAtom(*this, target, weakImport); + else if ( usingCompressedLINKEDIT() && !forLazyDylib && _options.noLazyBinding() && !stubToResolver ) + return new ld::passes::stubs::arm64e::NonLazyStubAtom(*this, target, weakImport); + else if ( _options.makeChainedFixups() && !stubToResolver ) + return new ld::passes::stubs::arm64e::NonLazyStubAtom(*this, target, weakImport); + else + return new ld::passes::stubs::arm64e::StubAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport, usingDataConst); + break; + } +#endif + if ( (_options.outputKind() == Options::kKextBundle) && _options.kextsUseStubs() ) + return new ld::passes::stubs::arm64::NonLazyStubAtom(*this, target, weakImport); + else if ( usingCompressedLINKEDIT() && !forLazyDylib && _options.noLazyBinding() && !stubToResolver ) + return new ld::passes::stubs::arm64::NonLazyStubAtom(*this, target, weakImport); + else if ( _options.makeChainedFixups() && !stubToResolver ) + return new ld::passes::stubs::arm64::NonLazyStubAtom(*this, target, weakImport); else return new ld::passes::stubs::arm64::StubAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport, usingDataConst); break; @@ -330,7 +377,7 @@ void Pass::process(ld::Internal& state) if ( atom->contentType() == ld::Atom::typeResolver ) { if ( _options.outputKind() != Options::kDynamicLibrary ) throwf("resolver functions (%s) can only be used in dylibs", atom->name()); - if ( !_options.makeCompressedDyldInfo() ) { + if ( !_options.makeCompressedDyldInfo() && !_options.makeChainedFixups() ) { if ( _options.architecture() == CPU_TYPE_ARM ) throwf("resolver functions (%s) can only be used when targeting iOS 4.2 or later", atom->name()); else @@ -357,7 +404,7 @@ void Pass::process(ld::Internal& state) return; // lazily check for helper - if ( !_options.makeCompressedDyldInfo() && (state.classicBindingHelper == NULL) && (_options.outputKind() != Options::kKextBundle) ) + if ( !_options.makeCompressedDyldInfo() && !_options.makeThreadedStartsSection() && !_options.makeChainedFixups() && (state.classicBindingHelper == NULL) && (_options.outputKind() != Options::kKextBundle) ) throw "symbol dyld_stub_binding_helper not found, normally in crt1.o/dylib1.o/bundle1.o"; // disable arm close stubs in some cases diff --git a/cctools/ld64/src/ld/passes/thread_starts.cpp b/cctools/ld64/src/ld/passes/thread_starts.cpp new file mode 100644 index 0000000..bdb9a7d --- /dev/null +++ b/cctools/ld64/src/ld/passes/thread_starts.cpp @@ -0,0 +1,329 @@ +/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- + * + * Copyright (c) 2009 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include +#include +#include + +#include +#include + +#include "MachOFileAbstraction.hpp" +#include "Architectures.hpp" +#include "ld.hpp" +#include "thread_starts.h" + +namespace ld { +namespace passes { +namespace thread_starts { + + +static std::map sAtomToAddress; + + + + +class ThreadStartsAtom : public ld::Atom { +public: + ThreadStartsAtom(uint32_t fixupAlignment, uint32_t numThreadStarts) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeUnclassified, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _fixupAlignment(fixupAlignment), _numThreadStarts(numThreadStarts) + { + assert(_fixupAlignment == 4 || _fixupAlignment == 8); + } + + virtual const ld::File* file() const { return NULL; } + virtual const char* name() const { return "thread starts"; } + virtual uint64_t size() const { return 4 + (_numThreadStarts * 4); } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + uint32_t header = 0; + if (_fixupAlignment == 8) + header |= 1; + bzero(buffer, size()); + *((uint32_t*)(&buffer[0])) = header; // header + // Fill in offsets with 0xFFFFFFFF's for now as that wouldn't be a valid offset + memset(&buffer[4], 0xFFFFFFFF, _numThreadStarts * sizeof(uint32_t)); + } + virtual void setScope(Scope) { } + virtual Fixup::iterator fixupsBegin() const { return NULL; } + virtual Fixup::iterator fixupsEnd() const { return NULL; } + +private: + + uint32_t _fixupAlignment; + uint32_t _numThreadStarts; + + static ld::Section _s_section; +}; + +ld::Section ThreadStartsAtom::_s_section("__TEXT", "__thread_starts", ld::Section::typeThreadStarts); + + + + +class ChainStartsAtom : public ld::Atom { +public: + ChainStartsAtom(uint32_t chainStartsCount) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeUnclassified, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _chainStartsCount(chainStartsCount) + { + } + + virtual const ld::File* file() const { return NULL; } + virtual const char* name() const { return "chain starts"; } + virtual uint64_t size() const { return offsetof(dyld_chained_starts_offsets, chain_starts[_chainStartsCount]); } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual void setScope(Scope) { } + virtual Fixup::iterator fixupsBegin() const { return NULL; } + virtual Fixup::iterator fixupsEnd() const { return NULL; } + +private: + + uint32_t _chainStartsCount; + + static ld::Section _s_section; +}; + +ld::Section ChainStartsAtom::_s_section("__TEXT", "__chain_starts", ld::Section::typeChainStarts); + + + + + +static void buildAddressMap(const Options& opts, ld::Internal& state) { + // Assign addresses to sections + state.setSectionSizesAndAlignments(); + state.assignFileOffsets(); + + // Assign addresses to atoms in a side table + static const bool log = false; + if ( log ) fprintf(stderr, "buildAddressMap()\n"); + for (std::vector::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) { + ld::Internal::FinalSection* sect = *sit; + uint16_t maxAlignment = 0; + uint64_t offset = 0; + if ( log ) fprintf(stderr, " section=%s/%s, address=0x%08llX\n", sect->segmentName(), sect->sectionName(), sect->address); + for (std::vector::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) { + const ld::Atom* atom = *ait; + uint32_t atomAlignmentPowerOf2 = atom->alignment().powerOf2; + uint32_t atomModulus = atom->alignment().modulus; + if ( atomAlignmentPowerOf2 > maxAlignment ) + maxAlignment = atomAlignmentPowerOf2; + // calculate section offset for this atom + uint64_t alignment = 1 << atomAlignmentPowerOf2; + uint64_t currentModulus = (offset % alignment); + uint64_t requiredModulus = atomModulus; + if ( currentModulus != requiredModulus ) { + if ( requiredModulus > currentModulus ) + offset += requiredModulus-currentModulus; + else + offset += requiredModulus+alignment-currentModulus; + } + + if ( log ) fprintf(stderr, " 0x%08llX atom=%p, name=%s\n", sect->address+offset, atom, atom->name()); + sAtomToAddress[atom] = sect->address + offset; + + offset += atom->size(); + } + } +} + +static uint32_t threadStartsCountInSection(std::vector& fixupAddressesInSection) { + if (fixupAddressesInSection.empty()) + return 0; + + std::sort(fixupAddressesInSection.begin(), fixupAddressesInSection.end()); + + uint32_t numThreadStarts = 0; + + uint64_t deltaBits = 11; + uint64_t minAlignment = 4; + uint64_t prevAddress = 0; + for (uint64_t address : fixupAddressesInSection) { + uint64_t delta = address - prevAddress; + assert( (delta & (minAlignment - 1)) == 0 ); + delta /= minAlignment; + if (delta >= (1 << deltaBits)) { + ++numThreadStarts; + } + prevAddress = address; + } + fixupAddressesInSection.clear(); + + return numThreadStarts; +} + +static uint32_t processSections(ld::Internal& state, uint64_t minAlignment) { + uint32_t numThreadStarts = 0; + + std::vector fixupAddressesInSection; + for (ld::Internal::FinalSection* sect : state.sections) { + if ( sect->isSectionHidden() ) + continue; + for (const ld::Atom* atom : sect->atoms) { + bool seenTarget = false; + bool seenSubtractTarget = false; + bool isPointerStore = false; + for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) { + if ( fit->firstInCluster() ) { + seenTarget = false; + seenSubtractTarget = false; + isPointerStore = false; + } + if ( fit->setsTarget(false) ) + seenTarget = true; + if ( fit->kind == ld::Fixup::kindSubtractTargetAddress ) + seenSubtractTarget = true; + if ( fit->isStore() ) { + if ( (fit->kind == ld::Fixup::kindStoreLittleEndian32) || (fit->kind == ld::Fixup::kindStoreLittleEndian64) ) + isPointerStore = true; + if ( (fit->kind == ld::Fixup::kindStoreTargetAddressLittleEndian32) || (fit->kind == ld::Fixup::kindStoreTargetAddressLittleEndian64) +#if SUPPORT_ARCH_arm64e + || (fit->kind == ld::Fixup::kindStoreTargetAddressLittleEndianAuth64) +#endif + ) + isPointerStore = true; + } + if ( fit->isPcRelStore(false) ) + seenSubtractTarget = true; + if ( fit->lastInCluster() ) { + //fprintf(stderr, "fixup at 0x%08llX, seenTarget=%d, seenSubtractTarget=%d, isPointerStore=%d\n", sAtomToAddress[atom] + fit->offsetInAtom, + // seenTarget, seenSubtractTarget, isPointerStore); + if ( seenTarget && !seenSubtractTarget && isPointerStore ) { + uint64_t address = sAtomToAddress[atom] + fit->offsetInAtom; + fixupAddressesInSection.push_back(address); + //fprintf(stderr, "pointer at 0x%08llX\n", address); + if ( (address & (minAlignment-1)) != 0 ) { + throwf("pointer not aligned at address 0x%llX (%s + %d from %s)", + address, atom->name(), fit->offsetInAtom, atom->safeFilePath()); + } + } + } + } + } + numThreadStarts += threadStartsCountInSection(fixupAddressesInSection); + } + + return numThreadStarts; +} + + +static uint32_t countChains(ld::Internal& state, uint32_t pointerFormat) { + uint32_t count = 0; + + uint64_t prevFixupAddress = 0; + const char* prevFixupSegName = nullptr; + for (ld::Internal::FinalSection* sect : state.sections) { + if ( sect->isSectionHidden() ) + continue; + if ( (prevFixupSegName != nullptr) && (strcmp(prevFixupSegName, sect->segmentName()) != 0) ) + prevFixupAddress = 0; + for (const ld::Atom* atom : sect->atoms) { + bool seenTarget = false; + bool seenSubtractTarget = false; + bool isPointerStore = false; + std::vector atomFixupOffsets; + for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) { + if ( fit->firstInCluster() ) { + seenTarget = false; + seenSubtractTarget = false; + isPointerStore = false; + } + if ( fit->setsTarget(false) ) + seenTarget = true; + if ( fit->kind == ld::Fixup::kindSubtractTargetAddress ) + seenSubtractTarget = true; + if ( fit->isStore() ) { + if ( (fit->kind == ld::Fixup::kindStoreLittleEndian32) || (fit->kind == ld::Fixup::kindStoreLittleEndian64) ) + isPointerStore = true; + if ( (fit->kind == ld::Fixup::kindStoreTargetAddressLittleEndian32) || (fit->kind == ld::Fixup::kindStoreTargetAddressLittleEndian64) ) + isPointerStore = true; + } + if ( fit->isPcRelStore(false) ) + seenSubtractTarget = true; + if ( fit->lastInCluster() ) { + //fprintf(stderr, "fixup at 0x%08llX, seenTarget=%d, seenSubtractTarget=%d, isPointerStore=%d\n", sAtomToAddress[atom] + fit->offsetInAtom, + // seenTarget, seenSubtractTarget, isPointerStore); + if ( seenTarget && !seenSubtractTarget && isPointerStore ) { + atomFixupOffsets.push_back(fit->offsetInAtom); + } + } + } + std::sort(atomFixupOffsets.begin(), atomFixupOffsets.end()); + for (uint32_t offset : atomFixupOffsets ) { + uint64_t address = sAtomToAddress[atom] + offset; + //fprintf(stderr, "0x%llX fixup\n", address-0x7000); + if ( prevFixupAddress == 0 ) { + ++count; + //fprintf(stderr, "first chain start at: 0x%llX\n", address-0x7000); + } + else { + uint64_t delta = address - prevFixupAddress; + if ( delta > 255 ) { + //fprintf(stderr, "new chain start at: 0x%llX\n", address-0x7000); + ++count; + } + } + prevFixupAddress = address; + prevFixupSegName = sect->segmentName(); + } + } + } + + return count; +} + + +void doPass(const Options& opts, ld::Internal& state) +{ + if ( opts.makeThreadedStartsSection() ) { + buildAddressMap(opts, state); + uint32_t fixupAlignment = 4; + uint32_t numThreadStarts = processSections(state, fixupAlignment); + // create atom that contains the whole chain starts section + state.addAtom(*new ThreadStartsAtom(fixupAlignment, numThreadStarts)); + } + else if ( opts.makeChainedFixups() && !opts.dyldLoadsOutput() ) { + buildAddressMap(opts, state); + uint32_t startsCount = countChains(state, DYLD_CHAINED_PTR_32_FIRMWARE); + state.addAtom(*new ChainStartsAtom(startsCount)); + } + else { + return; + } +} + + +} // namespace thread_starts +} // namespace passes +} // namespace ld diff --git a/cctools/ld64/src/ld/passes/thread_starts.h b/cctools/ld64/src/ld/passes/thread_starts.h new file mode 100644 index 0000000..a1213c4 --- /dev/null +++ b/cctools/ld64/src/ld/passes/thread_starts.h @@ -0,0 +1,45 @@ +/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- + * + * Copyright (c) 2009 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef __THREAD_STARTS_H__ +#define __THREAD_STARTS_H__ + +#include "Options.h" +#include "ld.hpp" + + +namespace ld { +namespace passes { +namespace thread_starts { + +// called by linker to generate a thread starts section +extern void doPass(const Options& opts, ld::Internal& internal); + + +} // namespace thread_starts +} // namespace passes +} // namespace ld + +#endif // __THREAD_STARTS_H__ diff --git a/cctools/ld64/src/ld/passes/tlvp.cpp b/cctools/ld64/src/ld/passes/tlvp.cpp index aec9562..729394f 100644 --- a/cctools/ld64/src/ld/passes/tlvp.cpp +++ b/cctools/ld64/src/ld/passes/tlvp.cpp @@ -42,17 +42,18 @@ class File; // forward reference class TLVEntryAtom : public ld::Atom { public: - TLVEntryAtom(ld::Internal& internal, const ld::Atom* target, bool weakImport) + TLVEntryAtom(ld::Internal& internal, const ld::Atom* target, bool weakImport, unsigned ptrSize) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), - _fixup(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, target), - _target(target) + _fixup(0, ld::Fixup::k1of1, (ptrSize ==8) ? ld::Fixup::kindStoreTargetAddressLittleEndian64 : ld::Fixup::kindStoreTargetAddressLittleEndian32, target), + _target(target), + _size(ptrSize) { _fixup.weakImport = weakImport; internal.addAtom(*this); } virtual const ld::File* file() const { return NULL; } virtual const char* name() const { return _target->name(); } - virtual uint64_t size() const { return 8; } + virtual uint64_t size() const { return _size; } virtual uint64_t objectAddress() const { return 0; } virtual void copyRawContent(uint8_t buffer[]) const { } virtual void setScope(Scope) { } @@ -62,7 +63,8 @@ public: private: mutable ld::Fixup _fixup; const ld::Atom* _target; - + unsigned _size; + static ld::Section _s_section; }; @@ -112,6 +114,8 @@ void doPass(const Options& opts, ld::Internal& internal) if ( opts.outputKind() == Options::kObjectFile ) return; + const unsigned ptrSize = (opts.architecture() == CPU_TYPE_ARM64_32) ? 4 : 8; + // walk all atoms and fixups looking for TLV references and add them to list std::vector references; for (std::vector::iterator sit=internal.sections.begin(); sit != internal.sections.end(); ++sit) { @@ -201,7 +205,7 @@ void doPass(const Options& opts, ld::Internal& internal) if (log) fprintf(stderr, "make TLV pointer for %s\n", it->first->name()); if ( it->first->contentType() != ld::Atom::typeTLV ) throwf("illegal thread local variable reference to regular symbol %s", it->first->name()); - TLVEntryAtom* tlvp = new TLVEntryAtom(internal, it->first, it->second); + TLVEntryAtom* tlvp = new TLVEntryAtom(internal, it->first, it->second, ptrSize); variableToPointerMap[it->first] = tlvp; } } diff --git a/cctools/ld64/src/other/Makefile.am b/cctools/ld64/src/other/Makefile.am index 15afea5..2123069 100644 --- a/cctools/ld64/src/other/Makefile.am +++ b/cctools/ld64/src/other/Makefile.am @@ -40,10 +40,15 @@ machocheck_LDADD = $(top_builddir)/ld64/src/3rd/libhelper.la ObjectDump_SOURCES = \ ObjectDump.cpp \ - $(top_srcdir)/ld64/src/ld/debugline.c + $(top_srcdir)/ld64/src/ld/PlatformSupport.cpp \ + $(top_srcdir)/ld64/src/ld/debugline.c + ObjectDump_LDADD = \ $(top_builddir)/ld64/src/ld/parsers/libParsers.la \ - $(LTO_LIB) + $(top_builddir)/ld64/src/3rd/BlocksRuntime/libBlocksRuntime.la \ + $(LTO_RPATH) \ + $(LTO_LIB) \ + $(DL_LIB) dyldinfo_SOURCES = dyldinfo.cpp dyldinfo_LDADD = $(top_builddir)/ld64/src/3rd/libhelper.la diff --git a/cctools/ld64/src/other/Makefile.in b/cctools/ld64/src/other/Makefile.in new file mode 100644 index 0000000..9de8216 --- /dev/null +++ b/cctools/ld64/src/other/Makefile.in @@ -0,0 +1,758 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = dyldinfo$(EXEEXT) ObjectDump$(EXEEXT) \ + unwinddump$(EXEEXT) machocheck$(EXEEXT) +subdir = ld64/src/other +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am__dirstamp = $(am__leading_dot)dirstamp +am_ObjectDump_OBJECTS = ObjectDump.$(OBJEXT) \ + $(top_builddir)/ld64/src/ld/PlatformSupport.$(OBJEXT) \ + $(top_builddir)/ld64/src/ld/debugline.$(OBJEXT) +ObjectDump_OBJECTS = $(am_ObjectDump_OBJECTS) +am__DEPENDENCIES_1 = +ObjectDump_DEPENDENCIES = \ + $(top_builddir)/ld64/src/ld/parsers/libParsers.la \ + $(top_builddir)/ld64/src/3rd/BlocksRuntime/libBlocksRuntime.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +am_dyldinfo_OBJECTS = dyldinfo.$(OBJEXT) +dyldinfo_OBJECTS = $(am_dyldinfo_OBJECTS) +dyldinfo_DEPENDENCIES = $(top_builddir)/ld64/src/3rd/libhelper.la +am_machocheck_OBJECTS = machochecker.$(OBJEXT) +machocheck_OBJECTS = $(am_machocheck_OBJECTS) +machocheck_DEPENDENCIES = $(top_builddir)/ld64/src/3rd/libhelper.la +am_unwinddump_OBJECTS = unwinddump.$(OBJEXT) +unwinddump_OBJECTS = $(am_unwinddump_OBJECTS) +unwinddump_LDADD = $(LDADD) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(ObjectDump_SOURCES) $(dyldinfo_SOURCES) \ + $(machocheck_SOURCES) $(unwinddump_SOURCES) +DIST_SOURCES = $(ObjectDump_SOURCES) $(dyldinfo_SOURCES) \ + $(machocheck_SOURCES) $(unwinddump_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CXXFLAGS = \ + -D__DARWIN_UNIX03 \ + $(WARNINGS) \ + -Wno-switch \ + $(LTO_DEF) \ + $(ENDIAN_FLAG) \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/include/foreign \ + -I$(top_srcdir)/ld64/src \ + -I$(top_srcdir)/ld64/src/3rd \ + -I$(top_srcdir)/ld64/src/abstraction \ + -I$(top_srcdir)/ld64/src/ld \ + -I$(top_srcdir)/ld64/src/ld/parsers \ + -I$(top_srcdir)/ld64/src/ld/passes + +AM_CFLAGS = \ + -D__DARWIN_UNIX03 \ + $(WARNINGS) \ + $(LTO_DEF) \ + $(ENDIAN_FLAG) \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/include/foreign \ + -I$(top_srcdir)/ld64/src \ + -I$(top_srcdir)/ld64/src/3rd \ + -I$(top_srcdir)/ld64/src/abstraction \ + -I$(top_srcdir)/ld64/src/ld \ + -I$(top_srcdir)/ld64/src/ld/parsers \ + -I$(top_srcdir)/ld64/src/ld/passes + +unwinddump_SOURCES = unwinddump.cpp +machocheck_SOURCES = machochecker.cpp +machocheck_LDADD = $(top_builddir)/ld64/src/3rd/libhelper.la +ObjectDump_SOURCES = \ + ObjectDump.cpp \ + $(top_srcdir)/ld64/src/ld/PlatformSupport.cpp \ + $(top_srcdir)/ld64/src/ld/debugline.c + +ObjectDump_LDADD = \ + $(top_builddir)/ld64/src/ld/parsers/libParsers.la \ + $(top_builddir)/ld64/src/3rd/BlocksRuntime/libBlocksRuntime.la \ + $(LTO_RPATH) \ + $(LTO_LIB) \ + $(DL_LIB) + +dyldinfo_SOURCES = dyldinfo.cpp +dyldinfo_LDADD = $(top_builddir)/ld64/src/3rd/libhelper.la +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .cpp .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps ld64/src/other/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps ld64/src/other/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +$(top_builddir)/ld64/src/ld/$(am__dirstamp): + @$(MKDIR_P) $(top_builddir)/ld64/src/ld + @: > $(top_builddir)/ld64/src/ld/$(am__dirstamp) +$(top_builddir)/ld64/src/ld/PlatformSupport.$(OBJEXT): \ + $(top_builddir)/ld64/src/ld/$(am__dirstamp) +$(top_builddir)/ld64/src/ld/debugline.$(OBJEXT): \ + $(top_builddir)/ld64/src/ld/$(am__dirstamp) + +ObjectDump$(EXEEXT): $(ObjectDump_OBJECTS) $(ObjectDump_DEPENDENCIES) $(EXTRA_ObjectDump_DEPENDENCIES) + @rm -f ObjectDump$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(ObjectDump_OBJECTS) $(ObjectDump_LDADD) $(LIBS) + +dyldinfo$(EXEEXT): $(dyldinfo_OBJECTS) $(dyldinfo_DEPENDENCIES) $(EXTRA_dyldinfo_DEPENDENCIES) + @rm -f dyldinfo$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(dyldinfo_OBJECTS) $(dyldinfo_LDADD) $(LIBS) + +machocheck$(EXEEXT): $(machocheck_OBJECTS) $(machocheck_DEPENDENCIES) $(EXTRA_machocheck_DEPENDENCIES) + @rm -f machocheck$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(machocheck_OBJECTS) $(machocheck_LDADD) $(LIBS) + +unwinddump$(EXEEXT): $(unwinddump_OBJECTS) $(unwinddump_DEPENDENCIES) $(EXTRA_unwinddump_DEPENDENCIES) + @rm -f unwinddump$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(unwinddump_OBJECTS) $(unwinddump_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f $(top_builddir)/ld64/src/ld/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +.cpp.o: + $(AM_V_CXX)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(AM_V_CXX)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: + $(AM_V_CXX)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(top_builddir)/ld64/src/ld/$(am__dirstamp)" || rm -f $(top_builddir)/ld64/src/ld/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-binPROGRAMS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/ld64/src/other/ObjectDump.cpp b/cctools/ld64/src/other/ObjectDump.cpp index 6adfda8..aa9ad04 100644 --- a/cctools/ld64/src/other/ObjectDump.cpp +++ b/cctools/ld64/src/other/ObjectDump.cpp @@ -39,6 +39,9 @@ #include #endif +const ld::VersionSet ld::File::_platforms; + + static bool sDumpContent= true; static bool sDumpStabs = false; static bool sSort = true; @@ -400,11 +403,13 @@ struct AtomSorter rightString = (char*)cstringAtom->rawContentPointer(); } } - assert(leftString != NULL); - assert(rightString != NULL); - diff = strcmp(leftString, rightString); - if ( diff != 0 ) - return (diff < 0); + if ( leftString != rightString ) { + assert(leftString != NULL); + assert(rightString != NULL); + diff = strcmp(leftString, rightString); + if ( diff != 0 ) + return (diff < 0); + } } else if ( left->section().type() == ld::Section::typeLiteral4 ) { // if literal sort by content @@ -558,6 +563,9 @@ const char* dumper::attributeString(const ld::Atom& atom) if ( atom.isAlias() ) strcat(buffer, "alias "); + if ( atom.cold() ) + strcat(buffer, "cold "); + if ( atom.contentType() == ld::Atom::typeResolver ) strcat(buffer, "resolver "); @@ -808,6 +816,7 @@ void dumper::dumpFixup(const ld::Fixup* ref) case ld::Fixup::kindStoreThumbHigh16: printf(", then store high-16 in Thumb movt"); break; +#if SUPPORT_ARCH_arm64 case ld::Fixup::kindStoreARM64Branch26: printf(", then store as ARM64 26-bit pcrel branch"); break; @@ -847,6 +856,7 @@ void dumper::dumpFixup(const ld::Fixup* ref) case ld::Fixup::kindStoreARM64PCRelToGOT: printf(", then store as 32-bit delta to GOT entry"); break; +#endif case ld::Fixup::kindDtraceExtra: printf("dtrace static probe extra info"); break; @@ -868,12 +878,14 @@ void dumper::dumpFixup(const ld::Fixup* ref) case ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear: printf("Thumb dtrace static is-enabled site"); break; +#if SUPPORT_ARCH_arm64 case ld::Fixup::kindStoreARM64DtraceCallSiteNop: printf("ARM64 dtrace static probe site"); break; case ld::Fixup::kindStoreARM64DtraceIsEnableSiteClear: printf("ARM64 dtrace static is-enabled site"); break; +#endif case ld::Fixup::kindLazyTarget: printf("lazy reference to external symbol %s", referenceTargetAtomName(ref)); break; @@ -991,6 +1003,7 @@ void dumper::dumpFixup(const ld::Fixup* ref) case ld::Fixup::kindSetTargetTLVTemplateOffsetLittleEndian64: printf("tlv template offset of %s", referenceTargetAtomName(ref)); break; +#if SUPPORT_ARCH_arm64 case ld::Fixup::kindStoreTargetAddressARM64Branch26: printf("ARM64 store 26-bit pcrel branch to %s", referenceTargetAtomName(ref)); break; @@ -1024,6 +1037,7 @@ void dumper::dumpFixup(const ld::Fixup* ref) case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12: printf("ARM64 store 12-bit page offset of lea for TLV of %s", referenceTargetAtomName(ref)); break; +#endif //default: // printf("unknown fixup"); // break; @@ -1247,6 +1261,9 @@ static ld::relocatable::File* createReader(const char* path) objOpts.forceDwarfConversion = false; objOpts.verboseOptimizationHints = true; objOpts.armUsesZeroCostExceptions = true; +#if SUPPORT_ARCH_arm64e + objOpts.supportsAuthenticatedPointers = true; +#endif objOpts.subType = sPreferredSubArch; objOpts.treateBitcodeAsData = false; objOpts.usingBitcode = true; @@ -1254,8 +1271,9 @@ static ld::relocatable::File* createReader(const char* path) if ( ! foundFatSlice ) { cpu_type_t archOfObj; cpu_subtype_t subArchOfObj; - Options::Platform platform; - if ( mach_o::relocatable::isObjectFile(p, &archOfObj, &subArchOfObj, &platform) ) { + ld::Platform platform; + uint32_t minOS; + if ( mach_o::relocatable::isObjectFile(p, fileLen, &archOfObj, &subArchOfObj, &platform, &minOS) ) { objOpts.architecture = archOfObj; objOpts.subType = subArchOfObj; } diff --git a/cctools/ld64/src/other/dyldinfo.cpp b/cctools/ld64/src/other/dyldinfo.cpp index f19538f..d98b9f8 100644 --- a/cctools/ld64/src/other/dyldinfo.cpp +++ b/cctools/ld64/src/other/dyldinfo.cpp @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -117,7 +118,8 @@ private: const uint8_t* printSharedRegionV2ToSectionOffset(const uint8_t* p, const uint8_t* end); const uint8_t* printSharedRegionV2Kind(const uint8_t* p, const uint8_t* end); - pint_t relocBase(); + pint_t localRelocBase(); + pint_t externalRelocBase(); const char* relocTypeName(uint8_t r_type); uint8_t segmentIndexForAddress(pint_t addr); void processExportGraphNode(const uint8_t* const start, const uint8_t* const end, @@ -236,6 +238,7 @@ bool DyldInfoPrinter::validFile(const uint8_t* fileContent) case MH_DYLIB_STUB: case MH_BUNDLE: case MH_DYLINKER: + case MH_KEXT_BUNDLE: return true; } return false; @@ -256,6 +259,7 @@ bool DyldInfoPrinter::validFile(const uint8_t* fileContent) case MH_DYLIB_STUB: case MH_BUNDLE: case MH_DYLINKER: + case MH_KEXT_BUNDLE: return true; } return false; @@ -274,14 +278,20 @@ bool DyldInfoPrinter::validFile(const uint8_t* fileContent) switch (header->filetype()) { case MH_EXECUTE: case MH_DYLIB: + case MH_DYLIB_STUB: case MH_BUNDLE: case MH_DYLINKER: + case MH_KEXT_BUNDLE: + case MH_PRELOAD: return true; + default: + return false; } return false; } #endif + template DyldInfoPrinter::DyldInfoPrinter(const uint8_t* fileContent, uint32_t fileLength, const char* path, bool printArch) : fHeader(NULL), fLength(fileLength), @@ -323,8 +333,13 @@ DyldInfoPrinter::DyldInfoPrinter(const uint8_t* fileContent, uint32_t fileLen { const macho_segment_command

* segCmd = (const macho_segment_command

*)cmd; fSegments.push_back(segCmd); - if ( (segCmd->fileoff() == 0) && (segCmd->filesize() != 0) ) - fBaseAddress = segCmd->vmaddr(); + if (fHeader->filetype() == MH_PRELOAD) { + if ( (fFirstSegment == NULL) && (segCmd->filesize() != 0) ) + fBaseAddress = segCmd->vmaddr(); + } else { + if ( (segCmd->fileoff() == 0) && (segCmd->filesize() != 0) ) + fBaseAddress = segCmd->vmaddr(); + } if ( fFirstSegment == NULL ) fFirstSegment = segCmd; if ( (segCmd->initprot() & VM_PROT_WRITE) != 0 ) { @@ -608,6 +623,8 @@ const char* DyldInfoPrinter::ordinalName(int libraryOrdinal) return "main-executable"; case BIND_SPECIAL_DYLIB_FLAT_LOOKUP: return "flat-namespace"; + case BIND_SPECIAL_DYLIB_WEAK_LOOKUP: + return "weak"; } if ( libraryOrdinal < BIND_SPECIAL_DYLIB_FLAT_LOOKUP ) throw "unknown special ordinal"; @@ -637,12 +654,164 @@ const char* DyldInfoPrinter::classicOrdinalName(int libraryOrdinal) template void DyldInfoPrinter::printRebaseInfo() { + bool seenThreadedRebase = false; if ( (fInfo == NULL) || (fInfo->rebase_off() == 0) ) { - printf("no compressed rebase info\n"); + // If we have no rebase opcodes, then we may be using the threaded rebase/bind combined + // format and need to parse the bind opcodes instead. + if ( (fInfo->rebase_size() == 0) && (fInfo->bind_size() != 0) ) { + const uint8_t* p = (uint8_t*)fHeader + fInfo->bind_off(); + const uint8_t* end = &p[fInfo->bind_size()]; + + uint8_t type = 0; + uint8_t flags = 0; + uint8_t segIndex = 0; + uint64_t segOffset = 0; + const char* symbolName = NULL; + const char* fromDylib = "??"; + int libraryOrdinal = 0; + int64_t addend = 0; + uint32_t count; + uint32_t skip; + pint_t segStartAddr = 0; + const char* segName = "??"; + const char* typeName = "??"; + const char* weak_import = ""; + bool done = false; + while ( !done && (p < end) ) { + uint8_t immediate = *p & BIND_IMMEDIATE_MASK; + uint8_t opcode = *p & BIND_OPCODE_MASK; + ++p; + switch (opcode) { + case BIND_OPCODE_DONE: + done = true; + break; + case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: + libraryOrdinal = immediate; + fromDylib = ordinalName(libraryOrdinal); + break; + case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: + libraryOrdinal = read_uleb128(p, end); + fromDylib = ordinalName(libraryOrdinal); + break; + case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: + // the special ordinals are negative numbers + if ( immediate == 0 ) + libraryOrdinal = 0; + else { + int8_t signExtended = BIND_OPCODE_MASK | immediate; + libraryOrdinal = signExtended; + } + fromDylib = ordinalName(libraryOrdinal); + break; + case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: + symbolName = (char*)p; + while (*p != '\0') + ++p; + ++p; + flags = immediate & BIND_SYMBOL_FLAGS_WEAK_IMPORT; + if ( flags != 0 ) + weak_import = " (weak import)"; + else + weak_import = ""; + break; + case BIND_OPCODE_SET_TYPE_IMM: + type = immediate; + typeName = bindTypeName(type); + break; + case BIND_OPCODE_SET_ADDEND_SLEB: + addend = read_sleb128(p, end); + break; + case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: + segIndex = immediate; + segStartAddr = segStartAddress(segIndex); + segName = segmentName(segIndex); + segOffset = read_uleb128(p, end); + break; + case BIND_OPCODE_ADD_ADDR_ULEB: + segOffset += read_uleb128(p, end); + break; + case BIND_OPCODE_DO_BIND: + break; + case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: + segOffset += read_uleb128(p, end) + sizeof(pint_t); + break; + case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: + segOffset += immediate*sizeof(pint_t) + sizeof(pint_t); + break; + case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: + count = read_uleb128(p, end); + skip = read_uleb128(p, end); + for (uint32_t i=0; i < count; ++i) { + segOffset += skip + sizeof(pint_t); + } + break; + case BIND_OPCODE_THREADED: + // Note the immediate is a sub opcode + switch (immediate) { + case BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB: + printf("rebase information (from compressed dyld info):\n"); + printf("segment section address type value\n"); + count = read_uleb128(p, end); + seenThreadedRebase = true; + break; + case BIND_SUBOPCODE_THREADED_APPLY: { + uint64_t delta = 0; + do { + const uint8_t* pointerLocation = (uint8_t*)fHeader + fSegments[segIndex]->fileoff() + segOffset; + uint64_t value = P::getP(*(uint64_t*)pointerLocation); +#if SUPPORT_ARCH_arm64e + uint16_t diversity = (uint16_t)(value >> 32); + bool hasAddressDiversity = (value & (1ULL << 48)) != 0; + uint8_t key = (uint8_t)((value >> 49) & 0x3); + bool isAuthenticated = (value & (1ULL << 63)) != 0; +#endif + bool isRebase = (value & (1ULL << 62)) == 0; + if (isRebase) { + +#if SUPPORT_ARCH_arm64e + static const char* keyNames[] = { + "IA", "IB", "DA", "DB" + }; + if (isAuthenticated) { + uint64_t targetValue = value & 0xFFFFFFFFULL; + targetValue += fBaseAddress; + printf("%-7s %-16s 0x%08llX %s 0x%08llX (JOP: diversity %d, address %s, %s)\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName, targetValue, diversity, hasAddressDiversity ? "true" : "false", keyNames[key]); + } else +#endif + { + // Regular pointer which needs to fit in 51-bits of value. + // C++ RTTI uses the top bit, so we'll allow the whole top-byte + // and the signed-extended bottom 43-bits to be fit in to 51-bits. + uint64_t top8Bits = value & 0x0007F80000000000ULL; + uint64_t bottom43Bits = value & 0x000007FFFFFFFFFFULL; + uint64_t targetValue = ( top8Bits << 13 ) | (((intptr_t)(bottom43Bits << 21) >> 21) & 0x00FFFFFFFFFFFFFF); + printf("%-7s %-16s 0x%08llX %s 0x%08llX\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName, targetValue); + } + } + // The delta is bits [51..61] + // And bit 62 is to tell us if we are a rebase (0) or bind (1) + value &= ~(1ULL << 62); + delta = ( value & 0x3FF8000000000000 ) >> 51; + segOffset += delta * sizeof(pint_t); + } while ( delta != 0); + break; + } + default: + throwf("unknown threaded bind subopcode %d", immediate); + } + break; + default: + throwf("bad bind opcode %d", *p); + } + } + } + + if (!seenThreadedRebase) + printf("no compressed rebase info\n"); } else { printf("rebase information (from compressed dyld info):\n"); - printf("segment section address type\n"); + printf("segment section address type value\n"); const uint8_t* p = (uint8_t*)fHeader + fInfo->rebase_off(); const uint8_t* end = &p[fInfo->rebase_size()]; @@ -655,6 +824,8 @@ void DyldInfoPrinter::printRebaseInfo() pint_t segStartAddr = 0; const char* segName = "??"; const char* typeName = "??"; + const uint8_t* pointerLocation = nullptr; + uint64_t value = 0; bool done = false; while ( !done && (p < end) ) { uint8_t immediate = *p & REBASE_IMMEDIATE_MASK; @@ -682,35 +853,42 @@ void DyldInfoPrinter::printRebaseInfo() break; case REBASE_OPCODE_DO_REBASE_IMM_TIMES: for (int i=0; i < immediate; ++i) { - printf("%-7s %-16s 0x%08llX %s\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName); + pointerLocation = (uint8_t*)fHeader + fSegments[segIndex]->fileoff() + segOffset; + value = P::getP(*(uint64_t*)pointerLocation); + printf("%-7s %-16s 0x%08llX %s 0x%08llX\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName, value); segOffset += sizeof(pint_t); } break; case REBASE_OPCODE_DO_REBASE_ULEB_TIMES: count = read_uleb128(p, end); for (uint32_t i=0; i < count; ++i) { - printf("%-7s %-16s 0x%08llX %s\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName); + pointerLocation = (uint8_t*)fHeader + fSegments[segIndex]->fileoff() + segOffset; + value = P::getP(*(uint64_t*)pointerLocation); + printf("%-7s %-16s 0x%08llX %s 0x%08llX\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName, value); segOffset += sizeof(pint_t); } break; case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: - printf("%-7s %-16s 0x%08llX %s\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName); + pointerLocation = (uint8_t*)fHeader + fSegments[segIndex]->fileoff() + segOffset; + value = P::getP(*(uint64_t*)pointerLocation); + printf("%-7s %-16s 0x%08llX %s 0x%08llX\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName, value); segOffset += read_uleb128(p, end) + sizeof(pint_t); break; case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: count = read_uleb128(p, end); skip = read_uleb128(p, end); for (uint32_t i=0; i < count; ++i) { - printf("%-7s %-16s 0x%08llX %s\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName); + pointerLocation = (uint8_t*)fHeader + fSegments[segIndex]->fileoff() + segOffset; + value = P::getP(*(uint64_t*)pointerLocation); + printf("%-7s %-16s 0x%08llX %s 0x%08llX\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName, value); segOffset += skip + sizeof(pint_t); } break; default: throwf("bad rebase opcode %d", *p); } - } + } } - } @@ -784,11 +962,6 @@ void DyldInfoPrinter::printRebaseInfoOpcodes() } - - - - - template void DyldInfoPrinter::printBindingInfoOpcodes(bool weakbinding) { @@ -894,6 +1067,20 @@ void DyldInfoPrinter::printBindingInfoOpcodes(bool weakbinding) skip = read_uleb128(p, end); printf("0x%04X BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB(%d, 0x%08X)\n", opcodeOffset, count, skip); break; + case BIND_OPCODE_THREADED: + // Note the immediate is a sub opcode + switch (immediate) { + case BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB: + count = read_uleb128(p, end); + printf("0x%04X BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB(%d)\n", opcodeOffset, count); + break; + case BIND_SUBOPCODE_THREADED_APPLY: + printf("0x%04X BIND_SUBOPCODE_THREADED_APPLY\n", opcodeOffset); + break; + default: + throwf("unknown threaded bind subopcode %d", immediate); + } + break; default: throwf("unknown bind opcode %d", *p); } @@ -902,7 +1089,20 @@ void DyldInfoPrinter::printBindingInfoOpcodes(bool weakbinding) } +struct ThreadedBindData { + ThreadedBindData(const char* symbolName, int64_t addend, int libraryOrdinal, uint8_t flags, uint8_t type) + : symbolName(symbolName), addend(addend), libraryOrdinal(libraryOrdinal), flags(flags), type(type) { } + std::tuple pack() const { + return std::make_tuple(symbolName, addend, libraryOrdinal, flags, type); + } + + const char* symbolName = nullptr; + int64_t addend = 0; + int libraryOrdinal = 0; + uint8_t flags = 0; + uint8_t type = 0; +}; template void DyldInfoPrinter::printBindingInfo() @@ -915,8 +1115,9 @@ void DyldInfoPrinter::printBindingInfo() printf("segment section address type addend dylib symbol\n"); const uint8_t* p = (uint8_t*)fHeader + fInfo->bind_off(); const uint8_t* end = &p[fInfo->bind_size()]; - + uint8_t type = 0; + uint8_t flags = 0; uint8_t segIndex = 0; uint64_t segOffset = 0; const char* symbolName = NULL; @@ -929,6 +1130,8 @@ void DyldInfoPrinter::printBindingInfo() const char* segName = "??"; const char* typeName = "??"; const char* weak_import = ""; + std::vector ordinalTable; + bool useThreadedRebaseBind = false; bool done = false; while ( !done && (p < end) ) { uint8_t immediate = *p & BIND_IMMEDIATE_MASK; @@ -961,7 +1164,8 @@ void DyldInfoPrinter::printBindingInfo() while (*p != '\0') ++p; ++p; - if ( (immediate & BIND_SYMBOL_FLAGS_WEAK_IMPORT) != 0 ) + flags = immediate & BIND_SYMBOL_FLAGS_WEAK_IMPORT; + if ( flags != 0 ) weak_import = " (weak import)"; else weak_import = ""; @@ -983,8 +1187,12 @@ void DyldInfoPrinter::printBindingInfo() segOffset += read_uleb128(p, end); break; case BIND_OPCODE_DO_BIND: - printf("%-7s %-16s 0x%08llX %10s %5lld %-16s %s%s\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName, addend, fromDylib, symbolName, weak_import ); - segOffset += sizeof(pint_t); + if (!useThreadedRebaseBind) { + printf("%-7s %-16s 0x%08llX %10s %5lld %-16s %s%s\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName, addend, fromDylib, symbolName, weak_import ); + segOffset += sizeof(pint_t); + } else { + ordinalTable.push_back(ThreadedBindData(symbolName, addend, libraryOrdinal, flags, type)); + } break; case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: printf("%-7s %-16s 0x%08llX %10s %5lld %-16s %s%s\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName, addend, fromDylib, symbolName, weak_import ); @@ -1002,6 +1210,68 @@ void DyldInfoPrinter::printBindingInfo() segOffset += skip + sizeof(pint_t); } break; + case BIND_OPCODE_THREADED: + // Note the immediate is a sub opcode + switch (immediate) { + case BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB: + count = read_uleb128(p, end); + ordinalTable.clear(); + ordinalTable.reserve(count); + useThreadedRebaseBind = true; + break; + case BIND_SUBOPCODE_THREADED_APPLY: { + uint64_t delta = 0; + do { + const uint8_t* pointerLocation = (uint8_t*)fHeader + fSegments[segIndex]->fileoff() + segOffset; + uint64_t value = P::getP(*(uint64_t*)pointerLocation); +#if SUPPORT_ARCH_arm64e + uint16_t diversity = (uint16_t)(value >> 32); + bool hasAddressDiversity = (value & (1ULL << 48)) != 0; + uint8_t key = (uint8_t)((value >> 49) & 0x3); + bool isAuthenticated = (value & (1ULL << 63)) != 0; +#endif + bool isRebase = (value & (1ULL << 62)) == 0; + + if (isRebase) { + //printf("(rebase): %-7s %-16s 0x%08llX %s\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName); + } else { + // the ordinal is bits [0..15] + uint16_t ordinal = value & 0xFFFF; + if (ordinal >= ordinalTable.size()) { + fprintf(stderr, "bind ordinal is out of range\n"); + break; + } + std::tie(symbolName, addend, libraryOrdinal, flags, type) = ordinalTable[ordinal].pack(); + if ( (flags & BIND_SYMBOL_FLAGS_WEAK_IMPORT) != 0 ) + weak_import = " (weak import)"; + else + weak_import = ""; + fromDylib = ordinalName(libraryOrdinal); +#if SUPPORT_ARCH_arm64e + if (isAuthenticated) { + static const char* keyNames[] = { + "IA", "IB", "DA", "DB" + }; + printf("%-7s %-16s 0x%08llX %10s %5lld %-16s %s%s with value 0x%016llX (JOP: diversity %d, address %s, %s)\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName, addend, fromDylib, symbolName, weak_import, value, diversity, hasAddressDiversity ? "true" : "false", keyNames[key]); + } else +#endif + { + printf("%-7s %-16s 0x%08llX %10s %5lld %-16s %s%s with value 0x%016llX\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName, addend, fromDylib, symbolName, weak_import, value ); + } + } + + // The delta is bits [51..61] + // And bit 62 is to tell us if we are a rebase (0) or bind (1) + value &= ~(1ULL << 62); + delta = ( value & 0x3FF8000000000000 ) >> 51; + segOffset += delta * sizeof(pint_t); + } while ( delta != 0); + break; + } + default: + throwf("unknown threaded bind subopcode %d", immediate); + } + break; default: throwf("bad bind opcode %d", *p); } @@ -1652,7 +1922,10 @@ void DyldInfoPrinter::printSharedRegionInfo() uint64_t toOffsetCount = read_uleb128(p, infoEnd); const macho_section

* fromSection = fSections[fromSectionIndex]; const macho_section

* toSection = fSections[toSectionIndex]; - printf("from sect=%s, to sect=%s, count=%lld:\n", fromSection->sectname(), toSection->sectname(), toOffsetCount); + char fromSectionName[20]; + strncpy(fromSectionName, fromSection->sectname(), 16); + fromSectionName[16] = '\0'; + printf("from sect=%s/%s, to sect=%s/%s, count=%lld:\n", fromSection->segname(), fromSectionName, toSection->segname(), toSection->sectname(), toOffsetCount); uint64_t toSectionOffset = 0; const char* lastFromSymbol = NULL; for (uint64_t j=0; j < toOffsetCount; ++j) { @@ -1724,6 +1997,8 @@ const char* DyldInfoPrinter::sharedRegionKindName(uint8_t kind) return "br22"; case DYLD_CACHE_ADJ_V2_IMAGE_OFF_32: return "off32"; + case DYLD_CACHE_ADJ_V2_THREADED_POINTER_64: + return "theaded-pointer64"; } } @@ -1882,56 +2157,40 @@ void DyldInfoPrinter::printDataInCode() template <> -ppc::P::uint_t DyldInfoPrinter::relocBase() +x86_64::P::uint_t DyldInfoPrinter::localRelocBase() { - if ( fHeader->flags() & MH_SPLIT_SEGS ) - return fFirstWritableSegment->vmaddr(); - else + if (fHeader->filetype() == MH_KEXT_BUNDLE) { + // for kext bundles the reloc base address starts at __TEXT segment return fFirstSegment->vmaddr(); -} - -template <> -ppc64::P::uint_t DyldInfoPrinter::relocBase() -{ - if ( fWriteableSegmentWithAddrOver4G ) - return fFirstWritableSegment->vmaddr(); - else - return fFirstSegment->vmaddr(); -} - -template <> -x86::P::uint_t DyldInfoPrinter::relocBase() -{ - if ( fHeader->flags() & MH_SPLIT_SEGS ) - return fFirstWritableSegment->vmaddr(); - else - return fFirstSegment->vmaddr(); -} - -template <> -x86_64::P::uint_t DyldInfoPrinter::relocBase() -{ + } + // for all other kinds, the x86_64 reloc base address starts at first writable segment (usually __DATA) return fFirstWritableSegment->vmaddr(); } -#if SUPPORT_ARCH_arm_any -template <> -arm::P::uint_t DyldInfoPrinter::relocBase() +template +typename A::P::uint_t DyldInfoPrinter::localRelocBase() { - if ( fHeader->flags() & MH_SPLIT_SEGS ) - return fFirstWritableSegment->vmaddr(); - else - return fFirstSegment->vmaddr(); + return fFirstSegment->vmaddr(); } -#endif -#if SUPPORT_ARCH_arm64 + template <> -arm64::P::uint_t DyldInfoPrinter::relocBase() +x86_64::P::uint_t DyldInfoPrinter::externalRelocBase() { + if (fHeader->filetype() == MH_KEXT_BUNDLE) { + // for kext bundles the reloc base address starts at __TEXT segment + return fFirstSegment->vmaddr();; + } return fFirstWritableSegment->vmaddr(); } -#endif + +template +typename A::P::uint_t DyldInfoPrinter::externalRelocBase() +{ + return 0; +} + + template <> const char* DyldInfoPrinter::relocTypeName(uint8_t r_type) @@ -1967,6 +2226,8 @@ const char* DyldInfoPrinter::relocTypeName(uint8_t r_type) { if ( r_type == X86_64_RELOC_UNSIGNED ) return "pointer"; + else if ( r_type == X86_64_RELOC_BRANCH ) + return "branch"; else return "??"; } @@ -1994,17 +2255,105 @@ const char* DyldInfoPrinter::relocTypeName(uint8_t r_type) } #endif + template void DyldInfoPrinter::printRelocRebaseInfo() { + // First check if we can find a magic section for threaded rebase + { + auto rebaseChain = [this](uintptr_t chainStartMappedAddress, uintptr_t chainStartVMAddress, uint64_t stepMultiplier, uintptr_t baseAddress) { + uint64_t delta = 0; + uintptr_t mappedAddress = chainStartMappedAddress; + uintptr_t vmAddress = chainStartVMAddress; + do { + uint64_t value = *(uint64_t*)mappedAddress; + + uint8_t segIndex = segmentIndexForAddress(vmAddress); + const char* segName = segmentName(segIndex); + const char* sectName = sectionName(segIndex, vmAddress); + +#if SUPPORT_ARCH_arm64e + uint16_t diversity = (uint16_t)(value >> 32); + bool hasAddressDiversity = (value & (1ULL << 48)) != 0; + uint8_t key = (uint8_t)((value >> 49) & 0x3); + bool isAuthenticated = (value & (1ULL << 63)) != 0; +#endif + bool isRebase = (value & (1ULL << 62)) == 0; + if (isRebase) { + +#if SUPPORT_ARCH_arm64e + if (isAuthenticated) { + uint64_t slide = 0; + static const char* keyNames[] = { + "IA", "IB", "DA", "DB" + }; + // The new value for a rebase is the low 32-bits of the threaded value plus the slide. + uint64_t newValue = (value & 0xFFFFFFFF) + slide; + // Add in the offset from the mach_header + newValue += baseAddress; + // We have bits to merge in to the discriminator + printf("%-7s %-16s 0x%08llX %s 0x%08llX with value 0x%016llX (JOP: diversity %d, address %s, %s)\n", + segName, sectName, (uint64_t)vmAddress, "pointer", newValue, value, + diversity, hasAddressDiversity ? "true" : "false", keyNames[key]); + } else +#endif + { + // Regular pointer which needs to fit in 51-bits of value. + // C++ RTTI uses the top bit, so we'll allow the whole top-byte + // and the bottom 43-bits to be fit in to 51-bits. + uint64_t top8Bits = value & 0x0007F80000000000ULL; + uint64_t bottom43Bits = value & 0x000007FFFFFFFFFFULL; + uint64_t targetValue = ( top8Bits << 13 ) | (((intptr_t)(bottom43Bits << 21) >> 21) & 0x00FFFFFFFFFFFFFF); + printf("%-7s %-16s 0x%08llX %s 0x%08llX with value 0x%016llX\n", segName, sectName, (uint64_t)vmAddress, "pointer", targetValue, value); + } + } + + // The delta is bits [51..61] + // And bit 62 is to tell us if we are a rebase (0) or bind (1) + value &= ~(1ULL << 62); + delta = ( value & 0x3FF8000000000000 ) >> 51; + mappedAddress += delta * stepMultiplier; + vmAddress += delta * stepMultiplier; + } while ( delta != 0 ); + }; + for(const macho_segment_command

* segCmd : fSegments) { + if (strcmp(segCmd->segname(), "__TEXT") != 0) + continue; + macho_section

* const sectionsStart = (macho_section

*)((char*)segCmd + sizeof(macho_segment_command

)); + macho_section

* const sectionsEnd = §ionsStart[segCmd->nsects()]; + for(macho_section

* sect = sectionsStart; sect < sectionsEnd; ++sect) { + if (strcmp(sect->sectname(), "__thread_starts") != 0) + continue; + printf("rebase information (from __TEXT,__thread_starts):\n"); + printf("segment section address type\n"); + const uint8_t* sectionContent = (uint8_t*)fHeader + sect->offset(); + uint32_t *threadStarts = (uint32_t*)sectionContent; + uint32_t *threadEnds = (uint32_t*)(sectionContent + sect->size()); + uint32_t threadStartsHeader = threadStarts[0]; + uint64_t stepMultiplier = (threadStartsHeader & 1) == 1 ? 8 : 4; + for (uint32_t* threadOffset = threadStarts + 1; threadOffset != threadEnds; ++threadOffset) { + //printf("Thread start offset: 0x%016X\n", *threadOffset); + // If we get a 0xFFFFFFFF offset then ld64 overestimated the size required. So skip the remainder + // of the entries. + if (*threadOffset == 0xFFFFFFFF) + break; + uint64_t chainStartVMAddr = fBaseAddress + *threadOffset; + uintptr_t chainStartMappedAddress = (uintptr_t)mappedAddressForVMAddress(chainStartVMAddr); + rebaseChain(chainStartMappedAddress, chainStartVMAddr, stepMultiplier, fBaseAddress); + } + return; + } + } + } + if ( fDynamicSymbolTable == NULL ) { printf("no classic dynamic symbol table"); } else { printf("rebase information (from local relocation records and indirect symbol table):\n"); - printf("segment section address type\n"); + printf("segment section address type\n"); // walk all local relocations - pint_t rbase = relocBase(); + pint_t rbase = localRelocBase(); const macho_relocation_info

* const relocsStart = (macho_relocation_info

*)(((uint8_t*)fHeader) + fDynamicSymbolTable->locreloff()); const macho_relocation_info

* const relocsEnd = &relocsStart[fDynamicSymbolTable->nlocrel()]; for (const macho_relocation_info

* reloc=relocsStart; reloc < relocsEnd; ++reloc) { @@ -2014,7 +2363,7 @@ void DyldInfoPrinter::printRelocRebaseInfo() const char* typeName = relocTypeName(reloc->r_type()); const char* segName = segmentName(segIndex); const char* sectName = sectionName(segIndex, addr); - printf("%-8s %-16s 0x%08llX %s\n", segName, sectName, (uint64_t)addr, typeName); + printf("%-12s %-16s 0x%08llX %s\n", segName, sectName, (uint64_t)addr, typeName); } else { const macho_scattered_relocation_info

* sreloc = (macho_scattered_relocation_info

*)reloc; @@ -2023,7 +2372,7 @@ void DyldInfoPrinter::printRelocRebaseInfo() const char* typeName = relocTypeName(sreloc->r_type()); const char* segName = segmentName(segIndex); const char* sectName = sectionName(segIndex, addr); - printf("%-8s %-16s 0x%08llX %s\n", segName, sectName, (uint64_t)addr, typeName); + printf("%-12s %-16s 0x%08llX %s\n", segName, sectName, (uint64_t)addr, typeName); } } // look for local non-lazy-pointers @@ -2045,7 +2394,7 @@ void DyldInfoPrinter::printRelocRebaseInfo() const char* typeName = "pointer"; const char* segName = segmentName(segIndex); const char* sectName = sectionName(segIndex, addr); - printf("%-8s %-16s 0x%08llX %s\n", segName, sectName, (uint64_t)addr, typeName); + printf("%-12s %-16s 0x%08llX %s\n", segName, sectName, (uint64_t)addr, typeName); } } } @@ -2143,10 +2492,10 @@ void DyldInfoPrinter::printClassicBindingInfo() printf("no classic dynamic symbol table"); } else { - printf("binding information (from relocations and indirect symbol table):\n"); - printf("segment section address type weak addend dylib symbol\n"); + printf("binding information (from external relocations and indirect symbol table):\n"); + printf("segment section address type weak addend dylib symbol\n"); // walk all external relocations - pint_t rbase = relocBase(); + pint_t rbase = externalRelocBase(); const macho_relocation_info

* const relocsStart = (macho_relocation_info

*)(((uint8_t*)fHeader) + fDynamicSymbolTable->extreloff()); const macho_relocation_info

* const relocsEnd = &relocsStart[fDynamicSymbolTable->nextrel()]; for (const macho_relocation_info

* reloc=relocsStart; reloc < relocsEnd; ++reloc) { @@ -2161,13 +2510,15 @@ void DyldInfoPrinter::printClassicBindingInfo() const char* segName = segmentName(segIndex); const char* sectName = sectionName(segIndex, addr); const pint_t* addressMapped = mappedAddressForVMAddress(addr); - int64_t addend = P::getP(*addressMapped); + int64_t addend = P::getP(*addressMapped); + if ( strcmp(typeName, "pointer") != 0 ) + addend = 0; if ( fHeader->flags() & MH_PREBOUND ) { // In prebound binaries the content is already pointing to the target. // To get the addend requires subtracting out the base address it was prebound to. addend -= sym->n_value(); } - printf("%-8s %-16s 0x%08llX %10s %4s %5lld %-16s %s\n", segName, sectName, (uint64_t)addr, + printf("%-12s %-16s 0x%08llX %10s %4s %5lld %-16s %s\n", segName, sectName, (uint64_t)addr, typeName, weak_import, addend, fromDylib, symbolName); } // look for non-lazy pointers @@ -2194,7 +2545,7 @@ void DyldInfoPrinter::printClassicBindingInfo() const char* segName = segmentName(segIndex); const char* sectName = sectionName(segIndex, addr); int64_t addend = 0; - printf("%-8s %-16s 0x%08llX %10s %4s %5lld %-16s %s\n", segName, sectName, (uint64_t)addr, + printf("%-12s %-16s 0x%08llX %10s %4s %5lld %-16s %s\n", segName, sectName, (uint64_t)addr, typeName, weak_import, addend, fromDylib, symbolName); } } @@ -2324,7 +2675,7 @@ static void dump(const char* path) if ( DyldInfoPrinter::validFile(p + offset) ) DyldInfoPrinter::make(p + offset, size, path, (sPreferredArch == 0)); else - throw "in universal file, arm64 slice does not contain arm mach-o"; + throw "in universal file, arm64 slice does not contain arm64 mach-o"; break; #endif default: @@ -2400,14 +2751,6 @@ int main(int argc, const char* argv[]) sPreferredArch = CPU_TYPE_POWERPC64; else if ( strcmp(arch, "ppc") == 0 ) sPreferredArch = CPU_TYPE_POWERPC; - else if ( strcmp(arch, "i386") == 0 ) - sPreferredArch = CPU_TYPE_I386; - else if ( strcmp(arch, "x86_64") == 0 ) - sPreferredArch = CPU_TYPE_X86_64; -#if SUPPORT_ARCH_arm64 - else if ( strcmp(arch, "arm64") == 0 ) - sPreferredArch = CPU_TYPE_ARM64; -#endif else { if ( arch == NULL ) throw "-arch missing architecture name"; diff --git a/cctools/ld64/src/other/machochecker.cpp b/cctools/ld64/src/other/machochecker.cpp index 0465cd5..e537861 100644 --- a/cctools/ld64/src/other/machochecker.cpp +++ b/cctools/ld64/src/other/machochecker.cpp @@ -101,8 +101,9 @@ class MachOChecker { public: static bool validFile(const uint8_t* fileContent); - static MachOChecker* make(const uint8_t* fileContent, uint32_t fileLength, const char* path, const char* verifierDstRoot) - { return new MachOChecker(fileContent, fileLength, path, verifierDstRoot); } + static MachOChecker* make(const uint8_t* fileContent, uint32_t fileLength, const char* path, + const char* verifierDstRoot, const std::vector& mergeRootPaths) + { return new MachOChecker(fileContent, fileLength, path, verifierDstRoot, mergeRootPaths); } virtual ~MachOChecker() {} @@ -127,13 +128,15 @@ private: typedef std::unordered_set StringSet; - MachOChecker(const uint8_t* fileContent, uint32_t fileLength, const char* path, const char* verifierDstRoot); + MachOChecker(const uint8_t* fileContent, uint32_t fileLength, const char* path, + const char* verifierDstRoot, const std::vector& mergeRootPaths); void checkMachHeader(); void checkLoadCommands(); void checkSection(const macho_segment_command

* segCmd, const macho_section

* sect); uint8_t loadCommandSizeMask(); void checkSymbolTable(); void checkInitTerms(); + void checkThreadedRebaseBind(); void checkIndirectSymbolTable(); void checkRelocations(); void checkExternalReloation(const macho_relocation_info

* reloc); @@ -142,12 +145,14 @@ private: void verifyInstallName(); void verifyNoRpaths(); void verifyNoFlatLookups(); + void verifyiOSMac(); + void verifyNoDylibMain(); pint_t relocBase(); bool addressInWritableSegment(pint_t address); bool hasTextRelocInRange(pint_t start, pint_t end); pint_t segStartAddress(uint8_t segIndex); - bool addressIsRebaseSite(pint_t addr); + bool addressIsRebaseSite(pint_t addr, pint_t& pointeeAddr); bool addressIsBindingSite(pint_t addr); pint_t getInitialStackPointer(const macho_thread_command

*); pint_t getEntryPoint(const macho_thread_command

*); @@ -173,12 +178,15 @@ private: bool fWriteableSegmentWithAddrOver4G; bool fSlidableImage; bool fHasLC_RPATH; + bool fIsDebugVariant; + uint64_t fBaseAddress = 0; const macho_segment_command

* fFirstSegment; const macho_segment_command

* fFirstWritableSegment; const macho_segment_command

* fTEXTSegment; const macho_dyld_info_command

* fDyldInfo; uint32_t fSectionCount; std::vector*>fSegments; + const std::vector& fMergeRootPaths; }; @@ -258,13 +266,15 @@ bool MachOChecker::validFile(const uint8_t* fileContent) } #endif + +template <> uint8_t MachOChecker::loadCommandSizeMask() { return 0x03; } +template <> uint8_t MachOChecker::loadCommandSizeMask() { return 0x07; } template <> uint8_t MachOChecker::loadCommandSizeMask() { return 0x03; } template <> uint8_t MachOChecker::loadCommandSizeMask() { return 0x07; } template <> uint8_t MachOChecker::loadCommandSizeMask() { return 0x03; } template <> uint8_t MachOChecker::loadCommandSizeMask() { return 0x07; } - template <> x86::P::uint_t MachOChecker::getInitialStackPointer(const macho_thread_command* threadInfo) { @@ -290,6 +300,13 @@ arm64::P::uint_t MachOChecker::getInitialStackPointer(const macho_thread_ } +template <> +ppc::P::uint_t MachOChecker::getEntryPoint(const macho_thread_command* threadInfo) +{ + return threadInfo->thread_register(0); +} + + template <> x86::P::uint_t MachOChecker::getEntryPoint(const macho_thread_command* threadInfo) { @@ -343,13 +360,13 @@ const char* MachOChecker::archName() } - template -MachOChecker::MachOChecker(const uint8_t* fileContent, uint32_t fileLength, const char* path, const char* verifierDstRoot) +MachOChecker::MachOChecker(const uint8_t* fileContent, uint32_t fileLength, const char* path, + const char* verifierDstRoot, const std::vector& mergeRootPaths) : fHeader(NULL), fLength(fileLength), fInstallName(NULL), fStrings(NULL), fSymbols(NULL), fSymbolCount(0), fDynamicSymbolTable(NULL), fIndirectTableCount(0), fLocalRelocations(NULL), fLocalRelocationsCount(0), fExternalRelocations(NULL), fExternalRelocationsCount(0), - fWriteableSegmentWithAddrOver4G(false), fSlidableImage(false), fHasLC_RPATH(false), fFirstSegment(NULL), fFirstWritableSegment(NULL), - fTEXTSegment(NULL), fDyldInfo(NULL), fSectionCount(0) + fWriteableSegmentWithAddrOver4G(false), fSlidableImage(false), fHasLC_RPATH(false), fIsDebugVariant(false), fFirstSegment(NULL), fFirstWritableSegment(NULL), + fTEXTSegment(NULL), fDyldInfo(NULL), fSectionCount(0), fMergeRootPaths(mergeRootPaths) { // sanity check if ( ! validFile(fileContent) ) @@ -373,6 +390,8 @@ MachOChecker::MachOChecker(const uint8_t* fileContent, uint32_t fileLength, c checkInitTerms(); + checkThreadedRebaseBind(); + if ( verifierDstRoot != NULL ) verify(); } @@ -385,7 +404,7 @@ void MachOChecker::checkMachHeader() throw "sizeofcmds in mach_header is larger than file"; uint32_t flags = fHeader->flags(); - const uint32_t invalidBits = MH_INCRLINK | MH_LAZY_INIT | 0xFC000000; + const uint32_t invalidBits = MH_INCRLINK | MH_LAZY_INIT | 0xF0000000; if ( flags & invalidBits ) throw "invalid bits in mach_header flags"; if ( (flags & MH_NO_REEXPORTED_DYLIBS) && (fHeader->filetype() != MH_DYLIB) ) @@ -447,11 +466,15 @@ void MachOChecker::checkLoadCommands() case LC_LOAD_UPWARD_DYLIB: case LC_VERSION_MIN_MACOSX: case LC_VERSION_MIN_IPHONEOS: + case LC_VERSION_MIN_TVOS: + case LC_VERSION_MIN_WATCHOS: case LC_FUNCTION_STARTS: case LC_DYLD_ENVIRONMENT: case LC_DATA_IN_CODE: case LC_DYLIB_CODE_SIGN_DRS: case LC_SOURCE_VERSION: + case LC_NOTE: + case LC_BUILD_VERSION: break; case LC_RPATH: fHasLC_RPATH = true; @@ -566,6 +589,8 @@ void MachOChecker::checkLoadCommands() if ( segCmd->vmaddr() > 0x100000000ULL ) fWriteableSegmentWithAddrOver4G = true; } + if ( (segCmd->fileoff() == 0) && (segCmd->filesize() != 0) ) + fBaseAddress = segCmd->vmaddr(); // check section ranges const macho_section

* const sectionsStart = (macho_section

*)((char*)segCmd + sizeof(macho_segment_command

)); @@ -661,8 +686,12 @@ void MachOChecker::checkLoadCommands() // verify encryption info if ( encryption_info != NULL ) { - if ( fHeader->filetype() != MH_EXECUTE ) - throw "LC_ENCRYPTION_INFO load command is only legal in main executables"; + switch ( fHeader->filetype() ) { + case MH_EXECUTE: case MH_DYLIB: case MH_BUNDLE: + break; // okay + default: + throw "LC_ENCRYPTION_INFO load command is not allowed in this file type"; + } if ( encryption_info->cryptoff() < (sizeof(macho_header

) + fHeader->sizeofcmds()) ) throw "LC_ENCRYPTION_INFO load command has cryptoff covers some load commands"; if ( (encryption_info->cryptoff() % 4096) != 0 ) @@ -712,8 +741,6 @@ void MachOChecker::checkLoadCommands() throw "string pool extends beyond __LINKEDIT"; if ( (symtab->stroff() % 4) != 0 ) // work around until rdar://problem/4737991 is fixed throw "string pool start not pointer aligned"; - if ( (symtab->strsize() % sizeof(pint_t)) != 0 ) - throw "string pool size not a multiple of pointer size"; } break; case LC_DYSYMTAB: @@ -727,7 +754,7 @@ void MachOChecker::checkLoadCommands() if ( fIndirectTableCount != 0 ) { if ( fDynamicSymbolTable->indirectsymoff() < linkEditSegment->fileoff() ) throw "indirect symbol table not in __LINKEDIT"; - if ( (fDynamicSymbolTable->indirectsymoff()+fIndirectTableCount*8) > (linkEditSegment->fileoff()+linkEditSegment->filesize()) ) + if ( (fDynamicSymbolTable->indirectsymoff()+fIndirectTableCount*4) > (linkEditSegment->fileoff()+linkEditSegment->filesize()) ) throw "indirect symbol table not in __LINKEDIT"; if ( (fDynamicSymbolTable->indirectsymoff() % sizeof(pint_t)) != 0 ) throw "indirect symbol table not pointer aligned"; @@ -834,19 +861,68 @@ void MachOChecker::checkSection(const macho_segment_command

* segCmd, const // more section tests here } +static bool endsWith(const char* str, const char* suffix) +{ + size_t suffixLen = strlen(suffix); + size_t strLen = strlen(str); + if ( strLen > suffixLen ) { + return (strcmp(&str[strLen-suffixLen], suffix) == 0); + } + return false; +} + + +static bool sharedCacheEligiblePath(const char* path) +{ + return ( (strncmp(path, "/usr/lib/", 9) == 0) + || (strncmp(path, "/System/Library/", 16) == 0) + || (strncmp(path, "/System/iOSSupport/usr/lib/", 27) == 0) + || (strncmp(path, "/System/iOSSupport/System/Library/", 34) == 0) + ); +} template void MachOChecker::verify() { - bool sharedCacheCandidate = false; - if ( fInstallName != NULL ) { - if ( (strncmp(fInstallName, "/usr/lib/", 9) == 0) || (strncmp(fInstallName, "/System/Library/", 16) == 0) ) { - sharedCacheCandidate = true; - verifyInstallName(); - verifyNoRpaths(); + static const char* debugSuffixes[] = { "_asan.dylib", "_asan", "_debug.dylib", "_debug", "_profile", "_profile.dylib", + "_trace", "_trace.dylib", "_tsan", "_tsan.dylib", "_ubsan" , "_ubsan.dylib" }; + for (const char* suffix : debugSuffixes) { + if ( endsWith(fPath, suffix) ) + fIsDebugVariant = true; + } + + if ( (fDstRoot != NULL) && (strlen(fDstRoot) < strlen(fPath)) ) { + const char* installLocationInDstRoot = &fPath[strlen(fDstRoot)]; + if ( installLocationInDstRoot[0] != '/' ) + --installLocationInDstRoot; + if ( fMergeRootPaths.empty() ) { + if ( sharedCacheEligiblePath(installLocationInDstRoot) ) { + if ( !fIsDebugVariant && (strstr(fPath, ".app/") == NULL) ) { + verifyInstallName(); + verifyNoRpaths(); + verifyNoDylibMain(); + } + } } + else { + for (const char* mergeRoot : fMergeRootPaths) { + // mergeRoot is a prefix of where the file will really be installed (such as in a toolchain) + char fullerPath[PATH_MAX]; + strlcpy(fullerPath, mergeRoot, PATH_MAX); + strlcat(fullerPath, installLocationInDstRoot, PATH_MAX); + if ( sharedCacheEligiblePath(fullerPath) ) { + if ( !fIsDebugVariant && (strstr(fullerPath, ".app/") == NULL) ) { + verifyInstallName(); + verifyNoRpaths(); + verifyNoDylibMain(); + } + } + } + } + } verifyNoFlatLookups(); + verifyiOSMac(); } @@ -915,6 +991,61 @@ void MachOChecker::verifyNoFlatLookups() } } + +template +void MachOChecker::verifyNoDylibMain() +{ + if ( fHeader->filetype() != MH_DYLIB ) + return; + + const macho_nlist

* const exportedStart = &fSymbols[fDynamicSymbolTable->iextdefsym()]; + const macho_nlist

* const exportedEnd = &exportedStart[fDynamicSymbolTable->nextdefsym()]; + int i = fDynamicSymbolTable->iextdefsym(); + for(const macho_nlist

* p = exportedStart; p < exportedEnd; ++p, ++i) { + const char* symName = &fStrings[p->n_strx()]; + if ( strcmp(symName, "_main") == 0 ) { + printf("os_dylib_exports_main\twarn\tdylibs should export '_main' symbol in arch %s\n", archName()); + return; + } + } +} + + +template +void MachOChecker::verifyiOSMac() +{ + const char* fileLocationWithinDstRoot = &fPath[strlen(fDstRoot)]; + if ( strncmp(fileLocationWithinDstRoot, "/System/iOSSupport/", 19) == 0 ) { + // everything in /System/iOSSupport/ should be iOSMac only + bool bad = false; + const uint32_t cmd_count = fHeader->ncmds(); + const macho_load_command

* cmd = (macho_load_command

*)((uint8_t*)fHeader + sizeof(macho_header

)); + for (uint32_t i = 0; i < cmd_count; ++i) { + const macho_build_version_command

* buildVersCmd; + switch ( cmd->cmd() ) { + case LC_VERSION_MIN_MACOSX: + case LC_VERSION_MIN_IPHONEOS: + case LC_VERSION_MIN_TVOS: + case LC_VERSION_MIN_WATCHOS: + bad = true; + break; + case LC_BUILD_VERSION: + buildVersCmd = (macho_build_version_command

*)cmd; + if ( buildVersCmd->platform() != PLATFORM_IOSMAC ) + bad = true; + break; + } + cmd = (const macho_load_command

*)(((uint8_t*)cmd)+cmd->cmdsize()); + } + if ( bad ) + printf("macos_in_ios_support\twarn\tnon-iOSMac in /System/iOSSupport/ in arch %s\n", archName()); + } + else { + // maybe someday warn about iOSMac only stuff not in /System/iOSSupport/ + } +} + + template void MachOChecker::checkIndirectSymbolTable() { @@ -1070,23 +1201,28 @@ void MachOChecker::checkInitTerms() throwf("%s section size is not an even multiple of element size", sect->sectname()); if ( (sect->addr() % sizeof(pint_t)) != 0 ) throwf("%s section size is not pointer size aligned", sect->sectname()); - // check each pointer in array points within TEXT arrayStart = (pint_t*)((char*)fHeader + sect->offset()); arrayEnd = (pint_t*)((char*)fHeader + sect->offset() + sect->size()); - for (pint_t* p=arrayStart; p < arrayEnd; ++p) { - pint_t pointer = P::getP(*p); - if ( (pointer < fTEXTSegment->vmaddr()) || (pointer >= (fTEXTSegment->vmaddr()+fTEXTSegment->vmsize())) ) - throwf("%s 0x%08llX points outside __TEXT segment", kind, (long long)pointer); - } // check each pointer in array will be rebased and not bound if ( fSlidableImage ) { pint_t sectionBeginAddr = sect->addr(); pint_t sectionEndddr = sect->addr() + sect->size(); - for(pint_t addr = sectionBeginAddr; addr < sectionEndddr; addr += sizeof(pint_t)) { + for(pint_t addr = sectionBeginAddr, *p = arrayStart; addr < sectionEndddr; addr += sizeof(pint_t), ++p) { if ( addressIsBindingSite(addr) ) throwf("%s at 0x%0llX has binding to external symbol", kind, (long long)addr); - if ( ! addressIsRebaseSite(addr) ) + pint_t pointer = P::getP(*p); + if ( ! addressIsRebaseSite(addr, pointer) ) throwf("%s at 0x%0llX is not rebased", kind, (long long)addr); + // check each pointer in array points within TEXT + if ( (pointer < fTEXTSegment->vmaddr()) || (pointer >= (fTEXTSegment->vmaddr()+fTEXTSegment->vmsize())) ) + throwf("%s 0x%08llX points outside __TEXT segment", kind, (long long)pointer); + } + } else { + // check each pointer in array points within TEXT + for (pint_t* p=arrayStart; p < arrayEnd; ++p) { + pint_t pointer = P::getP(*p); + if ( (pointer < fTEXTSegment->vmaddr()) || (pointer >= (fTEXTSegment->vmaddr()+fTEXTSegment->vmsize())) ) + throwf("%s 0x%08llX 3 points outside __TEXT segment", kind, (long long)pointer); } } break; @@ -1098,6 +1234,131 @@ void MachOChecker::checkInitTerms() } +template +void MachOChecker::checkThreadedRebaseBind() +{ + // look bind info + if ( fDyldInfo != NULL ) { + const uint8_t* p = (uint8_t*)fHeader + fDyldInfo->bind_off(); + const uint8_t* end = &p[fDyldInfo->bind_size()]; + + uint8_t type = 0; + uint64_t segOffset = 0; + uint32_t count; + uint32_t skip; + const char* symbolName = NULL; + int libraryOrdinal = 0; + int segIndex; + int64_t addend = 0; + pint_t segStartAddr = 0; + uint64_t ordinalTableSize = 0; + bool useThreadedRebaseBind = false; + bool done = false; + while ( !done && (p < end) ) { + uint8_t immediate = *p & BIND_IMMEDIATE_MASK; + uint8_t opcode = *p & BIND_OPCODE_MASK; + ++p; + switch (opcode) { + case BIND_OPCODE_DONE: + done = true; + break; + case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: + libraryOrdinal = immediate; + break; + case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: + libraryOrdinal = read_uleb128(p, end); + break; + case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: + // the special ordinals are negative numbers + if ( immediate == 0 ) + libraryOrdinal = 0; + else { + int8_t signExtended = BIND_OPCODE_MASK | immediate; + libraryOrdinal = signExtended; + } + break; + case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: + symbolName = (char*)p; + while (*p != '\0') + ++p; + ++p; + break; + case BIND_OPCODE_SET_TYPE_IMM: + type = immediate; + break; + case BIND_OPCODE_SET_ADDEND_SLEB: + addend = read_sleb128(p, end); + break; + case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: + segIndex = immediate; + segStartAddr = segStartAddress(segIndex); + segOffset = read_uleb128(p, end); + break; + case BIND_OPCODE_ADD_ADDR_ULEB: + segOffset += read_uleb128(p, end); + break; + case BIND_OPCODE_DO_BIND: + segOffset += sizeof(pint_t); + break; + case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: + segOffset += read_uleb128(p, end) + sizeof(pint_t); + break; + case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: + segOffset += immediate*sizeof(pint_t) + sizeof(pint_t); + break; + case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: + count = read_uleb128(p, end); + skip = read_uleb128(p, end); + for (uint32_t i=0; i < count; ++i) { + segOffset += skip + sizeof(pint_t); + } + break; + case BIND_OPCODE_THREADED: + // Note the immediate is a sub opcode + switch (immediate) { + case BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB: + ordinalTableSize = read_uleb128(p, end); + useThreadedRebaseBind = true; + break; + case BIND_SUBOPCODE_THREADED_APPLY: { + if ( !useThreadedRebaseBind ) { + throwf("BIND_SUBOPCODE_THREADED_APPLY without ordinal table"); + } + uint64_t delta = 0; + do { + const uint8_t* pointerLocation = (uint8_t*)fHeader + fSegments[segIndex]->fileoff() + segOffset; + uint64_t value = P::getP(*(uint64_t*)pointerLocation); + bool isRebase = (value & (1ULL << 62)) == 0; + + if (isRebase) { + //printf("(rebase): %-7s %-16s 0x%08llX %s\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName); + } else { + // the ordinal is bits [0..15] + uint16_t ordinal = value & 0xFFFF; + if (ordinal >= ordinalTableSize) { + throwf("bind ordinal is out of range"); + } + } + + // The delta is bits [51..61] + // And bit 62 is to tell us if we are a rebase (0) or bind (1) + value &= ~(1ULL << 62); + delta = ( value & 0x3FF8000000000000 ) >> 51; + segOffset += delta * sizeof(pint_t); + } while ( delta != 0); + break; + } + default: + throwf("unknown threaded bind subopcode %d", immediate); + } + break; + default: + throwf("bad bind opcode %d", *p); + } + } + } +} + template <> @@ -1131,6 +1392,7 @@ arm64::P::uint_t MachOChecker::relocBase() return fFirstWritableSegment->vmaddr(); } + template bool MachOChecker::addressInWritableSegment(pint_t address) { @@ -1274,6 +1536,7 @@ void MachOChecker::checkLocalReloation(const macho_relocation_info

* re } #endif + template void MachOChecker::checkRelocations() { @@ -1421,7 +1684,7 @@ bool MachOChecker::hasTextRelocInRange(pint_t rangeStart, pint_t rangeEnd) } template -bool MachOChecker::addressIsRebaseSite(pint_t targetAddr) +bool MachOChecker::addressIsRebaseSite(pint_t targetAddr, pint_t& pointeeAddr) { // look at local relocs const macho_relocation_info

* const localRelocsEnd = &fLocalRelocations[fLocalRelocationsCount]; @@ -1505,12 +1768,125 @@ bool MachOChecker::addressIsRebaseSite(pint_t targetAddr) default: throwf("bad rebase opcode %d", *p); } - } + } + + // If we have no rebase opcodes, then we may be using the threaded rebase/bind combined + // format and need to parse the bind opcodes instead. + if ( (fDyldInfo->rebase_size() == 0) && (fDyldInfo->bind_size() != 0) ) { + const uint8_t* p = (uint8_t*)fHeader + fDyldInfo->bind_off(); + const uint8_t* end = &p[fDyldInfo->bind_size()]; + + uint8_t segIndex = 0; + uint64_t segOffset = 0; + uint32_t count; + uint32_t skip; + pint_t segStartAddr = 0; + bool done = false; + while ( !done && (p < end) ) { + uint8_t immediate = *p & BIND_IMMEDIATE_MASK; + uint8_t opcode = *p & BIND_OPCODE_MASK; + ++p; + switch (opcode) { + case BIND_OPCODE_DONE: + done = true; + break; + case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: + break; + case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: + read_uleb128(p, end); + break; + case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: + break; + case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: + while (*p != '\0') + ++p; + ++p; + break; + case BIND_OPCODE_SET_TYPE_IMM: + break; + case BIND_OPCODE_SET_ADDEND_SLEB: + read_sleb128(p, end); + break; + case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: + segIndex = immediate; + segStartAddr = segStartAddress(segIndex); + segOffset = read_uleb128(p, end); + break; + case BIND_OPCODE_ADD_ADDR_ULEB: + segOffset += read_uleb128(p, end); + break; + case BIND_OPCODE_DO_BIND: + break; + case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: + segOffset += read_uleb128(p, end) + sizeof(pint_t); + break; + case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: + segOffset += immediate*sizeof(pint_t) + sizeof(pint_t); + break; + case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: + count = read_uleb128(p, end); + skip = read_uleb128(p, end); + for (uint32_t i=0; i < count; ++i) { + segOffset += skip + sizeof(pint_t); + } + break; + case BIND_OPCODE_THREADED: + // Note the immediate is a sub opcode + switch (immediate) { + case BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB: + count = read_uleb128(p, end); + break; + case BIND_SUBOPCODE_THREADED_APPLY: { + uint64_t delta = 0; + do { + uint8_t* pointerLocation = (uint8_t*)fHeader + fSegments[segIndex]->fileoff() + segOffset; + uint64_t value = P::getP(*(uint64_t*)pointerLocation); +#if SUPPORT_ARCH_arm64e + bool isAuthenticated = (value & (1ULL << 63)) != 0; +#endif + bool isRebase = (value & (1ULL << 62)) == 0; + if ( isRebase && ( (segStartAddr+segOffset) == targetAddr ) ) { + +#if SUPPORT_ARCH_arm64e + if (isAuthenticated) { + uint64_t targetValue = value & 0xFFFFFFFFULL; + targetValue += fBaseAddress; + pointeeAddr = (pint_t)targetValue; + } else +#endif + { + // Regular pointer which needs to fit in 51-bits of value. + // C++ RTTI uses the top bit, so we'll allow the whole top-byte + // and the signed-extended bottom 43-bits to be fit in to 51-bits. + uint64_t top8Bits = value & 0x0007F80000000000ULL; + uint64_t bottom43Bits = value & 0x000007FFFFFFFFFFULL; + uint64_t targetValue = ( top8Bits << 13 ) | (((intptr_t)(bottom43Bits << 21) >> 21) & 0x00FFFFFFFFFFFFFF); + pointeeAddr = (pint_t)targetValue; + } + return true; + } + + // The delta is bits [51..61] + // And bit 62 is to tell us if we are a rebase (0) or bind (1) + value &= ~(1ULL << 62); + delta = ( value & 0x3FF8000000000000 ) >> 51; + segOffset += delta * sizeof(pint_t); + } while ( delta != 0 ); + break; + } + default: + throwf("unknown threaded bind subopcode %d", immediate); + } + break; + default: + throwf("bad bind opcode %d", *p); + } + } + } } return false; } - template bool MachOChecker::addressIsBindingSite(pint_t targetAddr) { @@ -1530,13 +1906,11 @@ bool MachOChecker::addressIsBindingSite(pint_t targetAddr) uint64_t segOffset = 0; uint32_t count; uint32_t skip; - uint8_t flags; const char* symbolName = NULL; int libraryOrdinal = 0; int segIndex; int64_t addend = 0; pint_t segStartAddr = 0; - pint_t addr; bool done = false; while ( !done && (p < end) ) { uint8_t immediate = *p & BIND_IMMEDIATE_MASK; @@ -1605,6 +1979,35 @@ bool MachOChecker::addressIsBindingSite(pint_t targetAddr) segOffset += skip + sizeof(pint_t); } break; + case BIND_OPCODE_THREADED: + // Note the immediate is a sub opcode + switch (immediate) { + case BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB: + count = read_uleb128(p, end); + break; + case BIND_SUBOPCODE_THREADED_APPLY: { + uint64_t delta = 0; + do { + uint8_t* pointerLocation = (uint8_t*)fHeader + fSegments[segIndex]->fileoff() + segOffset; + uint64_t value = P::getP(*(uint64_t*)pointerLocation); + bool isRebase = (value & (1ULL << 62)) == 0; + if (!isRebase) { + if ( (segStartAddr+segOffset) == targetAddr ) + return true; + } + + // The delta is bits [51..61] + // And bit 62 is to tell us if we are a rebase (0) or bind (1) + value &= ~(1ULL << 62); + delta = ( value & 0x3FF8000000000000 ) >> 51; + segOffset += delta * sizeof(pint_t); + } while ( delta != 0 ); + break; + } + default: + throwf("unknown threaded bind subopcode %d", immediate); + } + break; default: throwf("bad bind opcode %d", *p); } @@ -1614,7 +2017,7 @@ bool MachOChecker::addressIsBindingSite(pint_t targetAddr) } -static void check(const char* path, const char* verifierDstRoot) +static void check(const char* path, const char* verifierDstRoot, const std::vector& mergeRootPaths) { struct stat stat_buf; @@ -1641,20 +2044,20 @@ static void check(const char* path, const char* verifierDstRoot) switch(cputype) { case CPU_TYPE_I386: if ( MachOChecker::validFile(p + offset) ) - MachOChecker::make(p + offset, size, path, verifierDstRoot); + MachOChecker::make(p + offset, size, path, verifierDstRoot, mergeRootPaths); else throw "in universal file, i386 slice does not contain i386 mach-o"; break; case CPU_TYPE_X86_64: if ( MachOChecker::validFile(p + offset) ) - MachOChecker::make(p + offset, size, path, verifierDstRoot); + MachOChecker::make(p + offset, size, path, verifierDstRoot, mergeRootPaths); else throw "in universal file, x86_64 slice does not contain x86_64 mach-o"; break; #if SUPPORT_ARCH_arm_any case CPU_TYPE_ARM: if ( MachOChecker::validFile(p + offset) ) - MachOChecker::make(p + offset, size, path, verifierDstRoot); + MachOChecker::make(p + offset, size, path, verifierDstRoot, mergeRootPaths); else throw "in universal file, arm slice does not contain arm mach-o"; break; @@ -1662,7 +2065,7 @@ static void check(const char* path, const char* verifierDstRoot) #if SUPPORT_ARCH_arm64 case CPU_TYPE_ARM64: if ( MachOChecker::validFile(p + offset) ) - MachOChecker::make(p + offset, size, path, verifierDstRoot); + MachOChecker::make(p + offset, size, path, verifierDstRoot, mergeRootPaths); else throw "in universal file, arm64 slice does not contain arm mach-o"; break; @@ -1673,19 +2076,19 @@ static void check(const char* path, const char* verifierDstRoot) } } else if ( MachOChecker::validFile(p) ) { - MachOChecker::make(p, length, path, verifierDstRoot); + MachOChecker::make(p, length, path, verifierDstRoot, mergeRootPaths); } else if ( MachOChecker::validFile(p) ) { - MachOChecker::make(p, length, path, verifierDstRoot); + MachOChecker::make(p, length, path, verifierDstRoot, mergeRootPaths); } #if SUPPORT_ARCH_arm_any else if ( MachOChecker::validFile(p) ) { - MachOChecker::make(p, length, path, verifierDstRoot); + MachOChecker::make(p, length, path, verifierDstRoot, mergeRootPaths); } #endif #if SUPPORT_ARCH_arm64 else if ( MachOChecker::validFile(p) ) { - MachOChecker::make(p, length, path, verifierDstRoot); + MachOChecker::make(p, length, path, verifierDstRoot, mergeRootPaths); } #endif else { @@ -1700,6 +2103,7 @@ static void check(const char* path, const char* verifierDstRoot) int main(int argc, const char* argv[]) { + std::vector mergeRootPaths; bool progress = false; const char* verifierDstRoot = NULL; int result = 0; @@ -1715,12 +2119,19 @@ int main(int argc, const char* argv[]) else if ( strcmp(arg, "-verifier_error_list") == 0 ) { printf("os_dylib_rpath_install_name\tOS dylibs (those in /usr/lib/ or /System/Library/) must be built with -install_name that is an absolute path - not an @rpath\n"); printf("os_dylib_bad_install_name\tOS dylibs (those in /usr/lib/ or /System/Library/) must be built with -install_name matching their file system location\n"); - printf("os_dylib_rpath\tOS dylibs should not contain LC_RPATH load commands (from -rpath linker option)\n"); + printf("os_dylib_rpath\tOS dylibs should not contain LC_RPATH load commands (from -rpath linker option)(remove LD_RUNPATH_SEARCH_PATHS Xcode build setting)\n"); printf("os_dylib_flat_namespace\tOS dylibs should not be built with -flat_namespace\n"); printf("os_dylib_undefined_dynamic_lookup\tOS dylibs should not be built with -undefined dynamic_lookup\n"); - printf("os_dylib_malformed\the mach-o is malformed\n"); + printf("os_dylib_malformed\tthe mach-o file is malformed\n"); + printf("macos_in_ios_support\t/System/iOSSupport/ should only contain mach-o files that support iosmac\n"); + printf("os_dylib_exports_main\tOS dylibs should not export '_main' symbol\n"); return 0; } + else if ( strcmp(arg, "-merge_root_path") == 0 ) { + const char* mergeRoot = argv[++i]; + if ( strcmp(mergeRoot, "/") != 0 ) + mergeRootPaths.push_back(mergeRoot); + } else { throwf("unknown option: %s\n", arg); } @@ -1728,7 +2139,7 @@ int main(int argc, const char* argv[]) else { bool success = true; try { - check(arg, verifierDstRoot); + check(arg, verifierDstRoot, mergeRootPaths); } catch (const char* msg) { if ( verifierDstRoot ) { diff --git a/cctools/ld64/src/other/objcimageinfo.cpp b/cctools/ld64/src/other/objcimageinfo.cpp new file mode 100644 index 0000000..0609d3b --- /dev/null +++ b/cctools/ld64/src/other/objcimageinfo.cpp @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2007-2009 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +// objcimageinfo.cpp +// Print or edit ObjC image info bits. +// This is used to verify ld's handling of these bits +// for values that are not emitted by current compilers. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "MachOFileAbstraction.hpp" + +#if __BIG_ENDIAN__ + typedef BigEndian CurrentEndian; + typedef LittleEndian OtherEndian; +#elif __LITTLE_ENDIAN__ + typedef LittleEndian CurrentEndian; + typedef BigEndian OtherEndian; +#else +# error unknown endianness +#endif + +static const bool debug = false; + +static bool processFile(const char *filename, uint32_t set, uint32_t clear); + +// fixme use objc/objc-abi.h instead +struct objc_image_info { + uint32_t version; + uint32_t flags; + + enum : uint32_t { + IsReplacement = 1<<0, // used for Fix&Continue, now ignored + SupportsGC = 1<<1, // image supports GC + RequiresGC = 1<<2, // image requires GC + OptimizedByDyld = 1<<3, // image is from an optimized shared cache + CorrectedSynthesize = 1<<4, // used for an old workaround, now ignored + IsSimulated = 1<<5, // image compiled for a simulator platform + HasCategoryClassProperties = 1<<6, // class properties in category_t + + SwiftVersionMask = 0xff << 8 // Swift ABI version + }; +}; + +// objc_image_info flags and their names +static const struct { + const char *name; + uint32_t value; +} Flags[] = { + { "supports-gc", objc_image_info::SupportsGC }, + { "requires-gc", objc_image_info::RequiresGC }, + { "has-category-class-properties", objc_image_info::HasCategoryClassProperties }, + { 0, 0 } +}; + +static void usage(const char *self) +{ + printf("usage: %s [+FLAG|-FLAG ...] file ...\n", self); + printf("Use +FLAG to set and -FLAG to clear.\n"); + printf("Known flags: "); + for (int i = 0; Flags[i].name != 0; i++) { + printf("%s ", Flags[i].name); + } + printf("\n"); +} + +static uint32_t flagForName(const char *name) +{ + for (int i = 0; Flags[i].name != 0; i++) { + if (0 == strcmp(Flags[i].name, name)) { + return Flags[i].value; + } + } + return 0; +} + +static const char *nameForFlag(uint32_t flag) +{ + for (int i = 0; Flags[i].name != 0; i++) { + if (Flags[i].value == flag) { + return Flags[i].name; + } + } + return 0; +} + +static void printFlags(uint32_t flags) +{ + printf("0x%x", flags); + + // Print flags and unknown bits + for (int i = 0; i < 24; i++) { + uint32_t flag = 1<> shift; + if (swift > 0) { + printf(" swift-version=%u", swift); + } +} + +static bool isFlagArgument(const char *arg) +{ + return (arg && (arg[0] == '+' || arg[0] == '-')); +} + +int main(int argc, const char *argv[]) { + uint32_t set = 0; + uint32_t clear = 0; + + // Find flag arguments (which are +FLAG or -FLAG). + int i; + for (i = 1; i < argc && isFlagArgument(argv[i]); i++) { + const char *arg = argv[i]; + uint32_t flag = flagForName(arg+1); + if (flag) { + if (arg[0] == '+') { + set |= flag; + } else { + clear |= flag; + } + } else { + printf("error: unrecognized ObjC flag '%s'\n", arg); + usage(argv[0]); + return 1; + } + } + + // Complain if +FLAG and -FLAG are both set for some flag. + uint32_t overlap = set & clear; + if (overlap) { + printf("error: conflicting changes specified: "); + printFlags(overlap); + printf("\n"); + usage(argv[0]); + return 1; + } + + // Complain if there are no filenames. + if (i == argc) { + printf("error: no files specified\n"); + usage(argv[0]); + return 1; + } + + // Process files. + for (; i < argc; i++) { + if (!processFile(argv[i], set, clear)) return 1; + } + return 0; +} + + +// Segment and section names are 16 bytes and may be un-terminated. +static bool segnameEquals(const char *lhs, const char *rhs) +{ + return 0 == strncmp(lhs, rhs, 16); +} + +static bool segnameStartsWith(const char *segname, const char *prefix) +{ + return 0 == strncmp(segname, prefix, strlen(prefix)); +} + +static bool sectnameEquals(const char *lhs, const char *rhs) +{ + return segnameEquals(lhs, rhs); +} + + +template +static void dosect(const char *filename, uint8_t *start, macho_section

*sect, + uint32_t set, uint32_t clear) +{ + if (debug) printf("section %.16s from segment %.16s\n", + sect->sectname(), sect->segname()); + + if ((segnameStartsWith(sect->segname(), "__DATA") && + sectnameEquals(sect->sectname(), "__objc_imageinfo")) || + (segnameEquals(sect->segname(), "__OBJC") && + sectnameEquals(sect->sectname(), "__image_info"))) + { + objc_image_info *ii = (objc_image_info *)(start + sect->offset()); + uint32_t oldFlags = P::E::get32(ii->flags); + uint32_t newFlags = (oldFlags | set) & ~clear; + if (oldFlags != newFlags) { + P::E::set32(ii->flags, newFlags); + if (debug) printf("changed flags from 0x%x to 0x%x\n", + oldFlags, newFlags); + } + + printf("%s: ", filename); + printFlags(newFlags); + printf("\n"); + } +} + +template +static void doseg(const char *filename, + uint8_t *start, macho_segment_command

*seg, + uint32_t set, uint32_t clear) +{ + if (debug) printf("segment name: %.16s, nsects %u\n", + seg->segname(), seg->nsects()); + macho_section

*sect = (macho_section

*)(seg + 1); + for (uint32_t i = 0; i < seg->nsects(); ++i) { + dosect(filename, start, §[i], set, clear); + } +} + + +template +static bool parse_macho(const char *filename, uint8_t *buffer, + uint32_t set, uint32_t clear) +{ + macho_header

* mh = (macho_header

*)buffer; + uint8_t *cmds = (uint8_t *)(mh + 1); + for (uint32_t c = 0; c < mh->ncmds(); c++) { + macho_load_command

* cmd = (macho_load_command

*)cmds; + cmds += cmd->cmdsize(); + if (cmd->cmd() == LC_SEGMENT || cmd->cmd() == LC_SEGMENT_64) { + doseg(filename, buffer, (macho_segment_command

*)cmd, set, clear); + } + } + + return true; +} + + +static bool parse_macho(const char *filename, uint8_t *buffer, + uint32_t set, uint32_t clear) +{ + uint32_t magic = *(uint32_t *)buffer; + + switch (magic) { + case MH_MAGIC_64: + return parse_macho> + (filename, buffer, set, clear); + case MH_MAGIC: + return parse_macho> + (filename, buffer, set, clear); + case MH_CIGAM_64: + return parse_macho> + (filename, buffer, set, clear); + case MH_CIGAM: + return parse_macho> + (filename, buffer, set, clear); + default: + printf("error: file '%s' is not mach-o (magic %x)\n", filename, magic); + return false; + } +} + + +static bool parse_fat(const char *filename, uint8_t *buffer, size_t size, + uint32_t set, uint32_t clear) +{ + uint32_t magic; + + if (size < sizeof(magic)) { + printf("error: file '%s' is too small\n", filename); + return false; + } + + magic = *(uint32_t *)buffer; + if (magic != FAT_MAGIC && magic != FAT_CIGAM) { + /* Not a fat file */ + return parse_macho(filename, buffer, set, clear); + } else { + struct fat_header *fh; + uint32_t fat_magic, fat_nfat_arch; + struct fat_arch *archs; + + if (size < sizeof(struct fat_header)) { + printf("error: file '%s' is too small\n", filename); + return false; + } + + fh = (struct fat_header *)buffer; + fat_magic = OSSwapBigToHostInt32(fh->magic); + fat_nfat_arch = OSSwapBigToHostInt32(fh->nfat_arch); + + if (size < (sizeof(struct fat_header) + fat_nfat_arch * sizeof(struct fat_arch))) { + printf("error: file '%s' is too small\n", filename); + return false; + } + + archs = (struct fat_arch *)(buffer + sizeof(struct fat_header)); + + /* Special case hidden CPU_TYPE_ARM64 */ + if (size >= (sizeof(struct fat_header) + (fat_nfat_arch + 1) * sizeof(struct fat_arch))) { + if (fat_nfat_arch > 0 + && OSSwapBigToHostInt32(archs[fat_nfat_arch].cputype) == CPU_TYPE_ARM64) { + fat_nfat_arch++; + } + } + /* End special case hidden CPU_TYPE_ARM64 */ + + if (debug) printf("%d fat architectures\n", fat_nfat_arch); + + for (uint32_t i = 0; i < fat_nfat_arch; i++) { + uint32_t arch_cputype = OSSwapBigToHostInt32(archs[i].cputype); + uint32_t arch_cpusubtype = OSSwapBigToHostInt32(archs[i].cpusubtype); + uint32_t arch_offset = OSSwapBigToHostInt32(archs[i].offset); + uint32_t arch_size = OSSwapBigToHostInt32(archs[i].size); + + if (debug) printf("cputype %d cpusubtype %d\n", + arch_cputype, arch_cpusubtype); + + /* Check that slice data is after all fat headers and archs */ + if (arch_offset < (sizeof(struct fat_header) + fat_nfat_arch * sizeof(struct fat_arch))) { + printf("error: file is badly formed\n"); + return false; + } + + /* Check that the slice ends before the file does */ + if (arch_offset > size) { + printf("error: file '%s' is badly formed\n", filename); + return false; + } + + if (arch_size > size) { + printf("error: file '%s' is badly formed\n", filename); + return false; + } + + if (arch_offset > (size - arch_size)) { + printf("error: file '%s' is badly formed\n", filename); + return false; + } + + bool ok = parse_macho(filename, buffer + arch_offset, set, clear); + if (!ok) return false; + } + return true; + } +} + +static bool processFile(const char *filename, uint32_t set, uint32_t clear) +{ + if (debug) printf("file %s\n", filename); + int openPerm = O_RDONLY; + int mmapPerm = PROT_READ; + if (set || clear) { + openPerm = O_RDWR; + mmapPerm = PROT_READ | PROT_WRITE; + } + + int fd = open(filename, openPerm); + if (fd < 0) { + printf("error: open %s: %s\n", filename, strerror(errno)); + return false; + } + + struct stat st; + if (fstat(fd, &st) < 0) { + printf("error: fstat %s: %s\n", filename, strerror(errno)); + return false; + } + + void *buffer = mmap(NULL, (size_t)st.st_size, mmapPerm, + MAP_FILE|MAP_SHARED, fd, 0); + if (buffer == MAP_FAILED) { + printf("error: mmap %s: %s\n", filename, strerror(errno)); + return false; + } + + bool result = + parse_fat(filename, (uint8_t *)buffer, (size_t)st.st_size, set, clear); + munmap(buffer, (size_t)st.st_size); + close(fd); + return result; +} diff --git a/cctools/ld64/src/other/rebase.cpp b/cctools/ld64/src/other/rebase.cpp deleted file mode 100644 index e2776cf..0000000 --- a/cctools/ld64/src/other/rebase.cpp +++ /dev/null @@ -1,1087 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- - * - * Copyright (c) 2006-2012 Apple Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "MachOFileAbstraction.hpp" -#include "Architectures.hpp" - -static bool verbose = false; - -__attribute__((noreturn)) -void throwf(const char* format, ...) -{ - va_list list; - char* p; - va_start(list, format); - vasprintf(&p, format, list); - va_end(list); - - const char* t = p; - throw t; -} - - -class AbstractRebaser -{ -public: - virtual cpu_type_t getArchitecture() const = 0; - virtual uint64_t getBaseAddress() const = 0; - virtual uint64_t getVMSize() const = 0; - virtual void setBaseAddress(uint64_t) = 0; -}; - - -template -class Rebaser : public AbstractRebaser -{ -public: - Rebaser(const void* machHeader); - virtual ~Rebaser() {} - - virtual cpu_type_t getArchitecture() const; - virtual uint64_t getBaseAddress() const; - virtual uint64_t getVMSize() const; - virtual void setBaseAddress(uint64_t); - -private: - typedef typename A::P P; - typedef typename A::P::E E; - typedef typename A::P::uint_t pint_t; - - struct vmmap { pint_t vmaddr; pint_t vmsize; pint_t fileoff; }; - - void setRelocBase(); - void buildSectionTable(); - void adjustLoadCommands(); - void adjustSymbolTable(); - void adjustDATA(); - void doLocalRelocation(const macho_relocation_info

* reloc); - pint_t* mappedAddressForVMAddress(uint32_t vmaddress); - void rebaseAt(int segIndex, uint64_t offset, uint8_t type); - - const macho_header

* fHeader; - pint_t fOrignalVMRelocBaseAddress; - pint_t fSlide; - std::vector fVMMApping; -}; - - - -class MultiArchRebaser -{ -public: - MultiArchRebaser(const char* path, bool writable=false); - ~MultiArchRebaser(); - - const std::vector& getArchs() const { return fRebasers; } - void commit(); - -private: - std::vector fRebasers; - void* fMappingAddress; - uint64_t fFileSize; -}; - - - -MultiArchRebaser::MultiArchRebaser(const char* path, bool writable) - : fMappingAddress(0), fFileSize(0) -{ - // map in whole file - int fd = ::open(path, (writable ? O_RDWR : O_RDONLY), 0); - if ( fd == -1 ) - throwf("can't open file %s, errno=%d", path, errno); - struct stat stat_buf; - if ( fstat(fd, &stat_buf) == -1) - throwf("can't stat open file %s, errno=%d", path, errno); - if ( stat_buf.st_size < 20 ) - throwf("file too small %s", path); - const int prot = writable ? (PROT_READ | PROT_WRITE) : PROT_READ; - const int flags = writable ? (MAP_FILE | MAP_SHARED) : (MAP_FILE | MAP_PRIVATE); - uint8_t* p = (uint8_t*)::mmap(NULL, stat_buf.st_size, prot, flags, fd, 0); - if ( p == (uint8_t*)(-1) ) - throwf("can't map file %s, errno=%d", path, errno); - ::close(fd); - - // if fat file, process each architecture - const fat_header* fh = (fat_header*)p; - const mach_header* mh = (mach_header*)p; - if ( fh->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) { - // Fat header is always big-endian - const struct fat_arch* archs = (struct fat_arch*)(p + sizeof(struct fat_header)); - for (unsigned long i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) { - uint32_t fileOffset = OSSwapBigToHostInt32(archs[i].offset); - try { - switch ( OSSwapBigToHostInt32(archs[i].cputype) ) { - case CPU_TYPE_POWERPC: - fRebasers.push_back(new Rebaser(&p[fileOffset])); - break; - case CPU_TYPE_POWERPC64: - fRebasers.push_back(new Rebaser(&p[fileOffset])); - break; - case CPU_TYPE_I386: - fRebasers.push_back(new Rebaser(&p[fileOffset])); - break; - case CPU_TYPE_X86_64: - fRebasers.push_back(new Rebaser(&p[fileOffset])); - break; - case CPU_TYPE_ARM: - fRebasers.push_back(new Rebaser(&p[fileOffset])); - break; - default: - throw "unknown file format"; - } - } - catch (const char* msg) { - fprintf(stderr, "rebase warning: %s for %s\n", msg, path); - } - } - } - else { - try { - if ( (OSSwapBigToHostInt32(mh->magic) == MH_MAGIC) && (OSSwapBigToHostInt32(mh->cputype) == CPU_TYPE_POWERPC)) { - fRebasers.push_back(new Rebaser(mh)); - } - else if ( (OSSwapBigToHostInt32(mh->magic) == MH_MAGIC_64) && (OSSwapBigToHostInt32(mh->cputype) == CPU_TYPE_POWERPC64)) { - fRebasers.push_back(new Rebaser(mh)); - } - else if ( (OSSwapLittleToHostInt32(mh->magic) == MH_MAGIC) && (OSSwapLittleToHostInt32(mh->cputype) == CPU_TYPE_I386)) { - fRebasers.push_back(new Rebaser(mh)); - } - else if ( (OSSwapLittleToHostInt32(mh->magic) == MH_MAGIC_64) && (OSSwapLittleToHostInt32(mh->cputype) == CPU_TYPE_X86_64)) { - fRebasers.push_back(new Rebaser(mh)); - } - else if ( (OSSwapLittleToHostInt32(mh->magic) == MH_MAGIC) && (OSSwapLittleToHostInt32(mh->cputype) == CPU_TYPE_ARM)) { - fRebasers.push_back(new Rebaser(mh)); - } - else { - throw "unknown file format"; - } - } - catch (const char* msg) { - fprintf(stderr, "rebase warning: %s for %s\n", msg, path); - } - } - - fMappingAddress = p; - fFileSize = stat_buf.st_size; -} - - -MultiArchRebaser::~MultiArchRebaser() -{ - ::munmap(fMappingAddress, fFileSize); -} - -void MultiArchRebaser::commit() -{ - ::msync(fMappingAddress, fFileSize, MS_ASYNC); -} - - - -template -Rebaser::Rebaser(const void* machHeader) - : fHeader((const macho_header

*)machHeader) -{ - switch ( fHeader->filetype() ) { - case MH_DYLIB: - if ( (fHeader->flags() & MH_SPLIT_SEGS) != 0 ) - throw "split-seg dylibs cannot be rebased"; - break; - case MH_BUNDLE: - break; - default: - throw "file is not a dylib or bundle"; - } - -} - -template <> cpu_type_t Rebaser::getArchitecture() const { return CPU_TYPE_POWERPC; } -template <> cpu_type_t Rebaser::getArchitecture() const { return CPU_TYPE_POWERPC64; } -template <> cpu_type_t Rebaser::getArchitecture() const { return CPU_TYPE_I386; } -template <> cpu_type_t Rebaser::getArchitecture() const { return CPU_TYPE_X86_64; } -template <> cpu_type_t Rebaser::getArchitecture() const { return CPU_TYPE_ARM; } - -template -uint64_t Rebaser::getBaseAddress() const -{ - uint64_t lowestSegmentAddress = LLONG_MAX; - const macho_load_command

* const cmds = (macho_load_command

*)((uint8_t*)fHeader + sizeof(macho_header

)); - const uint32_t cmd_count = fHeader->ncmds(); - const macho_load_command

* cmd = cmds; - for (uint32_t i = 0; i < cmd_count; ++i) { - if ( cmd->cmd() == macho_segment_command

::CMD ) { - const macho_segment_command

* segCmd = (const macho_segment_command

*)cmd; - if ( segCmd->vmaddr() < lowestSegmentAddress ) { - lowestSegmentAddress = segCmd->vmaddr(); - } - } - cmd = (const macho_load_command

*)(((uint8_t*)cmd)+cmd->cmdsize()); - } - return lowestSegmentAddress; -} - -template -uint64_t Rebaser::getVMSize() const -{ - const macho_segment_command

* highestSegmentCmd = NULL; - const macho_load_command

* const cmds = (macho_load_command

*)((uint8_t*)fHeader + sizeof(macho_header

)); - const uint32_t cmd_count = fHeader->ncmds(); - const macho_load_command

* cmd = cmds; - for (uint32_t i = 0; i < cmd_count; ++i) { - if ( cmd->cmd() == macho_segment_command

::CMD ) { - const macho_segment_command

* segCmd = (const macho_segment_command

*)cmd; - if ( (highestSegmentCmd == NULL) || (segCmd->vmaddr() > highestSegmentCmd->vmaddr()) ) { - highestSegmentCmd = segCmd; - } - } - cmd = (const macho_load_command

*)(((uint8_t*)cmd)+cmd->cmdsize()); - } - - return ((highestSegmentCmd->vmaddr() + highestSegmentCmd->vmsize() - this->getBaseAddress() + 4095) & (-4096)); -} - - -template -void Rebaser::setBaseAddress(uint64_t addr) -{ - // calculate slide - fSlide = addr - this->getBaseAddress(); - - // compute base address for relocations - this->setRelocBase(); - - // build cache of section index to section - this->buildSectionTable(); - - // update load commands - this->adjustLoadCommands(); - - // update symbol table - this->adjustSymbolTable(); - - // update writable segments that have internal pointers - this->adjustDATA(); -} - -template -void Rebaser::adjustLoadCommands() -{ - const macho_load_command

* const cmds = (macho_load_command

*)((uint8_t*)fHeader + sizeof(macho_header

)); - const uint32_t cmd_count = fHeader->ncmds(); - const macho_load_command

* cmd = cmds; - for (uint32_t i = 0; i < cmd_count; ++i) { - switch ( cmd->cmd() ) { - case LC_ID_DYLIB: - if ( (fHeader->flags() & MH_PREBOUND) != 0 ) { - // clear timestamp so that any prebound clients are invalidated - macho_dylib_command

* dylib = (macho_dylib_command

*)cmd; - dylib->set_timestamp(1); - } - break; - case LC_LOAD_DYLIB: - case LC_LOAD_WEAK_DYLIB: - case LC_REEXPORT_DYLIB: - case LC_LOAD_UPWARD_DYLIB: - if ( (fHeader->flags() & MH_PREBOUND) != 0 ) { - // clear expected timestamps so that this image will load with invalid prebinding - macho_dylib_command

* dylib = (macho_dylib_command

*)cmd; - dylib->set_timestamp(2); - } - break; - case macho_routines_command

::CMD: - // update -init command - { - macho_routines_command

* routines = (macho_routines_command

*)cmd; - routines->set_init_address(routines->init_address() + fSlide); - } - break; - case macho_segment_command

::CMD: - // update segment commands - { - macho_segment_command

* seg = (macho_segment_command

*)cmd; - seg->set_vmaddr(seg->vmaddr() + fSlide); - macho_section

* const sectionsStart = (macho_section

*)((char*)seg + sizeof(macho_segment_command

)); - macho_section

* const sectionsEnd = §ionsStart[seg->nsects()]; - for(macho_section

* sect = sectionsStart; sect < sectionsEnd; ++sect) { - sect->set_addr(sect->addr() + fSlide); - } - } - break; - } - cmd = (const macho_load_command

*)(((uint8_t*)cmd)+cmd->cmdsize()); - } -} - - -template -void Rebaser::buildSectionTable() -{ - // build vector of sections - const macho_load_command

* const cmds = (macho_load_command

*)((uint8_t*)fHeader + sizeof(macho_header

)); - const uint32_t cmd_count = fHeader->ncmds(); - const macho_load_command

* cmd = cmds; - for (uint32_t i = 0; i < cmd_count; ++i) { - if ( cmd->cmd() == macho_segment_command

::CMD ) { - const macho_segment_command

* seg = (macho_segment_command

*)cmd; - vmmap mapping; - mapping.vmaddr = seg->vmaddr(); - mapping.vmsize = seg->vmsize(); - mapping.fileoff = seg->fileoff(); - fVMMApping.push_back(mapping); - } - cmd = (const macho_load_command

*)(((uint8_t*)cmd)+cmd->cmdsize()); - } -} - - -template -void Rebaser::adjustSymbolTable() -{ - const macho_dysymtab_command

* dysymtab = NULL; - macho_nlist

* symbolTable = NULL; - const char* strings = NULL; - - // get symbol table info - const macho_load_command

* const cmds = (macho_load_command

*)((uint8_t*)fHeader + sizeof(macho_header

)); - const uint32_t cmd_count = fHeader->ncmds(); - const macho_load_command

* cmd = cmds; - for (uint32_t i = 0; i < cmd_count; ++i) { - switch (cmd->cmd()) { - case LC_SYMTAB: - { - const macho_symtab_command

* symtab = (macho_symtab_command

*)cmd; - symbolTable = (macho_nlist

*)(((uint8_t*)fHeader) + symtab->symoff()); - strings = (char*)(((uint8_t*)fHeader) + symtab->stroff()); - } - break; - case LC_DYSYMTAB: - dysymtab = (macho_dysymtab_command

*)cmd; - break; - } - cmd = (const macho_load_command

*)(((uint8_t*)cmd)+cmd->cmdsize()); - } - - // walk all exports and slide their n_value - macho_nlist

* lastExport = &symbolTable[dysymtab->iextdefsym()+dysymtab->nextdefsym()]; - for (macho_nlist

* entry = &symbolTable[dysymtab->iextdefsym()]; entry < lastExport; ++entry) { - if ( (entry->n_type() & N_TYPE) == N_SECT ) - entry->set_n_value(entry->n_value() + fSlide); - } - - // walk all local symbols and slide their n_value - macho_nlist

* lastLocal = &symbolTable[dysymtab->ilocalsym()+dysymtab->nlocalsym()]; - for (macho_nlist

* entry = &symbolTable[dysymtab->ilocalsym()]; entry < lastLocal; ++entry) { - if ( ((entry->n_type() & N_STAB) == 0) && ((entry->n_type() & N_TYPE) == N_SECT) ) { - entry->set_n_value(entry->n_value() + fSlide); - } - else if ( entry->n_type() & N_STAB ) { - // some stabs need to be slid too - switch ( entry->n_type() ) { - case N_FUN: - // don't slide end-of-function FUN which is FUN with no string - if ( (entry->n_strx() == 0) || (strings[entry->n_strx()] == '\0') ) - break; - case N_BNSYM: - case N_STSYM: - case N_LCSYM: - entry->set_n_value(entry->n_value() + fSlide); - break; - } - } - } - - // FIXME ¥¥¥ adjust dylib_module if it exists -} - -static uint64_t read_uleb128(const uint8_t*& p, const uint8_t* end) -{ - uint64_t result = 0; - int bit = 0; - do { - if (p == end) - throwf("malformed uleb128"); - - uint64_t slice = *p & 0x7f; - - if (bit >= 64 || slice << bit >> bit != slice) - throwf("uleb128 too big"); - else { - result |= (slice << bit); - bit += 7; - } - } - while (*p++ & 0x80); - return result; -} - -template -void Rebaser::rebaseAt(int segIndex, uint64_t offset, uint8_t type) -{ - //fprintf(stderr, "rebaseAt(seg=%d, offset=0x%08llX, type=%d\n", segIndex, offset, type); - static int lastSegIndex = -1; - static uint8_t* lastSegMappedStart = NULL; - if ( segIndex != lastSegIndex ) { - const macho_load_command

* const cmds = (macho_load_command

*)((uint8_t*)fHeader + sizeof(macho_header

)); - const uint32_t cmd_count = fHeader->ncmds(); - const macho_load_command

* cmd = cmds; - int segCount = 0; - for (uint32_t i = 0; i < cmd_count; ++i) { - if ( cmd->cmd() == macho_segment_command

::CMD ) { - if ( segIndex == segCount ) { - const macho_segment_command

* seg = (macho_segment_command

*)cmd; - lastSegMappedStart = (uint8_t*)fHeader + seg->fileoff(); - lastSegIndex = segCount; - break; - } - ++segCount; - } - cmd = (const macho_load_command

*)(((uint8_t*)cmd)+cmd->cmdsize()); - } - } - - pint_t* locationToFix = (pint_t*)(lastSegMappedStart+offset); - uint32_t* locationToFix32 = (uint32_t*)(lastSegMappedStart+offset); - switch (type) { - case REBASE_TYPE_POINTER: - P::setP(*locationToFix, A::P::getP(*locationToFix) + fSlide); - break; - case REBASE_TYPE_TEXT_ABSOLUTE32: - E::set32(*locationToFix32, E::get32(*locationToFix32) + fSlide); - break; - default: - throwf("bad rebase type %d", type); - } -} - - -template -void Rebaser::adjustDATA() -{ - const macho_dysymtab_command

* dysymtab = NULL; - const macho_dyld_info_command

* dyldInfo = NULL; - - // get symbol table info - const macho_load_command

* const cmds = (macho_load_command

*)((uint8_t*)fHeader + sizeof(macho_header

)); - const uint32_t cmd_count = fHeader->ncmds(); - const macho_load_command

* cmd = cmds; - for (uint32_t i = 0; i < cmd_count; ++i) { - switch (cmd->cmd()) { - case LC_DYSYMTAB: - dysymtab = (macho_dysymtab_command

*)cmd; - break; - case LC_DYLD_INFO: - case LC_DYLD_INFO_ONLY: - dyldInfo = (macho_dyld_info_command

*)cmd; - break; - } - cmd = (const macho_load_command

*)(((uint8_t*)cmd)+cmd->cmdsize()); - } - - // use new encoding of rebase info if present - if ( dyldInfo != NULL ) { - if ( dyldInfo->rebase_size() != 0 ) { - const uint8_t* p = (uint8_t*)fHeader + dyldInfo->rebase_off(); - const uint8_t* end = &p[dyldInfo->rebase_size()]; - - uint8_t type = 0; - uint64_t offset = 0; - uint32_t count; - uint32_t skip; - int segIndex; - bool done = false; - while ( !done && (p < end) ) { - uint8_t immediate = *p & REBASE_IMMEDIATE_MASK; - uint8_t opcode = *p & REBASE_OPCODE_MASK; - ++p; - switch (opcode) { - case REBASE_OPCODE_DONE: - done = true; - break; - case REBASE_OPCODE_SET_TYPE_IMM: - type = immediate; - break; - case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: - segIndex = immediate; - offset = read_uleb128(p, end); - break; - case REBASE_OPCODE_ADD_ADDR_ULEB: - offset += read_uleb128(p, end); - break; - case REBASE_OPCODE_ADD_ADDR_IMM_SCALED: - offset += immediate*sizeof(pint_t); - break; - case REBASE_OPCODE_DO_REBASE_IMM_TIMES: - for (int i=0; i < immediate; ++i) { - rebaseAt(segIndex, offset, type); - offset += sizeof(pint_t); - } - break; - case REBASE_OPCODE_DO_REBASE_ULEB_TIMES: - count = read_uleb128(p, end); - for (uint32_t i=0; i < count; ++i) { - rebaseAt(segIndex, offset, type); - offset += sizeof(pint_t); - } - break; - case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: - rebaseAt(segIndex, offset, type); - offset += read_uleb128(p, end) + sizeof(pint_t); - break; - case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: - count = read_uleb128(p, end); - skip = read_uleb128(p, end); - for (uint32_t i=0; i < count; ++i) { - rebaseAt(segIndex, offset, type); - offset += skip + sizeof(pint_t); - } - break; - default: - throwf("bad rebase opcode %d", *p); - } - } - - - - } - } - else { - // walk all local relocations and slide every pointer - const macho_relocation_info

* const relocsStart = (macho_relocation_info

*)(((uint8_t*)fHeader) + dysymtab->locreloff()); - const macho_relocation_info

* const relocsEnd = &relocsStart[dysymtab->nlocrel()]; - for (const macho_relocation_info

* reloc=relocsStart; reloc < relocsEnd; ++reloc) { - this->doLocalRelocation(reloc); - } - - // walk non-lazy-pointers and slide the ones that are LOCAL - cmd = cmds; - for (uint32_t i = 0; i < cmd_count; ++i) { - if ( cmd->cmd() == macho_segment_command

::CMD ) { - const macho_segment_command

* seg = (macho_segment_command

*)cmd; - const macho_section

* const sectionsStart = (macho_section

*)((char*)seg + sizeof(macho_segment_command

)); - const macho_section

* const sectionsEnd = §ionsStart[seg->nsects()]; - const uint32_t* const indirectTable = (uint32_t*)(((uint8_t*)fHeader) + dysymtab->indirectsymoff()); - for(const macho_section

* sect = sectionsStart; sect < sectionsEnd; ++sect) { - if ( (sect->flags() & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS ) { - const uint32_t indirectTableOffset = sect->reserved1(); - uint32_t pointerCount = sect->size() / sizeof(pint_t); - pint_t* nonLazyPointer = (pint_t*)(((uint8_t*)fHeader) + sect->offset()); - for (uint32_t i=0; i < pointerCount; ++i, ++nonLazyPointer) { - if ( E::get32(indirectTable[indirectTableOffset + i]) == INDIRECT_SYMBOL_LOCAL ) { - P::setP(*nonLazyPointer, A::P::getP(*nonLazyPointer) + fSlide); - } - } - } - } - } - cmd = (const macho_load_command

*)(((uint8_t*)cmd)+cmd->cmdsize()); - } - } -} - - -template -typename A::P::uint_t* Rebaser::mappedAddressForVMAddress(uint32_t vmaddress) -{ - for(typename std::vector::iterator it = fVMMApping.begin(); it != fVMMApping.end(); ++it) { - //fprintf(stderr, "vmaddr=0x%08lX, vmsize=0x%08lX\n", it->vmaddr, it->vmsize); - if ( (vmaddress >= it->vmaddr) && (vmaddress < (it->vmaddr+it->vmsize)) ) { - return (pint_t*)((vmaddress - it->vmaddr) + it->fileoff + (uint8_t*)fHeader); - } - } - throwf("reloc address 0x%08X not found", vmaddress); -} - - -template <> -void Rebaser::doLocalRelocation(const macho_relocation_info* reloc) -{ - if ( reloc->r_type() == X86_64_RELOC_UNSIGNED ) { - pint_t* addr = mappedAddressForVMAddress(reloc->r_address() + fOrignalVMRelocBaseAddress); - P::setP(*addr, P::getP(*addr) + fSlide); - } - else { - throw "invalid relocation type"; - } -} - -template <> -void Rebaser::doLocalRelocation(const macho_relocation_info

* reloc) -{ - if ( (reloc->r_address() & R_SCATTERED) == 0 ) { - if ( reloc->r_type() == GENERIC_RELOC_VANILLA ) { - pint_t* addr = mappedAddressForVMAddress(reloc->r_address() + fOrignalVMRelocBaseAddress); - P::setP(*addr, P::getP(*addr) + fSlide); - } - } - else { - throw "cannot rebase final linked image with scattered relocations"; - } -} - -template <> -void Rebaser::doLocalRelocation(const macho_relocation_info

* reloc) -{ - if ( (reloc->r_address() & R_SCATTERED) == 0 ) { - if ( reloc->r_type() == GENERIC_RELOC_VANILLA ) { - pint_t* addr = mappedAddressForVMAddress(reloc->r_address() + fOrignalVMRelocBaseAddress); - P::setP(*addr, P::getP(*addr) + fSlide); - } - } - else { - macho_scattered_relocation_info

* sreloc = (macho_scattered_relocation_info

*)reloc; - if ( sreloc->r_type() == GENERIC_RELOC_PB_LA_PTR ) { - sreloc->set_r_value( sreloc->r_value() + fSlide ); - } - else { - throw "cannot rebase final linked image with scattered relocations"; - } - } -} - -#if SUPPORT_ARCH_arm_any -template <> -void Rebaser::doLocalRelocation(const macho_relocation_info

* reloc) -{ - if ( (reloc->r_address() & R_SCATTERED) == 0 ) { - if ( reloc->r_type() == ARM_RELOC_VANILLA ) { - pint_t* addr = mappedAddressForVMAddress(reloc->r_address() + fOrignalVMRelocBaseAddress); - P::setP(*addr, P::getP(*addr) + fSlide); - } - } - else { - macho_scattered_relocation_info

* sreloc = (macho_scattered_relocation_info

*)reloc; - if ( sreloc->r_type() == ARM_RELOC_PB_LA_PTR ) { - sreloc->set_r_value( sreloc->r_value() + fSlide ); - } - else { - throw "cannot rebase final linked image with scattered relocations"; - } - } -} -#endif - -template -void Rebaser::doLocalRelocation(const macho_relocation_info

* reloc) -{ - if ( (reloc->r_address() & R_SCATTERED) == 0 ) { - if ( reloc->r_type() == GENERIC_RELOC_VANILLA ) { - pint_t* addr = mappedAddressForVMAddress(reloc->r_address() + fOrignalVMRelocBaseAddress); - P::setP(*addr, P::getP(*addr) + fSlide); - } - } - else { - throw "cannot rebase final linked image with scattered relocations"; - } -} - - -template -void Rebaser::setRelocBase() -{ - // reloc addresses are from the start of the mapped file (base address) - fOrignalVMRelocBaseAddress = this->getBaseAddress(); - //fprintf(stderr, "fOrignalVMRelocBaseAddress=0x%08X\n", fOrignalVMRelocBaseAddress); -} - -template <> -void Rebaser::setRelocBase() -{ - // reloc addresses either: - // 1) from the base address if no writable segment is > 4GB from base address - // 2) from start of first writable segment - const macho_load_command

* const cmds = (macho_load_command

*)((uint8_t*)fHeader + sizeof(macho_header

)); - const uint32_t cmd_count = fHeader->ncmds(); - const macho_load_command

* cmd = cmds; - for (uint32_t i = 0; i < cmd_count; ++i) { - if ( cmd->cmd() == macho_segment_command

::CMD ) { - const macho_segment_command

* segCmd = (const macho_segment_command

*)cmd; - if ( segCmd->initprot() & VM_PROT_WRITE ) { - if ( (segCmd->vmaddr() + segCmd->vmsize() - this->getBaseAddress()) > 0x100000000ULL ) { - // found writable segment with address > 4GB past base address - fOrignalVMRelocBaseAddress = segCmd->vmaddr(); - return; - } - } - } - cmd = (const macho_load_command

*)(((uint8_t*)cmd)+cmd->cmdsize()); - } - // just use base address - fOrignalVMRelocBaseAddress = this->getBaseAddress(); -} - -template <> -void Rebaser::setRelocBase() -{ - // reloc addresses are always based from the start of the first writable segment - const macho_load_command

* const cmds = (macho_load_command

*)((uint8_t*)fHeader + sizeof(macho_header

)); - const uint32_t cmd_count = fHeader->ncmds(); - const macho_load_command

* cmd = cmds; - for (uint32_t i = 0; i < cmd_count; ++i) { - if ( cmd->cmd() == macho_segment_command

::CMD ) { - const macho_segment_command

* segCmd = (const macho_segment_command

*)cmd; - if ( segCmd->initprot() & VM_PROT_WRITE ) { - fOrignalVMRelocBaseAddress = segCmd->vmaddr(); - return; - } - } - cmd = (const macho_load_command

*)(((uint8_t*)cmd)+cmd->cmdsize()); - } - throw "no writable segment"; -} - - -static void copyFile(const char* srcFile, const char* dstFile) -{ - // open files - int src = open(srcFile, O_RDONLY); - if ( src == -1 ) - throwf("can't open file %s, errno=%d", srcFile, errno); - struct stat stat_buf; - if ( fstat(src, &stat_buf) == -1) - throwf("can't stat open file %s, errno=%d", srcFile, errno); - - // create new file with all same permissions to hold copy of dylib - ::unlink(dstFile); - int dst = open(dstFile, O_CREAT | O_RDWR | O_TRUNC, stat_buf.st_mode); - if ( dst == -1 ) - throwf("can't create temp file %s, errnor=%d", dstFile, errno); - - // mark source as "don't cache" - (void)fcntl(src, F_NOCACHE, 1); - // we want to cache the dst because we are about to map it in and modify it - - // copy permission bits - if ( chmod(dstFile, stat_buf.st_mode & 07777) == -1 ) - throwf("can't chmod temp file %s, errno=%d", dstFile, errno); - if ( chown(dstFile, stat_buf.st_uid, stat_buf.st_gid) == -1) - throwf("can't chown temp file %s, errno=%d", dstFile, errno); - - // copy contents - ssize_t len; - const uint32_t kBufferSize = 128*1024; - static uint8_t* buffer = NULL; - if ( buffer == NULL ) { - vm_address_t addr = 0; - if ( vm_allocate(mach_task_self(), &addr, kBufferSize, true /*find range*/) == KERN_SUCCESS ) - buffer = (uint8_t*)addr; - else - throw "can't allcoate copy buffer"; - } - while ( (len = read(src, buffer, kBufferSize)) > 0 ) { - if ( write(dst, buffer, len) == -1 ) - throwf("write failure copying feil %s, errno=%d", dstFile, errno); - } - - // close files - int result1 = close(dst); - int result2 = close(src); - if ( (result1 != 0) || (result2 != 0) ) - throw "can't close file"; -} - - -// scan dylibs and collect size info -// calculate new base address for each dylib -// rebase each file -// copy to temp and mmap -// update content -// unmap/flush -// rename - -struct archInfo { - cpu_type_t arch; - uint64_t vmSize; - uint64_t orgBase; - uint64_t newBase; -}; - -struct fileInfo -{ - fileInfo(const char* p) : path(p) {} - - const char* path; - std::vector archs; -}; - -// -// add archInfos to fileInfo for every slice of a fat file -// for ppc, there may be duplicate architectures (with different sub-types) -// -static void setSizes(fileInfo& info, const std::set& onlyArchs) -{ - const MultiArchRebaser mar(info.path); - const std::vector& rebasers = mar.getArchs(); - for(std::set::iterator ait=onlyArchs.begin(); ait != onlyArchs.end(); ++ait) { - for(std::vector::const_iterator rit=rebasers.begin(); rit != rebasers.end(); ++rit) { - AbstractRebaser* rebaser = *rit; - if ( rebaser->getArchitecture() == *ait ) { - archInfo ai; - ai.arch = *ait; - ai.vmSize = rebaser->getVMSize(); - ai.orgBase = rebaser->getBaseAddress(); - ai.newBase = 0; - //fprintf(stderr, "base=0x%llX, size=0x%llX\n", ai.orgBase, ai.vmSize); - info.archs.push_back(ai); - } - } - } -} - -static const char* nameForArch(cpu_type_t arch) -{ - switch( arch ) { - case CPU_TYPE_POWERPC: - return "ppc"; - case CPU_TYPE_POWERPC64: - return "ppca64"; - case CPU_TYPE_I386: - return "i386"; - case CPU_TYPE_X86_64: - return "x86_64"; - case CPU_TYPE_ARM: - return "arm"; - } - return "unknown"; -} - -static void rebase(const fileInfo& info) -{ - // generate temp file name - char realFilePath[PATH_MAX]; - if ( realpath(info.path, realFilePath) == NULL ) { - throwf("realpath() failed on %s, errno=%d", info.path, errno); - } - const char* tempPath; - asprintf((char**)&tempPath, "%s_rebase", realFilePath); - - // copy whole file to temp file - copyFile(info.path, tempPath); - - try { - // rebase temp file - MultiArchRebaser mar(tempPath, true); - const std::vector& rebasers = mar.getArchs(); - for(std::vector::const_iterator fait=info.archs.begin(); fait != info.archs.end(); ++fait) { - for(std::vector::const_iterator rit=rebasers.begin(); rit != rebasers.end(); ++rit) { - if ( (*rit)->getArchitecture() == fait->arch ) { - (*rit)->setBaseAddress(fait->newBase); - if ( verbose ) - printf("%8s 0x%0llX -> 0x%0llX %s\n", nameForArch(fait->arch), fait->orgBase, fait->newBase, info.path); - } - } - } - - // flush temp file out to disk - mar.commit(); - - // rename - int result = rename(tempPath, info.path); - if ( result != 0 ) { - throwf("can't swap temporary rebased file: rename(%s,%s) returned errno=%d", tempPath, info.path, errno); - } - - // make sure every really gets out to disk - ::sync(); - } - catch (const char* msg) { - // delete temp file - ::unlink(tempPath); - - // throw exception with file name added - const char* newMsg; - asprintf((char**)&newMsg, "%s for file %s", msg, info.path); - throw newMsg; - } -} - -static uint64_t totalVMSize(cpu_type_t arch, std::vector& files) -{ - uint64_t totalSize = 0; - for(std::vector::iterator fit=files.begin(); fit != files.end(); ++fit) { - fileInfo& fi = *fit; - for(std::vector::iterator fait=fi.archs.begin(); fait != fi.archs.end(); ++fait) { - if ( fait->arch == arch ) - totalSize += fait->vmSize; - } - } - return totalSize; -} - -static uint64_t startAddress(cpu_type_t arch, std::vector& files, uint64_t lowAddress, uint64_t highAddress) -{ - if ( lowAddress != 0 ) - return lowAddress; - else if ( highAddress != 0 ) { - uint64_t totalSize = totalVMSize(arch, files); - if ( highAddress < totalSize ) - throwf("cannot use -high_address 0x%X because total size of images is greater: 0x%X", highAddress, totalSize); - return highAddress - totalSize; - } - else { - if ( (arch == CPU_TYPE_I386) || (arch == CPU_TYPE_POWERPC) ) { - // place dylibs below dyld - uint64_t topAddr = 0x8FE00000; - uint64_t totalSize = totalVMSize(arch, files); - if ( totalSize > topAddr ) - throwf("total size of images (0x%X) does not fit below 0x8FE00000", totalSize); - return topAddr - totalSize; - } - else if ( arch == CPU_TYPE_POWERPC64 ) { - return 0x200000000ULL; - } - else if ( arch == CPU_TYPE_X86_64 ) { - return 0x200000000ULL; - } - else if ( arch == CPU_TYPE_ARM ) { - // place dylibs below dyld - uint64_t topAddr = 0x2FE00000; - uint64_t totalSize = totalVMSize(arch, files); - if ( totalSize > topAddr ) - throwf("total size of images (0x%X) does not fit below 0x2FE00000", totalSize); - return topAddr - totalSize; - } - else - throw "unknown architecture"; - } -} - -static void usage() -{ - fprintf(stderr, "rebase [-low_address] [-high_address] [-v] [-arch ] files...\n"); -} - - -int main(int argc, const char* argv[]) -{ - std::vector files; - std::set onlyArchs; - uint64_t lowAddress = 0; - uint64_t highAddress = 0; - - try { - // parse command line options - char* endptr; - for(int i=1; i < argc; ++i) { - const char* arg = argv[i]; - if ( arg[0] == '-' ) { - if ( strcmp(arg, "-v") == 0 ) { - verbose = true; - } - else if ( strcmp(arg, "-low_address") == 0 ) { - lowAddress = strtoull(argv[++i], &endptr, 16); - } - else if ( strcmp(arg, "-high_address") == 0 ) { - highAddress = strtoull(argv[++i], &endptr, 16); - } - else if ( strcmp(arg, "-arch") == 0 ) { - const char* archName = argv[++i]; - if ( archName == NULL ) - throw "-arch missing architecture name"; - bool found = false; - for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) { - if ( strcmp(t->archName,archName) == 0 ) { - onlyArchs.insert(t->cpuType); - found = true; - } - } - if ( !found ) - throwf("unknown architecture %s", archName); - } - else { - usage(); - throwf("unknown option: %s\n", arg); - } - } - else { - files.push_back(fileInfo(arg)); - } - } - - if ( files.size() == 0 ) - throw "no files specified"; - - // use all architectures if no restrictions specified - if ( onlyArchs.size() == 0 ) { - onlyArchs.insert(CPU_TYPE_POWERPC); - onlyArchs.insert(CPU_TYPE_POWERPC64); - onlyArchs.insert(CPU_TYPE_I386); - onlyArchs.insert(CPU_TYPE_X86_64); - onlyArchs.insert(CPU_TYPE_ARM); - } - - // scan files and collect sizes - for(std::vector::iterator it=files.begin(); it != files.end(); ++it) { - setSizes(*it, onlyArchs); - } - - // assign new base address for each arch - for(std::set::iterator ait=onlyArchs.begin(); ait != onlyArchs.end(); ++ait) { - cpu_type_t arch = *ait; - uint64_t baseAddress = startAddress(arch, files, lowAddress, highAddress); - for(std::vector::iterator fit=files.begin(); fit != files.end(); ++fit) { - fileInfo& fi = *fit; - for(std::vector::iterator fait=fi.archs.begin(); fait != fi.archs.end(); ++fait) { - if ( fait->arch == arch ) { - fait->newBase = baseAddress; - baseAddress += fait->vmSize; - baseAddress = (baseAddress + 4095) & (-4096); // page align - } - } - } - } - - // rebase each file if it contains something rebaseable - for(std::vector::iterator it=files.begin(); it != files.end(); ++it) { - fileInfo& fi = *it; - if ( fi.archs.size() > 0 ) - rebase(fi); - } - - } - catch (const char* msg) { - fprintf(stderr, "rebase failed: %s\n", msg); - return 1; - } - - return 0; -} - - - diff --git a/cctools/ld64/src/other/unwinddump.cpp b/cctools/ld64/src/other/unwinddump.cpp index 53759b2..34938d8 100644 --- a/cctools/ld64/src/other/unwinddump.cpp +++ b/cctools/ld64/src/other/unwinddump.cpp @@ -163,6 +163,7 @@ bool UnwindPrinter::validFile(const uint8_t* fileContent) } #endif + template <> bool UnwindPrinter::validFile(const uint8_t* fileContent) { @@ -214,7 +215,6 @@ void UnwindPrinter::getSymbolTableInfo() const macho_load_command

* const cmds = (macho_load_command

*)((uint8_t*)fHeader + sizeof(macho_header

)); const macho_load_command

* cmd = cmds; for (uint32_t i = 0; i < cmd_count; ++i) { - uint32_t size = cmd->cmdsize(); const uint8_t* endOfCmd = ((uint8_t*)cmd)+cmd->cmdsize(); if ( endOfCmd > endOfLoadCommands ) throwf("load command #%d extends beyond the end of the load commands", i); @@ -288,7 +288,6 @@ bool UnwindPrinter::findUnwindSection() const macho_load_command

* const cmds = (macho_load_command

*)((uint8_t*)fHeader + sizeof(macho_header

)); const macho_load_command

* cmd = cmds; for (uint32_t i = 0; i < cmd_count; ++i) { - uint32_t size = cmd->cmdsize(); const uint8_t* endOfCmd = ((uint8_t*)cmd)+cmd->cmdsize(); if ( endOfCmd > endOfLoadCommands ) throwf("load command #%d extends beyond the end of the load commands", i); @@ -756,6 +755,7 @@ void UnwindPrinter::decode(uint32_t encoding, const uint8_t* funcStart, c } #endif + template <> void UnwindPrinter::decode(uint32_t encoding, const uint8_t* funcStart, char* str) { @@ -872,6 +872,7 @@ const char* UnwindPrinter::personalityName(const macho_relocation_info const char* UnwindPrinter::personalityName(const macho_relocation_info* reloc) { @@ -1138,7 +1139,7 @@ static void dump(const char* path, const std::set& onlyArchs, bool s else if ( UnwindPrinter::validFile(p) && onlyArchs.count(CPU_TYPE_ARM64) ) { UnwindPrinter::make(p, length, path, showFunctionNames); } -#endif +#endif else if ( UnwindPrinter::validFile(p) && onlyArchs.count(CPU_TYPE_ARM) ) { UnwindPrinter::make(p, length, path, showFunctionNames); } diff --git a/cctools/libmacho/Makefile.am b/cctools/libmacho/Makefile.am new file mode 100644 index 0000000..2cce428 --- /dev/null +++ b/cctools/libmacho/Makefile.am @@ -0,0 +1,6 @@ +noinst_LTLIBRARIES = libmacho.la + +libmacho_la_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -D__DARWIN_UNIX03 $(WARNINGS) $(LTO_DEF) -DPROGRAM_PREFIX="\"$(PROGRAM_PREFIX)\"" $(ENDIAN_FLAG) + +libmacho_la_SOURCES = \ + arch.c diff --git a/cctools/libmacho/Makefile.in b/cctools/libmacho/Makefile.in new file mode 100644 index 0000000..33523e0 --- /dev/null +++ b/cctools/libmacho/Makefile.in @@ -0,0 +1,612 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libmacho +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libmacho_la_LIBADD = +am_libmacho_la_OBJECTS = libmacho_la-arch.lo +libmacho_la_OBJECTS = $(am_libmacho_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libmacho_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libmacho_la_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libmacho_la_SOURCES) +DIST_SOURCES = $(libmacho_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libmacho.la +libmacho_la_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -D__DARWIN_UNIX03 $(WARNINGS) $(LTO_DEF) -DPROGRAM_PREFIX="\"$(PROGRAM_PREFIX)\"" $(ENDIAN_FLAG) +libmacho_la_SOURCES = \ + arch.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps libmacho/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps libmacho/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libmacho.la: $(libmacho_la_OBJECTS) $(libmacho_la_DEPENDENCIES) $(EXTRA_libmacho_la_DEPENDENCIES) + $(AM_V_CCLD)$(libmacho_la_LINK) $(libmacho_la_OBJECTS) $(libmacho_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +libmacho_la-arch.lo: arch.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmacho_la_CFLAGS) $(CFLAGS) -c -o libmacho_la-arch.lo `test -f 'arch.c' || echo '$(srcdir)/'`arch.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/libmacho/arch.c b/cctools/libmacho/arch.c new file mode 100644 index 0000000..a353c2c --- /dev/null +++ b/cctools/libmacho/arch.c @@ -0,0 +1,1330 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1993 NeXT Computer, Inc. + * + * Architecture computing functions. + * + * HISTORY + * + * 11 April 1997 + * Update m98k to ppc and removed the never supported architectures (mips, + * and vax). Apple Computer, Inc. + * + * 4 February 1993 Lennart Lovstrand + * Redesigned to use NXArchInfo based names and signatures. + * + * Originally written at NeXT, Inc. + * + */ +#ifndef RLD +#include +#include +#include +#include +#include + +#include "mach/machine.h" +#include "mach/mach.h" +#include "stuff/openstep_mach.h" +#include +#include + +/* The array of all currently know architecture flags (terminated with an entry + * with all zeros). Pointer to this returned with NXGetAllArchInfos(). + */ +static const NXArchInfo ArchInfoTable[] = { + /* architecture families */ + {"hppa", CPU_TYPE_HPPA, CPU_SUBTYPE_HPPA_ALL, NX_BigEndian, + "HP-PA"}, + {"i386", CPU_TYPE_I386, CPU_SUBTYPE_I386_ALL, NX_LittleEndian, + "Intel 80x86"}, + { "x86_64", CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL, NX_LittleEndian, + "Intel x86-64" }, + { "x86_64h", CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_H, NX_LittleEndian, + "Intel x86-64h Haswell" }, + {"i860", CPU_TYPE_I860, CPU_SUBTYPE_I860_ALL, NX_BigEndian, + "Intel 860"}, + {"m68k", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC680x0_ALL, NX_BigEndian, + "Motorola 68K"}, + {"m88k", CPU_TYPE_MC88000, CPU_SUBTYPE_MC88000_ALL, NX_BigEndian, + "Motorola 88K"}, + {"ppc", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL, NX_BigEndian, + "PowerPC"}, + {"ppc64", CPU_TYPE_POWERPC64, CPU_SUBTYPE_POWERPC_ALL, NX_BigEndian, + "PowerPC 64-bit"}, + {"sparc", CPU_TYPE_SPARC, CPU_SUBTYPE_SPARC_ALL, NX_BigEndian, + "SPARC"}, + {"arm", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_ALL, NX_LittleEndian, + "ARM"}, + {"arm64", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL, NX_LittleEndian, + "ARM64"}, + {"arm64_32",CPU_TYPE_ARM64_32,CPU_SUBTYPE_ARM64_32_V8, NX_LittleEndian, + "ARM64_32"}, + {"arm64e", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64E, NX_LittleEndian, + "ARM64E"}, + {"any", CPU_TYPE_ANY, CPU_SUBTYPE_MULTIPLE, NX_UnknownByteOrder, + "Architecture Independent"}, + {"veo", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_ALL, NX_BigEndian, + "veo"}, + /* specific architecture implementations */ + {"hppa7100LC", CPU_TYPE_HPPA, CPU_SUBTYPE_HPPA_7100LC, NX_BigEndian, + "HP-PA 7100LC"}, + {"m68030", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC68030_ONLY, NX_BigEndian, + "Motorola 68030"}, + {"m68040", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC68040, NX_BigEndian, + "Motorola 68040"}, + {"i486", CPU_TYPE_I386, CPU_SUBTYPE_486, NX_LittleEndian, + "Intel 80486"}, + {"i486SX", CPU_TYPE_I386, CPU_SUBTYPE_486SX, NX_LittleEndian, + "Intel 80486SX"}, + {"pentium",CPU_TYPE_I386, CPU_SUBTYPE_PENT, NX_LittleEndian, + "Intel Pentium"}, /* same as 586 */ + {"i586", CPU_TYPE_I386, CPU_SUBTYPE_586, NX_LittleEndian, + "Intel 80586"}, + {"pentpro", CPU_TYPE_I386, CPU_SUBTYPE_PENTPRO, NX_LittleEndian, + "Intel Pentium Pro"}, /* same as 686 */ + {"i686", CPU_TYPE_I386, CPU_SUBTYPE_PENTPRO, NX_LittleEndian, + "Intel Pentium Pro"}, + {"pentIIm3", CPU_TYPE_I386, CPU_SUBTYPE_PENTII_M3, NX_LittleEndian, + "Intel Pentium II Model 3" }, + {"pentIIm5", CPU_TYPE_I386, CPU_SUBTYPE_PENTII_M5, NX_LittleEndian, + "Intel Pentium II Model 5" }, + {"pentium4", CPU_TYPE_I386, CPU_SUBTYPE_PENTIUM_4, NX_LittleEndian, + "Intel Pentium 4" }, + { "x86_64h", CPU_TYPE_I386, CPU_SUBTYPE_X86_64_H, NX_LittleEndian, + "Intel x86-64h Haswell" }, + {"ppc601", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_601, NX_BigEndian, + "PowerPC 601" }, + {"ppc603", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_603, NX_BigEndian, + "PowerPC 603" }, + {"ppc603e",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_603e, NX_BigEndian, + "PowerPC 603e" }, + {"ppc603ev",CPU_TYPE_POWERPC,CPU_SUBTYPE_POWERPC_603ev,NX_BigEndian, + "PowerPC 603ev" }, + {"ppc604", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_604, NX_BigEndian, + "PowerPC 604" }, + {"ppc604e",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_604e, NX_BigEndian, + "PowerPC 604e" }, + {"ppc750", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_750, NX_BigEndian, + "PowerPC 750" }, + {"ppc7400",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_7400, NX_BigEndian, + "PowerPC 7400" }, + {"ppc7450",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_7450, NX_BigEndian, + "PowerPC 7450" }, + {"ppc970", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_970, NX_BigEndian, + "PowerPC 970" }, + {"ppc970-64", CPU_TYPE_POWERPC64, CPU_SUBTYPE_POWERPC_970, NX_BigEndian, + "PowerPC 970 64-bit"}, + {"armv4t", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V4T, NX_LittleEndian, + "arm v4t"}, + {"armv5", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V5TEJ, NX_LittleEndian, + "arm v5"}, + {"xscale", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_XSCALE, NX_LittleEndian, + "arm xscale"}, + {"armv6", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6, NX_LittleEndian, + "arm v6"}, + {"armv6m", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6M, NX_LittleEndian, + "arm v6m"}, + {"armv7", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7, NX_LittleEndian, + "arm v7"}, + {"armv7f", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7F, NX_LittleEndian, + "arm v7f"}, + {"armv7s", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7S, NX_LittleEndian, + "arm v7s"}, + {"armv7k", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7K, NX_LittleEndian, + "arm v7k"}, + {"armv7m", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7M, NX_LittleEndian, + "arm v7m"}, + {"armv7em",CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7EM, NX_LittleEndian, + "arm v7em"}, + {"armv8", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V8, NX_LittleEndian, + "arm v8"}, + {"arm64",CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_V8, NX_LittleEndian, + "arm64 v8"}, + {"little", CPU_TYPE_ANY, CPU_SUBTYPE_LITTLE_ENDIAN, NX_LittleEndian, + "Little Endian"}, + {"big", CPU_TYPE_ANY, CPU_SUBTYPE_BIG_ENDIAN, NX_BigEndian, + "Big Endian"}, + {"veo1",CPU_TYPE_VEO, CPU_SUBTYPE_VEO_1, NX_BigEndian, + "veo 1" }, + {"veo2",CPU_TYPE_VEO, CPU_SUBTYPE_VEO_2, NX_BigEndian, + "veo 2" }, + {NULL, 0, 0, 0, + NULL} +}; + +/* + * NXGetAllArchInfos() returns a pointer to an array of all currently know + * architecture flags (terminated with an entry with all zeros). + */ +const +NXArchInfo * +NXGetAllArchInfos(void) +{ + return(ArchInfoTable); +} + +#ifdef HOST_PREFERRED_USER_ARCH + +/* + * internal_NXGetHostUserCPU() returns the preferred userspace cputype and + * cpusubtype of the local host. it returns 0 on success, or -1 on error. + */ + +static +int32_t +internal_NXGetHostUserCPU( +cpu_type_t* out_cputype, +cpu_subtype_t* out_cpusubtype) +{ + struct host_preferred_user_arch hi; + kern_return_t ret; + unsigned int count; + mach_port_t my_mach_host_self; + + count = HOST_PREFERRED_USER_ARCH_COUNT; + my_mach_host_self = mach_host_self(); + ret = host_info(my_mach_host_self, HOST_PREFERRED_USER_ARCH, + (host_info_t)&hi, &count); + mach_port_deallocate(mach_task_self(), my_mach_host_self); + if(ret != KERN_SUCCESS) + return(-1); + + if (out_cputype != NULL) + *out_cputype = hi.cpu_type; + if (out_cpusubtype != NULL) + *out_cpusubtype = hi.cpu_subtype; + + return(0); +} + +#endif /* defined(HOST_PREFERRED_USER_ARCH) */ + +/* + * internal_NXGetHostBasicCPU() returns the basic kernelspace cputype and + * cpusubtype of the local host. it returns 0 on success, or -1 on error. + */ + +static +kern_return_t +internal_NXGetHostBasicCPU( +cpu_type_t* out_cputype, +cpu_subtype_t* out_cpusubtype) +{ + struct host_basic_info hi; + kern_return_t ret; + unsigned int count; + mach_port_t my_mach_host_self; + + count = HOST_BASIC_INFO_COUNT; + my_mach_host_self = mach_host_self(); + ret = host_info(my_mach_host_self, HOST_BASIC_INFO, (host_info_t)&hi, + &count); + mach_port_deallocate(mach_task_self(), my_mach_host_self); + if(ret != KERN_SUCCESS) + return(-1); + + if (out_cputype != NULL) + *out_cputype = hi.cpu_type; + if (out_cpusubtype != NULL) + *out_cpusubtype = hi.cpu_subtype; + + return(0); +} + +/* + * NXGetLocalArchInfo() returns the NXArchInfo matching the cputype and + * cpusubtype of the local host. NULL is returned if there is no matching + * entry in the ArchInfoTable. + */ +const +NXArchInfo * +NXGetLocalArchInfo(void) +{ + cpu_type_t cputype; + cpu_subtype_t cpusubtype; + int32_t ret; + + /* + * Attempt to get the preferred user arch values. If the + * call is not available, or if the call fails, fall back + * to the basic arch value. (Radar 40802057) + */ + ret = -1; + +#ifdef HOST_PREFERRED_USER_ARCH + ret = internal_NXGetHostUserCPU(&cputype, &cpusubtype); +#endif + + if (ret != 0) + ret = internal_NXGetHostBasicCPU(&cputype, &cpusubtype); + + if(ret != 0) + return(NULL); + + /* + * There is a "bug" in the kernel for compatiblity that on + * an 030 machine host_info() returns cpusubtype + * CPU_SUBTYPE_MC680x0_ALL and not CPU_SUBTYPE_MC68030_ONLY. + */ + if(cputype == CPU_TYPE_MC680x0 && cpusubtype == CPU_SUBTYPE_MC680x0_ALL) + cpusubtype = CPU_SUBTYPE_MC68030_ONLY; + + return(NXGetArchInfoFromCpuType(cputype, cpusubtype)); +} + +/* + * NXGetArchInfoFromName() is passed an architecture name (like "m68k") + * and returns the matching NXArchInfo struct, or NULL if none is found. + */ +const +NXArchInfo * +NXGetArchInfoFromName( +const char *name) +{ + const NXArchInfo *ai; + + for(ai = ArchInfoTable; ai->name != NULL; ai++) + if(strcmp(ai->name, name) == 0) + return(ai); + + return(NULL); +} + +/* + * NXGetArchInfoFromName() is passed a cputype and cpusubtype and returns + * the matching NXArchInfo struct, or NULL if none is found. If the + * cpusubtype is given as CPU_SUBTYPE_MULTIPLE, the first entry that + * matches the given cputype is returned. This is the NXArchInfo struct + * describing the CPU "family". + */ +const +NXArchInfo * +NXGetArchInfoFromCpuType( +cpu_type_t cputype, +cpu_subtype_t cpusubtype) +{ + const NXArchInfo *ai; + NXArchInfo *q; + + for(ai = ArchInfoTable; ai->name != NULL; ai++) + if(ai->cputype == cputype && + (cpusubtype == CPU_SUBTYPE_MULTIPLE || + ((ai->cpusubtype & ~CPU_SUBTYPE_MASK) == + (cpusubtype & ~CPU_SUBTYPE_MASK)))) + return(ai); + + if(cputype == CPU_TYPE_I386){ + q = malloc(sizeof(NXArchInfo)); + for(ai = ArchInfoTable; ai->name != NULL; ai++){ + if(ai->cputype == cputype){ + *q = *ai; + break; + } + } + q->cpusubtype = cpusubtype; + q->description = malloc(sizeof("Intel family model ") + 2 + 8); + if(q->description == NULL){ + free(q); + return(NULL); + } + sprintf((char *)q->description, "Intel family %u model %u", + CPU_SUBTYPE_INTEL_FAMILY(cpusubtype & ~CPU_SUBTYPE_MASK), + CPU_SUBTYPE_INTEL_MODEL(cpusubtype & ~CPU_SUBTYPE_MASK)); + return((const NXArchInfo *)q); + } + else if(cputype == CPU_TYPE_POWERPC){ + q = malloc(sizeof(NXArchInfo)); + for(ai = ArchInfoTable; ai->name != NULL; ai++){ + if(ai->cputype == cputype){ + *q = *ai; + break; + } + } + q->cpusubtype = cpusubtype; + q->description = malloc(sizeof("PowerPC cpusubtype ") + 10); + if(q->description == NULL){ + free(q); + return(NULL); + } + sprintf((char *)q->description, "PowerPC cpusubtype %u", cpusubtype); + return((const NXArchInfo *)q); + } + + return(NULL); +} + +/* The above interfaces that return pointers to NXArchInfo structs in normal + * cases returns a pointer from the array returned in NXGetAllArchInfos(). + * In some cases when the cputype is CPU_TYPE_I386 or CPU_TYPE_POWERPC it will + * return a malloc(3)'ed NXArchInfo struct which contains a string in the + * description field also a malloc(3)'ed pointer. To allow programs not to + * leak memory they can call NXFreeArchInfo() on pointers returned from the + * above interfaces. Going forward the above interfaces will only return + * pointers from the array returned in NXGetAllArchInfos(). + */ +void NXFreeArchInfo( +const NXArchInfo *x) +{ + const NXArchInfo *p; + + p = NXGetAllArchInfos(); + while(p->name != NULL){ + if(x == p) + return; + p++; + } + free((char *)x->description); + free((NXArchInfo *)x); +} + +/* + * internal_NXFindBestFatArch() is passed a cputype and cpusubtype and a + * either set of fat_arch structs or fat_arch_64 structs and selects the best + * one that matches (if any) and returns an index to the array of structs or + * -1 if none works for the cputype and cpusubtype. The fat_arch structs or + * fat_arch_64 structs must be in the host byte sex and correct such that the + * fat_archs really points to enough memory for nfat_arch structs. It is + * possible that this routine could fail if new cputypes or cpusubtypes are + * added and an old version of this routine is used. But if there is an exact + * match between the cputype and cpusubtype and one of the structs this routine + * will always succeed. + */ +static +int32_t +internal_NXFindBestFatArch( +cpu_type_t cputype, +cpu_subtype_t cpusubtype, +struct fat_arch *fat_archs, +struct fat_arch_64 *fat_archs64, +uint32_t nfat_archs) +{ + uint32_t i; + int32_t lowest_family, lowest_model, lowest_index; + cpu_type_t fat_cputype; + cpu_subtype_t fat_cpusubtype; + + /* + * Look for the first exact match. + */ + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype == cputype && + (fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + (cpusubtype & ~CPU_SUBTYPE_MASK)) + return(i); + } + + /* + * An exact match was not found so find the next best match which is + * cputype dependent. + */ + switch(cputype){ + case CPU_TYPE_I386: + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ + default: + /* + * Intel cpusubtypes after the pentium (same as 586) are handled + * such that they require an exact match or they can use the + * pentium. If that is not found call into the loop for the + * earilier subtypes. + */ + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_PENT) + return(i); + } + case CPU_SUBTYPE_PENT: + case CPU_SUBTYPE_486SX: + /* + * Since an exact match as not found look for the i486 else + * break into the loop to look for the i386_ALL. + */ + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_486) + return(i); + } + break; + case CPU_SUBTYPE_I386_ALL: + /* case CPU_SUBTYPE_I386: same as above */ + case CPU_SUBTYPE_486: + break; + } + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_I386_ALL) + return(i); + } + + /* + * A match failed, promote as little as possible. + */ + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_486) + return(i); + } + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_486SX) + return(i); + } + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_586) + return(i); + } + /* + * Now look for the lowest family and in that the lowest model. + */ + lowest_family = CPU_SUBTYPE_INTEL_FAMILY_MAX + 1; + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if(CPU_SUBTYPE_INTEL_FAMILY(fat_cpusubtype & + ~CPU_SUBTYPE_MASK) < lowest_family) + lowest_family = CPU_SUBTYPE_INTEL_FAMILY( + fat_cpusubtype & ~CPU_SUBTYPE_MASK); + } + /* if no intel cputypes found return NULL */ + if(lowest_family == CPU_SUBTYPE_INTEL_FAMILY_MAX + 1) + return(-1); + lowest_model = INT_MAX; + lowest_index = -1; + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if(CPU_SUBTYPE_INTEL_FAMILY(fat_cpusubtype & + ~CPU_SUBTYPE_MASK) == lowest_family){ + if(CPU_SUBTYPE_INTEL_MODEL(fat_cpusubtype & + ~CPU_SUBTYPE_MASK) < lowest_model){ + lowest_model = CPU_SUBTYPE_INTEL_MODEL( + fat_cpusubtype & + ~CPU_SUBTYPE_MASK); + lowest_index = i; + } + } + } + return(lowest_index); + case CPU_TYPE_X86_64: + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_X86_64_ALL) + return(i); + } + break; + case CPU_TYPE_MC680x0: + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_MC680x0_ALL) + return(i); + } + /* + * Try to promote if starting from CPU_SUBTYPE_MC680x0_ALL and + * favor the CPU_SUBTYPE_MC68040 over the CPU_SUBTYPE_MC68030_ONLY. + */ + if((cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC680x0_ALL){ + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_MC68040) + return(i); + } + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_MC68030_ONLY) + return(i); + } + } + break; + case CPU_TYPE_POWERPC: + /* + * An exact match as not found. So for all the PowerPC subtypes + * pick the subtype from the following order starting from a subtype + * that will work (contains 64-bit instructions or altivec if + * needed): + * 970, 7450, 7400, 750, 604e, 604, 603ev, 603e, 603, ALL + * Note the 601 is NOT in the list above. It is only picked via + * an exact match. For an unknown subtype pick only the ALL type if + * it exists. + */ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ + case CPU_SUBTYPE_POWERPC_ALL: + /* + * The CPU_SUBTYPE_POWERPC_ALL is only used by the development + * environment tools when building a generic ALL type binary. + * In the case of a non-exact match we pick the most current + * processor. + */ + case CPU_SUBTYPE_POWERPC_970: + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_POWERPC_970) + return(i); + } + case CPU_SUBTYPE_POWERPC_7450: + case CPU_SUBTYPE_POWERPC_7400: + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_POWERPC_7450) + return(i); + } + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_POWERPC_7400) + return(i); + } + case CPU_SUBTYPE_POWERPC_750: + case CPU_SUBTYPE_POWERPC_604e: + case CPU_SUBTYPE_POWERPC_604: + case CPU_SUBTYPE_POWERPC_603ev: + case CPU_SUBTYPE_POWERPC_603e: + case CPU_SUBTYPE_POWERPC_603: + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_POWERPC_750) + return(i); + } + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_POWERPC_604e) + return(i); + } + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_POWERPC_604) + return(i); + } + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if((fat_cputype & ~CPU_SUBTYPE_MASK) != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_POWERPC_603ev) + return(i); + } + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_POWERPC_603e) + return(i); + } + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_POWERPC_603) + return(i); + } + default: + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_POWERPC_ALL) + return(i); + } + } + break; + case CPU_TYPE_POWERPC64: + /* + * An exact match as not found. So for all the PowerPC64 subtypes + * pick the subtype from the following order starting from a subtype + * that will work (contains 64-bit instructions or altivec if + * needed): + * 970 (currently only the one 64-bit subtype) + * For an unknown subtype pick only the ALL type if it exists. + */ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ + case CPU_SUBTYPE_POWERPC_ALL: + /* + * The CPU_SUBTYPE_POWERPC_ALL is only used by the development + * environment tools when building a generic ALL type binary. + * In the case of a non-exact match we pick the most current + * processor. + */ + case CPU_SUBTYPE_POWERPC_970: + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_POWERPC_970) + return(i); + } + default: + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_POWERPC_ALL) + return(i); + } + } + break; + case CPU_TYPE_MC88000: + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_MC88000_ALL) + return(i); + } + break; + case CPU_TYPE_I860: + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_I860_ALL) + return(i); + } + break; + case CPU_TYPE_HPPA: + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_HPPA_ALL) + return(i); + } + break; + case CPU_TYPE_SPARC: + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_SPARC_ALL) + return(i); + } + break; + case CPU_TYPE_ARM64_32: + /* Only exact match is allowed for CPU_TYPE_ARM64_32. */ + return(-1); + case CPU_TYPE_ARM: + case CPU_TYPE_ARM64: + { + /* + * ARM is straightforward, since each architecture is backward + * compatible with previous architectures. So, we just take the + * highest that is less than our target. + */ + int fat_match_found = 0; + uint32_t best_fat_arch = 0; + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) + continue; + if(fat_cpusubtype > cpusubtype) + continue; + if(!fat_match_found){ + fat_match_found = 1; + best_fat_arch = i; + continue; + } + if(fat_archs64 != NULL){ + if(fat_cpusubtype > + fat_archs64[best_fat_arch].cpusubtype) + best_fat_arch = i; + } + else{ + if(fat_cpusubtype > + fat_archs[best_fat_arch].cpusubtype) + best_fat_arch = i; + } + } + if(fat_match_found) + return(best_fat_arch); + /* + * For CPU_TYPE_ARM64, we will fall back to a CPU_TYPE_ARM + * with the highest subtype. + */ + if(cputype == CPU_TYPE_ARM64){ + int fat_match_found = 0; + uint32_t best_fat_arch = 0; + for(i = 0; i < nfat_archs; i++){ + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != CPU_TYPE_ARM) + continue; + if(!fat_match_found){ + fat_match_found = 1; + best_fat_arch = i; + continue; + } + if(fat_archs64 != NULL){ + if(fat_cpusubtype > + fat_archs64[best_fat_arch].cpusubtype) + best_fat_arch = i; + } + else{ + if(fat_cpusubtype > + fat_archs[best_fat_arch].cpusubtype) + best_fat_arch = i; + } + } + if(fat_match_found) + return(best_fat_arch); + } + } + break; + default: + return(-1); + } + return(-1); +} + +/* + * NXFindBestFatArch() is passed a cputype and cpusubtype and a set of + * fat_arch structs and selects the best one that matches (if any) and returns + * a pointer to that fat_arch struct (or NULL). The fat_arch structs must be + * in the host byte order and correct such that the fat_archs really points to + * enough memory for nfat_arch structs. It is possible that this routine could + * fail if new cputypes or cpusubtypes are added and an old version of this + * routine is used. But if there is an exact match between the cputype and + * cpusubtype and one of the fat_arch structs this routine will always succeed. + */ +struct fat_arch * +NXFindBestFatArch( +cpu_type_t cputype, +cpu_subtype_t cpusubtype, +struct fat_arch *fat_archs, +uint32_t nfat_archs) +{ + int32_t i; + + i = internal_NXFindBestFatArch(cputype, cpusubtype, fat_archs, NULL, + nfat_archs); + if(i == -1) + return(NULL); + return(fat_archs + i); +} + +/* NXFindBestFatArch_64() is passed a cputype and cpusubtype and a set of + * fat_arch_64 structs and selects the best one that matches (if any) and + * returns a pointer to that fat_arch_64 struct (or NULL). The fat_arch_64 + * structs must be in the host byte order and correct such that the fat_archs64 + * really points to enough memory for nfat_arch structs. It is possible that + * this routine could fail if new cputypes or cpusubtypes are added and an old + * version of this routine is used. But if there is an exact match between the + * cputype and cpusubtype and one of the fat_arch_64 structs this routine will + * always succeed. + */ +struct fat_arch_64 * +NXFindBestFatArch_64( +cpu_type_t cputype, +cpu_subtype_t cpusubtype, +struct fat_arch_64 *fat_archs64, +uint32_t nfat_archs) +{ + int32_t i; + + i = internal_NXFindBestFatArch(cputype, cpusubtype, NULL, + fat_archs64, nfat_archs); + if(i == -1) + return(NULL); + return(fat_archs64 + i); +} + +/* + * NXCombineCpuSubtypes() returns the resulting cpusubtype when combining two + * different cpusubtypes for the specified cputype. If the two cpusubtypes + * can't be combined (the specific subtypes are mutually exclusive) -1 is + * returned indicating it is an error to combine them. This can also fail and + * return -1 if new cputypes or cpusubtypes are added and an old version of + * this routine is used. But if the cpusubtypes are the same they can always + * be combined and this routine will return the cpusubtype pass in. + */ +cpu_subtype_t +NXCombineCpuSubtypes( +cpu_type_t cputype, +cpu_subtype_t cpusubtype1, +cpu_subtype_t cpusubtype2) +{ + /* + * If this is an x86_64 cputype and either subtype is the + * "Haswell and compatible" it does not combine with anything else. + */ + if(cputype == CPU_TYPE_X86_64 && + (cpusubtype1 == CPU_SUBTYPE_X86_64_H || + cpusubtype2 == CPU_SUBTYPE_X86_64_H)) + return((cpu_subtype_t)-1); + + /* + * We now combine any i386 or x86-64 subtype to the ALL subtype. + */ + if(cputype == CPU_TYPE_I386) + return(CPU_SUBTYPE_I386_ALL); + + if(cputype == CPU_TYPE_X86_64) + return(CPU_SUBTYPE_X86_64_ALL); + + /* + * The same cpusubtypes for any cputype returns that cpusubtype. For + * some cputypes like CPU_TYPE_ARM64_32 there is no combining of + * cpusubtypes so there is no code for those cputypes below. + */ + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) == + (cpusubtype2 & ~CPU_SUBTYPE_MASK)) + return(cpusubtype1); + + switch(cputype){ + case CPU_TYPE_MC680x0: + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_MC680x0_ALL && + (cpusubtype1 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_MC68030_ONLY && + (cpusubtype1 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_MC68040) + return((cpu_subtype_t)-1); + if((cpusubtype2 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_MC680x0_ALL && + (cpusubtype2 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_MC68030_ONLY && + (cpusubtype2 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_MC68040) + return((cpu_subtype_t)-1); + + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC68030_ONLY && + (cpusubtype2 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC68040) + return((cpu_subtype_t)-1); + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC68040 && + (cpusubtype2 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC68030_ONLY) + return((cpu_subtype_t)-1); + + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC68030_ONLY || + (cpusubtype2 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC68030_ONLY) + return(CPU_SUBTYPE_MC68030_ONLY); + + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC68040 || + (cpusubtype2 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC68040) + return(CPU_SUBTYPE_MC68040); + break; /* logically can't get here */ + + case CPU_TYPE_POWERPC: + /* + * Combining with the ALL type becomes the other type. Combining + * anything with the 601 becomes 601. All other non exact matches + * combine to the higher value subtype. + */ + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_POWERPC_ALL) + return(cpusubtype2); + if((cpusubtype2 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_POWERPC_ALL) + return(cpusubtype1); + + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_POWERPC_601 || + (cpusubtype2 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_POWERPC_601) + return(CPU_SUBTYPE_POWERPC_601); + + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) > + (cpusubtype2 & ~CPU_SUBTYPE_MASK)) + return(cpusubtype1); + else + return(cpusubtype2); + break; /* logically can't get here */ + + case CPU_TYPE_MC88000: + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_MC88000_ALL && + (cpusubtype1 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_MC88110) + return((cpu_subtype_t)-1); + if((cpusubtype2 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_MC88000_ALL && + (cpusubtype2 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_MC88110) + return((cpu_subtype_t)-1); + + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC88110 || + (cpusubtype2 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC88110) + return(CPU_SUBTYPE_MC88110); + + break; /* logically can't get here */ + + case CPU_TYPE_I860: + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_I860_ALL && + (cpusubtype1 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_I860_860) + return((cpu_subtype_t)-1); + if((cpusubtype2 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_I860_ALL && + (cpusubtype2 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_I860_860) + return((cpu_subtype_t)-1); + + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_I860_860 || + (cpusubtype2 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_I860_860) + return(CPU_SUBTYPE_I860_860); + break; /* logically can't get here */ + + case CPU_TYPE_HPPA: + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_HPPA_ALL && + (cpusubtype1 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_HPPA_7100LC) + return((cpu_subtype_t)-1); + if((cpusubtype2 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_HPPA_ALL && + (cpusubtype2 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_HPPA_7100LC) + return((cpu_subtype_t)-1); + + return(CPU_SUBTYPE_HPPA_7100LC); + break; /* logically can't get here */ + + case CPU_TYPE_SPARC: + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_SPARC_ALL) + return((cpu_subtype_t)-1); + if((cpusubtype2 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_SPARC_ALL) + return((cpu_subtype_t)-1); + break; /* logically can't get here */ + + case CPU_TYPE_ARM: + /* + * Combinability matrix for ARM: + * V4T V5 XSCALE V6 V7 ALL + * ~~~ ~~ ~~~~~~ ~~ ~~ ~~~ + * V4T V4T V5 XSCALE V6 V7 ALL + * V5 V5 V5 -- V6 V7 ALL + * XSCALE XSCALE -- XSCALE -- -- ALL + * V6 V6 V6 -- V6 V7 ALL + * V7 V7 V7 -- V7 V7 ALL + * ALL ALL ALL ALL ALL ALL ALL + */ + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_ARM_ALL) + return(cpusubtype2); + if((cpusubtype2 & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_ARM_ALL) + return(cpusubtype1); + switch((cpusubtype1 & ~CPU_SUBTYPE_MASK)){ + case CPU_SUBTYPE_ARM_V7: + switch((cpusubtype2 & ~CPU_SUBTYPE_MASK)){ + case CPU_SUBTYPE_ARM_XSCALE: + return((cpu_subtype_t)-1); + default: + return(CPU_SUBTYPE_ARM_V7); + } + case CPU_SUBTYPE_ARM_V6: + switch((cpusubtype2 & ~CPU_SUBTYPE_MASK)){ + case CPU_SUBTYPE_ARM_XSCALE: + return((cpu_subtype_t)-1); + default: + return(CPU_SUBTYPE_ARM_V6); + } + case CPU_SUBTYPE_ARM_XSCALE: + switch((cpusubtype2 & ~CPU_SUBTYPE_MASK)){ + case CPU_SUBTYPE_ARM_V7: + case CPU_SUBTYPE_ARM_V6: + case CPU_SUBTYPE_ARM_V5TEJ: + return((cpu_subtype_t)-1); + default: + return(CPU_SUBTYPE_ARM_XSCALE); + } + case CPU_SUBTYPE_ARM_V5TEJ: + switch((cpusubtype2 & ~CPU_SUBTYPE_MASK)){ + case CPU_SUBTYPE_ARM_XSCALE: + return((cpu_subtype_t)-1); + case CPU_SUBTYPE_ARM_V7: + return(CPU_SUBTYPE_ARM_V7); + case CPU_SUBTYPE_ARM_V6: + return(CPU_SUBTYPE_ARM_V6); + default: + return(CPU_SUBTYPE_ARM_V5TEJ); + } + case CPU_SUBTYPE_ARM_V4T: + return((cpusubtype2 & ~CPU_SUBTYPE_MASK)); + default: + return((cpu_subtype_t)-1); + } + + case CPU_TYPE_ARM64: + if((cpusubtype1 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_ARM64_ALL) + return((cpu_subtype_t)-1); + if((cpusubtype2 & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_ARM64_ALL) + return((cpu_subtype_t)-1); + break; /* logically can't get here */ + + default: + return((cpu_subtype_t)-1); + } + return((cpu_subtype_t)-1); /* logically can't get here */ +} +#endif /* !defined(RLD) */ diff --git a/cctools/libmacho/get_end.c b/cctools/libmacho/get_end.c new file mode 100644 index 0000000..eef3a21 --- /dev/null +++ b/cctools/libmacho/get_end.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef RLD +#include +#include +#include +#ifndef __OPENSTEP__ +#include +#else /* defined(__OPENSTEP__) */ +#ifdef __DYNAMIC__ +#include "mach-o/dyld.h" /* defines _dyld_lookup_and_bind() */ +#endif + +#if !defined(__DYNAMIC__) +#define DECLARE_VAR(var, type) \ +extern type var +#define SETUP_VAR(var) +#define USE_VAR(var) var +#else +#define STRINGIFY(a) # a +#define DECLARE_VAR(var, type) \ +static type * var ## _pointer = 0 +#define SETUP_VAR(var) \ +if ( var ## _pointer == 0) { \ + _dyld_lookup_and_bind( STRINGIFY(_ ## var), \ + (uint32_t *) & var ## _pointer, 0); \ +} +#define USE_VAR(var) (* var ## _pointer) +#endif +#endif /* __OPENSTEP__ */ + +/* + * This routine returns the highest address of the segments in the program (NOT + * the shared libraries). It is intended to be used as a stop gap for programs + * that make UNIX style assumptions about how memory is allocated. Typicly the + * asumptions under which this is used is that memory is contiguously allocated + * by the program's text and data from address 0 with no gaps. The value of + * this differs from the value of &_end in a UNIX program in that this routine + * returns the address of the end of the segment not the end of the last section + * in that segment as would be the value of the symbol &_end. + */ +unsigned long +get_end(void) +{ +#ifndef __LP64__ + + struct segment_command *sgp; + unsigned long _end; + uint32_t i; +#ifndef __OPENSTEP__ + struct mach_header *mhp = _NSGetMachExecuteHeader(); +#else /* defined(__OPENSTEP__) */ + static struct mach_header *mhp = NULL; + DECLARE_VAR(_mh_execute_header, struct mach_header); + SETUP_VAR(_mh_execute_header); + + mhp = (struct mach_header *)(& USE_VAR(_mh_execute_header)); +#endif /* __OPENSTEP__ */ + _end = 0; + sgp = (struct segment_command *) + ((char *)mhp + sizeof(struct mach_header)); + for(i = 0; i < mhp->ncmds; i++){ + if(sgp->cmd == LC_SEGMENT) + if(sgp->vmaddr + sgp->vmsize > _end) + _end = sgp->vmaddr + sgp->vmsize; + sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); + } + return(_end); + +#else /* defined(__LP64__) */ + + struct mach_header_64 *mhp = _NSGetMachExecuteHeader(); + struct segment_command_64 *sgp; + unsigned long _end; + uint32_t i; + + _end = 0; + sgp = (struct segment_command_64 *) + ((char *)mhp + sizeof(struct mach_header_64)); + for(i = 0; i < mhp->ncmds; i++){ + if(sgp->cmd == LC_SEGMENT_64) + if(sgp->vmaddr + sgp->vmsize > _end) + _end = sgp->vmaddr + sgp->vmsize; + sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); + } + return(_end); + +#endif /* defined(__LP64__) */ +} + +/* + * This returns what was the value of the UNIX link editor defined symbol + * _etext (the first address after the text section). Note this my or may not + * be the only section in the __TEXT segment. + */ +unsigned long +get_etext(void) +{ +#ifndef __LP64__ + const struct section *sp; +#else /* defined(__LP64__) */ + const struct section_64 *sp; +#endif /* defined(__LP64__) */ + + sp = getsectbyname(SEG_TEXT, SECT_TEXT); + if(sp) + return(sp->addr + sp->size); + else + return(0); +} + +/* + * This returns what was the value of the UNIX link editor defined symbol + * _edata (the first address after the data section). Note this my or may not + * be the last non-zero fill section in the __DATA segment. + */ +unsigned long +get_edata(void) +{ +#ifndef __LP64__ + const struct section *sp; +#else /* defined(__LP64__) */ + const struct section_64 *sp; +#endif /* defined(__LP64__) */ + + sp = getsectbyname(SEG_DATA, SECT_DATA); + if(sp) + return(sp->addr + sp->size); + else + return(0); +} +#endif /* !defined(RLD) */ diff --git a/cctools/libmacho/getsecbyname.c b/cctools/libmacho/getsecbyname.c new file mode 100644 index 0000000..3de74de --- /dev/null +++ b/cctools/libmacho/getsecbyname.c @@ -0,0 +1,579 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef RLD +#include +#ifndef CCTB_DRIVERKIT_ENABLED +#include +#endif /* !defined(CCTB_DRIVERKIT_ENABLED) */ +#include +#ifdef __DYNAMIC__ +#include /* defines _dyld_lookup_and_bind() */ +#endif /* defined(__DYNAMIC__) */ +#ifndef __OPENSTEP__ +#include +#else /* defined(__OPENSTEP__) */ + +#if !defined(__DYNAMIC__) +#define DECLARE_VAR(var, type) \ +extern type var +#define SETUP_VAR(var) +#define USE_VAR(var) var +#else +#define STRINGIFY(a) # a +#define DECLARE_VAR(var, type) \ +static type * var ## _pointer = NULL +#define SETUP_VAR(var) \ +if ( var ## _pointer == NULL) { \ + _dyld_lookup_and_bind( STRINGIFY(_ ## var), \ + (uint32_t *) & var ## _pointer, NULL); \ +} +#define USE_VAR(var) (* var ## _pointer) +#endif +#endif /* __OPENSTEP__ */ + +#ifndef CCTB_DRIVERKIT_ENABLED + +/* + * This routine returns the section structure for the named section in the + * named segment for the mach_header pointer passed to it if it exist. + * Otherwise it returns zero. + */ +const struct section * +getsectbynamefromheader( +struct mach_header *mhp, +const char *segname, +const char *sectname) +{ + struct segment_command *sgp; + struct section *sp; + uint32_t i, j; + + sgp = (struct segment_command *) + ((char *)mhp + sizeof(struct mach_header)); + for(i = 0; i < mhp->ncmds; i++){ + if(sgp->cmd == LC_SEGMENT) + if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 || + mhp->filetype == MH_OBJECT){ + sp = (struct section *)((char *)sgp + + sizeof(struct segment_command)); + for(j = 0; j < sgp->nsects; j++){ + if(strncmp(sp->sectname, sectname, + sizeof(sp->sectname)) == 0 && + strncmp(sp->segname, segname, + sizeof(sp->segname)) == 0) + return(sp); + sp = (struct section *)((char *)sp + + sizeof(struct section)); + } + } + sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); + } + return((struct section *)0); +} + +/* + * This routine returns the section structure for the named section in the + * named segment for the mach_header_64 pointer passed to it if it exist. + * Otherwise it returns zero. + */ +const struct section_64 * +getsectbynamefromheader_64( +struct mach_header_64 *mhp, +const char *segname, +const char *sectname) +{ + struct segment_command_64 *sgp; + struct section_64 *sp; + uint32_t i, j; + + sgp = (struct segment_command_64 *) + ((char *)mhp + sizeof(struct mach_header_64)); + for(i = 0; i < mhp->ncmds; i++){ + if(sgp->cmd == LC_SEGMENT_64) + if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 || + mhp->filetype == MH_OBJECT){ + sp = (struct section_64 *)((char *)sgp + + sizeof(struct segment_command_64)); + for(j = 0; j < sgp->nsects; j++){ + if(strncmp(sp->sectname, sectname, + sizeof(sp->sectname)) == 0 && + strncmp(sp->segname, segname, + sizeof(sp->segname)) == 0) + return(sp); + sp = (struct section_64 *)((char *)sp + + sizeof(struct section_64)); + } + } + sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); + } + return((struct section_64 *)0); +} + +/* + * This routine returns the section structure for the named section in the + * named segment for the mach_header pointer passed to it if it exist. + * Otherwise it returns zero. If fSwap == YES (the mach header has been + * swapped to the endiannes of the current machine, but the segments and + * sections are different) then the segment and sections are swapped. + */ +const struct section * +getsectbynamefromheaderwithswap( + struct mach_header *mhp, + const char *segname, + const char *sectname, + int fSwap) +{ + struct segment_command *sgp; + struct section *sp; + uint32_t i, j; + + sgp = (struct segment_command *) + ((char *)mhp + sizeof(struct mach_header)); + for(i = 0; i < mhp->ncmds; i++){ + if(sgp->cmd == (fSwap ? OSSwapInt32(LC_SEGMENT) : LC_SEGMENT)) { + + if (fSwap) { +#ifdef __LITTLE_ENDIAN__ + swap_segment_command(sgp, NX_BigEndian); +#else + swap_segment_command(sgp, NX_LittleEndian); +#endif /* __LITTLE_ENDIAN__ */ + } + + if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 || + mhp->filetype == MH_OBJECT){ + sp = (struct section *)((char *)sgp + + sizeof(struct segment_command)); + + if (fSwap) { +#ifdef __LITTLE_ENDIAN__ + swap_section(sp, sgp->nsects, NX_BigEndian); +#else + swap_section(sp, sgp->nsects, NX_LittleEndian); +#endif /* __LITTLE_ENDIAN__ */ + } + + for(j = 0; j < sgp->nsects; j++){ + if(strncmp(sp->sectname, sectname, + sizeof(sp->sectname)) == 0 && + strncmp(sp->segname, segname, + sizeof(sp->segname)) == 0) + return(sp); + sp = (struct section *)((char *)sp + + sizeof(struct section)); + } + } + sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); + } else { + sgp = (struct segment_command *)((char *)sgp + + (fSwap ? OSSwapInt32(sgp->cmdsize) : sgp->cmdsize)); + } + } + return((struct section *)0); +} + +/* + * This routine returns the section_64 structure for the named section in the + * named segment for the mach_header_64 pointer passed to it if it exist. + * Otherwise it returns zero. If fSwap == YES (the mach header has been + * swapped to the endiannes of the current machine, but the segments and + * sections are different) then the segment and sections are swapped. + */ +const struct section_64 * +getsectbynamefromheaderwithswap_64( + struct mach_header_64 *mhp, + const char *segname, + const char *sectname, + int fSwap) +{ + struct segment_command_64 *sgp; + struct section_64 *sp; + uint32_t i, j; + + sgp = (struct segment_command_64 *) + ((char *)mhp + sizeof(struct mach_header_64)); + for(i = 0; i < mhp->ncmds; i++){ + if(sgp->cmd == (fSwap ? OSSwapInt32(LC_SEGMENT) : LC_SEGMENT)) { + + if (fSwap) { +#ifdef __LITTLE_ENDIAN__ + swap_segment_command_64(sgp, NX_BigEndian); +#else + swap_segment_command_64(sgp, NX_LittleEndian); +#endif /* __LITTLE_ENDIAN__ */ + } + + if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 || + mhp->filetype == MH_OBJECT){ + sp = (struct section_64 *)((char *)sgp + + sizeof(struct segment_command_64)); + + if (fSwap) { +#ifdef __LITTLE_ENDIAN__ + swap_section_64(sp, sgp->nsects, NX_BigEndian); +#else + swap_section_64(sp, sgp->nsects, NX_LittleEndian); +#endif /* __LITTLE_ENDIAN__ */ + } + + for(j = 0; j < sgp->nsects; j++){ + if(strncmp(sp->sectname, sectname, + sizeof(sp->sectname)) == 0 && + strncmp(sp->segname, segname, + sizeof(sp->segname)) == 0) + return(sp); + sp = (struct section_64 *)((char *)sp + + sizeof(struct section_64)); + } + } + sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); + } else { + sgp = (struct segment_command_64 *)((char *)sgp + + (fSwap ? OSSwapInt32(sgp->cmdsize) : sgp->cmdsize)); + } + } + return((struct section_64 *)0); +} + +/* + * This routine returns the a pointer the section structure of the named + * section in the named segment if it exist in the mach executable it is + * linked into. Otherwise it returns zero. + */ +#ifndef __LP64__ + +const struct section * +getsectbyname( +const char *segname, +const char *sectname) +{ +#ifndef __OPENSTEP__ + struct mach_header *mhp = _NSGetMachExecuteHeader(); +#else /* defined(__OPENSTEP__) */ + static struct mach_header *mhp = NULL; + DECLARE_VAR(_mh_execute_header, struct mach_header); + SETUP_VAR(_mh_execute_header); + mhp = (struct mach_header *)(& USE_VAR(_mh_execute_header)); +#endif /* __OPENSTEP__ */ + return(getsectbynamefromheader(mhp, segname, sectname)); +} + +#else /* defined(__LP64__) */ + +const struct section_64 * +getsectbyname( +const char *segname, +const char *sectname) +{ + struct mach_header_64 *mhp = _NSGetMachExecuteHeader(); + + return(getsectbynamefromheader_64(mhp, segname, sectname)); +} + +#endif /* defined(__LP64__) */ + +/* + * This routine returns the a pointer to the data for the named section in the + * named segment if it exist in the mach executable it is linked into. Also + * it returns the size of the section data indirectly through the pointer size. + * Otherwise it returns zero for the pointer and the size. + */ +char * +getsectdata( +const char *segname, +const char *sectname, +unsigned long *size) +{ +#ifndef __LP64__ + const struct section *sp; +#else /* defined(__LP64__) */ + const struct section_64 *sp; +#endif /* defined(__LP64__) */ + + sp = getsectbyname(segname, sectname); + if(sp == NULL){ + *size = 0; + return(NULL); + } + *size = sp->size; + return((char *)(sp->addr)); +} + +#endif /* !defined(CCTB_DRIVERKIT_ENABLED) */ + +/* + * This routine returns the a pointer to the section contents of the named + * section in the named segment if it exists in the image pointed to by the + * mach header. Otherwise it returns zero. + */ +#ifndef __LP64__ + +uint8_t * +getsectiondata( +const struct mach_header *mhp, +const char *segname, +const char *sectname, +unsigned long *size) +{ + struct segment_command *sgp; + struct section *sp; + uint32_t i, j; + intptr_t slide; + + slide = 0; + sp = 0; + sgp = (struct segment_command *) + ((char *)mhp + sizeof(struct mach_header)); + for(i = 0; i < mhp->ncmds; i++){ + if(sgp->cmd == LC_SEGMENT){ + if(strcmp(sgp->segname, "__TEXT") == 0){ + slide = (uintptr_t)mhp - sgp->vmaddr; + } + if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){ + sp = (struct section *)((char *)sgp + + sizeof(struct segment_command)); + for(j = 0; j < sgp->nsects; j++){ + if(strncmp(sp->sectname, sectname, + sizeof(sp->sectname)) == 0 && + strncmp(sp->segname, segname, + sizeof(sp->segname)) == 0){ + *size = sp->size; + return((uint8_t *)(sp->addr) + slide); + } + sp = (struct section *)((char *)sp + + sizeof(struct section)); + } + } + } + sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); + } + return(0); +} + +uint8_t * +getsegmentdata( +const struct mach_header *mhp, +const char *segname, +unsigned long *size) +{ + struct segment_command *sgp; + intptr_t slide; + uint32_t i; + + slide = 0; + sgp = (struct segment_command *) + ((char *)mhp + sizeof(struct mach_header)); + for(i = 0; i < mhp->ncmds; i++){ + if(sgp->cmd == LC_SEGMENT){ + if(strcmp(sgp->segname, "__TEXT") == 0){ + slide = (uintptr_t)mhp - sgp->vmaddr; + } + if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){ + *size = sgp->vmsize; + return((uint8_t *)(sgp->vmaddr + slide)); + } + } + sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); + } + return(0); +} + +#else /* defined(__LP64__) */ + +uint8_t * +getsectiondata( +const struct mach_header_64 *mhp, +const char *segname, +const char *sectname, +unsigned long *size) +{ + struct segment_command_64 *sgp; + struct section_64 *sp; + uint32_t i, j; + intptr_t slide; + + slide = 0; + sp = 0; + sgp = (struct segment_command_64 *) + ((char *)mhp + sizeof(struct mach_header_64)); + for(i = 0; i < mhp->ncmds; i++){ + if(sgp->cmd == LC_SEGMENT_64){ + if(strcmp(sgp->segname, "__TEXT") == 0){ + slide = (uintptr_t)mhp - sgp->vmaddr; + } + if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){ + sp = (struct section_64 *)((char *)sgp + + sizeof(struct segment_command_64)); + for(j = 0; j < sgp->nsects; j++){ + if(strncmp(sp->sectname, sectname, + sizeof(sp->sectname)) == 0 && + strncmp(sp->segname, segname, + sizeof(sp->segname)) == 0){ + *size = sp->size; + return((uint8_t *)(sp->addr) + slide); + } + sp = (struct section_64 *)((char *)sp + + sizeof(struct section_64)); + } + } + } + sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); + } + return(0); +} + +uint8_t * +getsegmentdata( +const struct mach_header_64 *mhp, +const char *segname, +unsigned long *size) +{ + struct segment_command_64 *sgp; + intptr_t slide; + uint32_t i; + + slide = 0; + sgp = (struct segment_command_64 *) + ((char *)mhp + sizeof(struct mach_header_64)); + for(i = 0; i < mhp->ncmds; i++){ + if(sgp->cmd == LC_SEGMENT_64){ + if(strcmp(sgp->segname, "__TEXT") == 0){ + slide = (uintptr_t)mhp - sgp->vmaddr; + } + if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){ + *size = sgp->vmsize; + return((uint8_t *)(sgp->vmaddr + slide)); + } + } + sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); + } + return(0); +} + +#endif /* defined(__LP64__) */ + +#ifndef CCTB_DRIVERKIT_ENABLED + +/* + * This routine returns the a pointer to the data for the named section in the + * named segment if it exist in the mach header passed to it. Also it returns + * the size of the section data indirectly through the pointer size. Otherwise + * it returns zero for the pointer and the size. + */ +char * +getsectdatafromheader( +struct mach_header *mhp, +const char *segname, +const char *sectname, +uint32_t *size) +{ + const struct section *sp; + + sp = getsectbynamefromheader(mhp, segname, sectname); + if(sp == NULL){ + *size = 0; + return(NULL); + } + *size = sp->size; + return((char *)((uintptr_t)(sp->addr))); +} + +/* + * This routine returns the a pointer to the data for the named section in the + * named segment if it exist in the 64-bit mach header passed to it. Also it + * returns the size of the section data indirectly through the pointer size. + * Otherwise it returns zero for the pointer and the size. + */ +char * +getsectdatafromheader_64( +struct mach_header_64 *mhp, +const char *segname, +const char *sectname, +uint64_t *size) +{ + const struct section_64 *sp; + + sp = getsectbynamefromheader_64(mhp, segname, sectname); + if(sp == NULL){ + *size = 0; + return(NULL); + } + *size = sp->size; + return((char *)((uintptr_t)(sp->addr))); +} + +#ifdef __DYNAMIC__ +/* + * This routine returns the a pointer to the data for the named section in the + * named segment if it exist in the named Framework. Also it returns the size + * of the section data indirectly through the pointer size. Otherwise it + * returns zero for the pointer and the size. The last component of the path + * of the Framework is passed as FrameworkName. + */ +void * +getsectdatafromFramework( +const char *FrameworkName, +const char *segname, +const char *sectname, +unsigned long *size) +{ + uint32_t i; + unsigned long n; + uintptr_t vmaddr_slide; +#ifndef __LP64__ + struct mach_header *mh; + const struct section *s; +#else /* defined(__LP64__) */ + struct mach_header_64 *mh; + const struct section_64 *s; +#endif /* defined(__LP64__) */ + char *name, *p; + + n = _dyld_image_count(); + for(i = 0; i < n ; i++){ + name = _dyld_get_image_name(i); + p = strrchr(name, '/'); + if(p != NULL && p[1] != '\0') + name = p + 1; + if(strcmp(name, FrameworkName) != 0) + continue; + mh = _dyld_get_image_header(i); + vmaddr_slide = _dyld_get_image_vmaddr_slide(i); +#ifndef __LP64__ + s = getsectbynamefromheader(mh, segname, sectname); +#else /* defined(__LP64__) */ + s = getsectbynamefromheader_64(mh, segname, sectname); +#endif /* defined(__LP64__) */ + if(s == NULL){ + *size = 0; + return(NULL); + } + *size = s->size; + return((void *)(s->addr + vmaddr_slide)); + } + *size = 0; + return(NULL); +} +#endif /* __DYNAMIC__ */ +#endif /* !defined(CCTB_DRIVERKIT_ENABLED) */ +#endif /* !defined(RLD) */ diff --git a/cctools/libmacho/getsegbyname.c b/cctools/libmacho/getsegbyname.c new file mode 100644 index 0000000..a83c04e --- /dev/null +++ b/cctools/libmacho/getsegbyname.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#include +#include +#ifndef __OPENSTEP__ + +#ifndef RLD +#include +#endif /* !defined(RLD) */ + +#else /* defined(__OPENSTEP__) */ +#ifdef __DYNAMIC__ +#include "mach-o/dyld.h" /* defines _dyld_lookup_and_bind() */ +#endif + +#if !defined(__DYNAMIC__) +#define DECLARE_VAR(var, type) \ +extern type var +#define SETUP_VAR(var) +#define USE_VAR(var) var +#else +#define STRINGIFY(a) # a +#define DECLARE_VAR(var, type) \ +static type * var ## _pointer = 0 +#define SETUP_VAR(var) \ +if ( var ## _pointer == 0) { \ + _dyld_lookup_and_bind( STRINGIFY(_ ## var), \ + (uint32_t *) & var ## _pointer, 0); \ +} +#define USE_VAR(var) (* var ## _pointer) +#endif +#endif /* __OPENSTEP__ */ + +/* + * This routine returns the segment_command structure for the named segment if + * it exist in the mach executible it is linked into. Otherwise it returns + * zero. It uses the link editor defined symbol _mh_execute_header and just + * looks through the load commands. Since these are mapped into the text + * segment they are read only and thus const. + */ +#ifndef __LP64__ + +const struct segment_command * +getsegbyname( +char *segname) +{ + struct segment_command *sgp; + uint32_t i; +#ifndef RLD +#ifndef __OPENSTEP__ + struct mach_header *mhp = _NSGetMachExecuteHeader(); +#else /* defined(__OPENSTEP__) */ + static struct mach_header *mhp = NULL; + DECLARE_VAR(_mh_execute_header, struct mach_header); + SETUP_VAR(_mh_execute_header); + mhp = (struct mach_header *)(& USE_VAR(_mh_execute_header)); +#endif /* __OPENSTEP__ */ +#else /* defined(RLD) */ + mhp = (struct mach_header *)(&_mh_execute_header); +#endif /* defined(RLD) */ + + sgp = (struct segment_command *) + ((char *)mhp + sizeof(struct mach_header)); + for(i = 0; i < mhp->ncmds; i++){ + if(sgp->cmd == LC_SEGMENT) + if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0) + return(sgp); + sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); + } + return(NULL); +} + +#else /* defined(__LP64__) */ + +const struct segment_command_64 * +getsegbyname( +char *segname) +{ + struct mach_header_64 *mhp = NULL; + struct segment_command_64 *sgp; + uint32_t i; + +#ifndef RLD + mhp = _NSGetMachExecuteHeader(); +#else /* defined(RLD) */ + mhp = (struct mach_header_64 *)(&_mh_execute_header); +#endif /* defined(RLD) */ + + sgp = (struct segment_command_64 *) + ((char *)mhp + sizeof(struct mach_header_64)); + for(i = 0; i < mhp->ncmds; i++){ + if(sgp->cmd == LC_SEGMENT_64) + if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0) + return(sgp); + sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); + } + return(NULL); +} +#endif /* defined(__LP64__) */ diff --git a/cctools/libmacho/hppa_swap.c b/cctools/libmacho/hppa_swap.c new file mode 100644 index 0000000..63569b7 --- /dev/null +++ b/cctools/libmacho/hppa_swap.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef RLD +#import + +void +swap_hppa_integer_thread_state( +struct hp_pa_integer_thread_state *regs, +enum NXByteOrder target_byte_order) +{ + regs->ts_gr1 = OSSwapInt32(regs->ts_gr1); + regs->ts_gr2 = OSSwapInt32(regs->ts_gr2); + regs->ts_gr3 = OSSwapInt32(regs->ts_gr3); + regs->ts_gr4 = OSSwapInt32(regs->ts_gr4); + regs->ts_gr5 = OSSwapInt32(regs->ts_gr5); + regs->ts_gr6 = OSSwapInt32(regs->ts_gr6); + regs->ts_gr7 = OSSwapInt32(regs->ts_gr7); + regs->ts_gr8 = OSSwapInt32(regs->ts_gr8); + regs->ts_gr9 = OSSwapInt32(regs->ts_gr9); + regs->ts_gr10 = OSSwapInt32(regs->ts_gr10); + regs->ts_gr11 = OSSwapInt32(regs->ts_gr11); + regs->ts_gr12 = OSSwapInt32(regs->ts_gr12); + regs->ts_gr13 = OSSwapInt32(regs->ts_gr13); + regs->ts_gr14 = OSSwapInt32(regs->ts_gr14); + regs->ts_gr15 = OSSwapInt32(regs->ts_gr15); + regs->ts_gr16 = OSSwapInt32(regs->ts_gr16); + regs->ts_gr17 = OSSwapInt32(regs->ts_gr17); + regs->ts_gr18 = OSSwapInt32(regs->ts_gr18); + regs->ts_gr19 = OSSwapInt32(regs->ts_gr19); + regs->ts_gr20 = OSSwapInt32(regs->ts_gr20); + regs->ts_gr21 = OSSwapInt32(regs->ts_gr21); + regs->ts_gr22 = OSSwapInt32(regs->ts_gr22); + regs->ts_gr23 = OSSwapInt32(regs->ts_gr23); + regs->ts_gr24 = OSSwapInt32(regs->ts_gr24); + regs->ts_gr25 = OSSwapInt32(regs->ts_gr25); + regs->ts_gr26 = OSSwapInt32(regs->ts_gr26); + regs->ts_gr27 = OSSwapInt32(regs->ts_gr27); + regs->ts_gr28 = OSSwapInt32(regs->ts_gr28); + regs->ts_gr29 = OSSwapInt32(regs->ts_gr29); + regs->ts_gr30 = OSSwapInt32(regs->ts_gr30); + regs->ts_gr31 = OSSwapInt32(regs->ts_gr31); + regs->ts_sr0 = OSSwapInt32(regs->ts_sr0); + regs->ts_sr1 = OSSwapInt32(regs->ts_sr1); + regs->ts_sr2 = OSSwapInt32(regs->ts_sr2); + regs->ts_sr3 = OSSwapInt32(regs->ts_sr3); + regs->ts_sar = OSSwapInt32(regs->ts_sar); +} + +void swap_hppa_frame_thread_state( +struct hp_pa_frame_thread_state *frame, +enum NXByteOrder target_byte_order) +{ + frame->ts_pcsq_front = OSSwapInt32(frame->ts_pcsq_front); + frame->ts_pcsq_back = OSSwapInt32(frame->ts_pcsq_back); + frame->ts_pcoq_front = OSSwapInt32(frame->ts_pcoq_front); + frame->ts_pcoq_back = OSSwapInt32(frame->ts_pcoq_back); + frame->ts_psw = OSSwapInt32(frame->ts_psw); + frame->ts_unaligned_faults = OSSwapInt32(frame->ts_unaligned_faults); + frame->ts_fault_address = OSSwapInt32(frame->ts_fault_address); + frame->ts_step_range_start = OSSwapInt32(frame->ts_step_range_start); + frame->ts_step_range_stop = OSSwapInt32(frame->ts_step_range_stop); +} + +void swap_hppa_fp_thread_state( +struct hp_pa_fp_thread_state *fp, +enum NXByteOrder target_byte_order) +{ + fp->ts_fp0 = OSSwapInt64(fp->ts_fp0); + fp->ts_fp1 = OSSwapInt64(fp->ts_fp1); + fp->ts_fp2 = OSSwapInt64(fp->ts_fp2); + fp->ts_fp3 = OSSwapInt64(fp->ts_fp3); + fp->ts_fp4 = OSSwapInt64(fp->ts_fp4); + fp->ts_fp5 = OSSwapInt64(fp->ts_fp5); + fp->ts_fp6 = OSSwapInt64(fp->ts_fp6); + fp->ts_fp7 = OSSwapInt64(fp->ts_fp7); + fp->ts_fp8 = OSSwapInt64(fp->ts_fp8); + fp->ts_fp9 = OSSwapInt64(fp->ts_fp9); + fp->ts_fp10 = OSSwapInt64(fp->ts_fp10); + fp->ts_fp11 = OSSwapInt64(fp->ts_fp11); + fp->ts_fp12 = OSSwapInt64(fp->ts_fp12); + fp->ts_fp13 = OSSwapInt64(fp->ts_fp13); + fp->ts_fp14 = OSSwapInt64(fp->ts_fp14); + fp->ts_fp15 = OSSwapInt64(fp->ts_fp15); + fp->ts_fp16 = OSSwapInt64(fp->ts_fp16); + fp->ts_fp17 = OSSwapInt64(fp->ts_fp17); + fp->ts_fp18 = OSSwapInt64(fp->ts_fp18); + fp->ts_fp19 = OSSwapInt64(fp->ts_fp19); + fp->ts_fp20 = OSSwapInt64(fp->ts_fp20); + fp->ts_fp21 = OSSwapInt64(fp->ts_fp21); + fp->ts_fp22 = OSSwapInt64(fp->ts_fp22); + fp->ts_fp23 = OSSwapInt64(fp->ts_fp23); + fp->ts_fp24 = OSSwapInt64(fp->ts_fp24); + fp->ts_fp25 = OSSwapInt64(fp->ts_fp25); + fp->ts_fp26 = OSSwapInt64(fp->ts_fp26); + fp->ts_fp27 = OSSwapInt64(fp->ts_fp27); + fp->ts_fp28 = OSSwapInt64(fp->ts_fp28); + fp->ts_fp29 = OSSwapInt64(fp->ts_fp29); + fp->ts_fp30 = OSSwapInt64(fp->ts_fp30); + fp->ts_fp31 = OSSwapInt64(fp->ts_fp31); +} +#endif /* !defined(RLD) */ diff --git a/cctools/libmacho/i386_swap.c b/cctools/libmacho/i386_swap.c new file mode 100644 index 0000000..b18c120 --- /dev/null +++ b/cctools/libmacho/i386_swap.c @@ -0,0 +1,922 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef RLD +#ifdef SHLIB +#undef environ +#endif + +#define __busy busy +#define __c0 c0 +#define __c1 c1 +#define __c2 c2 +#define __c3 c3 +#define __cs cs +#define __darwin_fp_control fp_control +#define __darwin_fp_status fp_status +#define __darwin_i386_exception_state i386_exception_state +#define __darwin_i386_float_state i386_float_state +#define __darwin_i386_thread_state i386_thread_state +#define __darwin_mmst_reg mmst_reg +#define __darwin_xmm_reg xmm_reg +#define __denorm denorm +#define __ds ds +#define __eax eax +#define __ebp ebp +#define __ebx ebx +#define __ecx ecx +#define __edi edi +#define __edx edx +#define __eflags eflags +#define __eip eip +#define __err err +#define __errsumm errsumm +#define __es es +#define __esi esi +#define __esp esp +#define __faultvaddr faultvaddr +#define __fpu_cs fpu_cs +#define __fpu_dp fpu_dp +#define __fpu_ds fpu_ds +#define __fpu_fcw fpu_fcw +#define __fpu_fop fpu_fop +#define __fpu_fsw fpu_fsw +#define __fpu_ftw fpu_ftw +#define __fpu_ip fpu_ip +#define __fpu_mxcsr fpu_mxcsr +#define __fpu_mxcsrmask fpu_mxcsrmask +#define __fpu_reserved fpu_reserved +#define __fpu_reserved1 fpu_reserved1 +#define __fpu_rsrv1 fpu_rsrv1 +#define __fpu_rsrv2 fpu_rsrv2 +#define __fpu_rsrv3 fpu_rsrv3 +#define __fpu_rsrv4 fpu_rsrv4 +#define __fpu_stmm0 fpu_stmm0 +#define __fpu_stmm1 fpu_stmm1 +#define __fpu_stmm2 fpu_stmm2 +#define __fpu_stmm3 fpu_stmm3 +#define __fpu_stmm4 fpu_stmm4 +#define __fpu_stmm5 fpu_stmm5 +#define __fpu_stmm6 fpu_stmm6 +#define __fpu_stmm7 fpu_stmm7 +#define __fpu_xmm0 fpu_xmm0 +#define __fpu_xmm1 fpu_xmm1 +#define __fpu_xmm2 fpu_xmm2 +#define __fpu_xmm3 fpu_xmm3 +#define __fpu_xmm4 fpu_xmm4 +#define __fpu_xmm5 fpu_xmm5 +#define __fpu_xmm6 fpu_xmm6 +#define __fpu_xmm7 fpu_xmm7 +#define __fs fs +#define __gs gs +#define __invalid invalid +#define __mmst_reg mmst_reg +#define __mmst_rsrv mmst_rsrv +#define __ovrfl ovrfl +#define __pc pc +#define __precis precis +#define __rc rc +#define __ss ss +#define __stkflt stkflt +#define __tos tos +#define __trapno trapno +#define __undfl undfl +#define __xmm_reg xmm_reg +#define __zdiv zdiv + +#define __rax rax +#define __rbx rbx +#define __rcx rcx +#define __rdx rdx +#define __rdi rdi +#define __rsi rsi +#define __rbp rbp +#define __rsp rsp +#define __r8 r8 +#define __r9 r9 +#define __r10 r10 +#define __r11 r11 +#define __r12 r12 +#define __r13 r13 +#define __r14 r14 +#define __r15 r15 +#define __rip rip +#define __rflags rflags + +#define __dr0 dr0 +#define __dr1 dr1 +#define __dr2 dr2 +#define __dr3 dr3 +#define __dr4 dr4 +#define __dr5 dr5 +#define __dr6 dr6 +#define __dr7 dr7 + +#include +#include +#import + +void +swap_i386_thread_state( +i386_thread_state_t *cpu, +enum NXByteOrder target_byte_sex) +{ + cpu->eax = OSSwapInt32(cpu->eax); + cpu->ebx = OSSwapInt32(cpu->ebx); + cpu->ecx = OSSwapInt32(cpu->ecx); + cpu->edx = OSSwapInt32(cpu->edx); + cpu->edi = OSSwapInt32(cpu->edi); + cpu->esi = OSSwapInt32(cpu->esi); + cpu->ebp = OSSwapInt32(cpu->ebp); + cpu->esp = OSSwapInt32(cpu->esp); + cpu->ss = OSSwapInt32(cpu->ss); + cpu->eflags = OSSwapInt32(cpu->eflags); + cpu->eip = OSSwapInt32(cpu->eip); + cpu->cs = OSSwapInt32(cpu->cs); + cpu->ds = OSSwapInt32(cpu->ds); + cpu->es = OSSwapInt32(cpu->es); + cpu->fs = OSSwapInt32(cpu->fs); + cpu->gs = OSSwapInt32(cpu->gs); +} + +#ifdef x86_THREAD_STATE64 +void +swap_x86_thread_state64( +x86_thread_state64_t *cpu, +enum NXByteOrder target_byte_sex) +{ + cpu->rax = OSSwapInt64(cpu->rax); + cpu->rbx = OSSwapInt64(cpu->rbx); + cpu->rcx = OSSwapInt64(cpu->rcx); + cpu->rdx = OSSwapInt64(cpu->rdx); + cpu->rdi = OSSwapInt64(cpu->rdi); + cpu->rsi = OSSwapInt64(cpu->rsi); + cpu->rbp = OSSwapInt64(cpu->rbp); + cpu->rsp = OSSwapInt64(cpu->rsp); + cpu->rflags = OSSwapInt64(cpu->rflags); + cpu->rip = OSSwapInt64(cpu->rip); + cpu->r8 = OSSwapInt64(cpu->r8); + cpu->r9 = OSSwapInt64(cpu->r9); + cpu->r10 = OSSwapInt64(cpu->r10); + cpu->r11 = OSSwapInt64(cpu->r11); + cpu->r12 = OSSwapInt64(cpu->r12); + cpu->r13 = OSSwapInt64(cpu->r13); + cpu->r14 = OSSwapInt64(cpu->r14); + cpu->r15 = OSSwapInt64(cpu->r15); + cpu->cs = OSSwapInt64(cpu->cs); + cpu->fs = OSSwapInt64(cpu->fs); + cpu->gs = OSSwapInt64(cpu->gs); +} + +void +swap_x86_state_hdr( +x86_state_hdr_t *hdr, +enum NXByteOrder target_byte_sex) +{ + hdr->flavor = OSSwapInt32(hdr->flavor); + hdr->count = OSSwapInt32(hdr->count); +} + +void +swap_x86_float_state64( +x86_float_state64_t *fpu, +enum NXByteOrder target_byte_sex) +{ + struct swapped_fp_control { + union { + struct { + unsigned short + :3, + /*inf*/ :1, + rc :2, + pc :2, + :2, + precis :1, + undfl :1, + ovrfl :1, + zdiv :1, + denorm :1, + invalid :1; + } fields; + unsigned short half; + } u; + } sfpc; + + struct swapped_fp_status { + union { + struct { + unsigned short + busy :1, + c3 :1, + tos :3, + c2 :1, + c1 :1, + c0 :1, + errsumm :1, + stkflt :1, + precis :1, + undfl :1, + ovrfl :1, + zdiv :1, + denorm :1, + invalid :1; + } fields; + unsigned short half; + } u; + } sfps; + + enum NXByteOrder host_byte_sex; + + host_byte_sex = NXHostByteOrder(); + + fpu->fpu_reserved[0] = OSSwapInt32(fpu->fpu_reserved[0]); + fpu->fpu_reserved[1] = OSSwapInt32(fpu->fpu_reserved[1]); + + if(target_byte_sex == host_byte_sex){ + memcpy(&sfpc, &(fpu->fpu_fcw), + sizeof(struct swapped_fp_control)); + sfpc.u.half = OSSwapInt16(sfpc.u.half); + fpu->fpu_fcw.rc = sfpc.u.fields.rc; + fpu->fpu_fcw.pc = sfpc.u.fields.pc; + fpu->fpu_fcw.precis = sfpc.u.fields.precis; + fpu->fpu_fcw.undfl = sfpc.u.fields.undfl; + fpu->fpu_fcw.ovrfl = sfpc.u.fields.ovrfl; + fpu->fpu_fcw.zdiv = sfpc.u.fields.zdiv; + fpu->fpu_fcw.denorm = sfpc.u.fields.denorm; + fpu->fpu_fcw.invalid = sfpc.u.fields.invalid; + + memcpy(&sfps, &(fpu->fpu_fsw), + sizeof(struct swapped_fp_status)); + sfps.u.half = OSSwapInt16(sfps.u.half); + fpu->fpu_fsw.busy = sfps.u.fields.busy; + fpu->fpu_fsw.c3 = sfps.u.fields.c3; + fpu->fpu_fsw.tos = sfps.u.fields.tos; + fpu->fpu_fsw.c2 = sfps.u.fields.c2; + fpu->fpu_fsw.c1 = sfps.u.fields.c1; + fpu->fpu_fsw.c0 = sfps.u.fields.c0; + fpu->fpu_fsw.errsumm = sfps.u.fields.errsumm; + fpu->fpu_fsw.stkflt = sfps.u.fields.stkflt; + fpu->fpu_fsw.precis = sfps.u.fields.precis; + fpu->fpu_fsw.undfl = sfps.u.fields.undfl; + fpu->fpu_fsw.ovrfl = sfps.u.fields.ovrfl; + fpu->fpu_fsw.zdiv = sfps.u.fields.zdiv; + fpu->fpu_fsw.denorm = sfps.u.fields.denorm; + fpu->fpu_fsw.invalid = sfps.u.fields.invalid; + } + else{ + sfpc.u.fields.rc = fpu->fpu_fcw.rc; + sfpc.u.fields.pc = fpu->fpu_fcw.pc; + sfpc.u.fields.precis = fpu->fpu_fcw.precis; + sfpc.u.fields.undfl = fpu->fpu_fcw.undfl; + sfpc.u.fields.ovrfl = fpu->fpu_fcw.ovrfl; + sfpc.u.fields.zdiv = fpu->fpu_fcw.zdiv; + sfpc.u.fields.denorm = fpu->fpu_fcw.denorm; + sfpc.u.fields.invalid = fpu->fpu_fcw.invalid; + sfpc.u.half = OSSwapInt16(sfpc.u.half); + memcpy(&(fpu->fpu_fcw), &sfpc, + sizeof(struct swapped_fp_control)); + + sfps.u.fields.busy = fpu->fpu_fsw.busy; + sfps.u.fields.c3 = fpu->fpu_fsw.c3; + sfps.u.fields.tos = fpu->fpu_fsw.tos; + sfps.u.fields.c2 = fpu->fpu_fsw.c2; + sfps.u.fields.c1 = fpu->fpu_fsw.c1; + sfps.u.fields.c0 = fpu->fpu_fsw.c0; + sfps.u.fields.errsumm = fpu->fpu_fsw.errsumm; + sfps.u.fields.stkflt = fpu->fpu_fsw.stkflt; + sfps.u.fields.precis = fpu->fpu_fsw.precis; + sfps.u.fields.undfl = fpu->fpu_fsw.undfl; + sfps.u.fields.ovrfl = fpu->fpu_fsw.ovrfl; + sfps.u.fields.zdiv = fpu->fpu_fsw.zdiv; + sfps.u.fields.denorm = fpu->fpu_fsw.denorm; + sfps.u.fields.invalid = fpu->fpu_fsw.invalid; + sfps.u.half = OSSwapInt16(sfps.u.half); + memcpy(&(fpu->fpu_fsw), &sfps, + sizeof(struct swapped_fp_status)); + } + fpu->fpu_fop = OSSwapInt16(fpu->fpu_fop); + fpu->fpu_ip = OSSwapInt32(fpu->fpu_ip); + fpu->fpu_cs = OSSwapInt16(fpu->fpu_cs); + fpu->fpu_rsrv2 = OSSwapInt16(fpu->fpu_rsrv2); + fpu->fpu_dp = OSSwapInt32(fpu->fpu_dp); + fpu->fpu_ds = OSSwapInt16(fpu->fpu_ds); + fpu->fpu_rsrv3 = OSSwapInt16(fpu->fpu_rsrv3); + fpu->fpu_mxcsr = OSSwapInt32(fpu->fpu_mxcsr); + fpu->fpu_mxcsrmask = OSSwapInt32(fpu->fpu_mxcsrmask); + fpu->fpu_reserved1 = OSSwapInt32(fpu->fpu_reserved1); +} + +void +swap_x86_exception_state64( +x86_exception_state64_t *exc, +enum NXByteOrder target_byte_sex) +{ + exc->trapno = OSSwapInt32(exc->trapno); + exc->err = OSSwapInt32(exc->err); + exc->faultvaddr = OSSwapInt64(exc->faultvaddr); +} + +void +swap_x86_thread_state( +x86_thread_state_t *cpu, +enum NXByteOrder target_byte_sex) +{ + x86_state_hdr_t hdr; + enum NXByteOrder host_byte_sex; + + host_byte_sex = NXHostByteOrder(); + hdr = cpu->tsh; + if(target_byte_sex == host_byte_sex) + swap_x86_state_hdr(&hdr, host_byte_sex); + + swap_x86_state_hdr(&cpu->tsh, target_byte_sex); + + if(hdr.flavor == x86_THREAD_STATE32) + swap_i386_thread_state(&cpu->uts.ts32, target_byte_sex); + else if(hdr.flavor == x86_THREAD_STATE64) + swap_x86_thread_state64(&cpu->uts.ts64, target_byte_sex); +} + +void +swap_x86_float_state( +x86_float_state_t *fpu, +enum NXByteOrder target_byte_sex) +{ + x86_state_hdr_t hdr; + enum NXByteOrder host_byte_sex; + + host_byte_sex = NXHostByteOrder(); + hdr = fpu->fsh; + if(target_byte_sex == host_byte_sex) + swap_x86_state_hdr(&hdr, host_byte_sex); + + swap_x86_state_hdr(&fpu->fsh, target_byte_sex); + +/* current i386 thread states */ +#if i386_THREAD_STATE == 1 + if(hdr.flavor == x86_FLOAT_STATE32) + swap_i386_float_state(&fpu->ufs.fs32, target_byte_sex); + else +#endif + if(hdr.flavor == x86_FLOAT_STATE64) + swap_x86_float_state64(&fpu->ufs.fs64, target_byte_sex); +} + +void +swap_x86_exception_state( +x86_exception_state_t *exc, +enum NXByteOrder target_byte_sex) +{ + x86_state_hdr_t hdr; + enum NXByteOrder host_byte_sex; + + host_byte_sex = NXHostByteOrder(); + hdr = exc->esh; + if(target_byte_sex == host_byte_sex) + swap_x86_state_hdr(&hdr, host_byte_sex); + + swap_x86_state_hdr(&exc->esh, target_byte_sex); + +/* current i386 thread states */ +#if i386_THREAD_STATE == 1 + if(hdr.flavor == x86_EXCEPTION_STATE32) + swap_i386_exception_state(&exc->ues.es32, target_byte_sex); + else +#endif + if(hdr.flavor == x86_EXCEPTION_STATE64) + swap_x86_exception_state64(&exc->ues.es64, target_byte_sex); +} + +void +swap_x86_debug_state32( +x86_debug_state32_t *debug, +enum NXByteOrder target_byte_sex) +{ + debug->dr0 = OSSwapInt32(debug->dr0); + debug->dr1 = OSSwapInt32(debug->dr1); + debug->dr2 = OSSwapInt32(debug->dr2); + debug->dr3 = OSSwapInt32(debug->dr3); + debug->dr4 = OSSwapInt32(debug->dr4); + debug->dr5 = OSSwapInt32(debug->dr5); + debug->dr6 = OSSwapInt32(debug->dr6); + debug->dr7 = OSSwapInt32(debug->dr7); +} + +void +swap_x86_debug_state64( +x86_debug_state64_t *debug, +enum NXByteOrder target_byte_sex) +{ + debug->dr0 = OSSwapInt64(debug->dr0); + debug->dr1 = OSSwapInt64(debug->dr1); + debug->dr2 = OSSwapInt64(debug->dr2); + debug->dr3 = OSSwapInt64(debug->dr3); + debug->dr4 = OSSwapInt64(debug->dr4); + debug->dr5 = OSSwapInt64(debug->dr5); + debug->dr6 = OSSwapInt64(debug->dr6); + debug->dr7 = OSSwapInt64(debug->dr7); +} + +void +swap_x86_debug_state( +x86_debug_state_t *debug, +enum NXByteOrder target_byte_sex) +{ + x86_state_hdr_t hdr; + enum NXByteOrder host_byte_sex; + + host_byte_sex = NXHostByteOrder(); + hdr = debug->dsh; + if(target_byte_sex == host_byte_sex) + swap_x86_state_hdr(&hdr, host_byte_sex); + + swap_x86_state_hdr(&debug->dsh, target_byte_sex); + + if(hdr.flavor == x86_DEBUG_STATE32) + swap_x86_debug_state32(&debug->uds.ds32, target_byte_sex); + else if(hdr.flavor == x86_DEBUG_STATE64) + swap_x86_debug_state64(&debug->uds.ds64, target_byte_sex); +} +#endif /* x86_THREAD_STATE64 */ + +/* current i386 thread states */ +#if i386_THREAD_STATE == 1 +void +swap_i386_float_state( +struct i386_float_state *fpu, +enum NXByteOrder target_byte_sex) +{ +#ifndef i386_EXCEPTION_STATE_COUNT + /* this routine does nothing as their are currently no non-byte fields */ +#else /* !defined(i386_EXCEPTION_STATE_COUNT) */ + struct swapped_fp_control { + union { + struct { + unsigned short + :3, + /*inf*/ :1, + rc :2, + pc :2, + :2, + precis :1, + undfl :1, + ovrfl :1, + zdiv :1, + denorm :1, + invalid :1; + } fields; + unsigned short half; + } u; + } sfpc; + + struct swapped_fp_status { + union { + struct { + unsigned short + busy :1, + c3 :1, + tos :3, + c2 :1, + c1 :1, + c0 :1, + errsumm :1, + stkflt :1, + precis :1, + undfl :1, + ovrfl :1, + zdiv :1, + denorm :1, + invalid :1; + } fields; + unsigned short half; + } u; + } sfps; + + enum NXByteOrder host_byte_sex; + + host_byte_sex = NXHostByteOrder(); + + fpu->fpu_reserved[0] = OSSwapInt32(fpu->fpu_reserved[0]); + fpu->fpu_reserved[1] = OSSwapInt32(fpu->fpu_reserved[1]); + + if(target_byte_sex == host_byte_sex){ + memcpy(&sfpc, &(fpu->fpu_fcw), + sizeof(struct swapped_fp_control)); + sfpc.u.half = OSSwapInt16(sfpc.u.half); + fpu->fpu_fcw.rc = sfpc.u.fields.rc; + fpu->fpu_fcw.pc = sfpc.u.fields.pc; + fpu->fpu_fcw.precis = sfpc.u.fields.precis; + fpu->fpu_fcw.undfl = sfpc.u.fields.undfl; + fpu->fpu_fcw.ovrfl = sfpc.u.fields.ovrfl; + fpu->fpu_fcw.zdiv = sfpc.u.fields.zdiv; + fpu->fpu_fcw.denorm = sfpc.u.fields.denorm; + fpu->fpu_fcw.invalid = sfpc.u.fields.invalid; + + memcpy(&sfps, &(fpu->fpu_fsw), + sizeof(struct swapped_fp_status)); + sfps.u.half = OSSwapInt16(sfps.u.half); + fpu->fpu_fsw.busy = sfps.u.fields.busy; + fpu->fpu_fsw.c3 = sfps.u.fields.c3; + fpu->fpu_fsw.tos = sfps.u.fields.tos; + fpu->fpu_fsw.c2 = sfps.u.fields.c2; + fpu->fpu_fsw.c1 = sfps.u.fields.c1; + fpu->fpu_fsw.c0 = sfps.u.fields.c0; + fpu->fpu_fsw.errsumm = sfps.u.fields.errsumm; + fpu->fpu_fsw.stkflt = sfps.u.fields.stkflt; + fpu->fpu_fsw.precis = sfps.u.fields.precis; + fpu->fpu_fsw.undfl = sfps.u.fields.undfl; + fpu->fpu_fsw.ovrfl = sfps.u.fields.ovrfl; + fpu->fpu_fsw.zdiv = sfps.u.fields.zdiv; + fpu->fpu_fsw.denorm = sfps.u.fields.denorm; + fpu->fpu_fsw.invalid = sfps.u.fields.invalid; + } + else{ + sfpc.u.fields.rc = fpu->fpu_fcw.rc; + sfpc.u.fields.pc = fpu->fpu_fcw.pc; + sfpc.u.fields.precis = fpu->fpu_fcw.precis; + sfpc.u.fields.undfl = fpu->fpu_fcw.undfl; + sfpc.u.fields.ovrfl = fpu->fpu_fcw.ovrfl; + sfpc.u.fields.zdiv = fpu->fpu_fcw.zdiv; + sfpc.u.fields.denorm = fpu->fpu_fcw.denorm; + sfpc.u.fields.invalid = fpu->fpu_fcw.invalid; + sfpc.u.half = OSSwapInt16(sfpc.u.half); + memcpy(&(fpu->fpu_fcw), &sfpc, + sizeof(struct swapped_fp_control)); + + sfps.u.fields.busy = fpu->fpu_fsw.busy; + sfps.u.fields.c3 = fpu->fpu_fsw.c3; + sfps.u.fields.tos = fpu->fpu_fsw.tos; + sfps.u.fields.c2 = fpu->fpu_fsw.c2; + sfps.u.fields.c1 = fpu->fpu_fsw.c1; + sfps.u.fields.c0 = fpu->fpu_fsw.c0; + sfps.u.fields.errsumm = fpu->fpu_fsw.errsumm; + sfps.u.fields.stkflt = fpu->fpu_fsw.stkflt; + sfps.u.fields.precis = fpu->fpu_fsw.precis; + sfps.u.fields.undfl = fpu->fpu_fsw.undfl; + sfps.u.fields.ovrfl = fpu->fpu_fsw.ovrfl; + sfps.u.fields.zdiv = fpu->fpu_fsw.zdiv; + sfps.u.fields.denorm = fpu->fpu_fsw.denorm; + sfps.u.fields.invalid = fpu->fpu_fsw.invalid; + sfps.u.half = OSSwapInt16(sfps.u.half); + memcpy(&(fpu->fpu_fsw), &sfps, + sizeof(struct swapped_fp_status)); + } + fpu->fpu_fop = OSSwapInt16(fpu->fpu_fop); + fpu->fpu_ip = OSSwapInt32(fpu->fpu_ip); + fpu->fpu_cs = OSSwapInt16(fpu->fpu_cs); + fpu->fpu_rsrv2 = OSSwapInt16(fpu->fpu_rsrv2); + fpu->fpu_dp = OSSwapInt32(fpu->fpu_dp); + fpu->fpu_ds = OSSwapInt16(fpu->fpu_ds); + fpu->fpu_rsrv3 = OSSwapInt16(fpu->fpu_rsrv3); + fpu->fpu_mxcsr = OSSwapInt32(fpu->fpu_mxcsr); + fpu->fpu_mxcsrmask = OSSwapInt32(fpu->fpu_mxcsrmask); + fpu->fpu_reserved1 = OSSwapInt32(fpu->fpu_reserved1); + +#endif /* !defined(i386_EXCEPTION_STATE_COUNT) */ +} + +void +swap_i386_exception_state( +i386_exception_state_t *exc, +enum NXByteOrder target_byte_sex) +{ + exc->trapno = OSSwapInt32(exc->trapno); + exc->err = OSSwapInt32(exc->err); + exc->faultvaddr = OSSwapInt32(exc->faultvaddr); +} +#endif /* i386_THREAD_STATE == 1 */ + +/* i386 thread states on older releases */ +#if i386_THREAD_STATE == -1 +void +swap_i386_thread_fpstate( +i386_thread_fpstate_t *fpu, +enum NXByteOrder target_byte_sex) +{ + struct swapped_fp_control { + union { + struct { + unsigned short + :3, + /*inf*/ :1, + rc :2, + pc :2, + :2, + precis :1, + undfl :1, + ovrfl :1, + zdiv :1, + denorm :1, + invalid :1; + } fields; + unsigned short half; + } u; + } sfpc; + + struct swapped_fp_status { + union { + struct { + unsigned short + busy :1, + c3 :1, + tos :3, + c2 :1, + c1 :1, + c0 :1, + errsumm :1, + stkflt :1, + precis :1, + undfl :1, + ovrfl :1, + zdiv :1, + denorm :1, + invalid :1; + } fields; + unsigned short half; + } u; + } sfps; + + struct swapped_fp_tag { + union { + struct { + unsigned short + tag7 :2, + tag6 :2, + tag5 :2, + tag4 :2, + tag3 :2, + tag2 :2, + tag1 :2, + tag0 :2; + } fields; + unsigned short half; + } u; + } sfpt; + + struct swapped_fp_data_reg { + unsigned short mant; + unsigned short mant1 :16, + mant2 :16, + mant3 :16; + union { + struct { + unsigned short sign :1, + exp :15; + } fields; + unsigned short half; + } u; + } sfpd; + + struct swapped_sel { + union { + struct { + unsigned short + index :13, + ti :1, + rpl :2; + } fields; + unsigned short half; + } u; + } ss; + + enum NXByteOrder host_byte_sex; + int i; + + host_byte_sex = NXHostByteOrder(); + + fpu->environ.ip = OSSwapInt32(fpu->environ.ip); + fpu->environ.opcode = OSSwapInt16(fpu->environ.opcode); + fpu->environ.dp = OSSwapInt32(fpu->environ.dp); + + if(target_byte_sex == host_byte_sex){ + memcpy(&sfpc, &(fpu->environ.control), + sizeof(struct swapped_fp_control)); + sfpc.u.half = OSSwapInt16(sfpc.u.half); + fpu->environ.control.rc = sfpc.u.fields.rc; + fpu->environ.control.pc = sfpc.u.fields.pc; + fpu->environ.control.precis = sfpc.u.fields.precis; + fpu->environ.control.undfl = sfpc.u.fields.undfl; + fpu->environ.control.ovrfl = sfpc.u.fields.ovrfl; + fpu->environ.control.zdiv = sfpc.u.fields.zdiv; + fpu->environ.control.denorm = sfpc.u.fields.denorm; + fpu->environ.control.invalid = sfpc.u.fields.invalid; + + memcpy(&sfps, &(fpu->environ.status), + sizeof(struct swapped_fp_status)); + sfps.u.half = OSSwapInt16(sfps.u.half); + fpu->environ.status.busy = sfps.u.fields.busy; + fpu->environ.status.c3 = sfps.u.fields.c3; + fpu->environ.status.tos = sfps.u.fields.tos; + fpu->environ.status.c2 = sfps.u.fields.c2; + fpu->environ.status.c1 = sfps.u.fields.c1; + fpu->environ.status.c0 = sfps.u.fields.c0; + fpu->environ.status.errsumm = sfps.u.fields.errsumm; + fpu->environ.status.stkflt = sfps.u.fields.stkflt; + fpu->environ.status.precis = sfps.u.fields.precis; + fpu->environ.status.undfl = sfps.u.fields.undfl; + fpu->environ.status.ovrfl = sfps.u.fields.ovrfl; + fpu->environ.status.zdiv = sfps.u.fields.zdiv; + fpu->environ.status.denorm = sfps.u.fields.denorm; + fpu->environ.status.invalid = sfps.u.fields.invalid; + + memcpy(&sfpt, &(fpu->environ.tag), + sizeof(struct swapped_fp_tag)); + sfpt.u.half = OSSwapInt16(sfpt.u.half); + fpu->environ.tag.tag7 = sfpt.u.fields.tag7; + fpu->environ.tag.tag6 = sfpt.u.fields.tag6; + fpu->environ.tag.tag5 = sfpt.u.fields.tag5; + fpu->environ.tag.tag4 = sfpt.u.fields.tag4; + fpu->environ.tag.tag3 = sfpt.u.fields.tag3; + fpu->environ.tag.tag2 = sfpt.u.fields.tag2; + fpu->environ.tag.tag1 = sfpt.u.fields.tag1; + fpu->environ.tag.tag0 = sfpt.u.fields.tag0; + + memcpy(&ss, &(fpu->environ.cs), + sizeof(struct swapped_sel)); + ss.u.half = OSSwapInt16(ss.u.half); + fpu->environ.cs.index = ss.u.fields.index; + fpu->environ.cs.ti = ss.u.fields.ti; + fpu->environ.cs.rpl = ss.u.fields.rpl; + + memcpy(&ss, &(fpu->environ.ds), + sizeof(struct swapped_sel)); + ss.u.half = OSSwapInt16(ss.u.half); + fpu->environ.ds.index = ss.u.fields.index; + fpu->environ.ds.ti = ss.u.fields.ti; + fpu->environ.ds.rpl = ss.u.fields.rpl; + + for(i = 0; i < 8; i++){ + memcpy(&sfpd, &(fpu->stack.ST[i]), + sizeof(struct swapped_fp_data_reg)); + fpu->stack.ST[i].mant = OSSwapInt16(sfpd.mant); + fpu->stack.ST[i].mant1 = OSSwapInt16(sfpd.mant1); + fpu->stack.ST[i].mant2 = OSSwapInt16(sfpd.mant2); + fpu->stack.ST[i].mant3 = OSSwapInt16(sfpd.mant3); + sfpd.u.half = OSSwapInt16(sfpd.u.half); + fpu->stack.ST[i].exp = sfpd.u.fields.exp; + fpu->stack.ST[i].sign = sfpd.u.fields.sign; + } + } + else{ + sfpc.u.fields.rc = fpu->environ.control.rc; + sfpc.u.fields.pc = fpu->environ.control.pc; + sfpc.u.fields.precis = fpu->environ.control.precis; + sfpc.u.fields.undfl = fpu->environ.control.undfl; + sfpc.u.fields.ovrfl = fpu->environ.control.ovrfl; + sfpc.u.fields.zdiv = fpu->environ.control.zdiv; + sfpc.u.fields.denorm = fpu->environ.control.denorm; + sfpc.u.fields.invalid = fpu->environ.control.invalid; + sfpc.u.half = OSSwapInt16(sfpc.u.half); + memcpy(&(fpu->environ.control), &sfpc, + sizeof(struct swapped_fp_control)); + + sfps.u.fields.busy = fpu->environ.status.busy; + sfps.u.fields.c3 = fpu->environ.status.c3; + sfps.u.fields.tos = fpu->environ.status.tos; + sfps.u.fields.c2 = fpu->environ.status.c2; + sfps.u.fields.c1 = fpu->environ.status.c1; + sfps.u.fields.c0 = fpu->environ.status.c0; + sfps.u.fields.errsumm = fpu->environ.status.errsumm; + sfps.u.fields.stkflt = fpu->environ.status.stkflt; + sfps.u.fields.precis = fpu->environ.status.precis; + sfps.u.fields.undfl = fpu->environ.status.undfl; + sfps.u.fields.ovrfl = fpu->environ.status.ovrfl; + sfps.u.fields.zdiv = fpu->environ.status.zdiv; + sfps.u.fields.denorm = fpu->environ.status.denorm; + sfps.u.fields.invalid = fpu->environ.status.invalid; + sfps.u.half = OSSwapInt16(sfps.u.half); + memcpy(&(fpu->environ.status), &sfps, + sizeof(struct swapped_fp_status)); + + sfpt.u.fields.tag7 = fpu->environ.tag.tag7; + sfpt.u.fields.tag6 = fpu->environ.tag.tag6; + sfpt.u.fields.tag5 = fpu->environ.tag.tag5; + sfpt.u.fields.tag4 = fpu->environ.tag.tag4; + sfpt.u.fields.tag3 = fpu->environ.tag.tag3; + sfpt.u.fields.tag2 = fpu->environ.tag.tag2; + sfpt.u.fields.tag1 = fpu->environ.tag.tag1; + sfpt.u.fields.tag0 = fpu->environ.tag.tag0; + sfpt.u.half = OSSwapInt16(sfpt.u.half); + memcpy(&(fpu->environ.tag), &sfpt, + sizeof(struct swapped_fp_tag)); + + ss.u.fields.index = fpu->environ.cs.index; + ss.u.fields.ti = fpu->environ.cs.ti; + ss.u.fields.rpl = fpu->environ.cs.rpl; + ss.u.half = OSSwapInt16(ss.u.half); + memcpy(&(fpu->environ.cs), &ss, + sizeof(struct swapped_sel)); + + ss.u.fields.index = fpu->environ.ds.index; + ss.u.fields.ti = fpu->environ.ds.ti; + ss.u.fields.rpl = fpu->environ.ds.rpl; + ss.u.half = OSSwapInt16(ss.u.half); + memcpy(&(fpu->environ.cs), &ss, + sizeof(struct swapped_sel)); + + for(i = 0; i < 8; i++){ + sfpd.mant = OSSwapInt16(fpu->stack.ST[i].mant); + sfpd.mant1 = OSSwapInt16(fpu->stack.ST[i].mant1); + sfpd.mant2 = OSSwapInt16(fpu->stack.ST[i].mant2); + sfpd.mant3 = OSSwapInt16(fpu->stack.ST[i].mant3); + sfpd.u.fields.exp = fpu->stack.ST[i].exp; + sfpd.u.fields.sign = fpu->stack.ST[i].sign; + sfpd.u.half = OSSwapInt16(sfpd.u.half); + memcpy(&(fpu->stack.ST[i]), &sfpd, + sizeof(struct swapped_fp_data_reg)); + } + } +} + +void +swap_i386_thread_exceptstate( +i386_thread_exceptstate_t *exc, +enum NXByteOrder target_byte_sex) +{ + struct swapped_err_code { + union { + struct err_code_normal { + unsigned int :16, + index :13, + tbl :2, + ext :1; + } normal; + struct err_code_pgfault { + unsigned int :29, + user :1, + wrtflt :1, + prot :1; + } pgfault; + uint32_t word; + } u; + } sec; + uint32_t word; + enum NXByteOrder host_byte_sex; + + host_byte_sex = NXHostByteOrder(); + + exc->trapno = OSSwapInt32(exc->trapno); + if(exc->trapno == 14){ + if(target_byte_sex == host_byte_sex){ + memcpy(&sec, &(exc->err), sizeof(struct swapped_err_code)); + sec.u.word = OSSwapInt32(sec.u.word); + exc->err.pgfault.user = sec.u.pgfault.user; + exc->err.pgfault.wrtflt = sec.u.pgfault.wrtflt; + exc->err.pgfault.prot = sec.u.pgfault.prot; + } + else{ + sec.u.pgfault.prot = exc->err.pgfault.prot; + sec.u.pgfault.wrtflt = exc->err.pgfault.wrtflt; + sec.u.pgfault.user = exc->err.pgfault.user; + sec.u.word = OSSwapInt32(sec.u.word); + memcpy(&(exc->err), &sec, sizeof(struct swapped_err_code)); + } + } + else{ + if(target_byte_sex == host_byte_sex){ + memcpy(&sec, &(exc->err), sizeof(struct swapped_err_code)); + sec.u.word = OSSwapInt32(sec.u.word); + word = sec.u.normal.index; + exc->err.normal.index = OSSwapInt32(word); + exc->err.normal.tbl = sec.u.normal.tbl; + exc->err.normal.ext = sec.u.normal.ext; + } + else{ + sec.u.normal.ext = exc->err.normal.ext; + sec.u.normal.tbl = exc->err.normal.tbl; + word = exc->err.normal.index; + sec.u.normal.index = OSSwapInt32(word); + sec.u.word = OSSwapInt32(sec.u.word); + memcpy(&(exc->err), &sec, sizeof(struct swapped_err_code)); + } + } +} + +void +swap_i386_thread_cthreadstate( +i386_thread_cthreadstate_t *user, +enum NXByteOrder target_byte_sex) +{ + user->self = OSSwapInt32(user->self); +} +#endif /* i386_THREAD_STATE == -1 */ +#endif /* !defined(RLD) */ diff --git a/cctools/libmacho/i860_swap.c b/cctools/libmacho/i860_swap.c new file mode 100644 index 0000000..ffed8d7 --- /dev/null +++ b/cctools/libmacho/i860_swap.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef RLD +#import + +void +swap_i860_thread_state_regs( +struct i860_thread_state_regs *cpu, +enum NXByteOrder target_byte_sex) +{ + int i; + + for(i = 0; i < 31; i++) + cpu->ireg[i] = OSSwapInt32(cpu->ireg[i]); + for(i = 0; i < 30; i++) + cpu->freg[i] = OSSwapInt32(cpu->freg[i]); + cpu->psr = OSSwapInt32(cpu->psr); + cpu->epsr = OSSwapInt32(cpu->epsr); + cpu->db = OSSwapInt32(cpu->db); + cpu->pc = OSSwapInt32(cpu->pc); + cpu->_padding_ = OSSwapInt32(cpu->_padding_); + cpu->Mres3 = OSSwapInt64(cpu->Mres3); + cpu->Ares3 = OSSwapInt64(cpu->Ares3); + cpu->Mres2 = OSSwapInt64(cpu->Mres2); + cpu->Ares2 = OSSwapInt64(cpu->Ares2); + cpu->Mres1 = OSSwapInt64(cpu->Mres1); + cpu->Ares1 = OSSwapInt64(cpu->Ares1); + cpu->Ires1 = OSSwapInt64(cpu->Ires1); + cpu->Lres3m = OSSwapInt64(cpu->Lres3m); + cpu->Lres2m = OSSwapInt64(cpu->Lres2m); + cpu->Lres1m = OSSwapInt64(cpu->Lres1m); + cpu->KR = OSSwapInt64(cpu->KR); + cpu->KI = OSSwapInt64(cpu->KI); + cpu->T = OSSwapInt64(cpu->T); + cpu->Fsr3 = OSSwapInt32(cpu->Fsr3); + cpu->Fsr2 = OSSwapInt32(cpu->Fsr2); + cpu->Fsr1 = OSSwapInt32(cpu->Fsr1); + cpu->Mergelo32 = OSSwapInt32(cpu->Mergelo32); + cpu->Mergehi32 = OSSwapInt32(cpu->Mergehi32); +} +#endif /* !defined(RLD) */ diff --git a/cctools/libmacho/m68k_swap.c b/cctools/libmacho/m68k_swap.c new file mode 100644 index 0000000..79af1f5 --- /dev/null +++ b/cctools/libmacho/m68k_swap.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef RLD +#import + +void +swap_m68k_thread_state_regs( +struct m68k_thread_state_regs *cpu, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + + for(i = 0; i < 8; i++) + cpu->dreg[i] = OSSwapInt32(cpu->dreg[i]); + for(i = 0; i < 8; i++) + cpu->areg[i] = OSSwapInt32(cpu->areg[i]); + cpu->pad0 = OSSwapInt16(cpu->pad0); + cpu->sr = OSSwapInt16(cpu->sr); + cpu->pc = OSSwapInt32(cpu->pc); +} + +void +swap_m68k_thread_state_68882( +struct m68k_thread_state_68882 *fpu, +enum NXByteOrder target_byte_sex) +{ + uint32_t i, tmp; + + for(i = 0; i < 8; i++){ + tmp = OSSwapInt32(fpu->regs[i].fp[0]); + fpu->regs[i].fp[1] = OSSwapInt32(fpu->regs[i].fp[1]); + fpu->regs[i].fp[0] = OSSwapInt32(fpu->regs[i].fp[2]); + fpu->regs[i].fp[2] = tmp; + } + fpu->cr = OSSwapInt32(fpu->cr); + fpu->sr = OSSwapInt32(fpu->sr); + fpu->iar = OSSwapInt32(fpu->iar); + fpu->state = OSSwapInt32(fpu->state); +} + +void +swap_m68k_thread_state_user_reg( +struct m68k_thread_state_user_reg *user_reg, +enum NXByteOrder target_byte_sex) +{ + user_reg->user_reg = OSSwapInt32(user_reg->user_reg); +} +#endif /* !defined(RLD) */ diff --git a/cctools/libmacho/m88k_swap.c b/cctools/libmacho/m88k_swap.c new file mode 100644 index 0000000..dde84e3 --- /dev/null +++ b/cctools/libmacho/m88k_swap.c @@ -0,0 +1,430 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef RLD +#include +#import +#import + +void +swap_m88k_thread_state_grf_t( +m88k_thread_state_grf_t *cpu, +enum NXByteOrder target_byte_sex) +{ + cpu->r1 = OSSwapInt32(cpu->r1); + cpu->r2 = OSSwapInt32(cpu->r2); + cpu->r3 = OSSwapInt32(cpu->r3); + cpu->r4 = OSSwapInt32(cpu->r4); + cpu->r5 = OSSwapInt32(cpu->r5); + cpu->r6 = OSSwapInt32(cpu->r6); + cpu->r7 = OSSwapInt32(cpu->r7); + cpu->r8 = OSSwapInt32(cpu->r8); + cpu->r9 = OSSwapInt32(cpu->r9); + cpu->r10 = OSSwapInt32(cpu->r10); + cpu->r11 = OSSwapInt32(cpu->r11); + cpu->r12 = OSSwapInt32(cpu->r12); + cpu->r13 = OSSwapInt32(cpu->r13); + cpu->r14 = OSSwapInt32(cpu->r14); + cpu->r15 = OSSwapInt32(cpu->r15); + cpu->r16 = OSSwapInt32(cpu->r16); + cpu->r17 = OSSwapInt32(cpu->r17); + cpu->r18 = OSSwapInt32(cpu->r18); + cpu->r19 = OSSwapInt32(cpu->r19); + cpu->r20 = OSSwapInt32(cpu->r20); + cpu->r21 = OSSwapInt32(cpu->r21); + cpu->r22 = OSSwapInt32(cpu->r22); + cpu->r23 = OSSwapInt32(cpu->r23); + cpu->r24 = OSSwapInt32(cpu->r24); + cpu->r25 = OSSwapInt32(cpu->r25); + cpu->r26 = OSSwapInt32(cpu->r26); + cpu->r27 = OSSwapInt32(cpu->r27); + cpu->r28 = OSSwapInt32(cpu->r28); + cpu->r29 = OSSwapInt32(cpu->r29); + cpu->r30 = OSSwapInt32(cpu->r30); + cpu->r31 = OSSwapInt32(cpu->r31); + cpu->xip = OSSwapInt32(cpu->xip); + cpu->xip_in_bd = OSSwapInt32(cpu->xip_in_bd); + cpu->nip = OSSwapInt32(cpu->nip); +} + +void +swap_m88k_thread_state_xrf_t( +m88k_thread_state_xrf_t *fpu, +enum NXByteOrder target_byte_sex) +{ + enum NXByteOrder host_byte_sex; + + struct swapped_m88k_fpsr { + union { + struct { + unsigned afinx:BIT_WIDTH(0); + unsigned afovf:BIT_WIDTH(1); + unsigned afunf:BIT_WIDTH(2); + unsigned afdvz:BIT_WIDTH(3); + unsigned afinv:BIT_WIDTH(4); + unsigned :BITS_WIDTH(15,5); + unsigned xmod:BIT_WIDTH(16); + unsigned :BITS_WIDTH(31,17); + } fields; + uint32_t word; + } u; + } ssr; + struct swapped_m88k_fpcr { + union { + struct { + unsigned efinx:BIT_WIDTH(0); + unsigned efovf:BIT_WIDTH(1); + unsigned efunf:BIT_WIDTH(2); + unsigned efdvz:BIT_WIDTH(3); + unsigned efinv:BIT_WIDTH(4); + unsigned :BITS_WIDTH(13,5); + m88k_fpcr_rm_t rm:BITS_WIDTH(15,14); + unsigned :BITS_WIDTH(31,16); + } fields; + uint32_t word; + } u; + } scr; + + host_byte_sex = NXHostByteOrder(); + + fpu->x1.x[0] = OSSwapInt32(fpu->x1.x[0]); + fpu->x1.x[1] = OSSwapInt32(fpu->x1.x[1]); + fpu->x1.x[2] = OSSwapInt32(fpu->x1.x[2]); + fpu->x1.x[3] = OSSwapInt32(fpu->x1.x[3]); + fpu->x2.x[0] = OSSwapInt32(fpu->x2.x[0]); + fpu->x2.x[1] = OSSwapInt32(fpu->x2.x[1]); + fpu->x2.x[2] = OSSwapInt32(fpu->x2.x[2]); + fpu->x2.x[3] = OSSwapInt32(fpu->x2.x[3]); + fpu->x3.x[0] = OSSwapInt32(fpu->x3.x[0]); + fpu->x3.x[1] = OSSwapInt32(fpu->x3.x[1]); + fpu->x3.x[2] = OSSwapInt32(fpu->x3.x[2]); + fpu->x3.x[3] = OSSwapInt32(fpu->x3.x[3]); + fpu->x4.x[0] = OSSwapInt32(fpu->x4.x[0]); + fpu->x4.x[1] = OSSwapInt32(fpu->x4.x[1]); + fpu->x4.x[2] = OSSwapInt32(fpu->x4.x[2]); + fpu->x4.x[3] = OSSwapInt32(fpu->x4.x[3]); + fpu->x5.x[0] = OSSwapInt32(fpu->x5.x[0]); + fpu->x5.x[1] = OSSwapInt32(fpu->x5.x[1]); + fpu->x5.x[2] = OSSwapInt32(fpu->x5.x[2]); + fpu->x5.x[3] = OSSwapInt32(fpu->x5.x[3]); + fpu->x6.x[0] = OSSwapInt32(fpu->x6.x[0]); + fpu->x6.x[1] = OSSwapInt32(fpu->x6.x[1]); + fpu->x6.x[2] = OSSwapInt32(fpu->x6.x[2]); + fpu->x6.x[3] = OSSwapInt32(fpu->x6.x[3]); + fpu->x7.x[0] = OSSwapInt32(fpu->x7.x[0]); + fpu->x7.x[1] = OSSwapInt32(fpu->x7.x[1]); + fpu->x7.x[2] = OSSwapInt32(fpu->x7.x[2]); + fpu->x7.x[3] = OSSwapInt32(fpu->x7.x[3]); + fpu->x8.x[0] = OSSwapInt32(fpu->x8.x[0]); + fpu->x8.x[1] = OSSwapInt32(fpu->x8.x[1]); + fpu->x8.x[2] = OSSwapInt32(fpu->x8.x[2]); + fpu->x8.x[3] = OSSwapInt32(fpu->x8.x[3]); + fpu->x9.x[0] = OSSwapInt32(fpu->x9.x[0]); + fpu->x9.x[1] = OSSwapInt32(fpu->x9.x[1]); + fpu->x9.x[2] = OSSwapInt32(fpu->x9.x[2]); + fpu->x9.x[3] = OSSwapInt32(fpu->x9.x[3]); + fpu->x10.x[0] = OSSwapInt32(fpu->x10.x[0]); + fpu->x10.x[1] = OSSwapInt32(fpu->x10.x[1]); + fpu->x10.x[2] = OSSwapInt32(fpu->x10.x[2]); + fpu->x10.x[3] = OSSwapInt32(fpu->x10.x[3]); + fpu->x11.x[0] = OSSwapInt32(fpu->x11.x[0]); + fpu->x11.x[1] = OSSwapInt32(fpu->x11.x[1]); + fpu->x11.x[2] = OSSwapInt32(fpu->x11.x[2]); + fpu->x11.x[3] = OSSwapInt32(fpu->x11.x[3]); + fpu->x12.x[0] = OSSwapInt32(fpu->x12.x[0]); + fpu->x12.x[1] = OSSwapInt32(fpu->x12.x[1]); + fpu->x12.x[2] = OSSwapInt32(fpu->x12.x[2]); + fpu->x12.x[3] = OSSwapInt32(fpu->x12.x[3]); + fpu->x13.x[0] = OSSwapInt32(fpu->x13.x[0]); + fpu->x13.x[1] = OSSwapInt32(fpu->x13.x[1]); + fpu->x13.x[2] = OSSwapInt32(fpu->x13.x[2]); + fpu->x13.x[3] = OSSwapInt32(fpu->x13.x[3]); + fpu->x14.x[0] = OSSwapInt32(fpu->x14.x[0]); + fpu->x14.x[1] = OSSwapInt32(fpu->x14.x[1]); + fpu->x14.x[2] = OSSwapInt32(fpu->x14.x[2]); + fpu->x14.x[3] = OSSwapInt32(fpu->x14.x[3]); + fpu->x15.x[0] = OSSwapInt32(fpu->x15.x[0]); + fpu->x15.x[1] = OSSwapInt32(fpu->x15.x[1]); + fpu->x15.x[2] = OSSwapInt32(fpu->x15.x[2]); + fpu->x15.x[3] = OSSwapInt32(fpu->x15.x[3]); + fpu->x16.x[0] = OSSwapInt32(fpu->x16.x[0]); + fpu->x16.x[1] = OSSwapInt32(fpu->x16.x[1]); + fpu->x16.x[2] = OSSwapInt32(fpu->x16.x[2]); + fpu->x16.x[3] = OSSwapInt32(fpu->x16.x[3]); + fpu->x17.x[0] = OSSwapInt32(fpu->x17.x[0]); + fpu->x17.x[1] = OSSwapInt32(fpu->x17.x[1]); + fpu->x17.x[2] = OSSwapInt32(fpu->x17.x[2]); + fpu->x17.x[3] = OSSwapInt32(fpu->x17.x[3]); + fpu->x18.x[0] = OSSwapInt32(fpu->x18.x[0]); + fpu->x18.x[1] = OSSwapInt32(fpu->x18.x[1]); + fpu->x18.x[2] = OSSwapInt32(fpu->x18.x[2]); + fpu->x18.x[3] = OSSwapInt32(fpu->x18.x[3]); + fpu->x19.x[0] = OSSwapInt32(fpu->x19.x[0]); + fpu->x19.x[1] = OSSwapInt32(fpu->x19.x[1]); + fpu->x19.x[2] = OSSwapInt32(fpu->x19.x[2]); + fpu->x19.x[3] = OSSwapInt32(fpu->x19.x[3]); + fpu->x20.x[0] = OSSwapInt32(fpu->x20.x[0]); + fpu->x20.x[1] = OSSwapInt32(fpu->x20.x[1]); + fpu->x20.x[2] = OSSwapInt32(fpu->x20.x[2]); + fpu->x20.x[3] = OSSwapInt32(fpu->x20.x[3]); + fpu->x21.x[0] = OSSwapInt32(fpu->x21.x[0]); + fpu->x21.x[1] = OSSwapInt32(fpu->x21.x[1]); + fpu->x21.x[2] = OSSwapInt32(fpu->x21.x[2]); + fpu->x21.x[3] = OSSwapInt32(fpu->x21.x[3]); + fpu->x22.x[0] = OSSwapInt32(fpu->x22.x[0]); + fpu->x22.x[1] = OSSwapInt32(fpu->x22.x[1]); + fpu->x22.x[2] = OSSwapInt32(fpu->x22.x[2]); + fpu->x22.x[3] = OSSwapInt32(fpu->x22.x[3]); + fpu->x23.x[0] = OSSwapInt32(fpu->x23.x[0]); + fpu->x23.x[1] = OSSwapInt32(fpu->x23.x[1]); + fpu->x23.x[2] = OSSwapInt32(fpu->x23.x[2]); + fpu->x23.x[3] = OSSwapInt32(fpu->x23.x[3]); + fpu->x24.x[0] = OSSwapInt32(fpu->x24.x[0]); + fpu->x24.x[1] = OSSwapInt32(fpu->x24.x[1]); + fpu->x24.x[2] = OSSwapInt32(fpu->x24.x[2]); + fpu->x24.x[3] = OSSwapInt32(fpu->x24.x[3]); + fpu->x25.x[0] = OSSwapInt32(fpu->x25.x[0]); + fpu->x25.x[1] = OSSwapInt32(fpu->x25.x[1]); + fpu->x25.x[2] = OSSwapInt32(fpu->x25.x[2]); + fpu->x25.x[3] = OSSwapInt32(fpu->x25.x[3]); + fpu->x26.x[0] = OSSwapInt32(fpu->x26.x[0]); + fpu->x26.x[1] = OSSwapInt32(fpu->x26.x[1]); + fpu->x26.x[2] = OSSwapInt32(fpu->x26.x[2]); + fpu->x26.x[3] = OSSwapInt32(fpu->x26.x[3]); + fpu->x27.x[0] = OSSwapInt32(fpu->x27.x[0]); + fpu->x27.x[1] = OSSwapInt32(fpu->x27.x[1]); + fpu->x27.x[2] = OSSwapInt32(fpu->x27.x[2]); + fpu->x27.x[3] = OSSwapInt32(fpu->x27.x[3]); + fpu->x28.x[0] = OSSwapInt32(fpu->x28.x[0]); + fpu->x28.x[1] = OSSwapInt32(fpu->x28.x[1]); + fpu->x28.x[2] = OSSwapInt32(fpu->x28.x[2]); + fpu->x28.x[3] = OSSwapInt32(fpu->x28.x[3]); + fpu->x29.x[0] = OSSwapInt32(fpu->x29.x[0]); + fpu->x29.x[1] = OSSwapInt32(fpu->x29.x[1]); + fpu->x29.x[2] = OSSwapInt32(fpu->x29.x[2]); + fpu->x29.x[3] = OSSwapInt32(fpu->x29.x[3]); + fpu->x30.x[0] = OSSwapInt32(fpu->x30.x[0]); + fpu->x30.x[1] = OSSwapInt32(fpu->x30.x[1]); + fpu->x30.x[2] = OSSwapInt32(fpu->x30.x[2]); + fpu->x30.x[3] = OSSwapInt32(fpu->x30.x[3]); + fpu->x31.x[0] = OSSwapInt32(fpu->x31.x[0]); + fpu->x31.x[1] = OSSwapInt32(fpu->x31.x[1]); + fpu->x31.x[2] = OSSwapInt32(fpu->x31.x[2]); + fpu->x31.x[3] = OSSwapInt32(fpu->x31.x[3]); + + if(target_byte_sex == host_byte_sex){ + memcpy(&ssr, &(fpu->fpsr), sizeof(struct swapped_m88k_fpsr)); + ssr.u.word = OSSwapInt32(ssr.u.word); + fpu->fpsr.afinx = ssr.u.fields.afinx; + fpu->fpsr.afovf = ssr.u.fields.afovf; + fpu->fpsr.afunf = ssr.u.fields.afunf; + fpu->fpsr.afdvz = ssr.u.fields.afdvz; + fpu->fpsr.afinv = ssr.u.fields.afinv; + fpu->fpsr.xmod = ssr.u.fields.xmod; + + memcpy(&scr, &(fpu->fpcr), sizeof(struct swapped_m88k_fpcr)); + scr.u.word = OSSwapInt32(scr.u.word); + fpu->fpcr.efinx = scr.u.fields.efinx; + fpu->fpcr.efovf = scr.u.fields.efovf; + fpu->fpcr.efunf = scr.u.fields.efunf; + fpu->fpcr.efdvz = scr.u.fields.efdvz; + fpu->fpcr.efinv = scr.u.fields.efinv; + fpu->fpcr.rm = scr.u.fields.rm; + } + else{ + ssr.u.fields.afinx = fpu->fpsr.afinx; + ssr.u.fields.afovf = fpu->fpsr.afovf; + ssr.u.fields.afunf = fpu->fpsr.afunf; + ssr.u.fields.afdvz = fpu->fpsr.afdvz; + ssr.u.fields.afinv = fpu->fpsr.afinv; + ssr.u.fields.xmod = fpu->fpsr.xmod; + ssr.u.word = OSSwapInt32(ssr.u.word); + memcpy(&(fpu->fpsr), &ssr, sizeof(struct swapped_m88k_fpsr)); + + scr.u.fields.efinx = fpu->fpcr.efinx; + scr.u.fields.efovf = fpu->fpcr.efovf; + scr.u.fields.efunf = fpu->fpcr.efunf; + scr.u.fields.efdvz = fpu->fpcr.efdvz; + scr.u.fields.efinv = fpu->fpcr.efinv; + scr.u.fields.rm = fpu->fpcr.rm; + scr.u.word = OSSwapInt32(scr.u.word); + memcpy(&(fpu->fpcr), &scr, sizeof(struct swapped_m88k_fpcr)); + } +} + +void +swap_m88k_thread_state_user_t( +m88k_thread_state_user_t *user, +enum NXByteOrder target_byte_sex) +{ + user->user = OSSwapInt32(user->user); +} + +void +swap_m88110_thread_state_impl_t( +m88110_thread_state_impl_t *spu, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + enum NXByteOrder host_byte_sex; + + struct swapped_m88110_bp_ctrl { + union { + struct { + unsigned v:BIT_WIDTH(0); + m88110_match_t addr_match:BITS_WIDTH(12,1); + unsigned :BITS_WIDTH(26,13); + unsigned rwm:BIT_WIDTH(27); + unsigned rw:BIT_WIDTH(28); + unsigned :BITS_WIDTH(31,29); + } fields; + uint32_t word; + } u; + } sbpc; + + struct swap_m88110_psr { + union { + struct { + unsigned :BITS_WIDTH(1,0); + unsigned mxm_dis:BIT_WIDTH(2); + unsigned sfu1dis:BIT_WIDTH(3); + unsigned :BITS_WIDTH(22,4); + unsigned trace:BIT_WIDTH(23); + unsigned :BIT_WIDTH(24); + unsigned sm:BIT_WIDTH(25); + unsigned sgn_imd:BIT_WIDTH(26); + unsigned :BIT_WIDTH(27); + unsigned c:BIT_WIDTH(28); + unsigned se:BIT_WIDTH(29); + unsigned le:BIT_WIDTH(30); + unsigned supr:BIT_WIDTH(31); + } fields; + uint32_t word; + } u; + } spsr; + + struct swapped_m88110_fp_trap_status { + union { + struct { + unsigned efinx:BIT_WIDTH(0); + unsigned efovf:BIT_WIDTH(1); + unsigned efunf:BIT_WIDTH(2); + unsigned efdvz:BIT_WIDTH(3); + unsigned efinv:BIT_WIDTH(4); + unsigned priv:BIT_WIDTH(5); + unsigned unimp:BIT_WIDTH(6); + unsigned int:BIT_WIDTH(7); + unsigned sfu1_disabled:BIT_WIDTH(8); + unsigned :BITS_WIDTH(13,9); + m88110_iresult_size_t iresult_size:BITS_WIDTH(15,14); + unsigned :BITS_WIDTH(31,16); + } fields; + uint32_t word; + } u; + } sfps; + + host_byte_sex = NXHostByteOrder(); + + if(target_byte_sex == host_byte_sex){ + for(i = 0; i < M88110_N_DATA_BP; i++){ + spu->data_bp[i].addr = OSSwapInt32(spu->data_bp[i].addr); + memcpy(&sbpc, &(spu->data_bp[i].ctrl), + sizeof(struct swapped_m88110_bp_ctrl)); + sbpc.u.word = OSSwapInt32(sbpc.u.word); + spu->data_bp[i].ctrl.v = sbpc.u.fields.v; + spu->data_bp[i].ctrl.addr_match = sbpc.u.fields.addr_match; + spu->data_bp[i].ctrl.rwm = sbpc.u.fields.rwm; + spu->data_bp[i].ctrl.rw = sbpc.u.fields.rw; + } + + memcpy(&spsr, &(spu->psr), sizeof(struct swap_m88110_psr)); + spsr.u.word = OSSwapInt32(spsr.u.word); + spu->psr.mxm_dis = spsr.u.fields.mxm_dis; + spu->psr.sfu1dis = spsr.u.fields.sfu1dis; + spu->psr.trace = spsr.u.fields.trace; + spu->psr.sm = spsr.u.fields.sm; + spu->psr.sgn_imd = spsr.u.fields.sgn_imd; + spu->psr.c = spsr.u.fields.c; + spu->psr.se = spsr.u.fields.se; + spu->psr.le = spsr.u.fields.le; + spu->psr.supr = spsr.u.fields.supr; + + memcpy(&sfps, &(spu->fp_trap_status), + sizeof(struct swapped_m88110_fp_trap_status)); + sfps.u.word = OSSwapInt32(sfps.u.word); + spu->fp_trap_status.efinx = sfps.u.fields.efinx; + spu->fp_trap_status.efovf = sfps.u.fields.efovf; + spu->fp_trap_status.efunf = sfps.u.fields.efunf; + spu->fp_trap_status.efdvz = sfps.u.fields.efdvz; + spu->fp_trap_status.efinv = sfps.u.fields.efinv; + spu->fp_trap_status.priv = sfps.u.fields.priv; + spu->fp_trap_status.unimp = sfps.u.fields.unimp; + spu->fp_trap_status.sfu1_disabled = sfps.u.fields.sfu1_disabled; + spu->fp_trap_status.iresult_size = sfps.u.fields.iresult_size; + } + else{ + for(i = 0; i < M88110_N_DATA_BP; i++){ + spu->data_bp[i].addr = OSSwapInt32(spu->data_bp[i].addr); + sbpc.u.fields.v = spu->data_bp[i].ctrl.v; + sbpc.u.fields.addr_match = spu->data_bp[i].ctrl.addr_match; + sbpc.u.fields.rwm = spu->data_bp[i].ctrl.rwm; + sbpc.u.fields.rw = spu->data_bp[i].ctrl.rw; + sbpc.u.word = OSSwapInt32(sbpc.u.word); + memcpy(&(spu->data_bp[i].ctrl), &sbpc, + sizeof(struct swapped_m88110_bp_ctrl)); + } + + spsr.u.fields.mxm_dis = spu->psr.mxm_dis; + spsr.u.fields.sfu1dis = spu->psr.sfu1dis; + spsr.u.fields.trace = spu->psr.trace; + spsr.u.fields.sm = spu->psr.sm; + spsr.u.fields.sgn_imd = spu->psr.sgn_imd; + spsr.u.fields.c = spu->psr.c; + spsr.u.fields.se = spu->psr.se; + spsr.u.fields.le = spu->psr.le; + spsr.u.fields.supr = spu->psr.supr; + spsr.u.word = OSSwapInt32(spsr.u.word); + memcpy(&(spu->psr), &spsr, sizeof(struct swap_m88110_psr)); + + sfps.u.fields.efinx = spu->fp_trap_status.efinx; + sfps.u.fields.efovf = spu->fp_trap_status.efovf; + sfps.u.fields.efunf = spu->fp_trap_status.efunf; + sfps.u.fields.efdvz = spu->fp_trap_status.efdvz; + sfps.u.fields.efinv = spu->fp_trap_status.efinv; + sfps.u.fields.priv = spu->fp_trap_status.priv; + sfps.u.fields.unimp = spu->fp_trap_status.unimp; + sfps.u.fields.sfu1_disabled = spu->fp_trap_status.sfu1_disabled; + sfps.u.fields.iresult_size = spu->fp_trap_status.iresult_size; + sfps.u.word = OSSwapInt32(sfps.u.word); + memcpy(&(spu->fp_trap_status), &sfps, + sizeof(struct swapped_m88110_fp_trap_status)); + } + spu->intermediate_result.x[0] = + OSSwapInt32(spu->intermediate_result.x[0]); + spu->intermediate_result.x[1] = + OSSwapInt32(spu->intermediate_result.x[1]); + spu->intermediate_result.x[2] = + OSSwapInt32(spu->intermediate_result.x[2]); + spu->intermediate_result.x[3] = + OSSwapInt32(spu->intermediate_result.x[3]); +} +#endif /* !defined(RLD) */ diff --git a/cctools/libmacho/ppc_swap.c b/cctools/libmacho/ppc_swap.c new file mode 100644 index 0000000..08b1977 --- /dev/null +++ b/cctools/libmacho/ppc_swap.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef RLD + +#define __cr cr +#define __ctr ctr +#define __dar dar +#define __dsisr dsisr +#define __exception exception +#define __fpregs fpregs +#define __fpscr fpscr +#define __fpscr_pad fpscr_pad +#define __lr lr +#define __mq mq +#define __pad0 pad0 +#define __pad1 pad1 +#define __r0 r0 +#define __r1 r1 +#define __r10 r10 +#define __r11 r11 +#define __r12 r12 +#define __r13 r13 +#define __r14 r14 +#define __r15 r15 +#define __r16 r16 +#define __r17 r17 +#define __r18 r18 +#define __r19 r19 +#define __r2 r2 +#define __r20 r20 +#define __r21 r21 +#define __r22 r22 +#define __r23 r23 +#define __r24 r24 +#define __r25 r25 +#define __r26 r26 +#define __r27 r27 +#define __r28 r28 +#define __r29 r29 +#define __r3 r3 +#define __r30 r30 +#define __r31 r31 +#define __r4 r4 +#define __r5 r5 +#define __r6 r6 +#define __r7 r7 +#define __r8 r8 +#define __r9 r9 +#define __srr0 srr0 +#define __srr1 srr1 +#define __vrsave vrsave +#define __xer xer + +#import +#import + +void +swap_ppc_thread_state_t( +ppc_thread_state_t *cpu, +enum NXByteOrder target_byte_sex) +{ + cpu->srr0 = OSSwapInt32(cpu->srr0); + cpu->srr1 = OSSwapInt32(cpu->srr1); + cpu->r0 = OSSwapInt32(cpu->r0); + cpu->r1 = OSSwapInt32(cpu->r1); + cpu->r2 = OSSwapInt32(cpu->r2); + cpu->r3 = OSSwapInt32(cpu->r3); + cpu->r4 = OSSwapInt32(cpu->r4); + cpu->r5 = OSSwapInt32(cpu->r5); + cpu->r6 = OSSwapInt32(cpu->r6); + cpu->r7 = OSSwapInt32(cpu->r7); + cpu->r8 = OSSwapInt32(cpu->r8); + cpu->r9 = OSSwapInt32(cpu->r9); + cpu->r10 = OSSwapInt32(cpu->r10); + cpu->r11 = OSSwapInt32(cpu->r11); + cpu->r12 = OSSwapInt32(cpu->r12); + cpu->r13 = OSSwapInt32(cpu->r13); + cpu->r14 = OSSwapInt32(cpu->r14); + cpu->r15 = OSSwapInt32(cpu->r15); + cpu->r16 = OSSwapInt32(cpu->r16); + cpu->r17 = OSSwapInt32(cpu->r17); + cpu->r18 = OSSwapInt32(cpu->r18); + cpu->r19 = OSSwapInt32(cpu->r19); + cpu->r20 = OSSwapInt32(cpu->r20); + cpu->r21 = OSSwapInt32(cpu->r21); + cpu->r22 = OSSwapInt32(cpu->r22); + cpu->r23 = OSSwapInt32(cpu->r23); + cpu->r24 = OSSwapInt32(cpu->r24); + cpu->r25 = OSSwapInt32(cpu->r25); + cpu->r26 = OSSwapInt32(cpu->r26); + cpu->r27 = OSSwapInt32(cpu->r27); + cpu->r28 = OSSwapInt32(cpu->r28); + cpu->r29 = OSSwapInt32(cpu->r29); + cpu->r30 = OSSwapInt32(cpu->r30); + cpu->r31 = OSSwapInt32(cpu->r31); + cpu->lr = OSSwapInt32(cpu->lr); + cpu->cr = OSSwapInt32(cpu->cr); + cpu->xer = OSSwapInt32(cpu->xer); + cpu->ctr = OSSwapInt32(cpu->ctr); + cpu->mq = OSSwapInt32(cpu->mq); + cpu->vrsave = OSSwapInt32(cpu->vrsave); + +} + +void +swap_ppc_float_state_t( +ppc_float_state_t *fpu, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + + for(i = 0; i < 32; i++) + fpu->fpregs[i] = OSSwapInt64(fpu->fpregs[i]); + + fpu->fpscr_pad = OSSwapInt32(fpu->fpscr_pad); + fpu->fpscr = OSSwapInt32(fpu->fpscr); +} + +void +swap_ppc_exception_state_t( +ppc_exception_state_t *state, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + + state->dar = OSSwapInt32(state->dar); + state->dsisr = OSSwapInt32(state->dsisr); + state->exception = OSSwapInt32(state->exception); + state->pad0 = OSSwapInt32(state->pad0); + + for(i = 0; i < 4; i++) + state->pad1[i] = OSSwapInt32(state->pad1[i]); +} +#endif /* !defined(RLD) */ diff --git a/cctools/libmacho/slot_name.c b/cctools/libmacho/slot_name.c new file mode 100644 index 0000000..1911166 --- /dev/null +++ b/cctools/libmacho/slot_name.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* + * File: slot_name.c + * Author: Avadis Tevanian, Jr. + * + * Copyright (C) 1987, Avadis Tevanian, Jr. + * + * Convert machine slot values to human readable strings. + * + * HISTORY + * 26-Jan-88 Mary Thompson (mrt) at Carnegie Mellon + * added case for CUP_SUBTYPE_RT_APC + * + * 28-Feb-87 Avadis Tevanian (avie) at Carnegie-Mellon University + * Created. + * + */ + +#include +#include + +/* + * Convert the specified cpu_type/cpu_subtype pair to their + * human readable form. + */ +void slot_name(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype, char **cpu_name, +char **cpu_subname) +{ + register char *name = "Unknown CPU"; + register char *subname = ""; + const NXArchInfo *ai = NXGetArchInfoFromCpuType(cpu_type, cpu_subtype); + if (ai != NULL) { + name = (char *)ai->name; + subname = (char *)ai->description; + } + *cpu_name = name; + *cpu_subname = subname; +} diff --git a/cctools/libmacho/sparc_swap.c b/cctools/libmacho/sparc_swap.c new file mode 100644 index 0000000..63ecb9b --- /dev/null +++ b/cctools/libmacho/sparc_swap.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef RLD +#include +#import +#import + +void +swap_sparc_thread_state_regs( +struct sparc_thread_state_regs *cpu, +enum NXByteOrder target_byte_sex) +{ + struct swapped_psr { + union { + struct { + unsigned int + cwp:BITS_WIDTH(4,0), + et:BIT_WIDTH(5), + ps:BIT_WIDTH(6), + s:BIT_WIDTH(7), + pil:BITS_WIDTH(11,8), + ef:BIT_WIDTH(12), + ec:BIT_WIDTH(13), + reserved:BITS_WIDTH(19,14), + icc:BITS_WIDTH(23,20), + ver:BITS_WIDTH(27,24), + impl:BITS_WIDTH(31,28); + } fields; + unsigned int word; + } u; + } spsr; + struct p_status *pr_status; + enum NXByteOrder host_byte_sex; + + host_byte_sex = NXHostByteOrder(); + + cpu->regs.r_pc = OSSwapInt32(cpu->regs.r_pc); + cpu->regs.r_npc = OSSwapInt32(cpu->regs.r_npc); + cpu->regs.r_y = OSSwapInt32(cpu->regs.r_y); + cpu->regs.r_g1 = OSSwapInt32(cpu->regs.r_g1); + cpu->regs.r_g2 = OSSwapInt32(cpu->regs.r_g2); + cpu->regs.r_g3 = OSSwapInt32(cpu->regs.r_g3); + cpu->regs.r_g4 = OSSwapInt32(cpu->regs.r_g4); + cpu->regs.r_g5 = OSSwapInt32(cpu->regs.r_g5); + cpu->regs.r_g6 = OSSwapInt32(cpu->regs.r_g6); + cpu->regs.r_g7 = OSSwapInt32(cpu->regs.r_g7); + cpu->regs.r_o0 = OSSwapInt32(cpu->regs.r_o0); + cpu->regs.r_o1 = OSSwapInt32(cpu->regs.r_o1); + cpu->regs.r_o2 = OSSwapInt32(cpu->regs.r_o2); + cpu->regs.r_o3 = OSSwapInt32(cpu->regs.r_o3); + cpu->regs.r_o4 = OSSwapInt32(cpu->regs.r_o4); + cpu->regs.r_o5 = OSSwapInt32(cpu->regs.r_o5); + cpu->regs.r_o6 = OSSwapInt32(cpu->regs.r_o6); + cpu->regs.r_o7 = OSSwapInt32(cpu->regs.r_o7); + + pr_status = (struct p_status *) &(cpu->regs.r_psr); + if(target_byte_sex == host_byte_sex){ + memcpy(&spsr, &(cpu->regs.r_psr), sizeof(struct swapped_psr)); + spsr.u.word = OSSwapInt32(spsr.u.word); + pr_status->PSRREG.psr_bits.cwp = spsr.u.fields.cwp; + pr_status->PSRREG.psr_bits.ps = spsr.u.fields.ps; + pr_status->PSRREG.psr_bits.s = spsr.u.fields.s; + pr_status->PSRREG.psr_bits.pil = spsr.u.fields.pil; + pr_status->PSRREG.psr_bits.ef = spsr.u.fields.ef; + pr_status->PSRREG.psr_bits.ec = spsr.u.fields.ec; + pr_status->PSRREG.psr_bits.reserved = spsr.u.fields.reserved; + pr_status->PSRREG.psr_bits.icc = spsr.u.fields.icc; + pr_status->PSRREG.psr_bits.et = spsr.u.fields.ver; + pr_status->PSRREG.psr_bits.impl = spsr.u.fields.impl; + } + else{ + spsr.u.fields.cwp = pr_status->PSRREG.psr_bits.cwp; + spsr.u.fields.ps = pr_status->PSRREG.psr_bits.ps; + spsr.u.fields.s = pr_status->PSRREG.psr_bits.s; + spsr.u.fields.pil = pr_status->PSRREG.psr_bits.pil; + spsr.u.fields.ef = pr_status->PSRREG.psr_bits.ef; + spsr.u.fields.ec = pr_status->PSRREG.psr_bits.ec; + spsr.u.fields.reserved = pr_status->PSRREG.psr_bits.reserved; + spsr.u.fields.icc = pr_status->PSRREG.psr_bits.icc; + spsr.u.fields.ver = pr_status->PSRREG.psr_bits.et; + spsr.u.fields.impl = pr_status->PSRREG.psr_bits.impl; + spsr.u.word = OSSwapInt32(spsr.u.word); + memcpy(&(cpu->regs.r_psr), &spsr, sizeof(struct swapped_psr)); + } +} + +void +swap_sparc_thread_state_fpu( +struct sparc_thread_state_fpu *fpu, +enum NXByteOrder target_byte_sex) +{ + struct swapped_fsr { + union { + struct { + unsigned int + cexc:BITS_WIDTH(4,0), + aexc:BITS_WIDTH(9,5), + fcc:BITS_WIDTH(11,10), + pr:BIT_WIDTH(12), + qne:BIT_WIDTH(13), + ftt:BITS_WIDTH(16,14), + res:BITS_WIDTH(22,17), + tem:BITS_WIDTH(27,23), + rp:BITS_WIDTH(29,28), + rd:BITS_WIDTH(31,30); + } fields; + unsigned int word; + } u; + } sfsr; + uint32_t i; + struct f_status *fpu_status; + enum NXByteOrder host_byte_sex; + + host_byte_sex = NXHostByteOrder(); + + + /* floating point registers */ + for(i = 0; i < 16; i++) /* 16 doubles */ + fpu->fpu.fpu_fr.Fpu_dregs[i] = + OSSwapInt64(fpu->fpu.fpu_fr.Fpu_dregs[i]); + + fpu->fpu.Fpu_q[0].FQu.whole = OSSwapInt64(fpu->fpu.Fpu_q[0].FQu.whole); + fpu->fpu.Fpu_q[1].FQu.whole = OSSwapInt64(fpu->fpu.Fpu_q[1].FQu.whole); + fpu->fpu.Fpu_flags = OSSwapInt32(fpu->fpu.Fpu_flags); + fpu->fpu.Fpu_extra = OSSwapInt32(fpu->fpu.Fpu_extra); + fpu->fpu.Fpu_qcnt = OSSwapInt32(fpu->fpu.Fpu_qcnt); + + fpu_status = (struct f_status *) &(fpu->fpu.Fpu_fsr); + if(target_byte_sex == host_byte_sex){ + memcpy(&sfsr, &(fpu->fpu.Fpu_fsr), sizeof(unsigned int)); + sfsr.u.word = OSSwapInt32(sfsr.u.word); + fpu_status->FPUREG.Fpu_fsr_bits.rd = sfsr.u.fields.rd; + fpu_status->FPUREG.Fpu_fsr_bits.rp = sfsr.u.fields.rp; + fpu_status->FPUREG.Fpu_fsr_bits.tem = sfsr.u.fields.tem; + fpu_status->FPUREG.Fpu_fsr_bits.res = sfsr.u.fields.res; + fpu_status->FPUREG.Fpu_fsr_bits.ftt = sfsr.u.fields.ftt; + fpu_status->FPUREG.Fpu_fsr_bits.qne = sfsr.u.fields.qne; + fpu_status->FPUREG.Fpu_fsr_bits.pr = sfsr.u.fields.pr; + fpu_status->FPUREG.Fpu_fsr_bits.fcc = sfsr.u.fields.fcc; + fpu_status->FPUREG.Fpu_fsr_bits.aexc = sfsr.u.fields.aexc; + fpu_status->FPUREG.Fpu_fsr_bits.cexc = sfsr.u.fields.cexc; + } + else{ + sfsr.u.fields.rd = fpu_status->FPUREG.Fpu_fsr_bits.rd; + sfsr.u.fields.rp = fpu_status->FPUREG.Fpu_fsr_bits.rp; + sfsr.u.fields.tem = fpu_status->FPUREG.Fpu_fsr_bits.tem; + sfsr.u.fields.res = fpu_status->FPUREG.Fpu_fsr_bits.res; + sfsr.u.fields.ftt = fpu_status->FPUREG.Fpu_fsr_bits.ftt; + sfsr.u.fields.qne = fpu_status->FPUREG.Fpu_fsr_bits.qne; + sfsr.u.fields.pr = fpu_status->FPUREG.Fpu_fsr_bits.pr; + sfsr.u.fields.fcc = fpu_status->FPUREG.Fpu_fsr_bits.fcc; + sfsr.u.fields.aexc = fpu_status->FPUREG.Fpu_fsr_bits.aexc; + sfsr.u.fields.cexc = fpu_status->FPUREG.Fpu_fsr_bits.cexc; + sfsr.u.word = OSSwapInt32(sfsr.u.word); + memcpy(&(fpu->fpu.Fpu_fsr), &sfsr, sizeof(struct swapped_fsr)); + } +} +#endif /* !defined(RLD) */ diff --git a/cctools/libmacho/swap.c b/cctools/libmacho/swap.c new file mode 100644 index 0000000..b7f8f1c --- /dev/null +++ b/cctools/libmacho/swap.c @@ -0,0 +1,857 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef RLD +#include +#include +#include +#include + +void +swap_fat_header( +struct fat_header *fat_header, +enum NXByteOrder target_byte_sex) +{ + fat_header->magic = OSSwapInt32(fat_header->magic); + fat_header->nfat_arch = OSSwapInt32(fat_header->nfat_arch); +} + +void +swap_fat_arch( +struct fat_arch *fat_archs, +uint32_t nfat_arch, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + + for(i = 0; i < nfat_arch; i++){ + fat_archs[i].cputype = OSSwapInt32(fat_archs[i].cputype); + fat_archs[i].cpusubtype = OSSwapInt32(fat_archs[i].cpusubtype); + fat_archs[i].offset = OSSwapInt32(fat_archs[i].offset); + fat_archs[i].size = OSSwapInt32(fat_archs[i].size); + fat_archs[i].align = OSSwapInt32(fat_archs[i].align); + } +} + +void +swap_fat_arch_64( +struct fat_arch_64 *fat_archs64, +uint32_t nfat_arch, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + + for(i = 0; i < nfat_arch; i++){ + fat_archs64[i].cputype = OSSwapInt32(fat_archs64[i].cputype); + fat_archs64[i].cpusubtype = OSSwapInt32(fat_archs64[i].cpusubtype); + fat_archs64[i].offset = OSSwapInt64(fat_archs64[i].offset); + fat_archs64[i].size = OSSwapInt64(fat_archs64[i].size); + fat_archs64[i].align = OSSwapInt32(fat_archs64[i].align); + fat_archs64[i].reserved = OSSwapInt32(fat_archs64[i].reserved); + } +} + +void +swap_mach_header( +struct mach_header *mh, +enum NXByteOrder target_byte_sex) +{ + mh->magic = OSSwapInt32(mh->magic); + mh->cputype = OSSwapInt32(mh->cputype); + mh->cpusubtype = OSSwapInt32(mh->cpusubtype); + mh->filetype = OSSwapInt32(mh->filetype); + mh->ncmds = OSSwapInt32(mh->ncmds); + mh->sizeofcmds = OSSwapInt32(mh->sizeofcmds); + mh->flags = OSSwapInt32(mh->flags); +} + +void +swap_mach_header_64( +struct mach_header_64 *mh, +enum NXByteOrder target_byte_sex) +{ + mh->magic = OSSwapInt32(mh->magic); + mh->cputype = OSSwapInt32(mh->cputype); + mh->cpusubtype = OSSwapInt32(mh->cpusubtype); + mh->filetype = OSSwapInt32(mh->filetype); + mh->ncmds = OSSwapInt32(mh->ncmds); + mh->sizeofcmds = OSSwapInt32(mh->sizeofcmds); + mh->flags = OSSwapInt32(mh->flags); + mh->reserved = OSSwapInt32(mh->reserved); +} + +void +swap_load_command( +struct load_command *lc, +enum NXByteOrder target_byte_sex) +{ + lc->cmd = OSSwapInt32(lc->cmd); + lc->cmdsize = OSSwapInt32(lc->cmdsize); +} + +void +swap_segment_command( +struct segment_command *sg, +enum NXByteOrder target_byte_sex) +{ + /* segname[16] */ + sg->cmd = OSSwapInt32(sg->cmd); + sg->cmdsize = OSSwapInt32(sg->cmdsize); + sg->vmaddr = OSSwapInt32(sg->vmaddr); + sg->vmsize = OSSwapInt32(sg->vmsize); + sg->fileoff = OSSwapInt32(sg->fileoff); + sg->filesize = OSSwapInt32(sg->filesize); + sg->maxprot = OSSwapInt32(sg->maxprot); + sg->initprot = OSSwapInt32(sg->initprot); + sg->nsects = OSSwapInt32(sg->nsects); + sg->flags = OSSwapInt32(sg->flags); +} + +void +swap_segment_command_64( +struct segment_command_64* sg, +enum NXByteOrder target_byte_sex) +{ + /* char segname[16] */ + sg->cmd = OSSwapInt32(sg->cmd); + sg->cmdsize = OSSwapInt32(sg->cmdsize); + sg->vmaddr = OSSwapInt64(sg->vmaddr); + sg->vmsize = OSSwapInt64(sg->vmsize); + sg->fileoff = OSSwapInt64(sg->fileoff); + sg->filesize = OSSwapInt64(sg->filesize); + sg->maxprot = OSSwapInt32(sg->maxprot); + sg->initprot = OSSwapInt32(sg->initprot); + sg->nsects = OSSwapInt32(sg->nsects); + sg->flags = OSSwapInt32(sg->flags); +} + +void +swap_section( +struct section *s, +uint32_t nsects, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + + for(i = 0; i < nsects; i++){ + /* sectname[16] */ + /* segname[16] */ + s[i].addr = OSSwapInt32(s[i].addr); + s[i].size = OSSwapInt32(s[i].size); + s[i].offset = OSSwapInt32(s[i].offset); + s[i].align = OSSwapInt32(s[i].align); + s[i].reloff = OSSwapInt32(s[i].reloff); + s[i].nreloc = OSSwapInt32(s[i].nreloc); + s[i].flags = OSSwapInt32(s[i].flags); + s[i].reserved1 = OSSwapInt32(s[i].reserved1); + s[i].reserved2 = OSSwapInt32(s[i].reserved2); + } +} + +void +swap_section_64( +struct section_64 *s, +uint32_t nsects, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + + for(i = 0; i < nsects; i++){ + /* sectname[16] */ + /* segname[16] */ + s[i].addr = OSSwapInt64(s[i].addr); + s[i].size = OSSwapInt64(s[i].size); + s[i].offset = OSSwapInt32(s[i].offset); + s[i].align = OSSwapInt32(s[i].align); + s[i].reloff = OSSwapInt32(s[i].reloff); + s[i].nreloc = OSSwapInt32(s[i].nreloc); + s[i].flags = OSSwapInt32(s[i].flags); + s[i].reserved1 = OSSwapInt32(s[i].reserved1); + s[i].reserved2 = OSSwapInt32(s[i].reserved2); + s[i].reserved3 = OSSwapInt32(s[i].reserved3); + } +} + +void +swap_symtab_command( +struct symtab_command *st, +enum NXByteOrder target_byte_sex) +{ + st->cmd = OSSwapInt32(st->cmd); + st->cmdsize = OSSwapInt32(st->cmdsize); + st->symoff = OSSwapInt32(st->symoff); + st->nsyms = OSSwapInt32(st->nsyms); + st->stroff = OSSwapInt32(st->stroff); + st->strsize = OSSwapInt32(st->strsize); +} + +void +swap_dysymtab_command( +struct dysymtab_command *dyst, +enum NXByteOrder target_byte_sex) +{ + dyst->cmd = OSSwapInt32(dyst->cmd); + dyst->cmdsize = OSSwapInt32(dyst->cmdsize); + dyst->ilocalsym = OSSwapInt32(dyst->ilocalsym); + dyst->nlocalsym = OSSwapInt32(dyst->nlocalsym); + dyst->iextdefsym = OSSwapInt32(dyst->iextdefsym); + dyst->nextdefsym = OSSwapInt32(dyst->nextdefsym); + dyst->iundefsym = OSSwapInt32(dyst->iundefsym); + dyst->nundefsym = OSSwapInt32(dyst->nundefsym); + dyst->tocoff = OSSwapInt32(dyst->tocoff); + dyst->ntoc = OSSwapInt32(dyst->ntoc); + dyst->modtaboff = OSSwapInt32(dyst->modtaboff); + dyst->nmodtab = OSSwapInt32(dyst->nmodtab); + dyst->extrefsymoff = OSSwapInt32(dyst->extrefsymoff); + dyst->nextrefsyms = OSSwapInt32(dyst->nextrefsyms); + dyst->indirectsymoff = OSSwapInt32(dyst->indirectsymoff); + dyst->nindirectsyms = OSSwapInt32(dyst->nindirectsyms); + dyst->extreloff = OSSwapInt32(dyst->extreloff); + dyst->nextrel = OSSwapInt32(dyst->nextrel); + dyst->locreloff = OSSwapInt32(dyst->locreloff); + dyst->nlocrel = OSSwapInt32(dyst->nlocrel); +} + +void +swap_symseg_command( +struct symseg_command *ss, +enum NXByteOrder target_byte_sex) +{ + ss->cmd = OSSwapInt32(ss->cmd); + ss->cmdsize = OSSwapInt32(ss->cmdsize); + ss->offset = OSSwapInt32(ss->offset); + ss->size = OSSwapInt32(ss->size); +} + +void +swap_fvmlib_command( +struct fvmlib_command *fl, +enum NXByteOrder target_byte_sex) +{ + fl->cmd = OSSwapInt32(fl->cmd); + fl->cmdsize = OSSwapInt32(fl->cmdsize); + fl->fvmlib.name.offset = OSSwapInt32(fl->fvmlib.name.offset); + fl->fvmlib.minor_version = OSSwapInt32(fl->fvmlib.minor_version); + fl->fvmlib.header_addr = OSSwapInt32(fl->fvmlib.header_addr); +} + +void +swap_dylib_command( +struct dylib_command *dl, +enum NXByteOrder target_byte_sex) +{ + dl->cmd = OSSwapInt32(dl->cmd); + dl->cmdsize = OSSwapInt32(dl->cmdsize); + dl->dylib.name.offset = OSSwapInt32(dl->dylib.name.offset); + dl->dylib.timestamp = OSSwapInt32(dl->dylib.timestamp); + dl->dylib.current_version = OSSwapInt32(dl->dylib.current_version); + dl->dylib.compatibility_version = + OSSwapInt32(dl->dylib.compatibility_version); +} + +void +swap_sub_framework_command( +struct sub_framework_command *sub, +enum NXByteOrder target_byte_sex) +{ + sub->cmd = OSSwapInt32(sub->cmd); + sub->cmdsize = OSSwapInt32(sub->cmdsize); + sub->umbrella.offset = OSSwapInt32(sub->umbrella.offset); +} + +void +swap_sub_umbrella_command( +struct sub_umbrella_command *usub, +enum NXByteOrder target_byte_sex) +{ + usub->cmd = OSSwapInt32(usub->cmd); + usub->cmdsize = OSSwapInt32(usub->cmdsize); + usub->sub_umbrella.offset = OSSwapInt32(usub->sub_umbrella.offset); +} + +void +swap_sub_library_command( +struct sub_library_command *lsub, +enum NXByteOrder target_byte_sex) +{ + lsub->cmd = OSSwapInt32(lsub->cmd); + lsub->cmdsize = OSSwapInt32(lsub->cmdsize); + lsub->sub_library.offset = OSSwapInt32(lsub->sub_library.offset); +} + +void +swap_sub_client_command( +struct sub_client_command *csub, +enum NXByteOrder target_byte_sex) +{ + csub->cmd = OSSwapInt32(csub->cmd); + csub->cmdsize = OSSwapInt32(csub->cmdsize); + csub->client.offset = OSSwapInt32(csub->client.offset); +} + + +void +swap_prebound_dylib_command( +struct prebound_dylib_command *pbdylib, +enum NXByteOrder target_byte_sex) +{ + pbdylib->cmd = OSSwapInt32(pbdylib->cmd); + pbdylib->cmdsize = OSSwapInt32(pbdylib->cmdsize); + pbdylib->name.offset = OSSwapInt32(pbdylib->name.offset); + pbdylib->nmodules = OSSwapInt32(pbdylib->nmodules); + pbdylib->linked_modules.offset = + OSSwapInt32(pbdylib->linked_modules.offset); +} + +void +swap_dylinker_command( +struct dylinker_command *dyld, +enum NXByteOrder target_byte_sex) +{ + dyld->cmd = OSSwapInt32(dyld->cmd); + dyld->cmdsize = OSSwapInt32(dyld->cmdsize); + dyld->name.offset = OSSwapInt32(dyld->name.offset); +} + +void +swap_fvmfile_command( +struct fvmfile_command *ff, +enum NXByteOrder target_byte_sex) +{ + ff->cmd = OSSwapInt32(ff->cmd); + ff->cmdsize = OSSwapInt32(ff->cmdsize); + ff->name.offset = OSSwapInt32(ff->name.offset); + ff->header_addr = OSSwapInt32(ff->header_addr); +} + + +void +swap_thread_command( +struct thread_command *ut, +enum NXByteOrder target_byte_sex) +{ + ut->cmd = OSSwapInt32(ut->cmd); + ut->cmdsize = OSSwapInt32(ut->cmdsize); +} + +void +swap_ident_command( +struct ident_command *id_cmd, +enum NXByteOrder target_byte_sex) +{ + id_cmd->cmd = OSSwapInt32(id_cmd->cmd); + id_cmd->cmdsize = OSSwapInt32(id_cmd->cmdsize); +} + +void +swap_routines_command( +struct routines_command *r_cmd, +enum NXByteOrder target_byte_sex) +{ + r_cmd->cmd = OSSwapInt32(r_cmd->cmd); + r_cmd->cmdsize = OSSwapInt32(r_cmd->cmdsize); + r_cmd->init_address = OSSwapInt32(r_cmd->init_address); + r_cmd->init_module = OSSwapInt32(r_cmd->init_module); + r_cmd->reserved1 = OSSwapInt32(r_cmd->reserved1); + r_cmd->reserved2 = OSSwapInt32(r_cmd->reserved2); + r_cmd->reserved3 = OSSwapInt32(r_cmd->reserved3); + r_cmd->reserved4 = OSSwapInt32(r_cmd->reserved4); + r_cmd->reserved5 = OSSwapInt32(r_cmd->reserved5); + r_cmd->reserved6 = OSSwapInt32(r_cmd->reserved6); +} + +void +swap_routines_command_64( +struct routines_command_64 *r_cmd, +enum NXByteOrder target_byte_sex) +{ + r_cmd->cmd = OSSwapInt32(r_cmd->cmd); + r_cmd->cmdsize = OSSwapInt32(r_cmd->cmdsize); + r_cmd->init_address = OSSwapInt64(r_cmd->init_address); + r_cmd->init_module = OSSwapInt64(r_cmd->init_module); + r_cmd->reserved1 = OSSwapInt64(r_cmd->reserved1); + r_cmd->reserved2 = OSSwapInt64(r_cmd->reserved2); + r_cmd->reserved3 = OSSwapInt64(r_cmd->reserved3); + r_cmd->reserved4 = OSSwapInt64(r_cmd->reserved4); + r_cmd->reserved5 = OSSwapInt64(r_cmd->reserved5); + r_cmd->reserved6 = OSSwapInt64(r_cmd->reserved6); +} + +void +swap_twolevel_hints_command( +struct twolevel_hints_command *hints_cmd, +enum NXByteOrder target_byte_sex) +{ + hints_cmd->cmd = OSSwapInt32(hints_cmd->cmd); + hints_cmd->cmdsize = OSSwapInt32(hints_cmd->cmdsize); + hints_cmd->offset = OSSwapInt32(hints_cmd->offset); + hints_cmd->nhints = OSSwapInt32(hints_cmd->nhints); +} + +void +swap_twolevel_hint( +struct twolevel_hint *hints, +uint32_t nhints, +enum NXByteOrder target_byte_sex) +{ + struct swapped_twolevel_hint { + union { + struct { + uint32_t + itoc:24, + isub_image:8; + } fields; + uint32_t word; + } u; + } shint; + + uint32_t i; + enum NXByteOrder host_byte_sex; + + host_byte_sex = NXHostByteOrder(); + + for(i = 0; i < nhints; i++){ + if(target_byte_sex == host_byte_sex){ + memcpy(&shint, hints + i, sizeof(struct swapped_twolevel_hint)); + shint.u.word = OSSwapInt32(shint.u.word); + hints[i].itoc = shint.u.fields.itoc; + hints[i].isub_image = shint.u.fields.isub_image; + } + else{ + shint.u.fields.isub_image = hints[i].isub_image; + shint.u.fields.itoc = hints[i].itoc; + shint.u.word = OSSwapInt32(shint.u.word); + memcpy(hints + i, &shint, sizeof(struct swapped_twolevel_hint)); + } + } +} + +void +swap_prebind_cksum_command( +struct prebind_cksum_command *cksum_cmd, +enum NXByteOrder target_byte_sex) +{ + cksum_cmd->cmd = OSSwapInt32(cksum_cmd->cmd); + cksum_cmd->cmdsize = OSSwapInt32(cksum_cmd->cmdsize); + cksum_cmd->cksum = OSSwapInt32(cksum_cmd->cksum); +} + +void +swap_uuid_command( +struct uuid_command *uuid_cmd, +enum NXByteOrder target_byte_sex) +{ + uuid_cmd->cmd = OSSwapInt32(uuid_cmd->cmd); + uuid_cmd->cmdsize = OSSwapInt32(uuid_cmd->cmdsize); +} + +void +swap_linkedit_data_command( +struct linkedit_data_command *ld, +enum NXByteOrder target_byte_sex) +{ + ld->cmd = OSSwapInt32(ld->cmd); + ld->cmdsize = OSSwapInt32(ld->cmdsize); + ld->dataoff = OSSwapInt32(ld->dataoff); + ld->datasize = OSSwapInt32(ld->datasize); +} + +void +swap_version_min_command( +struct version_min_command *ver_cmd, +enum NXByteOrder target_byte_sex) +{ + ver_cmd->cmd = OSSwapInt32(ver_cmd->cmd); + ver_cmd->cmdsize = OSSwapInt32(ver_cmd->cmdsize); + ver_cmd->version = OSSwapInt32(ver_cmd->version); +} + +void +swap_build_version_command( +struct build_version_command *bv, +enum NXByteOrder target_byte_sex) +{ + bv->cmd = OSSwapInt32(bv->cmd); + bv->cmdsize = OSSwapInt32(bv->cmdsize); + bv->platform = OSSwapInt32(bv->platform); + bv->minos = OSSwapInt32(bv->minos); + bv->sdk = OSSwapInt32(bv->sdk); + bv->ntools = OSSwapInt32(bv->ntools); +} + +void +swap_build_tool_version( +struct build_tool_version *btv, +uint32_t ntools, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + + for(i = 0; i < ntools; i++){ + btv[i].tool = OSSwapInt32(btv[i].tool); + btv[i].version = OSSwapInt32(btv[i].version); + } +} + +void +swap_rpath_command( +struct rpath_command *rpath_cmd, +enum NXByteOrder target_byte_sex) +{ + rpath_cmd->cmd = OSSwapInt32(rpath_cmd->cmd); + rpath_cmd->cmdsize = OSSwapInt32(rpath_cmd->cmdsize); + rpath_cmd->path.offset = OSSwapInt32(rpath_cmd->path.offset); +} + +void +swap_encryption_command( +struct encryption_info_command *ec, +enum NXByteOrder target_byte_sex) +{ + ec->cmd = OSSwapInt32(ec->cmd); + ec->cmdsize = OSSwapInt32(ec->cmdsize); + ec->cryptoff = OSSwapInt32(ec->cryptoff); + ec->cryptsize = OSSwapInt32(ec->cryptsize); + ec->cryptid = OSSwapInt32(ec->cryptid); +} + +void +swap_encryption_command_64( +struct encryption_info_command_64 *ec, +enum NXByteOrder target_byte_sex) +{ + ec->cmd = OSSwapInt32(ec->cmd); + ec->cmdsize = OSSwapInt32(ec->cmdsize); + ec->cryptoff = OSSwapInt32(ec->cryptoff); + ec->cryptsize = OSSwapInt32(ec->cryptsize); + ec->cryptid = OSSwapInt32(ec->cryptid); + ec->cryptid = OSSwapInt32(ec->pad); +} + +void +swap_linker_option_command( +struct linker_option_command *lo, +enum NXByteOrder target_byte_sex) +{ + lo->cmd = OSSwapInt32(lo->cmd); + lo->cmdsize = OSSwapInt32(lo->cmdsize); + lo->count = OSSwapInt32(lo->count); +} + +void +swap_dyld_info_command( +struct dyld_info_command *ed, +enum NXByteOrder target_byte_sex) +{ + ed->cmd = OSSwapInt32(ed->cmd); + ed->cmdsize = OSSwapInt32(ed->cmdsize); + ed->rebase_off = OSSwapInt32(ed->rebase_off); + ed->rebase_size = OSSwapInt32(ed->rebase_size); + ed->bind_off = OSSwapInt32(ed->bind_off); + ed->bind_size = OSSwapInt32(ed->bind_size); + ed->weak_bind_off = OSSwapInt32(ed->weak_bind_off); + ed->weak_bind_size = OSSwapInt32(ed->weak_bind_size); + ed->lazy_bind_off = OSSwapInt32(ed->lazy_bind_off); + ed->lazy_bind_size = OSSwapInt32(ed->lazy_bind_size); + ed->export_off = OSSwapInt32(ed->export_off); + ed->export_size = OSSwapInt32(ed->export_size); +} + +void +swap_entry_point_command( +struct entry_point_command *ep, +enum NXByteOrder target_byte_sex) +{ + ep->cmd = OSSwapInt32(ep->cmd); + ep->cmdsize = OSSwapInt32(ep->cmdsize); + ep->entryoff = OSSwapInt64(ep->entryoff); + ep->stacksize = OSSwapInt64(ep->stacksize); +} + +void +swap_source_version_command( +struct source_version_command *sv, +enum NXByteOrder target_byte_sex) +{ + sv->cmd = OSSwapInt32(sv->cmd); + sv->cmdsize = OSSwapInt32(sv->cmdsize); + sv->version = OSSwapInt64(sv->version); +} + +void +swap_note_command( +struct note_command *nc, +enum NXByteOrder target_byte_sex) +{ + nc->cmd = OSSwapInt32(nc->cmd); + nc->cmdsize = OSSwapInt32(nc->cmdsize); + nc->offset = OSSwapInt64(nc->offset); + nc->size = OSSwapInt64(nc->size); +} + +void +swap_nlist( +struct nlist *symbols, +uint32_t nsymbols, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + + for(i = 0; i < nsymbols; i++){ + symbols[i].n_un.n_strx = OSSwapInt32(symbols[i].n_un.n_strx); + /* n_type */ + /* n_sect */ + symbols[i].n_desc = OSSwapInt16(symbols[i].n_desc); + symbols[i].n_value = OSSwapInt32(symbols[i].n_value); + } +} + +void +swap_nlist_64( +struct nlist_64 *symbols, +uint32_t nsymbols, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + + for(i = 0; i < nsymbols; i++){ + symbols[i].n_un.n_strx = OSSwapInt32(symbols[i].n_un.n_strx); + /* n_type */ + /* n_sect */ + symbols[i].n_desc = OSSwapInt16(symbols[i].n_desc); + symbols[i].n_value = OSSwapInt64(symbols[i].n_value); + } +} + +void +swap_ranlib( +struct ranlib *ranlibs, +uint32_t nranlibs, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + + for(i = 0; i < nranlibs; i++){ + ranlibs[i].ran_un.ran_strx = OSSwapInt32(ranlibs[i].ran_un.ran_strx); + ranlibs[i].ran_off = OSSwapInt32(ranlibs[i].ran_off); + } +} + +void +swap_ranlib_64( +struct ranlib_64 *ranlibs, +uint64_t nranlibs, +enum NXByteOrder target_byte_sex) +{ + uint64_t i; + + for(i = 0; i < nranlibs; i++){ + ranlibs[i].ran_un.ran_strx = OSSwapInt64(ranlibs[i].ran_un.ran_strx); + ranlibs[i].ran_off = OSSwapInt64(ranlibs[i].ran_off); + } +} + +void +swap_relocation_info( +struct relocation_info *relocs, +uint32_t nrelocs, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + enum NXByteOrder host_byte_sex; + uint32_t to_host_byte_sex, scattered; + + struct swapped_relocation_info { + uint32_t r_address; + union { + struct { + unsigned int + r_type:4, + r_extern:1, + r_length:2, + r_pcrel:1, + r_symbolnum:24; + } fields; + uint32_t word; + } u; + } sr; + + struct swapped_scattered_relocation_info { + uint32_t word; + uint32_t r_value; + } *ssr; + + host_byte_sex = NXHostByteOrder(); + to_host_byte_sex = target_byte_sex == host_byte_sex; + + for(i = 0; i < nrelocs; i++){ + if(to_host_byte_sex) + scattered = (OSSwapInt32(relocs[i].r_address) & R_SCATTERED) != 0; + else + scattered = ((relocs[i].r_address) & R_SCATTERED) != 0; + if(scattered == FALSE){ + if(to_host_byte_sex){ + memcpy(&sr, relocs + i, sizeof(struct relocation_info)); + sr.r_address = OSSwapInt32(sr.r_address); + sr.u.word = OSSwapInt32(sr.u.word); + relocs[i].r_address = sr.r_address; + relocs[i].r_symbolnum = sr.u.fields.r_symbolnum; + relocs[i].r_pcrel = sr.u.fields.r_pcrel; + relocs[i].r_length = sr.u.fields.r_length; + relocs[i].r_extern = sr.u.fields.r_extern; + relocs[i].r_type = sr.u.fields.r_type; + } + else{ + sr.r_address = relocs[i].r_address; + sr.u.fields.r_symbolnum = relocs[i].r_symbolnum; + sr.u.fields.r_length = relocs[i].r_length; + sr.u.fields.r_pcrel = relocs[i].r_pcrel; + sr.u.fields.r_extern = relocs[i].r_extern; + sr.u.fields.r_type = relocs[i].r_type; + sr.r_address = OSSwapInt32(sr.r_address); + sr.u.word = OSSwapInt32(sr.u.word); + memcpy(relocs + i, &sr, sizeof(struct relocation_info)); + } + } + else{ + ssr = (struct swapped_scattered_relocation_info *)(relocs + i); + ssr->word = OSSwapInt32(ssr->word); + ssr->r_value = OSSwapInt32(ssr->r_value); + } + } +} + +void +swap_indirect_symbols( +uint32_t *indirect_symbols, +uint32_t nindirect_symbols, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + + for(i = 0; i < nindirect_symbols; i++) + indirect_symbols[i] = OSSwapInt32(indirect_symbols[i]); +} + +void +swap_dylib_reference( +struct dylib_reference *refs, +uint32_t nrefs, +enum NXByteOrder target_byte_sex) +{ + struct swapped_dylib_reference { + union { + struct { + uint32_t + flags:8, + isym:24; + } fields; + uint32_t word; + } u; + } sref; + + uint32_t i; + enum NXByteOrder host_byte_sex; + + host_byte_sex = NXHostByteOrder(); + + for(i = 0; i < nrefs; i++){ + if(target_byte_sex == host_byte_sex){ + memcpy(&sref, refs + i, sizeof(struct swapped_dylib_reference)); + sref.u.word = OSSwapInt32(sref.u.word); + refs[i].flags = sref.u.fields.flags; + refs[i].isym = sref.u.fields.isym; + } + else{ + sref.u.fields.isym = refs[i].isym; + sref.u.fields.flags = refs[i].flags; + sref.u.word = OSSwapInt32(sref.u.word); + memcpy(refs + i, &sref, sizeof(struct swapped_dylib_reference)); + } + } + +} + +void +swap_dylib_module( +struct dylib_module *mods, +uint32_t nmods, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + + for(i = 0; i < nmods; i++){ + mods[i].module_name = OSSwapInt32(mods[i].module_name); + mods[i].iextdefsym = OSSwapInt32(mods[i].iextdefsym); + mods[i].nextdefsym = OSSwapInt32(mods[i].nextdefsym); + mods[i].irefsym = OSSwapInt32(mods[i].irefsym); + mods[i].nrefsym = OSSwapInt32(mods[i].nrefsym); + mods[i].ilocalsym = OSSwapInt32(mods[i].ilocalsym); + mods[i].nlocalsym = OSSwapInt32(mods[i].nlocalsym); + mods[i].iextrel = OSSwapInt32(mods[i].iextrel); + mods[i].nextrel = OSSwapInt32(mods[i].nextrel); + mods[i].iinit_iterm = OSSwapInt32(mods[i].iinit_iterm); + mods[i].ninit_nterm = OSSwapInt32(mods[i].ninit_nterm); + mods[i].objc_module_info_size = OSSwapInt32(mods[i].objc_module_info_size); + mods[i].objc_module_info_addr = OSSwapInt32(mods[i].objc_module_info_addr); + } +} + +void +swap_dylib_module_64( +struct dylib_module_64 *mods, +uint32_t nmods, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + + for(i = 0; i < nmods; i++){ + mods[i].module_name = OSSwapInt32(mods[i].module_name); + mods[i].iextdefsym = OSSwapInt32(mods[i].iextdefsym); + mods[i].nextdefsym = OSSwapInt32(mods[i].nextdefsym); + mods[i].irefsym = OSSwapInt32(mods[i].irefsym); + mods[i].nrefsym = OSSwapInt32(mods[i].nrefsym); + mods[i].ilocalsym = OSSwapInt32(mods[i].ilocalsym); + mods[i].nlocalsym = OSSwapInt32(mods[i].nlocalsym); + mods[i].iextrel = OSSwapInt32(mods[i].iextrel); + mods[i].nextrel = OSSwapInt32(mods[i].nextrel); + mods[i].iinit_iterm = OSSwapInt32(mods[i].iinit_iterm); + mods[i].ninit_nterm = OSSwapInt32(mods[i].ninit_nterm); + mods[i].objc_module_info_size = OSSwapInt32(mods[i].objc_module_info_size); + mods[i].objc_module_info_addr = OSSwapInt64(mods[i].objc_module_info_addr); + } +} + +void +swap_dylib_table_of_contents( +struct dylib_table_of_contents *tocs, +uint32_t ntocs, +enum NXByteOrder target_byte_sex) +{ + uint32_t i; + + for(i = 0; i < ntocs; i++){ + tocs[i].symbol_index = OSSwapInt32(tocs[i].symbol_index); + tocs[i].module_index = OSSwapInt32(tocs[i].module_index); + } +} +#endif /* !defined(RLD) */ diff --git a/cctools/libobjc2/Makefile.in b/cctools/libobjc2/Makefile.in new file mode 100644 index 0000000..2d90427 --- /dev/null +++ b/cctools/libobjc2/Makefile.in @@ -0,0 +1,795 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libobjc2 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libobjc_la_LIBADD = +am_libobjc_la_OBJECTS = libobjc_la-NSBlocks.lo libobjc_la-Protocol2.lo \ + libobjc_la-abi_version.lo libobjc_la-alias_table.lo \ + libobjc_la-arc.lo libobjc_la-associate.lo \ + libobjc_la-blocks_runtime.lo libobjc_la-block_to_imp.lo \ + libobjc_la-block_trampolines.lo libobjc_la-objc_msgSend.lo \ + libobjc_la-caps.lo libobjc_la-category_loader.lo \ + libobjc_la-class_table.lo libobjc_la-dtable.lo \ + libobjc_la-eh_personality.lo libobjc_la-encoding2.lo \ + libobjc_la-gc_none.lo libobjc_la-hash_table.lo \ + libobjc_la-hooks.lo libobjc_la-ivar.lo \ + libobjc_la-legacy_malloc.lo libobjc_la-loader.lo \ + libobjc_la-mutation.lo libobjc_la-properties.lo \ + libobjc_la-protocol.lo libobjc_la-runtime.lo \ + libobjc_la-sarray2.lo libobjc_la-selector_table.lo \ + libobjc_la-sendmsg2.lo libobjc_la-statics_loader.lo \ + libobjc_la-toydispatch.lo +libobjc_la_OBJECTS = $(am_libobjc_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libobjc_la_LINK = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(OBJCLD) $(libobjc_la_OBJCFLAGS) \ + $(OBJCFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +CPPASCOMPILE = $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) +LTCPPASCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CCASFLAGS) $(CCASFLAGS) +AM_V_CPPAS = $(am__v_CPPAS_@AM_V@) +am__v_CPPAS_ = $(am__v_CPPAS_@AM_DEFAULT_V@) +am__v_CPPAS_0 = @echo " CPPAS " $@; +am__v_CPPAS_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +OBJCCOMPILE = $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_OBJCFLAGS) $(OBJCFLAGS) +LTOBJCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_OBJCFLAGS) $(OBJCFLAGS) +AM_V_OBJC = $(am__v_OBJC_@AM_V@) +am__v_OBJC_ = $(am__v_OBJC_@AM_DEFAULT_V@) +am__v_OBJC_0 = @echo " OBJC " $@; +am__v_OBJC_1 = +OBJCLD = $(OBJC) +OBJCLINK = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(OBJCLD) $(AM_OBJCFLAGS) $(OBJCFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_OBJCLD = $(am__v_OBJCLD_@AM_V@) +am__v_OBJCLD_ = $(am__v_OBJCLD_@AM_DEFAULT_V@) +am__v_OBJCLD_0 = @echo " OBJCLD " $@; +am__v_OBJCLD_1 = +SOURCES = $(libobjc_la_SOURCES) +DIST_SOURCES = $(libobjc_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in COPYING INSTALL README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libobjc.la +libobjc_la_CPPFLAGS = -DTYPE_DEPENDENT_DISPATCH -DGNUSTEP -D__OBJC_RUNTIME_INTERNAL__=1 -D_XOPEN_SOURCE=500 -D__BSD_VISIBLE=1 -D_DEFAULT_SOURCE=1 -DNO_SELECTOR_MISMATCH_WARNINGS +libobjc_la_CFLAGS = -std=gnu99 -fPIC -fexceptions $(WARNINGS) +libobjc_la_OBJCFLAGS = -std=gnu99 $(OBJCWARNINGS) +libobjc_la_SOURCES = \ + NSBlocks.m\ + Protocol2.m\ + abi_version.c\ + alias_table.c\ + arc.m\ + associate.m\ + blocks_runtime.m\ + block_to_imp.c\ + block_trampolines.S\ + objc_msgSend.S\ + caps.c\ + category_loader.c\ + class_table.c\ + dtable.c\ + eh_personality.c\ + encoding2.c\ + gc_none.c\ + hash_table.c\ + hooks.c\ + ivar.c\ + legacy_malloc.c\ + loader.c\ + mutation.m\ + properties.m\ + protocol.c\ + runtime.c\ + sarray2.c\ + selector_table.c\ + sendmsg2.c\ + statics_loader.c\ + toydispatch.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .S .c .lo .m .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps libobjc2/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps libobjc2/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libobjc.la: $(libobjc_la_OBJECTS) $(libobjc_la_DEPENDENCIES) $(EXTRA_libobjc_la_DEPENDENCIES) + $(AM_V_OBJCLD)$(libobjc_la_LINK) $(libobjc_la_OBJECTS) $(libobjc_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.S.o: + $(AM_V_CPPAS)$(CPPASCOMPILE) -c -o $@ $< + +.S.obj: + $(AM_V_CPPAS)$(CPPASCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.S.lo: + $(AM_V_CPPAS)$(LTCPPASCOMPILE) -c -o $@ $< + +libobjc_la-block_trampolines.lo: block_trampolines.S + $(AM_V_CPPAS)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o libobjc_la-block_trampolines.lo `test -f 'block_trampolines.S' || echo '$(srcdir)/'`block_trampolines.S + +libobjc_la-objc_msgSend.lo: objc_msgSend.S + $(AM_V_CPPAS)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o libobjc_la-objc_msgSend.lo `test -f 'objc_msgSend.S' || echo '$(srcdir)/'`objc_msgSend.S + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +libobjc_la-abi_version.lo: abi_version.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-abi_version.lo `test -f 'abi_version.c' || echo '$(srcdir)/'`abi_version.c + +libobjc_la-alias_table.lo: alias_table.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-alias_table.lo `test -f 'alias_table.c' || echo '$(srcdir)/'`alias_table.c + +libobjc_la-block_to_imp.lo: block_to_imp.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-block_to_imp.lo `test -f 'block_to_imp.c' || echo '$(srcdir)/'`block_to_imp.c + +libobjc_la-caps.lo: caps.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-caps.lo `test -f 'caps.c' || echo '$(srcdir)/'`caps.c + +libobjc_la-category_loader.lo: category_loader.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-category_loader.lo `test -f 'category_loader.c' || echo '$(srcdir)/'`category_loader.c + +libobjc_la-class_table.lo: class_table.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-class_table.lo `test -f 'class_table.c' || echo '$(srcdir)/'`class_table.c + +libobjc_la-dtable.lo: dtable.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-dtable.lo `test -f 'dtable.c' || echo '$(srcdir)/'`dtable.c + +libobjc_la-eh_personality.lo: eh_personality.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-eh_personality.lo `test -f 'eh_personality.c' || echo '$(srcdir)/'`eh_personality.c + +libobjc_la-encoding2.lo: encoding2.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-encoding2.lo `test -f 'encoding2.c' || echo '$(srcdir)/'`encoding2.c + +libobjc_la-gc_none.lo: gc_none.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-gc_none.lo `test -f 'gc_none.c' || echo '$(srcdir)/'`gc_none.c + +libobjc_la-hash_table.lo: hash_table.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-hash_table.lo `test -f 'hash_table.c' || echo '$(srcdir)/'`hash_table.c + +libobjc_la-hooks.lo: hooks.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-hooks.lo `test -f 'hooks.c' || echo '$(srcdir)/'`hooks.c + +libobjc_la-ivar.lo: ivar.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-ivar.lo `test -f 'ivar.c' || echo '$(srcdir)/'`ivar.c + +libobjc_la-legacy_malloc.lo: legacy_malloc.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-legacy_malloc.lo `test -f 'legacy_malloc.c' || echo '$(srcdir)/'`legacy_malloc.c + +libobjc_la-loader.lo: loader.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-loader.lo `test -f 'loader.c' || echo '$(srcdir)/'`loader.c + +libobjc_la-protocol.lo: protocol.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-protocol.lo `test -f 'protocol.c' || echo '$(srcdir)/'`protocol.c + +libobjc_la-runtime.lo: runtime.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-runtime.lo `test -f 'runtime.c' || echo '$(srcdir)/'`runtime.c + +libobjc_la-sarray2.lo: sarray2.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-sarray2.lo `test -f 'sarray2.c' || echo '$(srcdir)/'`sarray2.c + +libobjc_la-selector_table.lo: selector_table.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-selector_table.lo `test -f 'selector_table.c' || echo '$(srcdir)/'`selector_table.c + +libobjc_la-sendmsg2.lo: sendmsg2.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-sendmsg2.lo `test -f 'sendmsg2.c' || echo '$(srcdir)/'`sendmsg2.c + +libobjc_la-statics_loader.lo: statics_loader.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-statics_loader.lo `test -f 'statics_loader.c' || echo '$(srcdir)/'`statics_loader.c + +libobjc_la-toydispatch.lo: toydispatch.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_CFLAGS) $(CFLAGS) -c -o libobjc_la-toydispatch.lo `test -f 'toydispatch.c' || echo '$(srcdir)/'`toydispatch.c + +.m.o: + $(AM_V_OBJC)$(OBJCCOMPILE) -c -o $@ $< + +.m.obj: + $(AM_V_OBJC)$(OBJCCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.m.lo: + $(AM_V_OBJC)$(LTOBJCCOMPILE) -c -o $@ $< + +libobjc_la-NSBlocks.lo: NSBlocks.m + $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libobjc_la-NSBlocks.lo `test -f 'NSBlocks.m' || echo '$(srcdir)/'`NSBlocks.m + +libobjc_la-Protocol2.lo: Protocol2.m + $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libobjc_la-Protocol2.lo `test -f 'Protocol2.m' || echo '$(srcdir)/'`Protocol2.m + +libobjc_la-arc.lo: arc.m + $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libobjc_la-arc.lo `test -f 'arc.m' || echo '$(srcdir)/'`arc.m + +libobjc_la-associate.lo: associate.m + $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libobjc_la-associate.lo `test -f 'associate.m' || echo '$(srcdir)/'`associate.m + +libobjc_la-blocks_runtime.lo: blocks_runtime.m + $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libobjc_la-blocks_runtime.lo `test -f 'blocks_runtime.m' || echo '$(srcdir)/'`blocks_runtime.m + +libobjc_la-mutation.lo: mutation.m + $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libobjc_la-mutation.lo `test -f 'mutation.m' || echo '$(srcdir)/'`mutation.m + +libobjc_la-properties.lo: properties.m + $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libobjc_la_CPPFLAGS) $(CPPFLAGS) $(libobjc_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libobjc_la-properties.lo `test -f 'properties.m' || echo '$(srcdir)/'`properties.m + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/libstuff/Makefile.am b/cctools/libstuff/Makefile.am index 0219b9c..2d54494 100644 --- a/cctools/libstuff/Makefile.am +++ b/cctools/libstuff/Makefile.am @@ -2,6 +2,8 @@ noinst_LTLIBRARIES = libstuff.la libstuff_la_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -D__DARWIN_UNIX03 $(WARNINGS) $(LTO_DEF) -DPROGRAM_PREFIX="\"$(PROGRAM_PREFIX)\"" $(ENDIAN_FLAG) +libstuff_la_LDFLAGS = $(FTS_LIB) + libstuff_la_SOURCES = \ allocate.c \ apple_version.c \ @@ -41,5 +43,8 @@ libstuff_la_SOURCES = \ unix_standard_mode.c \ version_number.c \ writeout.c \ - coff_bytesex.c + write64.c \ + coff_bytesex.c \ + args.c + diff --git a/cctools/libstuff/Makefile.in b/cctools/libstuff/Makefile.in new file mode 100644 index 0000000..b2d2d31 --- /dev/null +++ b/cctools/libstuff/Makefile.in @@ -0,0 +1,794 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libstuff +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libstuff_la_LIBADD = +am_libstuff_la_OBJECTS = libstuff_la-allocate.lo \ + libstuff_la-apple_version.lo libstuff_la-arch.lo \ + libstuff_la-arch_usage.lo libstuff_la-best_arch.lo \ + libstuff_la-breakout.lo libstuff_la-bytesex.lo \ + libstuff_la-checkout.lo libstuff_la-crc32.lo \ + libstuff_la-dylib_roots.lo libstuff_la-dylib_table.lo \ + libstuff_la-port.lo libstuff_la-errors.lo \ + libstuff_la-execute.lo libstuff_la-fatal_arch.lo \ + libstuff_la-fatals.lo libstuff_la-get_arch_from_host.lo \ + libstuff_la-get_toc_byte_sex.lo \ + libstuff_la-guess_short_name.lo libstuff_la-hash_string.lo \ + libstuff_la-hppa.lo libstuff_la-llvm.lo libstuff_la-lto.lo \ + libstuff_la-macosx_deployment_target.lo libstuff_la-ofile.lo \ + libstuff_la-ofile_error.lo libstuff_la-ofile_get_word.lo \ + libstuff_la-print.lo libstuff_la-reloc.lo libstuff_la-rnd.lo \ + libstuff_la-seg_addr_table.lo \ + libstuff_la-set_arch_flag_name.lo libstuff_la-swap_headers.lo \ + libstuff_la-symbol_list.lo libstuff_la-SymLoc.lo \ + libstuff_la-unix_standard_mode.lo \ + libstuff_la-version_number.lo libstuff_la-writeout.lo \ + libstuff_la-write64.lo libstuff_la-coff_bytesex.lo \ + libstuff_la-args.lo +libstuff_la_OBJECTS = $(am_libstuff_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libstuff_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libstuff_la_CFLAGS) \ + $(CFLAGS) $(libstuff_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libstuff_la_SOURCES) +DIST_SOURCES = $(libstuff_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libstuff.la +libstuff_la_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -D__DARWIN_UNIX03 $(WARNINGS) $(LTO_DEF) -DPROGRAM_PREFIX="\"$(PROGRAM_PREFIX)\"" $(ENDIAN_FLAG) +libstuff_la_LDFLAGS = $(FTS_LIB) +libstuff_la_SOURCES = \ + allocate.c \ + apple_version.c \ + arch.c \ + arch_usage.c \ + best_arch.c \ + breakout.c \ + bytesex.c \ + checkout.c \ + crc32.c \ + dylib_roots.c \ + dylib_table.c \ + port.c \ + errors.c \ + execute.c \ + fatal_arch.c \ + fatals.c \ + get_arch_from_host.c \ + get_toc_byte_sex.c \ + guess_short_name.c \ + hash_string.c \ + hppa.c \ + llvm.c \ + lto.c \ + macosx_deployment_target.c \ + ofile.c \ + ofile_error.c \ + ofile_get_word.c \ + print.c \ + reloc.c \ + rnd.c \ + seg_addr_table.c \ + set_arch_flag_name.c \ + swap_headers.c \ + symbol_list.c \ + SymLoc.c \ + unix_standard_mode.c \ + version_number.c \ + writeout.c \ + write64.c \ + coff_bytesex.c \ + args.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps libstuff/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps libstuff/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libstuff.la: $(libstuff_la_OBJECTS) $(libstuff_la_DEPENDENCIES) $(EXTRA_libstuff_la_DEPENDENCIES) + $(AM_V_CCLD)$(libstuff_la_LINK) $(libstuff_la_OBJECTS) $(libstuff_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +libstuff_la-allocate.lo: allocate.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-allocate.lo `test -f 'allocate.c' || echo '$(srcdir)/'`allocate.c + +libstuff_la-apple_version.lo: apple_version.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-apple_version.lo `test -f 'apple_version.c' || echo '$(srcdir)/'`apple_version.c + +libstuff_la-arch.lo: arch.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-arch.lo `test -f 'arch.c' || echo '$(srcdir)/'`arch.c + +libstuff_la-arch_usage.lo: arch_usage.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-arch_usage.lo `test -f 'arch_usage.c' || echo '$(srcdir)/'`arch_usage.c + +libstuff_la-best_arch.lo: best_arch.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-best_arch.lo `test -f 'best_arch.c' || echo '$(srcdir)/'`best_arch.c + +libstuff_la-breakout.lo: breakout.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-breakout.lo `test -f 'breakout.c' || echo '$(srcdir)/'`breakout.c + +libstuff_la-bytesex.lo: bytesex.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-bytesex.lo `test -f 'bytesex.c' || echo '$(srcdir)/'`bytesex.c + +libstuff_la-checkout.lo: checkout.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-checkout.lo `test -f 'checkout.c' || echo '$(srcdir)/'`checkout.c + +libstuff_la-crc32.lo: crc32.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-crc32.lo `test -f 'crc32.c' || echo '$(srcdir)/'`crc32.c + +libstuff_la-dylib_roots.lo: dylib_roots.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-dylib_roots.lo `test -f 'dylib_roots.c' || echo '$(srcdir)/'`dylib_roots.c + +libstuff_la-dylib_table.lo: dylib_table.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-dylib_table.lo `test -f 'dylib_table.c' || echo '$(srcdir)/'`dylib_table.c + +libstuff_la-port.lo: port.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-port.lo `test -f 'port.c' || echo '$(srcdir)/'`port.c + +libstuff_la-errors.lo: errors.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-errors.lo `test -f 'errors.c' || echo '$(srcdir)/'`errors.c + +libstuff_la-execute.lo: execute.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-execute.lo `test -f 'execute.c' || echo '$(srcdir)/'`execute.c + +libstuff_la-fatal_arch.lo: fatal_arch.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-fatal_arch.lo `test -f 'fatal_arch.c' || echo '$(srcdir)/'`fatal_arch.c + +libstuff_la-fatals.lo: fatals.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-fatals.lo `test -f 'fatals.c' || echo '$(srcdir)/'`fatals.c + +libstuff_la-get_arch_from_host.lo: get_arch_from_host.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-get_arch_from_host.lo `test -f 'get_arch_from_host.c' || echo '$(srcdir)/'`get_arch_from_host.c + +libstuff_la-get_toc_byte_sex.lo: get_toc_byte_sex.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-get_toc_byte_sex.lo `test -f 'get_toc_byte_sex.c' || echo '$(srcdir)/'`get_toc_byte_sex.c + +libstuff_la-guess_short_name.lo: guess_short_name.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-guess_short_name.lo `test -f 'guess_short_name.c' || echo '$(srcdir)/'`guess_short_name.c + +libstuff_la-hash_string.lo: hash_string.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-hash_string.lo `test -f 'hash_string.c' || echo '$(srcdir)/'`hash_string.c + +libstuff_la-hppa.lo: hppa.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-hppa.lo `test -f 'hppa.c' || echo '$(srcdir)/'`hppa.c + +libstuff_la-llvm.lo: llvm.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-llvm.lo `test -f 'llvm.c' || echo '$(srcdir)/'`llvm.c + +libstuff_la-lto.lo: lto.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-lto.lo `test -f 'lto.c' || echo '$(srcdir)/'`lto.c + +libstuff_la-macosx_deployment_target.lo: macosx_deployment_target.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-macosx_deployment_target.lo `test -f 'macosx_deployment_target.c' || echo '$(srcdir)/'`macosx_deployment_target.c + +libstuff_la-ofile.lo: ofile.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-ofile.lo `test -f 'ofile.c' || echo '$(srcdir)/'`ofile.c + +libstuff_la-ofile_error.lo: ofile_error.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-ofile_error.lo `test -f 'ofile_error.c' || echo '$(srcdir)/'`ofile_error.c + +libstuff_la-ofile_get_word.lo: ofile_get_word.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-ofile_get_word.lo `test -f 'ofile_get_word.c' || echo '$(srcdir)/'`ofile_get_word.c + +libstuff_la-print.lo: print.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-print.lo `test -f 'print.c' || echo '$(srcdir)/'`print.c + +libstuff_la-reloc.lo: reloc.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-reloc.lo `test -f 'reloc.c' || echo '$(srcdir)/'`reloc.c + +libstuff_la-rnd.lo: rnd.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-rnd.lo `test -f 'rnd.c' || echo '$(srcdir)/'`rnd.c + +libstuff_la-seg_addr_table.lo: seg_addr_table.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-seg_addr_table.lo `test -f 'seg_addr_table.c' || echo '$(srcdir)/'`seg_addr_table.c + +libstuff_la-set_arch_flag_name.lo: set_arch_flag_name.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-set_arch_flag_name.lo `test -f 'set_arch_flag_name.c' || echo '$(srcdir)/'`set_arch_flag_name.c + +libstuff_la-swap_headers.lo: swap_headers.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-swap_headers.lo `test -f 'swap_headers.c' || echo '$(srcdir)/'`swap_headers.c + +libstuff_la-symbol_list.lo: symbol_list.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-symbol_list.lo `test -f 'symbol_list.c' || echo '$(srcdir)/'`symbol_list.c + +libstuff_la-SymLoc.lo: SymLoc.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-SymLoc.lo `test -f 'SymLoc.c' || echo '$(srcdir)/'`SymLoc.c + +libstuff_la-unix_standard_mode.lo: unix_standard_mode.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-unix_standard_mode.lo `test -f 'unix_standard_mode.c' || echo '$(srcdir)/'`unix_standard_mode.c + +libstuff_la-version_number.lo: version_number.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-version_number.lo `test -f 'version_number.c' || echo '$(srcdir)/'`version_number.c + +libstuff_la-writeout.lo: writeout.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-writeout.lo `test -f 'writeout.c' || echo '$(srcdir)/'`writeout.c + +libstuff_la-write64.lo: write64.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-write64.lo `test -f 'write64.c' || echo '$(srcdir)/'`write64.c + +libstuff_la-coff_bytesex.lo: coff_bytesex.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-coff_bytesex.lo `test -f 'coff_bytesex.c' || echo '$(srcdir)/'`coff_bytesex.c + +libstuff_la-args.lo: args.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstuff_la_CFLAGS) $(CFLAGS) -c -o libstuff_la-args.lo `test -f 'args.c' || echo '$(srcdir)/'`args.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/libstuff/SymLoc.c b/cctools/libstuff/SymLoc.c index 08098e5..c2301f5 100644 --- a/cctools/libstuff/SymLoc.c +++ b/cctools/libstuff/SymLoc.c @@ -71,7 +71,7 @@ enum bool no_error_if_missing) char *c = NULL; char *v = NULL; char *viewMap = NULL; - int releaseLen = strlen(releaseName); + size_t releaseLen = strlen(releaseName); char buf[MAXPATHLEN+MAXNAMLEN+64]; char readbuf[MAXPATHLEN+64]; char viewPath[MAXPATHLEN]; diff --git a/cctools/libstuff/allocate.c b/cctools/libstuff/allocate.c index 318fba4..fa8b44c 100644 --- a/cctools/libstuff/allocate.c +++ b/cctools/libstuff/allocate.c @@ -105,6 +105,7 @@ const char *args, size += strlen(p); p = (char *)va_arg(ap, char *); } + va_end(ap); } s = allocate(size + 1); *s = '\0'; diff --git a/cctools/libstuff/arch.c b/cctools/libstuff/arch.c index e43c240..6f2332f 100644 --- a/cctools/libstuff/arch.c +++ b/cctools/libstuff/arch.c @@ -52,6 +52,8 @@ static const struct arch_flag arch_flags[] = { { "arm64", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL }, /* specific architecture implementations */ { "ppc970-64", CPU_TYPE_POWERPC64, CPU_SUBTYPE_POWERPC_970 }, + { "arm64_32", CPU_TYPE_ARM64_32, CPU_SUBTYPE_ARM64_32_V8 }, + { "arm64e", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64E }, /* 32-bit Mach-O architectures */ @@ -107,6 +109,50 @@ static const struct arch_flag arch_flags[] = { { NULL, 0, 0 } }; +struct cpu_entry { + cpu_type_t cputype; + enum byte_sex endian; + uint64_t staddr; + uint32_t segalign; +}; + +/* + * The cpu_entries table holds vital statistics for a number of entries in the + * arch_info table. Functions such as get_byte_sex_from_flag() are driven off + * the contents of this table, making it easier to add new cputypes. Rows in + * the table are organized by frequency, with the most common / recent at the + * top of the list. + * + * Note that some historical architectures, such as NeXTSTEP's i386 and + * Rhapsody's PPC, are no longer addressible with this design. + */ + +static const struct cpu_entry cpu_entries[] = { + /* embedded */ + { CPU_TYPE_ARM64, LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000 }, + { CPU_TYPE_ARM64_32, LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000 }, + { CPU_TYPE_ARM, LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000 }, + + /* desktop */ + { CPU_TYPE_X86_64, LITTLE_ENDIAN_BYTE_SEX, 0x7fff5fc00000LL, 0x1000 }, + { CPU_TYPE_I386, LITTLE_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000 }, + { CPU_TYPE_POWERPC, BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000 }, + { CPU_TYPE_POWERPC64, BIG_ENDIAN_BYTE_SEX, 0x7ffff00000000LL, 0x1000 }, + { CPU_TYPE_VEO, BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000 }, + + /* NeXTSTEP / Rhapsody */ + /* + { CPU_TYPE_I386, LITTLE_ENDIAN_BYTE_SEX, 0xc0000000, 0x2000 }, + { CPU_TYPE_POWERPC, BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x2000 }, + */ + { CPU_TYPE_MC680x0, BIG_ENDIAN_BYTE_SEX, 0x04000000, 0x2000 }, + { CPU_TYPE_MC88000, BIG_ENDIAN_BYTE_SEX, 0xffffe000, 0x2000 }, + { CPU_TYPE_SPARC, BIG_ENDIAN_BYTE_SEX, 0xf0000000, 0x2000 }, + { CPU_TYPE_I860, BIG_ENDIAN_BYTE_SEX, 0, 0x2000 }, + { CPU_TYPE_HPPA, BIG_ENDIAN_BYTE_SEX, 0, 0x2000 }, + { 0 }, +}; + #ifndef RLD /* * get_arch_from_flag() is passed a name of an architecture flag and returns @@ -159,25 +205,46 @@ get_arch_name_from_types( cpu_type_t cputype, cpu_subtype_t cpusubtype) { - uint32_t i; + const char *s; char *p; + s = get_arch_name_if_known(cputype, cpusubtype); + if (s == NULL) { +#ifndef RLD + p = savestr("cputype 1234567890 cpusubtype 1234567890"); + if(p != NULL) + sprintf(p, "cputype %u cpusubtype %u", cputype, + cpusubtype & ~CPU_SUBTYPE_MASK); +#else + /* there is no sprintf() in the rld kernel API's */ + p = savestr("cputype ?? cpusubtype ??"); +#endif + s = p; + } + + return(s); +} + +/* + * get_arch_name_if_known() returns the name of the architecture for the + * specified cputype and cpusubtype if known. If unknown it returns NULL. + */ +__private_extern__ +const char * +get_arch_name_if_known( +cpu_type_t cputype, +cpu_subtype_t cpusubtype) +{ + uint32_t i; + for(i = 0; arch_flags[i].name != NULL; i++){ if(arch_flags[i].cputype == cputype && (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) == (cpusubtype & ~CPU_SUBTYPE_MASK)) return(arch_flags[i].name); } -#ifndef RLD - p = savestr("cputype 1234567890 cpusubtype 1234567890"); - if(p != NULL) - sprintf(p, "cputype %u cpusubtype %u", cputype, - cpusubtype & ~CPU_SUBTYPE_MASK); -#else - /* there is no sprintf() in the rld kernel API's */ - p = savestr("cputype ?? cpusubtype ??"); -#endif - return(p); + + return(NULL); } /* @@ -191,6 +258,9 @@ cpu_type_t cputype) { uint32_t i; + /* arm64 is not to match a family but the specific arm64 arch */ + if(cputype == CPU_TYPE_ARM64) + return(NULL); for(i = 0; arch_flags[i].name != NULL; i++){ if(arch_flags[i].cputype == cputype) return(arch_flags + i); @@ -198,6 +268,36 @@ cpu_type_t cputype) return(NULL); } +/* + * abort_with_unknown_cputype() is a helper function to make calls to abort() + * more descriptive in a symbolicated backtrace. + */ +static +void +abort_with_unknown_cputype(cpu_type_t cputype) +{ + abort(); +} + +/* + * get_cpu_entry_from_cputype() for the specified cputype. If unknown it + * calls abort_with_unknown_cputype(). + */ +static +const struct cpu_entry * +get_cpu_entry_from_cputype(cpu_type_t cputype) +{ + for (uint32_t i = 0; cpu_entries[i].cputype != 0; ++i) + { + if (cpu_entries[i].cputype == cputype) + return cpu_entries + i; + } + + abort_with_unknown_cputype(cputype); + + return NULL; /* unreachable */ +} + /* * get_byte_sex_from_flag() returns the byte sex of the architecture for the * specified cputype and cpusubtype if known. If unknown it returns @@ -210,49 +310,12 @@ enum byte_sex get_byte_sex_from_flag( const struct arch_flag *flag) { - if(flag->cputype == CPU_TYPE_MC680x0 || - flag->cputype == CPU_TYPE_MC88000 || - flag->cputype == CPU_TYPE_POWERPC || - flag->cputype == CPU_TYPE_POWERPC64 || - flag->cputype == CPU_TYPE_HPPA || - flag->cputype == CPU_TYPE_SPARC || - flag->cputype == CPU_TYPE_I860 || - flag->cputype == CPU_TYPE_VEO) - return BIG_ENDIAN_BYTE_SEX; - else if(flag->cputype == CPU_TYPE_I386 || - flag->cputype == CPU_TYPE_X86_64 || - flag->cputype == CPU_TYPE_ARM64 || - flag->cputype == CPU_TYPE_ARM) - return LITTLE_ENDIAN_BYTE_SEX; - else - return UNKNOWN_BYTE_SEX; + const struct cpu_entry *entry = get_cpu_entry_from_cputype(flag->cputype); + + return entry->endian; } #ifndef RLD -/* - * get_stack_direction_from_flag() returns the direction the stack grows as - * either positive (+1) or negative (-1) of the architecture for the - * specified cputype and cpusubtype if known. If unknown it returns 0. - */ -__private_extern__ -int -get_stack_direction_from_flag( -const struct arch_flag *flag) -{ - if(flag->cputype == CPU_TYPE_MC680x0 || - flag->cputype == CPU_TYPE_MC88000 || - flag->cputype == CPU_TYPE_POWERPC || - flag->cputype == CPU_TYPE_I386 || - flag->cputype == CPU_TYPE_SPARC || - flag->cputype == CPU_TYPE_I860 || - flag->cputype == CPU_TYPE_VEO || - flag->cputype == CPU_TYPE_ARM) - return(-1); - else if(flag->cputype == CPU_TYPE_HPPA) - return(+1); - else - return(0); -} /* * get_stack_addr_from_flag() returns the default starting address of the user @@ -266,53 +329,11 @@ uint64_t get_stack_addr_from_flag( const struct arch_flag *flag) { - switch(flag->cputype){ - case CPU_TYPE_MC680x0: - return(0x04000000); - case CPU_TYPE_MC88000: - return(0xffffe000); - case CPU_TYPE_POWERPC: - case CPU_TYPE_VEO: - case CPU_TYPE_I386: - return(0xc0000000); - case CPU_TYPE_ARM: - return(0x30000000); - case CPU_TYPE_SPARC: - return(0xf0000000); - case CPU_TYPE_I860: - return(0); - case CPU_TYPE_HPPA: - return(0xc0000000-0x04000000); - case CPU_TYPE_POWERPC64: - return(0x7ffff00000000LL); - case CPU_TYPE_X86_64: - return(0x7fff5fc00000LL); - default: - return(0); - } + const struct cpu_entry *entry = get_cpu_entry_from_cputype(flag->cputype); + + return entry->staddr; } -/* - * get_stack_size_from_flag() returns the default size of the userstack. This - * should be in the header file as MAXSSIZ. Since some - * architectures have come and gone and come back, you can't include all of - * these headers in one source and some of the constants covered the whole - * address space the common value of 64meg was chosen. - */ -__private_extern__ -uint32_t -get_stack_size_from_flag( -const struct arch_flag *flag) -{ -#ifdef __MWERKS__ - const struct arch_flag *dummy; - dummy = flag; -#endif - - return(64*1024*1024); -} -#endif /* !defined(RLD) */ - /* * get_segalign_from_flag() returns the default segment alignment (page size). */ @@ -321,32 +342,9 @@ uint32_t get_segalign_from_flag( const struct arch_flag *flag) { - if(flag->cputype == CPU_TYPE_ARM || - flag->cputype == CPU_TYPE_ARM64) - return(0x4000); /* 16K */ - - if(flag->cputype == CPU_TYPE_POWERPC || - flag->cputype == CPU_TYPE_POWERPC64 || - flag->cputype == CPU_TYPE_VEO || - flag->cputype == CPU_TYPE_I386 || - flag->cputype == CPU_TYPE_X86_64) - return(0x1000); /* 4K */ - else - return(0x2000); /* 8K */ -} - -/* - * get_segprot_from_flag() returns the default segment protection. - */ -__private_extern__ -vm_prot_t -get_segprot_from_flag( -const struct arch_flag *flag) -{ - if(flag->cputype == CPU_TYPE_I386) - return(VM_PROT_READ | VM_PROT_WRITE); - else - return(VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE); + const struct cpu_entry *entry = get_cpu_entry_from_cputype(flag->cputype); + + return entry->segalign; } /* @@ -379,3 +377,5 @@ cpu_type_t cputype) else return(FALSE); } + +#endif /* !defined(RLD) */ diff --git a/cctools/libstuff/args.c b/cctools/libstuff/args.c new file mode 100644 index 0000000..c54b530 --- /dev/null +++ b/cctools/libstuff/args.c @@ -0,0 +1,423 @@ +// +// args.c +// stuff +// +// Created by Michael Trent on 5/31/19. +// + +#include "stuff/args.h" +#include "stuff/errors.h" +#include "stuff/port.h" /* cctools-port: reallocf() */ + +#include +#include +#include +#include /* cctools-port */ +#include +#include +#include +#include + +enum expand_result { + EXPAND_ERROR = -1, + EXPAND_COMPLETE = 0, + EXPAND_CONTINUE = 1, +}; + +/* + * struct string_list is a poor-man's alternative to std::vector, + * "managing" a list of strings. a zeroed structure represents a valid empty + * string list; i.e., "struct string_list strings = {0};". if non-NULL, the + * strs member must point to malloced, reallocable memory; each string in the + * strs array must also be individually malloced. the strs array is expected + * to be only large enough to hold nstr string pointers, it is not generally + * null terminated. + * + * it should become its own libstuff module if it has utility in other placees. + */ +struct string_list { + int nstr; + char** strs; +}; + +static enum expand_result expand_at(struct string_list *args, +struct string_list* at_paths, int *hint_p); + +static char* get_option(char** buf); + +static void string_list_add(struct string_list* list, const char* str); +static void string_list_add_argv(struct string_list* list, int argc, +char** argv); +static int string_list_find(const struct string_list* list, const char* str); +static void string_list_dest(struct string_list* list); + +/* + * args_expand_at() recursively expands "@file" options as they appear in the + * argc/argv options list. + */ +int args_expand_at(int* argc_p, char** argv_p[]) +{ + int hint = 0; + enum expand_result result = EXPAND_CONTINUE; + struct string_list at_paths = {0}; + struct string_list args = {0}; + + if (!argc_p || !argv_p) { + errno = EINVAL; + return -1; + } + + // copy the arguments into a private structure + string_list_add_argv(&args, *argc_p, *argv_p); + + // "recursively" expand at files + while (EXPAND_CONTINUE == result) { + result = expand_at(&args, &at_paths, &hint); + } + + // destroy the at_paths strings + string_list_dest(&at_paths); + + // return the modified values, adding a NULL terminator to the string list + if (result == EXPAND_COMPLETE) { + args.strs = reallocf(args.strs, sizeof(char*) * (args.nstr + 1)); + if (!args.strs) + system_fatal("reallocf failed"); + args.strs[args.nstr] = NULL; + + *argc_p = args.nstr; + *argv_p = args.strs; + } + + return result == EXPAND_COMPLETE ? 0 : -1; +} + +/* + * expand_at is the worker function that expands "@file" options as they + * appear in the argv array. it's designed to be called interatively, so that + * we can provide recursive "@file" references without blowing out the stack + * or imposing an arbitrary maximum. + * + * args is the argc/argv options list expressed in a string_list structure. the + * contents of the struct may be modified if arguments need to be inserted into + * the options list. expand_at requires args to be a proper string_list so it + * can resize or clean up memory as necessary. + * + * expand_at will record the name of @files it encounters during the expansion + * process so that it can return an error on infinitely-recursive input. callers + * should providee memory to an empty struct string_list via at_paths to support + * this feature, and then destroy the string_list contents when the expansion + * process has completed. alternatively, callers can set at_paths to NULL to + * disable the infinite recursion check. + * + * similarly, callers an provide memory for an int via hint_p across multiple + * calls to expand_at. the initial value of *hint_p must be 0. expand_at() will + * use this value to avoid re-examining elements in the option list that have + * already been fully expanded. this optimization can be disabled by passing + * NULL to hint_p. + * + * expand_at will return one of three states: + * + * EXPAND_CONTINUE - expand_at() has modified the options list and additional + * expansion appears to be necessary. callers should re- + * invoke expand_at() with the same set of arguments. + * EXPAND_COMPLETE - expand_at() has examined the options list and no further + * expansion is necessary. expand_at() may or may not have + * modified the args string list. at this point, callers + * are free to examine the contents of args and tear down + * related data structures. + * EXPAND_ERROR - an error was encountered during the expansion process. + * an error message was printed to stderr, and callers can + * examine errno if they like. + * + * usage is typically in a while loop, such as: + * + * // "recursively" expand at files + * enum expand_result result = EXPAND_CONTINUE; + * while (EXPAND_CONTINUE == result) { + * result = expand_at(&args, &at_paths, &hint); + * } + */ +enum expand_result expand_at(struct string_list *args, +struct string_list* at_paths, int *hint_p) +{ + int argc = args->nstr; + char** argv = args->strs; + int hint = hint_p ? *hint_p : 0; + struct string_list newargs = {0}; + enum expand_result result = EXPAND_COMPLETE; + + for (int i = hint; i < argc; ++i) { + if ('@' == argv[i][0]) { + char* at_path = &(argv[i][1]); + + // error if we have seen this path before. + if (at_paths && -1 != string_list_find(at_paths, at_path)) { + fprintf(stderr, "error: recursively loading %s\n", at_path); + return EXPAND_ERROR; + } + + // open the file at this path. If the file does not exist, treat the + // entry like a literal string and continue. + int fd = open(at_path, O_RDONLY); + if (-1 == fd) { + if (ENOENT == errno) { + // awkward. add this option if necessary. + if (newargs.nstr) { + string_list_add(&newargs, argv[i]); + } + continue; + } + fprintf(stderr, "error: can't open %s: %s\n", at_path, strerror(errno)); + return EXPAND_ERROR; + } + + // remember we have opened this file previously + if (at_paths && -1 == string_list_find(at_paths, at_path)) { + string_list_add(at_paths, at_path); + } + + // attempt to map the file into memory. if the file is empty, we will + // simply treat this as an empty buffer. + struct stat sb; + if (fstat(fd, &sb)) { + fprintf(stderr, "error: can't stat %s: %s\n", at_path, strerror(errno)); + close(fd); + return EXPAND_ERROR; + } + + char* addr = NULL; + if (sb.st_size) { + addr = mmap(0, sb.st_size, PROT_READ | PROT_WRITE, + MAP_FILE | MAP_PRIVATE, fd, 0); + if (!addr) { + fprintf(stderr, "error: can't mmap %s: %s\n", at_path, + strerror(errno)); + close(fd); + return EXPAND_ERROR; + } + } + + if (close(fd)) { + fprintf(stderr, "error: can't close %s: %s\n", at_path, + strerror(errno)); + if (munmap(addr, sb.st_size)) + fprintf(stderr, "error: can't munmap %s: %s\n", at_path, + strerror(errno)); + return EXPAND_ERROR; + } + + // build a new argument list now + if (0 == newargs.nstr) { + string_list_add_argv(&newargs, i, args->strs); + *hint_p = i; + } + + // copy the strings in from the at file. If we see another at symbol + // set result to EXPAND_CONTINUE to request additional expansion. + if (addr) { + char* p = addr; + for (char* arg = get_option(&p); arg; arg = get_option(&p)) { + string_list_add(&newargs, arg); + if ('@' == arg[0]) + result = EXPAND_CONTINUE; + } + } + + // unmap the file + if (addr) { + if (munmap(addr, sb.st_size)) { + fprintf(stderr, "error: can't munmap %s: %s\n", at_path, + strerror(errno)); + return EXPAND_ERROR; + } + } + } + else { // if ('@' != argv[i][0]) + // add this literal option if necessary. + if (newargs.nstr) { + string_list_add(&newargs, argv[i]); + } + } + } + + if (newargs.nstr) { + string_list_dest(args); + args->nstr = newargs.nstr; + args->strs = newargs.strs; + } + + return result; +} + +/* + * get_option() tokenizes a string of command-line options separated by + * whitespace. given a pointer to a string, get_option() will return a pointer + * to the first word in that string and adjust the pointer to point to the + * remainder of the string. this promotes usage in a simple loop: + * + * if (string) { + * char* p = string; + * for (char* arg = get_option(&p); arg; arg = get_option(&p)) { + * // do something + * } + * } + * + * the string, buf, provides all of the storage necessary for tokenization; + * both the contents of buf as well as the value of *buf will be modified by + * get_option(). + * + * get_option() honors characters escaped by \ or wrapped in single or double + * quotes. using these features callers can force options to contain whitespace, + * other backslashes, or quote characters. + * + * BUG: get_option() will not return an error if an option contains an + * unterminated quote character. The string "'one more time" will yield a single + * option "'one more time". callers will need to deal with this explicitly, if + * they care. + * + * NB: get_option() will allow callers to incldude quotes in the middle of + * an option; e.g., "one' 'two" will expand to "one two" rather than + * "one" and "two". This is consistent with unix shell behavior, but not + * consistent with some implementations of the @file command line option. + */ +static char* get_option(char** buf) +{ + char* p = NULL; // beginning of option + char* q = NULL; // end of option + + while (buf && *buf && *(*buf)) { + char c = *(*buf); + + // whitespace + // ignore the space. if in an option, end option parsing. the option + // string (q) will be terminated later. + if (' ' == c || '\t' == c || '\n' == c || '\r' == c) { + (*buf)++; + if (p) + break; + } + + // backslash + // ignore the backslash, but treat the next character as a literal + // character. start an option if not yet in an option. + else if ('\\' == c) { + // ignore the backslash (don't advance q) + (*buf)++; + // start a new option if necessary + if (!p) + p = q = *buf; + // if the string continues, include that next character in the option. + if (*(*buf)) { + *q++ = *(*buf); + (*buf)++; + } + } + + // single or double quote + // ignore the quote character, but treat all characters (except backslash + // escaped cahracters) until a closing character as literal characters. + // + // BUG: unterminated quotes are indistinguishable from terminated ones. + else if ('\'' == c || '"' == c) { + // ignore the quote (don't advance q) + (*buf)++; + // start a new option if necessary + if (!p) + p = q = *buf; + // consume remaining characters + while (*(*buf) && c != *(*buf)) { + if ('\\' == *(*buf)) { + // ignore the backslash (don't advance q) + (*buf)++; + // if the string continues, include that next character in the option. + if (*(*buf)) { + *q++ = *(*buf); + (*buf)++; + } + } + else { + // include this character in the option. + *q++ = *(*buf); + (*buf)++; + } + } + // ignore the closing quote if we found one (don't advance q) + if (*(*buf)) + (*buf)++; + } + + // default (all other characters) + // start an option if necessary, and consume the character + else { + if (!p) + p = q = *buf; + *q++ = *(*buf); + (*buf)++; + } + } + + // terminate the option string + if (q) + *q = '\0'; + + return p; +} + +/* + * string_list_add() adds a string to the list. + */ +static void string_list_add(struct string_list* list, const char* str) +{ + list->strs = reallocf(list->strs, sizeof(char*) * (list->nstr + 1)); + if (!list->strs) { + system_fatal("reallocf failed"); + } + list->strs[list->nstr++] = strdup(str); +} + +/* + * string_list_add_argv() adds an array of strings to the string list. + */ +static void string_list_add_argv(struct string_list* list, int argc, +char* argv[]) +{ + list->strs = reallocf(list->strs, sizeof(char*) * (list->nstr + argc)); + if (!list->strs) { + system_fatal("reallocf failed"); + } + for (int i = 0; i < argc; ++i) { + list->strs[list->nstr++] = strdup(argv[i]); + } +} + +/* + * string_list_find() returns the index of str in the string list, or -1 if + * the string is not found. + */ +static int string_list_find(const struct string_list* list, const char* str) +{ + for (int i = 0; i < list->nstr; ++i) { + if (0 == strcmp(str, list->strs[i])) + return i; + } + return -1; +} + +/* + * string_list_dest() frees the individual strings being held in the strs + * array, as well as the strs array itself. it does not free the struct + * strings_list pointer; instead it zeroes out the struct members. + * + * BUG: this function is not called string_list_free() because that might + * imply it also frees the struct string_list, which it does not. + */ +static void string_list_dest(struct string_list* list) +{ + for (int i = 0; i < list->nstr; ++i) { + free(list->strs[i]); + } + free(list->strs); + list->strs = NULL; + list->nstr = 0; +} diff --git a/cctools/libstuff/best_arch.c b/cctools/libstuff/best_arch.c index 23c1a29..1d1eec8 100644 --- a/cctools/libstuff/best_arch.c +++ b/cctools/libstuff/best_arch.c @@ -29,34 +29,47 @@ #ifndef RLD /* - * cpusubtype_findbestarch() is passed a cputype and cpusubtype and a set of - * fat_arch structs and selects the best one that matches (if any) and returns - * a pointer to that fat_arch struct (or NULL). The fat_arch structs must be - * in the host byte sex and correct such that the fat_archs really points to - * enough memory for nfat_arch structs. It is possible that this routine could - * fail if new cputypes or cpusubtypes are added and an old version of this - * routine is used. But if there is an exact match between the cputype and - * cpusubtype and one of the fat_arch structs this routine will always succeed. + * internal_cpusubtype_findbestarch() is passed a cputype and cpusubtype and a + * either set of fat_arch structs or fat_arch_64 structs and selects the best + * one that matches (if any) and returns an index to the array of structs or + * -1 if none works for the cputype and cpusubtype. The fat_arch structs or + * fat_arch_64 structs must be in the host byte sex and correct such that the + * fat_archs really points to enough memory for nfat_arch structs. It is + * possible that this routine could fail if new cputypes or cpusubtypes are + * added and an old version of this routine is used. But if there is an exact + * match between the cputype and cpusubtype and one of the structs this routine + * will always succeed. */ -__private_extern__ -struct fat_arch * -cpusubtype_findbestarch( +static +int32_t +internal_cpusubtype_findbestarch( cpu_type_t cputype, cpu_subtype_t cpusubtype, struct fat_arch *fat_archs, +struct fat_arch_64 *fat_archs64, uint32_t nfat_archs) { - uint32_t i; - long lowest_family, lowest_model, lowest_index; + uint32_t i, lowest_index; + long lowest_family, lowest_model; + cpu_type_t fat_cputype; + cpu_subtype_t fat_cpusubtype; /* * Look for the first exact match. */ for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype == cputype && - (fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype == cputype && + (fat_cpusubtype & ~CPU_SUBTYPE_MASK) == (cpusubtype & ~CPU_SUBTYPE_MASK)) - return(fat_archs + i); + return(i); } /* @@ -86,19 +99,35 @@ uint32_t nfat_archs) */ case CPU_SUBTYPE_POWERPC_970: for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_POWERPC_970) - return(fat_archs + i); + return(i); } default: for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_POWERPC_ALL) - return(fat_archs + i); + return(i); } } break; @@ -110,11 +139,19 @@ uint32_t nfat_archs) switch(cpusubtype & ~CPU_SUBTYPE_MASK){ default: for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_I386_ALL) - return(fat_archs + i); + return(i); } } break; @@ -131,11 +168,19 @@ uint32_t nfat_archs) * earilier subtypes. */ for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_PENT) - return(fat_archs + i); + return(i); } case CPU_SUBTYPE_PENT: case CPU_SUBTYPE_486SX: @@ -144,11 +189,19 @@ uint32_t nfat_archs) * break into the loop to look for the i386_ALL. */ for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_486) - return(fat_archs + i); + return(i); } break; case CPU_SUBTYPE_I386_ALL: @@ -157,78 +210,134 @@ uint32_t nfat_archs) break; } for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_I386_ALL) - return(fat_archs + i); + return(i); } /* * A match failed, promote as little as possible. */ for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_486) - return(fat_archs + i); + return(i); } for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_486SX) - return(fat_archs + i); + return(i); } for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_586) - return(fat_archs + i); + return(i); } /* * Now look for the lowest family and in that the lowest model. */ lowest_family = CPU_SUBTYPE_INTEL_FAMILY_MAX + 1; for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if(CPU_SUBTYPE_INTEL_FAMILY(fat_archs[i].cpusubtype & + if(CPU_SUBTYPE_INTEL_FAMILY(fat_cpusubtype & ~CPU_SUBTYPE_MASK) < lowest_family) lowest_family = CPU_SUBTYPE_INTEL_FAMILY( - fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); + fat_cpusubtype & ~CPU_SUBTYPE_MASK); } /* if no intel cputypes found return NULL */ if(lowest_family == CPU_SUBTYPE_INTEL_FAMILY_MAX + 1) - return(NULL); + return(-1); lowest_model = LONG_MAX; lowest_index = -1; for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if(CPU_SUBTYPE_INTEL_FAMILY(fat_archs[i].cpusubtype & + if(CPU_SUBTYPE_INTEL_FAMILY(fat_cpusubtype & ~CPU_SUBTYPE_MASK) == lowest_family){ - if(CPU_SUBTYPE_INTEL_MODEL(fat_archs[i].cpusubtype & + if(CPU_SUBTYPE_INTEL_MODEL(fat_cpusubtype & ~CPU_SUBTYPE_MASK) < lowest_model){ lowest_model = CPU_SUBTYPE_INTEL_MODEL( - fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); + fat_cpusubtype & ~CPU_SUBTYPE_MASK); lowest_index = i; } } } - return(fat_archs + lowest_index); + return(lowest_index); case CPU_TYPE_MC680x0: for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC680x0_ALL) - return(fat_archs + i); + return(i); } /* * Try to promote if starting from CPU_SUBTYPE_MC680x0_ALL and @@ -236,18 +345,34 @@ uint32_t nfat_archs) */ if((cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC680x0_ALL){ for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC68040) - return(fat_archs + i); + return(i); } for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC68030_ONLY) - return(fat_archs + i); + return(i); } } break; @@ -272,27 +397,51 @@ uint32_t nfat_archs) */ case CPU_SUBTYPE_POWERPC_970: for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_POWERPC_970) - return(fat_archs + i); + return(i); } case CPU_SUBTYPE_POWERPC_7450: case CPU_SUBTYPE_POWERPC_7400: for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_POWERPC_7450) - return(fat_archs + i); + return(i); } for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_POWERPC_7400) - return(fat_archs + i); + return(i); } case CPU_SUBTYPE_POWERPC_750: case CPU_SUBTYPE_POWERPC_604e: @@ -301,54 +450,110 @@ uint32_t nfat_archs) case CPU_SUBTYPE_POWERPC_603e: case CPU_SUBTYPE_POWERPC_603: for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_POWERPC_750) - return(fat_archs + i); + return(i); } for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_POWERPC_604e) - return(fat_archs + i); + return(i); } for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_POWERPC_604) - return(fat_archs + i); + return(i); } for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_POWERPC_603ev) - return(fat_archs + i); + return(i); } for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_POWERPC_603e) - return(fat_archs + i); + return(i); } for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_POWERPC_603) - return(fat_archs + i); + return(i); } default: for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_POWERPC_ALL) - return(fat_archs + i); + return(i); } } break; @@ -363,69 +568,125 @@ uint32_t nfat_archs) case CPU_SUBTYPE_VEO_1: case CPU_SUBTYPE_VEO_3: for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_VEO_2) - return(fat_archs + i); + return(i); } case CPU_SUBTYPE_VEO_4: for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_VEO_3) - return(fat_archs + i); + return(i); } for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_VEO_2) - return(fat_archs + i); + return(i); } } break; case CPU_TYPE_MC88000: for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC88000_ALL) - return(fat_archs + i); + return(i); } break; case CPU_TYPE_I860: for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_I860_ALL) - return(fat_archs + i); + return(i); } break; case CPU_TYPE_HPPA: for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_HPPA_ALL) - return(fat_archs + i); + return(i); } break; case CPU_TYPE_SPARC: for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_SPARC_ALL) - return(fat_archs + i); + return(i); } break; case CPU_TYPE_ARM: /* * If it weren't for xscale, we could have a simple - * heirarchy like ppc. However, xscale has instructions + * hierarchy like ppc. However, xscale has instructions * which aren't present on v5 or v6. Here's the acceptable * fat slices for each ARM subtype, for most to least * preferred: @@ -438,93 +699,246 @@ uint32_t nfat_archs) if(cpusubtype == CPU_SUBTYPE_ARM_ALL || cpusubtype == CPU_SUBTYPE_ARM_V7K){ for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype == cputype && - fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V7S) - return(fat_archs + i); + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype == cputype && + fat_cpusubtype == CPU_SUBTYPE_ARM_V7S) + return(i); } } if(cpusubtype == CPU_SUBTYPE_ARM_ALL || cpusubtype == CPU_SUBTYPE_ARM_V7S){ for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype == cputype && - fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V7F) - return(fat_archs + i); + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype == cputype && + fat_cpusubtype == CPU_SUBTYPE_ARM_V7F) + return(i); } } if(cpusubtype == CPU_SUBTYPE_ARM_ALL || cpusubtype == CPU_SUBTYPE_ARM_V7F){ for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype == cputype && - fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V7) - return(fat_archs + i); + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype == cputype && + fat_cpusubtype == CPU_SUBTYPE_ARM_V7) + return(i); } } if(cpusubtype == CPU_SUBTYPE_ARM_ALL || cpusubtype == CPU_SUBTYPE_ARM_V7 || cpusubtype == CPU_SUBTYPE_ARM_V6){ for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype == cputype && - fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V6) - return(fat_archs + i); + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype == cputype && + fat_cpusubtype == CPU_SUBTYPE_ARM_V6) + return(i); } } if(cpusubtype == CPU_SUBTYPE_ARM_ALL || cpusubtype == CPU_SUBTYPE_ARM_V6 || cpusubtype == CPU_SUBTYPE_ARM_V5TEJ){ for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype == cputype && - fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V5TEJ) - return(fat_archs + i); + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype == cputype && + fat_cpusubtype == CPU_SUBTYPE_ARM_V5TEJ) + return(i); } } if(cpusubtype == CPU_SUBTYPE_ARM_ALL || cpusubtype == CPU_SUBTYPE_ARM_XSCALE){ for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype == cputype && - fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_XSCALE) - return(fat_archs + i); + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype == cputype && + fat_cpusubtype == CPU_SUBTYPE_ARM_XSCALE) + return(i); } } for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype == cputype && - fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V4T) - return(fat_archs + i); + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype == cputype && + fat_cpusubtype == CPU_SUBTYPE_ARM_V4T) + return(i); } for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype == cputype && - fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V6M) - return(fat_archs + i); + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype == cputype && + fat_cpusubtype == CPU_SUBTYPE_ARM_V6M) + return(i); } for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype == cputype && - fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V7M) - return(fat_archs + i); + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype == cputype && + fat_cpusubtype == CPU_SUBTYPE_ARM_V7M) + return(i); } for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype == cputype && - fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V7EM) - return(fat_archs + i); + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype == cputype && + fat_cpusubtype == CPU_SUBTYPE_ARM_V7EM) + return(i); } for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype == cputype && - fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_ALL) - return(fat_archs + i); + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype == cputype && + fat_cpusubtype == CPU_SUBTYPE_ARM_ALL) + return(i); } case CPU_TYPE_ARM64: for(i = 0; i < nfat_archs; i++){ - if(fat_archs[i].cputype != cputype) + if(fat_archs64 != NULL){ + fat_cputype = fat_archs64[i].cputype; + fat_cpusubtype = fat_archs64[i].cpusubtype; + } + else{ + fat_cputype = fat_archs[i].cputype; + fat_cpusubtype = fat_archs[i].cpusubtype; + } + if(fat_cputype != cputype) continue; - if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + if((fat_cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_ARM64_ALL) - return(fat_archs + i); + return(i); } break; + /* For CPU_TYPE_ARM64_32 only an exact match is allowed. */ + default: - return(NULL); + return(-1); } - return(NULL); + return(-1); +} + +/* + * cpusubtype_findbestarch_64() is passed a cputype and cpusubtype and a set of + * fat_arch_64 structs and selects the best one that matches (if any) and + * returns a pointer to that fat_arch_64 struct (or NULL). The fat_arch_64 + * structs must be in the host byte sex and correct such that the fat_archs64 + * really points to enough memory for nfat_arch_64 structs. It is possible + * that this routine could fail if new cputypes or cpusubtypes are added and an + * old version of this routine is used. But if there is an exact match between + * the cputype and cpusubtype and one of the fat_arch structs this routine will + * always succeed. + */ +__private_extern__ +struct fat_arch_64 * +cpusubtype_findbestarch_64( +cpu_type_t cputype, +cpu_subtype_t cpusubtype, +struct fat_arch_64 *fat_archs64, +uint32_t nfat_archs) +{ + int32_t i; + + i = internal_cpusubtype_findbestarch(cputype, cpusubtype, NULL, + fat_archs64, nfat_archs); + if(i == -1) + return(NULL); + return(fat_archs64 + i); +} + +/* + * cpusubtype_findbestarch() is passed a cputype and cpusubtype and a set of + * fat_arch structs and selects the best one that matches (if any) and returns + * a pointer to that fat_arch struct (or NULL). The fat_arch structs must be + * in the host byte sex and correct such that the fat_archs really points to + * enough memory for nfat_arch structs. It is possible that this routine could + * fail if new cputypes or cpusubtypes are added and an old version of this + * routine is used. But if there is an exact match between the cputype and + * cpusubtype and one of the fat_arch structs this routine will always succeed. + */ +__private_extern__ +struct fat_arch * +cpusubtype_findbestarch( +cpu_type_t cputype, +cpu_subtype_t cpusubtype, +struct fat_arch *fat_archs, +uint32_t nfat_archs) +{ + int32_t i; + + i = internal_cpusubtype_findbestarch(cputype, cpusubtype, fat_archs, + NULL, nfat_archs); + if(i == -1) + return(NULL); + return(fat_archs + i); } #endif /* RLD */ @@ -559,6 +973,11 @@ cpu_subtype_t cpusubtype2) if(cputype == CPU_TYPE_I386 || cputype == CPU_TYPE_X86_64) return(CPU_SUBTYPE_I386_ALL); + /* + * The same cpusubtypes for any cputype returns that cpusubtype. For + * some cputypes like CPU_TYPE_ARM64_32 there is no combining of + * cpusubtypes so there is no code for those cputypes below. + */ if((cpusubtype1 & ~CPU_SUBTYPE_MASK) == (cpusubtype2 & ~CPU_SUBTYPE_MASK)) return(cpusubtype1); @@ -1041,12 +1460,30 @@ cpu_subtype_t exec_cpusubtype) /* can be the ALL type */ } break; /* logically can't get here */ + case CPU_TYPE_ARM64_32: + /* + * For CPU_TYPE_ARM64_32 we only have CPU_SUBTYPE_ARM64_32_V8 + * defined. + */ + switch (host_cpusubtype){ + case CPU_SUBTYPE_ARM64_32_V8: + switch(exec_cpusubtype){ + case CPU_SUBTYPE_ARM64_32_V8: + return(TRUE); + default: + return(FALSE); + } + break; + } + break; + case CPU_TYPE_ARM64: switch (host_cpusubtype){ case CPU_SUBTYPE_ARM64_V8: switch(exec_cpusubtype){ case CPU_SUBTYPE_ARM64_ALL: case CPU_SUBTYPE_ARM64_V8: + case CPU_SUBTYPE_ARM64E: return(TRUE); default: break; /* fall through to arm 32-bit types below */ diff --git a/cctools/libstuff/breakout.c b/cctools/libstuff/breakout.c index 5f10307..18b3d0f 100644 --- a/cctools/libstuff/breakout.c +++ b/cctools/libstuff/breakout.c @@ -153,7 +153,14 @@ struct ofile *ofile) arch = new_arch(archs, narchs); arch->file_name = savestr(filename); arch->type = ofile->arch_type; - arch->fat_arch = ofile->fat_archs + ofile->narch; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + arch->fat_arch64 = ofile->fat_archs64 + ofile->narch; + arch->fat_arch = NULL; + } + else{ + arch->fat_arch = ofile->fat_archs + ofile->narch; + arch->fat_arch64 = NULL; + } arch->fat_arch_name = savestr(ofile->arch_flag.name); if(ofile->arch_type == OFILE_ARCHIVE){ @@ -176,15 +183,29 @@ struct ofile *ofile) #ifdef LTO_SUPPORT else if(ofile->arch_type == OFILE_LLVM_BITCODE){ arch->lto = ofile->lto; - arch->unknown_addr = ofile->file_addr + - arch->fat_arch->offset; - arch->unknown_size = arch->fat_arch->size; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + arch->unknown_addr = ofile->file_addr + + arch->fat_arch64->offset; + arch->unknown_size = arch->fat_arch64->size; + } + else{ + arch->unknown_addr = ofile->file_addr + + arch->fat_arch->offset; + arch->unknown_size = arch->fat_arch->size; + } } #endif /* LTO_SUPPORT */ else{ /* ofile->arch_type == OFILE_UNKNOWN */ - arch->unknown_addr = ofile->file_addr + - arch->fat_arch->offset; - arch->unknown_size = arch->fat_arch->size; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + arch->unknown_addr = ofile->file_addr + + arch->fat_arch64->offset; + arch->unknown_size = arch->fat_arch64->size; + } + else{ + arch->unknown_addr = ofile->file_addr + + arch->fat_arch->offset; + arch->unknown_size = arch->fat_arch->size; + } } }while(ofile_next_arch(ofile) == TRUE); } @@ -246,7 +267,7 @@ struct ofile *ofile) struct member *member; enum bool flag; struct ar_hdr *ar_hdr; - uint32_t size, ar_name_size; + uint64_t size, ar_name_size; char ar_name_buf[sizeof(ofile->member_ar_hdr->ar_name) + 1]; char ar_size_buf[sizeof(ofile->member_ar_hdr->ar_size) + 1]; @@ -301,7 +322,7 @@ struct ofile *ofile) if(ofile->member_name[ar_name_size - 1] != '\0') break; } - member->member_name_size = ar_name_size; + member->member_name_size = (uint32_t)ar_name_size; ar_name_size = rnd(ar_name_size, 8) + (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr)); diff --git a/cctools/libstuff/bytesex.c b/cctools/libstuff/bytesex.c index 65dcdbf..3829799 100644 --- a/cctools/libstuff/bytesex.c +++ b/cctools/libstuff/bytesex.c @@ -325,6 +325,29 @@ enum byte_sex target_byte_sex) } } +__private_extern__ +void +swap_fat_arch_64( +struct fat_arch_64 *fat_archs64, +uint32_t nfat_arch, +enum byte_sex target_byte_sex) +{ + uint32_t i; +#ifdef __MWERKS__ + enum byte_sex dummy; + dummy = target_byte_sex; +#endif + + for(i = 0; i < nfat_arch; i++){ + fat_archs64[i].cputype = SWAP_INT(fat_archs64[i].cputype); + fat_archs64[i].cpusubtype = SWAP_INT(fat_archs64[i].cpusubtype); + fat_archs64[i].offset = SWAP_LONG_LONG(fat_archs64[i].offset); + fat_archs64[i].size = SWAP_LONG_LONG(fat_archs64[i].size); + fat_archs64[i].align = SWAP_INT(fat_archs64[i].align); + fat_archs64[i].reserved = SWAP_INT(fat_archs64[i].reserved); + } +} + __private_extern__ void swap_mach_header( @@ -2368,6 +2391,16 @@ enum byte_sex target_byte_sex) cpu->__cpsr = SWAP_INT(cpu->__cpsr); } +void +swap_arm_exception_state64_t( +arm_exception_state64_t *except, +enum byte_sex target_byte_sex) +{ + except->__far = SWAP_LONG_LONG(except->__far); + except->__esr = SWAP_INT(except->__esr); + except->__exception = SWAP_INT(except->__exception); +} + __private_extern__ void swap_ident_command( @@ -2545,6 +2578,35 @@ enum byte_sex target_byte_sex) ver_cmd->version = SWAP_INT(ver_cmd->version); } +__private_extern__ +void +swap_build_version_command( +struct build_version_command *bv, +enum byte_sex target_byte_sex) +{ + bv->cmd = SWAP_INT(bv->cmd); + bv->cmdsize = SWAP_INT(bv->cmdsize); + bv->platform = SWAP_INT(bv->platform); + bv->minos = SWAP_INT(bv->minos); + bv->sdk = SWAP_INT(bv->sdk); + bv->ntools = SWAP_INT(bv->ntools); +} + +__private_extern__ +void +swap_build_tool_version( +struct build_tool_version *btv, +uint32_t ntools, +enum byte_sex target_byte_sex) +{ + uint32_t i; + + for(i = 0; i < ntools; i++){ + btv[i].tool = SWAP_INT(btv[i].tool); + btv[i].version = SWAP_INT(btv[i].version); + } +} + __private_extern__ void swap_rpath_command( struct rpath_command *rpath_cmd, @@ -2636,6 +2698,18 @@ enum byte_sex target_byte_sex) sv->version = SWAP_LONG_LONG(sv->version); } +__private_extern__ +void +swap_note_command( +struct note_command *nc, +enum byte_sex target_byte_sex) +{ + nc->cmd = SWAP_INT(nc->cmd); + nc->cmdsize = SWAP_INT(nc->cmdsize); + nc->offset = SWAP_LONG_LONG(nc->offset); + nc->size = SWAP_LONG_LONG(nc->size); +} + __private_extern__ void swap_nlist( @@ -2699,6 +2773,22 @@ enum byte_sex target_byte_sex) } } +__private_extern__ +void +swap_ranlib_64( +struct ranlib_64 *ranlibs, +uint64_t nranlibs, +enum byte_sex target_byte_sex) +{ + uint64_t i; + + for(i = 0; i < nranlibs; i++){ + ranlibs[i].ran_un.ran_strx = + SWAP_LONG_LONG(ranlibs[i].ran_un.ran_strx); + ranlibs[i].ran_off = SWAP_LONG_LONG(ranlibs[i].ran_off); + } +} + __private_extern__ void swap_relocation_info( @@ -2889,7 +2979,7 @@ enum byte_sex target_byte_sex) mods[i].objc_module_info_addr = SWAP_LONG_LONG(mods[i].objc_module_info_addr); mods[i].objc_module_info_size = - SWAP_LONG_LONG(mods[i].objc_module_info_size); + SWAP_INT(mods[i].objc_module_info_size); } } diff --git a/cctools/libstuff/checkout.c b/cctools/libstuff/checkout.c index 837f54d..3291b6a 100644 --- a/cctools/libstuff/checkout.c +++ b/cctools/libstuff/checkout.c @@ -172,6 +172,20 @@ struct object *object) "LC_DYLD_INFO load command): "); object->dyld_info = (struct dyld_info_command *)lc; } + else if(lc->cmd == LC_DYLD_EXPORTS_TRIE){ + if(object->dyld_exports_trie != NULL) + fatal_arch(arch, member, "malformed file (more than one " + "LC_DYLD_EXPORTS_TRIE load command): "); + object->dyld_exports_trie = + (struct linkedit_data_command *)lc; + } + else if(lc->cmd == LC_DYLD_CHAINED_FIXUPS){ + if(object->dyld_chained_fixups != NULL) + fatal_arch(arch, member, "malformed file (more than one " + "LC_DYLD_CHAINED_FIXUPS load command): "); + object->dyld_chained_fixups = + (struct linkedit_data_command *)lc; + } else if(lc->cmd == LC_SEGMENT){ sg = (struct segment_command *)lc; if(strcmp(sg->segname, SEG_LINKEDIT) == 0){ @@ -269,7 +283,8 @@ struct object *object) */ dyld_order(arch, member, object); } - else if(flags & MH_DYLDLINK){ + else if(flags & MH_DYLDLINK || + object->mh_filetype == MH_KEXT_BUNDLE){ /* * This is a file for the dynamic linker (output of ld(1) with * -output_for_dyld . That is the relocation entries are split @@ -333,7 +348,8 @@ struct arch *arch, struct member *member, struct object *object) { - uint32_t offset, rounded_offset, isym; + uint64_t offset, rounded_offset; + uint32_t isym; if(object->mh != NULL){ if(object->seg_linkedit == NULL) @@ -392,6 +408,7 @@ struct object *object) SEG_LINKEDIT " segment in: "); } } + if(object->dyld_info != NULL){ /* dyld_info starts at beginning of __LINKEDIT */ if (object->dyld_info->rebase_off != 0){ @@ -428,6 +445,21 @@ struct object *object) offset = object->dyld_info->rebase_off + object->dyld_info->rebase_size; } + if(object->dyld_chained_fixups != NULL){ + /* dyld_chained_fixups starts at beginning of __LINKEDIT */ + if (object->dyld_chained_fixups->dataoff != offset) + order_error(arch, member, "dyld chained fixups " + "out of place"); + offset = object->dyld_chained_fixups->dataoff + + object->dyld_chained_fixups->datasize; + } + if(object->dyld_exports_trie != NULL){ + if (object->dyld_exports_trie->dataoff != offset) + order_error(arch, member, "dyld exports trie " + "out of place"); + offset = object->dyld_exports_trie->dataoff + + object->dyld_exports_trie->datasize; + } if(object->dyst->nlocrel != 0){ if(object->dyst->locreloff != offset) order_error(arch, member, "local relocation entries " @@ -536,7 +568,8 @@ struct object *object) rounded_offset = offset; } else if(object->dyst->tocoff == rounded_offset){ - object->input_indirectsym_pad = rounded_offset - offset; + object->input_indirectsym_pad = (uint32_t)(rounded_offset - + offset); rounded_offset += object->dyst->ntoc * sizeof(struct dylib_table_of_contents); offset = rounded_offset; @@ -558,7 +591,8 @@ struct object *object) rounded_offset = offset; } else if(object->dyst->modtaboff == rounded_offset){ - object->input_indirectsym_pad = rounded_offset - offset; + object->input_indirectsym_pad = (uint32_t)(rounded_offset - + offset); rounded_offset += object->dyst->nmodtab * sizeof(struct dylib_module_64); offset = rounded_offset; @@ -575,7 +609,8 @@ struct object *object) rounded_offset = offset; } else if(object->dyst->extrefsymoff == rounded_offset){ - object->input_indirectsym_pad = rounded_offset - offset; + object->input_indirectsym_pad = (uint32_t)(rounded_offset - + offset); rounded_offset += object->dyst->nextrefsyms * sizeof(struct dylib_reference); offset = rounded_offset; @@ -590,7 +625,8 @@ struct object *object) rounded_offset = offset; } else if(object->st->stroff == rounded_offset){ - object->input_indirectsym_pad = rounded_offset - offset; + object->input_indirectsym_pad = (uint32_t)(rounded_offset - + offset); rounded_offset += object->st->strsize; offset = rounded_offset; } @@ -646,7 +682,7 @@ struct object *object) end = object->code_sig_cmd->dataoff; if(object->st->strsize != 0){ strend = object->st->stroff + object->st->strsize; - rounded_strend = rnd(strend, 16); + rounded_strend = (uint32_t)rnd(strend, 16); if(object->code_sig_cmd->dataoff == rounded_strend) end = strend; } @@ -658,7 +694,7 @@ struct object *object) * string table may not be exactly at the end of the * object_size due to rounding. */ - rounded_strend = rnd(strend, 8); + rounded_strend = (uint32_t)rnd(strend, 8); if(strend != end && rounded_strend != end) fatal_arch(arch, member, "string table not at the end " "of the file (can't be processed) in file: "); @@ -691,7 +727,7 @@ struct object *object) */ if(object->mh64 != NULL && (object->dyst->nindirectsyms % 2) != 0){ - rounded_indirectend = rnd(indirectend, 8); + rounded_indirectend = (uint32_t)rnd(indirectend, 8); } else{ rounded_indirectend = indirectend; diff --git a/cctools/libstuff/dylib_roots.c b/cctools/libstuff/dylib_roots.c index 5f1f106..f483efd 100644 --- a/cctools/libstuff/dylib_roots.c +++ b/cctools/libstuff/dylib_roots.c @@ -28,7 +28,8 @@ #include #include #include -#ifndef __OPENSTEP__ +#if defined(__APPLE__) || defined(__GLIBC__) || defined(__MINGW32__) +#define HAVE_FTS #include #endif #include @@ -116,7 +117,7 @@ find_dylib_in_root( char *install_name, const char *root) { -#ifndef __OPENSTEP__ +#ifdef HAVE_FTS char *base_name, start[MAXPATHLEN + 1], *image_file_name; char const *paths[2]; FTS *fts; diff --git a/cctools/libstuff/dylib_table.c b/cctools/libstuff/dylib_table.c index 9a25898..33d65e9 100644 --- a/cctools/libstuff/dylib_table.c +++ b/cctools/libstuff/dylib_table.c @@ -20,6 +20,7 @@ * * @APPLE_LICENSE_HEADER_END@ */ +/* NOTE: This is no longer compiled into libstuff as of 2/27/2019 */ #ifndef RLD #include #include @@ -66,22 +67,29 @@ char *argument) /* -dylib_file argument or "dylib table" */ if(fstat(fd, &stat_buf) == -1) system_fatal("Can't stat file: %s for %s %s", file_name, flag, argument); + /* * For some reason mapping files with zero size fails - * so it has to be handled specially. + * so it has to be handled specially. Also, deal with files that are + * too large to be valid seg_addr tables. */ file_addr = NULL; - if(stat_buf.st_size != 0){ + if (stat_buf.st_size > 0xFFFFFFFF) { + fatal("File too large (%llu): %s for %s %s", stat_buf.st_size, + file_name, flag, argument); + } + else if (stat_buf.st_size == 0) { + fatal("Empty file: %s for %s %s", file_name, flag, argument); + } + else { file_addr = mmap(0, stat_buf.st_size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0); if((intptr_t)file_addr == -1) system_error("can't map file: %s for %s %s", file_name, flag, argument); } - else - fatal("Empty file: %s for %s %s", file_name, flag, argument); close(fd); - file_size = stat_buf.st_size; + file_size = (uint32_t)stat_buf.st_size; /* * Got the file mapped now parse it. @@ -108,11 +116,11 @@ char *argument) /* -dylib_file argument or "dylib table" */ continue; } new_dylib_table[k].seg1addr = - strtoul(file_addr + j, &endp, 16); + (uint32_t)strtoul(file_addr + j, &endp, 16); if(endp == NULL) fatal("improper hexadecimal number on line %u in " "file: %s for %s %s", j, file_name, flag, argument); - j = endp - file_addr; + j = (uint32_t)(endp - file_addr); if(j == file_size) fatal("missing library name on line %u in file: " "%s for %s %s", j, file_name, flag, argument); @@ -144,7 +152,7 @@ struct dylib_table * parse_default_dylib_table( char **file_name) { - uint32_t i; + size_t i; FILE *fp; *file_name = allocate(MAXPATHLEN+1); diff --git a/cctools/libstuff/execute.c b/cctools/libstuff/execute.c index 7c8d95e..622d21d 100644 --- a/cctools/libstuff/execute.c +++ b/cctools/libstuff/execute.c @@ -24,6 +24,7 @@ #include /* first to get rid of pre-comp warning */ #include /* first to get rid of pre-comp warning */ #include "stdio.h" +#include /* cctools-port: For bcmp, bzero ... */ #include #include #include @@ -72,7 +73,6 @@ int verbose) return(1); /* can't get here, removes a warning from the compiler */ } else{ - waitpid = -1; do{ waitpid = wait(&waitstatus); } while (waitpid == -1 && errno == EINTR); @@ -83,7 +83,7 @@ int verbose) #else termsig = waitstatus.w_termsig; #endif - if(termsig != 0 && termsig != SIGINT) + if(termsig != 0 && termsig != SIGINT && termsig != SIGPIPE) fatal("fatal error in %s", name); return( #ifndef __OPENSTEP__ diff --git a/cctools/libstuff/get_arch_from_host.c b/cctools/libstuff/get_arch_from_host.c index 6a67922..1388367 100644 --- a/cctools/libstuff/get_arch_from_host.c +++ b/cctools/libstuff/get_arch_from_host.c @@ -515,6 +515,26 @@ struct arch_flag *specific_arch_flag) if(specific_arch_flag != NULL) specific_arch_flag->name = "arm64v8"; return(1); + case CPU_SUBTYPE_ARM64E: + if(family_arch_flag != NULL){ + family_arch_flag->name = "arm64"; + family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM64_ALL; + } + if(specific_arch_flag != NULL) + specific_arch_flag->name = "arm64e"; + return(1); + } + break; + case CPU_TYPE_ARM64_32: + switch(host_basic_info.cpu_subtype){ + case CPU_SUBTYPE_ARM64_32_V8: + if(family_arch_flag != NULL){ + family_arch_flag->name = "arm64_32"; + family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM64_32_V8; + } + if(specific_arch_flag != NULL) + specific_arch_flag->name = "arm64_32"; + return(1); } break; } diff --git a/cctools/libstuff/get_toc_byte_sex.c b/cctools/libstuff/get_toc_byte_sex.c index 000870d..c484760 100644 --- a/cctools/libstuff/get_toc_byte_sex.c +++ b/cctools/libstuff/get_toc_byte_sex.c @@ -40,7 +40,7 @@ __private_extern__ enum byte_sex get_toc_byte_sex( char *addr, -uint32_t size) +uint64_t size) { uint32_t magic; uint32_t ar_name_size; @@ -54,8 +54,8 @@ uint32_t size) while(p + sizeof(struct ar_hdr) + sizeof(uint32_t) < addr + size){ ar_hdr = (struct ar_hdr *)p; if(strncmp(ar_hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0) - ar_name_size = strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1, - NULL, 10); + ar_name_size = (uint32_t) + strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1, NULL, 10); else ar_name_size = 0; p += sizeof(struct ar_hdr); diff --git a/cctools/libstuff/guess_short_name.c b/cctools/libstuff/guess_short_name.c index 353eb57..8376c7e 100644 --- a/cctools/libstuff/guess_short_name.c +++ b/cctools/libstuff/guess_short_name.c @@ -59,6 +59,14 @@ static char *look_back_for_slash( * If the name of the dynamic library is none of the forms above then NULL is * returned. */ +/* + * MDT 20190119 rdar://12400897 + * guess_short_name() will require suffixes be either "_debug" or "_profile". + * If a '_' substring has any other value, guess_short_name() will assume that + * substring is part of the short name. This is because a large number of dylib + * authors -- 1st party and 3rd party -- don't realize '_' is a reserved + * character in dylib names, and some cctools get confused. + */ __private_extern__ char * guess_short_name( @@ -71,6 +79,7 @@ char **return_suffix) *is_framework = FALSE; *return_suffix = NULL; + /* pull off the last component and make foo point to it */ a = strrchr(name, '/'); if(a == NULL) @@ -86,6 +95,10 @@ char **return_suffix) s = strlen(suffix); if(suffix == foo || s < 2) suffix = NULL; + else if (0 != strncmp("_debug", suffix, 6) && + 0 != strncmp("_profile", suffix, 8)) { + suffix = NULL; + } else{ l -= s; *return_suffix = allocate(s + 1); @@ -174,7 +187,10 @@ guess_library: /* ignore any suffix after an underbar like Foo_profile.A.dylib */ c = strchr(name, '_'); - if(c != NULL && c != name){ + if (c != NULL && c != name && + (0 == strncmp("_debug", c, 6) || + 0 == strncmp("_profile", c, 8))) + { l = c - name; suffix = c; for(s = 0; suffix[s] != '.'; s++) @@ -197,8 +213,11 @@ guess_library: else{ /* ignore any suffix after an underbar like Foo_profile.A.dylib */ - c = strchr(b+1, '_'); - if(c != NULL && c != b+1){ + c = strrchr(b+1, '_'); + if (c != NULL && c != b+1 && + (0 == strncmp("_debug", c, 6) || + 0 == strncmp("_profile", c, 8))) + { l = c - (b+1); suffix = c; for(s = 0; suffix[s] != '.'; s++) diff --git a/cctools/libstuff/llvm.c b/cctools/libstuff/llvm.c index 30952bb..76674d4 100644 --- a/cctools/libstuff/llvm.c +++ b/cctools/libstuff/llvm.c @@ -1,4 +1,5 @@ #include +#include /* cctools-port: For bcmp, bzero ... */ #include #include #include diff --git a/cctools/libstuff/lto.c b/cctools/libstuff/lto.c index 319e142..30f8fe4 100644 --- a/cctools/libstuff/lto.c +++ b/cctools/libstuff/lto.c @@ -1,6 +1,7 @@ #ifdef LTO_SUPPORT #include +#include /* cctools-port: For bcmp, bzero ... */ #include #include #include @@ -12,21 +13,28 @@ #include #include +/* cctools-port */ +#if LTO_API_VERSION < 5 +typedef unsigned char lto_bool_t; +#endif +/* cctools-port end */ + static int get_lto_cputype( struct arch_flag *arch_flag, - char *target_triple); + const char *target_triple); static int tried_to_load_lto = 0; static void *lto_handle = NULL; -static int (*lto_is_object)(const void* mem, size_t length) = NULL; +static lto_bool_t (*lto_is_object)(const void* mem, size_t length) = NULL; static lto_module_t (*lto_create)(const void* mem, size_t length) = NULL; static lto_module_t (*lto_create_local)(const void* mem, size_t length, const char *path) = NULL; static void (*lto_dispose)(void *mod) = NULL; -static char * (*lto_get_target)(void *mod) = NULL; -static uint32_t (*lto_get_num_symbols)(void *mod) = NULL; -static lto_symbol_attributes (*lto_get_sym_attr)(void *mod, uint32_t n) = NULL; -static char * (*lto_get_sym_name)(void *mod, uint32_t n) = NULL; +static const char * (*lto_get_target)(void *mod) = NULL; +static unsigned int (*lto_get_num_symbols)(void *mod) = NULL; +static lto_symbol_attributes (*lto_get_sym_attr)(void *mod, + unsigned int n) = NULL; +static const char * (*lto_get_sym_name)(void *mod, unsigned int n) = NULL; /* * is_llvm_bitcode() is passed an ofile struct pointer and a pointer and size @@ -55,7 +63,7 @@ size_t size) *"llvm bitcode file" could be in an archive or fat file. */ - if(is_llvm_bitcode_from_memory(addr, size, &arch_flag, + if(is_llvm_bitcode_from_memory(addr, (uint32_t)size, &arch_flag, &ofile->lto) != 0){ ofile->lto_cputype = arch_flag.cputype; ofile->lto_cpusubtype = arch_flag.cpusubtype; @@ -156,6 +164,7 @@ void **pmod) /* maybe NULL */ lto_get_num_symbols == NULL || lto_get_sym_attr == NULL || lto_get_sym_name == NULL){ + fprintf(stderr, "libLTO: %s", dlerror()); /* cctools-port */ dlclose(lto_handle); if(lto_path != NULL) free(lto_path); @@ -205,7 +214,7 @@ static int get_lto_cputype( struct arch_flag *arch_flag, -char *target_triple) +const char *target_triple) { char *p; size_t n; @@ -292,6 +301,14 @@ char *target_triple) arch_flag->cputype = CPU_TYPE_ARM64; arch_flag->cpusubtype = CPU_SUBTYPE_ARM64_ALL; } + else if(strncmp(target_triple, "arm64e", n) == 0){ + arch_flag->cputype = CPU_TYPE_ARM64; + arch_flag->cpusubtype = CPU_SUBTYPE_ARM64E; + } + else if(strncmp(target_triple, "arm64_32", n) == 0){ + arch_flag->cputype = CPU_TYPE_ARM64_32; + arch_flag->cpusubtype = CPU_SUBTYPE_ARM64_32_V8; + } else{ return(0); } @@ -406,7 +423,7 @@ uint32_t symbol_index) * and returns the name of that symbol. */ __private_extern__ -char * +const char * lto_symbol_name( void *mod, uint32_t symbol_index) diff --git a/cctools/libstuff/macosx_deployment_target.c b/cctools/libstuff/macosx_deployment_target.c index f8cd0f6..d6411f2 100644 --- a/cctools/libstuff/macosx_deployment_target.c +++ b/cctools/libstuff/macosx_deployment_target.c @@ -26,7 +26,9 @@ #include #include #include +#ifdef __APPLE__ /* cctools-port */ #include +#endif #include "stuff/errors.h" #include "stuff/allocate.h" #include "stuff/macosx_deployment_target.h" @@ -81,20 +83,20 @@ struct macosx_deployment_target *value) else p = getenv("MACOSX_DEPLOYMENT_TARGET"); if(p != NULL){ - ten = strtoul(p, &endp, 10); + ten = (uint32_t)strtoul(p, &endp, 10); if(*endp != '.') goto use_default; if(ten != 10) goto use_default; q = endp + 1; - major = strtoul(q, &endp, 10); + major = (uint32_t)strtoul(q, &endp, 10); if(major == 0) goto use_default; if(*endp != '.' && *endp != '\0') goto use_default; if(*endp == '.'){ q = endp + 1; - minor = strtoul(q, &endp, 10); + minor = (uint32_t)strtoul(q, &endp, 10); if(*endp != '\0') goto use_default; } @@ -128,14 +130,14 @@ use_default: * version number, and y is the minor version number. We don't parse * out the value of z. */ - major = strtoul(osversion, &endp, 10); + major = (uint32_t)strtoul(osversion, &endp, 10); if(*endp != '.') goto bad_system_value; if(major <= 4) goto bad_system_value; major = major - 4; q = endp + 1; - minor = strtoul(q, &endp, 10); + minor = (uint32_t)strtoul(q, &endp, 10); if(*endp != '.') goto bad_system_value; diff --git a/cctools/libstuff/ofile.c b/cctools/libstuff/ofile.c index 1b9199c..57721c7 100644 --- a/cctools/libstuff/ofile.c +++ b/cctools/libstuff/ofile.c @@ -90,10 +90,11 @@ static enum bool otool_first_ofile_map = TRUE; #else /* !define(OTOOL) */ -#if (!defined(m68k) && !defined(__i386__) && !defined(__x86_64__) && !defined(__ppc__) && !defined(__arm__)) +/* cctools-port: Added && !defined(__arm64__) && !defined(__aarch64__) */ +#if (!defined(m68k) && !defined(__i386__) && !defined(__x86_64__) && !defined(__ppc__) && !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__)) #define ALIGNMENT_CHECKS_ARCHIVE_64_BIT static enum bool archive_64_bit_align_warning = FALSE; -#endif /* (!defined(m68k) && !defined(__i386__) && !defined(__x86_64__) && !defined(__ppc__) && !defined(__arm__)) */ +#endif /* (!defined(m68k) && !defined(__i386__) && !defined(__x86_64__) && !defined(__ppc__) && !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__)) */ #endif /* OTOOL */ @@ -208,7 +209,8 @@ void (*processor)(struct ofile *ofile, char *arch_name, void *cookie), void *cookie) { char *member_name, *p, *arch_name; - uint32_t len, i; + uint32_t i; + size_t len; struct ofile ofile; enum bool flag, hostflag, arch_found, family; struct arch_flag host_arch_flag, specific_arch_flag; @@ -921,6 +923,11 @@ enum bool archives_with_fat_objects) #ifdef OTOOL uint32_t small_nfat_arch; #endif /* OTOOL */ + uint64_t offset; + uint32_t align; + + /* silence clang warning */ + magic = 0; /* fill in the start of the ofile structure */ ofile->file_name = savestr(file_name); @@ -939,10 +946,12 @@ enum bool archives_with_fat_objects) /* see if this file is a fat file (always in big endian byte sex) */ #ifdef __BIG_ENDIAN__ - if(size >= sizeof(struct fat_header) && magic == FAT_MAGIC) + if(size >= sizeof(struct fat_header) && + (magic == FAT_MAGIC || magic == FAT_MAGIC_64)) #endif /* __BIG_ENDIAN__ */ #ifdef __LITTLE_ENDIAN__ - if(size >= sizeof(struct fat_header) && SWAP_INT(magic) == FAT_MAGIC) + if(size >= sizeof(struct fat_header) && + (SWAP_INT(magic) == FAT_MAGIC || SWAP_INT(magic) == FAT_MAGIC_64)) #endif /* __LITTLE_ENDIAN__ */ { ofile->file_type = OFILE_FAT; @@ -955,44 +964,81 @@ enum bool archives_with_fat_objects) printf("Fat headers\n"); #endif /* OTOOL */ big_size = ofile->fat_header->nfat_arch; - big_size *= sizeof(struct fat_arch); + if(ofile->fat_header->magic == FAT_MAGIC_64) + big_size *= sizeof(struct fat_arch_64); + else + big_size *= sizeof(struct fat_arch); big_size += sizeof(struct fat_header); if(big_size > size){ #ifdef OTOOL - error("fat file: %s truncated or malformed (fat_arch structs " - "would extend past the end of the file)", file_name); - ofile->fat_archs = allocate(size - sizeof(struct fat_header)); - memset(ofile->fat_archs, '\0', - size - sizeof(struct fat_header)); - memcpy(ofile->fat_archs, - addr + sizeof(struct fat_header), - size - sizeof(struct fat_header)); - small_nfat_arch = (size - sizeof(struct fat_header)) / - sizeof(struct fat_arch); + error("fat file: %s truncated or malformed (fat_arch%s structs " + "would extend past the end of the file)", file_name, + ofile->fat_header->magic == FAT_MAGIC_64 ? "_64" : ""); + if(ofile->fat_header->magic == FAT_MAGIC_64){ + ofile->fat_archs64 = allocate(size - + sizeof(struct fat_header)); + memset(ofile->fat_archs64, '\0', + size - sizeof(struct fat_header)); + memcpy(ofile->fat_archs64, + addr + sizeof(struct fat_header), + size - sizeof(struct fat_header)); + small_nfat_arch = (uint32_t) + ((size - sizeof(struct fat_header)) / + sizeof(struct fat_arch_64)); #ifdef __LITTLE_ENDIAN__ - swap_fat_arch(ofile->fat_archs, small_nfat_arch, - host_byte_sex); + swap_fat_arch_64(ofile->fat_archs64, small_nfat_arch, + host_byte_sex); #endif /* __LITTLE_ENDIAN__ */ + } + else{ + ofile->fat_archs = allocate(size - + sizeof(struct fat_header)); + memset(ofile->fat_archs, '\0', + size - sizeof(struct fat_header)); + memcpy(ofile->fat_archs, + addr + sizeof(struct fat_header), + size - sizeof(struct fat_header)); + small_nfat_arch = (uint32_t) + ((size - sizeof(struct fat_header)) / + sizeof(struct fat_arch)); +#ifdef __LITTLE_ENDIAN__ + swap_fat_arch(ofile->fat_archs, small_nfat_arch, + host_byte_sex); +#endif /* __LITTLE_ENDIAN__ */ + } if(otool_first_ofile_map && fflag) print_fat_headers(ofile->fat_header, ofile->fat_archs, - size, vflag); - free(ofile->fat_archs); + ofile->fat_archs64, size, vflag); + if(ofile->fat_header->magic == FAT_MAGIC_64) + free(ofile->fat_archs64); + else + free(ofile->fat_archs); ofile_unmap(ofile); return(FALSE); #else /* !defined(OTOOL) */ goto unknown; #endif /* OTOOL */ } - ofile->fat_archs = (struct fat_arch *)(addr + - sizeof(struct fat_header)); + if(ofile->fat_header->magic == FAT_MAGIC_64){ + ofile->fat_archs64 = (struct fat_arch_64 *) + (addr + sizeof(struct fat_header)); #ifdef __LITTLE_ENDIAN__ - swap_fat_arch(ofile->fat_archs, ofile->fat_header->nfat_arch, - host_byte_sex); + swap_fat_arch_64(ofile->fat_archs64, + ofile->fat_header->nfat_arch, host_byte_sex); #endif /* __LITTLE_ENDIAN__ */ + } + else{ + ofile->fat_archs = (struct fat_arch *) + (addr + sizeof(struct fat_header)); +#ifdef __LITTLE_ENDIAN__ + swap_fat_arch(ofile->fat_archs, ofile->fat_header->nfat_arch, + host_byte_sex); +#endif /* __LITTLE_ENDIAN__ */ + } #ifdef OTOOL if(otool_first_ofile_map && fflag) print_fat_headers(ofile->fat_header, ofile->fat_archs, - size, vflag); + ofile->fat_archs64, size, vflag); #endif /* OTOOL */ if(check_fat(ofile) == CHECK_BAD){ ofile_unmap(ofile); @@ -1032,12 +1078,23 @@ enum bool archives_with_fat_objects) ofile->narch = UINT_MAX; for(i = 0; i < ofile->fat_header->nfat_arch; i++){ - if(ofile->fat_archs[i].cputype == - ofile->arch_flag.cputype && - (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == - (ofile->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK)){ - ofile->narch = i; - break; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + if(ofile->fat_archs64[i].cputype == + ofile->arch_flag.cputype && + (ofile->fat_archs64[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + (ofile->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK)){ + ofile->narch = i; + break; + } + } + else{ + if(ofile->fat_archs[i].cputype == + ofile->arch_flag.cputype && + (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + (ofile->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK)){ + ofile->narch = i; + break; + } } } if(ofile->narch == UINT_MAX){ @@ -1050,15 +1107,33 @@ enum bool archives_with_fat_objects) (ofile->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK)); ofile->narch = UINT_MAX; for(i = 0; i < ofile->fat_header->nfat_arch; i++){ - if(ofile->fat_archs[i].cputype == - ofile->arch_flag.cputype && - (family == TRUE || - (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == - (ofile->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK))){ - ofile->arch_flag.cpusubtype = - ofile->fat_archs[i].cpusubtype; - ofile->narch = i; - break; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + if(ofile->fat_archs64[i].cputype == + ofile->arch_flag.cputype && + (family == TRUE || + (ofile->fat_archs64[i].cpusubtype & + ~CPU_SUBTYPE_MASK) == + (ofile->arch_flag.cpusubtype & + ~CPU_SUBTYPE_MASK))){ + ofile->arch_flag.cpusubtype = + ofile->fat_archs64[i].cpusubtype; + ofile->narch = i; + break; + } + } + else{ + if(ofile->fat_archs[i].cputype == + ofile->arch_flag.cputype && + (family == TRUE || + (ofile->fat_archs[i].cpusubtype & + ~CPU_SUBTYPE_MASK) == + (ofile->arch_flag.cpusubtype & + ~CPU_SUBTYPE_MASK))){ + ofile->arch_flag.cpusubtype = + ofile->fat_archs[i].cpusubtype; + ofile->narch = i; + break; + } } } } @@ -1074,8 +1149,18 @@ enum bool archives_with_fat_objects) #endif } /* Now determine the file type for this specific architecture */ - size = ofile->fat_archs[i].size; - addr = addr + ofile->fat_archs[i].offset; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + size = ofile->fat_archs64[i].size; + addr = addr + ofile->fat_archs64[i].offset; + offset = ofile->fat_archs64[i].offset; + align = ofile->fat_archs64[i].align; + } + else{ + size = ofile->fat_archs[i].size; + addr = addr + ofile->fat_archs[i].offset; + offset = ofile->fat_archs[i].offset; + align = ofile->fat_archs[i].align; + } if(size >= sizeof(struct mach_header)) memcpy(&magic, addr, sizeof(uint32_t)); /* see if this file is a 32-bit Mach-O file */ @@ -1083,7 +1168,7 @@ enum bool archives_with_fat_objects) (magic == MH_MAGIC || magic == SWAP_INT(MH_MAGIC))){ #ifdef ALIGNMENT_CHECKS - if(ofile->fat_archs[i].offset % 4 != 0){ + if(offset % 4 != 0){ error("fat file: %s architecture %s malformed for a 32-bit " "object file (offset is not a multiple of 4)", ofile->file_name, arch_flag->name); @@ -1097,7 +1182,7 @@ enum bool archives_with_fat_objects) #endif /* ALIGNMENT_CHECKS */ ofile->arch_type = OFILE_Mach_O; ofile->object_addr = addr; - ofile->object_size = size; + ofile->object_size = (uint32_t)size; if(magic == MH_MAGIC) ofile->object_byte_sex = host_byte_sex; else @@ -1128,7 +1213,7 @@ enum bool archives_with_fat_objects) (magic == MH_MAGIC_64 || magic == SWAP_INT(MH_MAGIC_64))){ #ifdef ALIGNMENT_CHECKS - if(ofile->fat_archs[i].offset % 8 != 0){ + if(offset % 8 != 0){ error("fat file: %s architecture %s malformed for a 64-bit " "object file (offset is not a multiple of 8)", ofile->file_name, arch_flag->name); @@ -1142,7 +1227,7 @@ enum bool archives_with_fat_objects) #endif /* ALIGNMENT_CHECKS */ ofile->arch_type = OFILE_Mach_O; ofile->object_addr = addr; - ofile->object_size = size; + ofile->object_size = (uint32_t)size; if(magic == MH_MAGIC_64) ofile->object_byte_sex = host_byte_sex; else @@ -1181,7 +1266,7 @@ enum bool archives_with_fat_objects) } #ifdef ALIGNMENT_CHECKS if(ofile->archive_cputype != 0 && - ofile->fat_archs[i].offset % sizeof(uint32_t) != 0){ + offset % sizeof(uint32_t) != 0){ error("fat file: %s architecture %s malformed archive that " "contains object files (offset to archive is not a " "multiple of sizeof(uint32_t))", @@ -1217,7 +1302,7 @@ enum bool archives_with_fat_objects) magic == SWAP_INT(MH_MAGIC))){ ofile->file_type = OFILE_Mach_O; ofile->object_addr = addr; - ofile->object_size = size; + ofile->object_size = (uint32_t)size; if(magic == MH_MAGIC) ofile->object_byte_sex = host_byte_sex; else @@ -1251,10 +1336,8 @@ enum bool archives_with_fat_objects) error("object file: %s does not match specified arch_flag: " "%s passed to ofile_map()", ofile->file_name, arch_flag->name); - ofile_unmap(ofile); - return(FALSE); -#endif goto cleanup; +#endif } } } @@ -1264,7 +1347,7 @@ enum bool archives_with_fat_objects) magic == SWAP_INT(MH_MAGIC_64))){ ofile->file_type = OFILE_Mach_O; ofile->object_addr = addr; - ofile->object_size = size; + ofile->object_size = (uint32_t)size; if(magic == MH_MAGIC_64) ofile->object_byte_sex = host_byte_sex; else @@ -1298,10 +1381,8 @@ enum bool archives_with_fat_objects) error("object file: %s does not match specified arch_flag: " "%s passed to ofile_map()", ofile->file_name, arch_flag->name); - ofile_unmap(ofile); - return(FALSE); -#endif goto cleanup; +#endif } } } @@ -1478,7 +1559,7 @@ struct ofile *ofile, uint32_t narch) { char *addr; - uint32_t size; + uint64_t size, offset; uint32_t magic; enum byte_sex host_byte_sex; @@ -1498,10 +1579,22 @@ uint32_t narch) ofile->mh64 = NULL; ofile->load_commands = NULL; - ofile->arch_flag.cputype = ofile->fat_archs[ofile->narch].cputype; - ofile->arch_flag.cpusubtype = ofile->fat_archs[ofile->narch].cpusubtype; - set_arch_flag_name(&(ofile->arch_flag)); + /* silence clang warning */ + magic = 0; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + ofile->arch_flag.cputype = + ofile->fat_archs64[ofile->narch].cputype; + ofile->arch_flag.cpusubtype = + ofile->fat_archs64[ofile->narch].cpusubtype; + } + else{ + ofile->arch_flag.cputype = + ofile->fat_archs[ofile->narch].cputype; + ofile->arch_flag.cpusubtype = + ofile->fat_archs[ofile->narch].cpusubtype; + } + set_arch_flag_name(&(ofile->arch_flag)); /* Now determine the file type for this specific architecture */ if(ofile->file_type == OFILE_FAT){ @@ -1511,8 +1604,16 @@ uint32_t narch) ofile->member_ar_hdr = NULL; ofile->member_type = OFILE_UNKNOWN; - size = ofile->fat_archs[ofile->narch].size; - addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + size = ofile->fat_archs64[ofile->narch].size; + addr = ofile->file_addr + + ofile->fat_archs64[ofile->narch].offset; + } + else{ + size = ofile->fat_archs[ofile->narch].size; + addr = ofile->file_addr + + ofile->fat_archs[ofile->narch].offset; + } } else{ if(ofile->file_type != OFILE_ARCHIVE || @@ -1520,10 +1621,18 @@ uint32_t narch) error("internal error. ofile_specific_arch() called but file " "is not a fat file or an archive with a fat member "); } - size = ofile->fat_archs[ofile->narch].size; - addr = ofile->file_addr + - ofile->member_offset + - ofile->fat_archs[ofile->narch].offset; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + size = ofile->fat_archs64[ofile->narch].size; + addr = ofile->file_addr + + ofile->member_offset + + ofile->fat_archs64[ofile->narch].offset; + } + else{ + size = ofile->fat_archs[ofile->narch].size; + addr = ofile->file_addr + + ofile->member_offset + + ofile->fat_archs[ofile->narch].offset; + } } #ifdef OTOOL @@ -1535,6 +1644,10 @@ uint32_t narch) if(addr + size > ofile->file_addr + ofile->file_size) size = (ofile->file_addr + ofile->file_size) - addr; #endif /* OTOOL */ + if(ofile->fat_header->magic == FAT_MAGIC_64) + offset = ofile->fat_archs64[ofile->narch].offset; + else + offset = ofile->fat_archs[ofile->narch].offset; if(size >= sizeof(struct mach_header)) memcpy(&magic, addr, sizeof(uint32_t)); @@ -1542,7 +1655,7 @@ uint32_t narch) if(size >= sizeof(struct mach_header) && (magic == MH_MAGIC || magic == SWAP_INT(MH_MAGIC))){ #ifdef ALIGNMENT_CHECKS - if(ofile->fat_archs[ofile->narch].offset % 4 != 0){ + if(offset % 4 != 0){ if(ofile->file_type == OFILE_ARCHIVE){ error("fat file: %s(%.*s) architecture %s malformed for a " "32-bit object file (offset is not a multiple of 4)", @@ -1558,7 +1671,7 @@ uint32_t narch) #endif /* ALIGNMENT_CHECKS */ ofile->arch_type = OFILE_Mach_O; ofile->object_addr = addr; - ofile->object_size = size; + ofile->object_size = (uint32_t)size; host_byte_sex = get_host_byte_sex(); if(magic == MH_MAGIC) ofile->object_byte_sex = host_byte_sex; @@ -1576,7 +1689,7 @@ uint32_t narch) else if(size >= sizeof(struct mach_header_64) && (magic == MH_MAGIC_64 || magic == SWAP_INT(MH_MAGIC_64))){ #ifdef ALIGNMENT_CHECKS - if(ofile->fat_archs[ofile->narch].offset % 8 != 0){ + if(offset % 8 != 0){ if(ofile->file_type == OFILE_ARCHIVE){ error("fat file: %s(%.*s) architecture %s malformed for an " "object file (offset is not a multiple of 8)", @@ -1592,7 +1705,7 @@ uint32_t narch) #endif /* ALIGNMENT_CHECKS */ ofile->arch_type = OFILE_Mach_O; ofile->object_addr = addr; - ofile->object_size = size; + ofile->object_size = (uint32_t)size; host_byte_sex = get_host_byte_sex(); if(magic == MH_MAGIC_64) ofile->object_byte_sex = host_byte_sex; @@ -1612,9 +1725,7 @@ uint32_t narch) if(check_archive(ofile, FALSE) == CHECK_BAD) goto cleanup; #ifdef ALIGNMENT_CHECKS - if(ofile->archive_cputype != 0 && - ofile->fat_archs[ofile->narch].offset % - sizeof(uint32_t) != 0){ + if(ofile->archive_cputype != 0 && offset % sizeof(uint32_t) != 0){ error("fat file: %s architecture %s malformed archive that " "contains object files (offset to archive is not a " "multiple of sizeof(uint32_t))", @@ -1632,7 +1743,7 @@ uint32_t narch) if(is_llvm_bitcode(ofile, addr, size) == TRUE){ ofile->arch_type = OFILE_LLVM_BITCODE; ofile->object_addr = addr; - ofile->object_size = size; + ofile->object_size = (uint32_t)size; } else #endif /* LTO_SUPPORT */ @@ -1681,6 +1792,7 @@ struct ofile *ofile) enum byte_sex host_byte_sex; struct ar_hdr *ar_hdr; uint32_t ar_name_size; + uint32_t sizeof_fat_archs; /* These fields are to be filled in by this routine, clear them first */ ofile->member_offset = 0; @@ -1714,8 +1826,16 @@ struct ofile *ofile) ofile->file_name); return(FALSE); } - addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset; - size = ofile->fat_archs[ofile->narch].size; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + addr = ofile->file_addr + + ofile->fat_archs64[ofile->narch].offset; + size = ofile->fat_archs64[ofile->narch].size; + } + else{ + addr = ofile->file_addr + + ofile->fat_archs[ofile->narch].offset; + size = ofile->fat_archs[ofile->narch].size; + } } else if(ofile->file_type == OFILE_ARCHIVE){ addr = ofile->file_addr; @@ -1758,19 +1878,19 @@ struct ofile *ofile) offset += sizeof(struct ar_hdr); ofile->member_offset = offset; ofile->member_addr = addr + offset; - ofile->member_size = strtoul(ar_hdr->ar_size, NULL, 10); + ofile->member_size = (uint32_t)strtoul(ar_hdr->ar_size, NULL, 10); if(ofile->member_size > size - sizeof(struct ar_hdr)){ archive_error(ofile, "size of first archive member extends past " "the end of the archive"); - ofile->member_size = size - sizeof(struct ar_hdr); + ofile->member_size = (uint32_t)(size - sizeof(struct ar_hdr)); } ofile->member_ar_hdr = ar_hdr; ofile->member_type = OFILE_UNKNOWN; ofile->member_name = ar_hdr->ar_name; if(strncmp(ofile->member_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){ ofile->member_name = ar_hdr->ar_name + sizeof(struct ar_hdr); - ar_name_size = strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1, - NULL, 10); + ar_name_size = (uint32_t) + strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1, NULL, 10); if(ar_name_size > ofile->member_size){ archive_error(ofile, "size of first archive member name " "extends past the end of the archive"); @@ -1792,6 +1912,7 @@ struct ofile *ofile) ofile->toc_name = NULL; ofile->toc_name_size = 0; ofile->toc_ranlibs = NULL; + ofile->toc_ranlibs64 = NULL; ofile->toc_nranlibs = 0; ofile->toc_strings = NULL; ofile->toc_strsize = 0; @@ -1806,10 +1927,10 @@ struct ofile *ofile) if(ofile->member_size > sizeof(uint32_t)){ memcpy(&magic, ofile->member_addr, sizeof(uint32_t)); #ifdef __BIG_ENDIAN__ - if(magic == FAT_MAGIC) + if(magic == FAT_MAGIC || magic == FAT_MAGIC_64) #endif /* __BIG_ENDIAN__ */ #ifdef __LITTLE_ENDIAN__ - if(magic == SWAP_INT(FAT_MAGIC)) + if(magic == SWAP_INT(FAT_MAGIC) || magic == SWAP_INT(FAT_MAGIC_64)) #endif /* __LITTLE_ENDIAN__ */ { ofile->member_type = OFILE_FAT; @@ -1818,20 +1939,38 @@ struct ofile *ofile) #ifdef __LITTLE_ENDIAN__ swap_fat_header(ofile->fat_header, host_byte_sex); #endif /* __LITTLE_ENDIAN__ */ - if(sizeof(struct fat_header) + - ofile->fat_header->nfat_arch * - sizeof(struct fat_arch) > ofile->member_size){ + if(ofile->fat_header->magic == FAT_MAGIC_64) + sizeof_fat_archs = ofile->fat_header->nfat_arch * + sizeof(struct fat_arch_64); + else + sizeof_fat_archs = ofile->fat_header->nfat_arch * + sizeof(struct fat_arch); + if(sizeof(struct fat_header) + sizeof_fat_archs > + ofile->member_size){ archive_member_error(ofile, "fat file truncated or " - "malformed (fat_arch structs would extend past " - "the end of the archive member)"); + "malformed (fat_arch%s structs would extend past " + "the end of the archive member)", + ofile->fat_header->magic == FAT_MAGIC_64 ? + "_64" : ""); goto fatcleanup; } - ofile->fat_archs = (struct fat_arch *) - (ofile->member_addr + sizeof(struct fat_header)); + if(ofile->fat_header->magic == FAT_MAGIC_64){ + ofile->fat_archs64 = (struct fat_arch_64 *) + (ofile->member_addr + sizeof(struct fat_header)); #ifdef __LITTLE_ENDIAN__ - swap_fat_arch(ofile->fat_archs, - ofile->fat_header->nfat_arch, host_byte_sex); + swap_fat_arch_64(ofile->fat_archs64, + ofile->fat_header->nfat_arch, + host_byte_sex); #endif /* __LITTLE_ENDIAN__ */ + } + else{ + ofile->fat_archs = (struct fat_arch *) + (ofile->member_addr + sizeof(struct fat_header)); +#ifdef __LITTLE_ENDIAN__ + swap_fat_arch(ofile->fat_archs, + ofile->fat_header->nfat_arch, host_byte_sex); +#endif /* __LITTLE_ENDIAN__ */ + } if(check_fat_object_in_archive(ofile) == FALSE) goto fatcleanup; } @@ -1893,7 +2032,11 @@ struct ofile *ofile) (strncmp(ofile->member_name, SYMDEF_SORTED, sizeof(SYMDEF_SORTED) - 1) == 0 || strncmp(ofile->member_name, SYMDEF, - sizeof(SYMDEF) - 1) == 0)){ + sizeof(SYMDEF) - 1) == 0 || + strncmp(ofile->member_name, SYMDEF_64_SORTED, + sizeof(SYMDEF_64_SORTED) - 1) == 0 || + strncmp(ofile->member_name, SYMDEF_64, + sizeof(SYMDEF_64) - 1) == 0)){ ofile->toc_addr = ofile->member_addr; ofile->toc_size = ofile->member_size; ofile->toc_ar_hdr = ofile->member_ar_hdr; @@ -1926,6 +2069,7 @@ struct ofile *ofile) fatcleanup: ofile->fat_header = NULL; ofile->fat_archs = NULL; + ofile->fat_archs64 = NULL; cleanup: ofile->member_offset = 0; ofile->member_addr = 0; @@ -1964,8 +2108,10 @@ struct ofile *ofile) enum byte_sex host_byte_sex; struct ar_hdr *ar_hdr; uint32_t ar_name_size, member_name_offset, n; + uint32_t sizeof_fat_archs; - ar_name_size = 0; /* cctools-port */ + /* silence clang warning */ + ar_name_size = 0; /* * Get the address and size of the archive. @@ -1977,8 +2123,16 @@ struct ofile *ofile) ofile->file_name); return(FALSE); } - addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset; - size = ofile->fat_archs[ofile->narch].size; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + addr = ofile->file_addr + + ofile->fat_archs64[ofile->narch].offset; + size = ofile->fat_archs64[ofile->narch].size; + } + else{ + addr = ofile->file_addr + + ofile->fat_archs[ofile->narch].offset; + size = ofile->fat_archs[ofile->narch].size; + } } else if(ofile->file_type == OFILE_ARCHIVE){ addr = ofile->file_addr; @@ -2025,11 +2179,11 @@ struct ofile *ofile) offset += sizeof(struct ar_hdr); ofile->member_offset = offset; ofile->member_addr = addr + offset; - ofile->member_size = strtoul(ar_hdr->ar_size, NULL, 10); + ofile->member_size = (uint32_t)strtoul(ar_hdr->ar_size, NULL, 10); if(ofile->member_size > size - sizeof(struct ar_hdr)){ archive_error(ofile, "size of archive member extends past " "the end of the archive"); - ofile->member_size = size - sizeof(struct ar_hdr); + ofile->member_size = (uint32_t)(size - sizeof(struct ar_hdr)); } ofile->member_ar_hdr = ar_hdr; ofile->member_name = ar_hdr->ar_name; @@ -2040,7 +2194,8 @@ struct ofile *ofile) } if(ofile->member_name[0] == '/' && (ofile->member_name[1] != ' ' && ofile->member_name[1] != '/')){ - member_name_offset = strtoul(ar_hdr->ar_name + 1, NULL, 10); + member_name_offset = + (uint32_t)strtoul(ar_hdr->ar_name + 1, NULL, 10); if(member_name_offset < ofile->sysv_ar_strtab_size){ ofile->member_name = ofile->sysv_ar_strtab + member_name_offset; ofile->member_name_size = 0; @@ -2057,8 +2212,8 @@ struct ofile *ofile) else if(strncmp(ofile->member_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){ ofile->member_name = ar_hdr->ar_name + sizeof(struct ar_hdr); - ar_name_size = strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1, - NULL, 10); + ar_name_size = (uint32_t) + strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1, NULL, 10); if(ar_name_size > ofile->member_size){ archive_error(ofile, "size of archive member name " "extends past the end of the archive"); @@ -2080,16 +2235,21 @@ struct ofile *ofile) ofile->mh = NULL; ofile->mh64 = NULL; ofile->load_commands = NULL; +#ifdef LTO_SUPPORT + ofile->lto = NULL; + ofile->lto_cputype = 0; + ofile->lto_cpusubtype = 0; +#endif /* LTO_SUPPORT */ host_byte_sex = get_host_byte_sex(); if(ofile->member_size > sizeof(uint32_t)){ memcpy(&magic, ofile->member_addr, sizeof(uint32_t)); #ifdef __BIG_ENDIAN__ - if(magic == FAT_MAGIC) + if(magic == FAT_MAGIC || magic == FAT_MAGIC_64) #endif /* __BIG_ENDIAN__ */ #ifdef __LITTLE_ENDIAN__ - if(magic == SWAP_INT(FAT_MAGIC)) + if(magic == SWAP_INT(FAT_MAGIC) || magic == SWAP_INT(FAT_MAGIC_64)) #endif /* __LITTLE_ENDIAN__ */ { ofile->member_type = OFILE_FAT; @@ -2097,20 +2257,38 @@ struct ofile *ofile) #ifdef __LITTLE_ENDIAN__ swap_fat_header(ofile->fat_header, host_byte_sex); #endif /* __LITTLE_ENDIAN__ */ - if(sizeof(struct fat_header) + - ofile->fat_header->nfat_arch * - sizeof(struct fat_arch) > ofile->member_size){ + if(ofile->fat_header->magic == FAT_MAGIC_64) + sizeof_fat_archs = ofile->fat_header->nfat_arch * + sizeof(struct fat_arch_64); + else + sizeof_fat_archs = ofile->fat_header->nfat_arch * + sizeof(struct fat_arch); + if(sizeof(struct fat_header) + sizeof_fat_archs > + ofile->member_size){ archive_member_error(ofile, "fat file truncated or " - "malformed (fat_arch structs would extend past " - "the end of the archive member)"); + "malformed (fat_arch%s structs would extend past " + "the end of the archive member)", + ofile->fat_header->magic == FAT_MAGIC_64 ? + "_64" : ""); goto cleanup; } - ofile->fat_archs = (struct fat_arch *)(ofile->member_addr + - sizeof(struct fat_header)); + if(ofile->fat_header->magic == FAT_MAGIC_64){ + ofile->fat_archs64 = (struct fat_arch_64 *) + (ofile->member_addr + sizeof(struct fat_header)); #ifdef __LITTLE_ENDIAN__ - swap_fat_arch(ofile->fat_archs, - ofile->fat_header->nfat_arch, host_byte_sex); + swap_fat_arch_64(ofile->fat_archs64, + ofile->fat_header->nfat_arch, + host_byte_sex); #endif /* __LITTLE_ENDIAN__ */ + } + else{ + ofile->fat_archs = (struct fat_arch *) + (ofile->member_addr + sizeof(struct fat_header)); +#ifdef __LITTLE_ENDIAN__ + swap_fat_arch(ofile->fat_archs, + ofile->fat_header->nfat_arch, host_byte_sex); +#endif /* __LITTLE_ENDIAN__ */ + } if(check_fat_object_in_archive(ofile) == FALSE) goto cleanup; } @@ -2186,6 +2364,7 @@ cleanup: if(ofile->member_type == OFILE_FAT){ ofile->fat_header = NULL; ofile->fat_archs = NULL; + ofile->fat_archs64 = NULL; } ofile->member_offset = 0; ofile->member_addr = NULL; @@ -2227,6 +2406,7 @@ struct ofile *ofile) char *ar_name; uint32_t ar_name_size, member_name_offset; struct ar_hdr *ar_hdr; + uint32_t sizeof_fat_archs; /* These fields are to be filled in by this routine, clear them first */ ofile->member_offset = 0; @@ -2242,6 +2422,11 @@ struct ofile *ofile) ofile->mh = NULL; ofile->mh64 = NULL; ofile->load_commands = NULL; +#ifdef LTO_SUPPORT + ofile->lto = NULL; + ofile->lto_cputype = 0; + ofile->lto_cpusubtype = 0; +#endif /* LTO_SUPPORT */ /* * Get the address and size of the archive. @@ -2253,8 +2438,16 @@ struct ofile *ofile) ofile->file_name); return(FALSE); } - addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset; - size = ofile->fat_archs[ofile->narch].size; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + addr = ofile->file_addr + + ofile->fat_archs64[ofile->narch].offset; + size = ofile->fat_archs64[ofile->narch].size; + } + else{ + addr = ofile->file_addr + + ofile->fat_archs[ofile->narch].offset; + size = ofile->fat_archs[ofile->narch].size; + } } else if(ofile->file_type == OFILE_ARCHIVE){ addr = ofile->file_addr; @@ -2290,12 +2483,14 @@ struct ofile *ofile) ofile->sysv_ar_strtab_size == 0 && strncmp(ar_hdr->ar_name, "// ", sizeof("// ") - 1) == 0){ ofile->sysv_ar_strtab = addr + offset; - ofile->sysv_ar_strtab_size = strtoul(ar_hdr->ar_size, NULL, 10); + ofile->sysv_ar_strtab_size = + (uint32_t)strtoul(ar_hdr->ar_size, NULL, 10); } if(ar_hdr->ar_name[0] == '/' && (ar_hdr->ar_name[1] != ' ' && ar_hdr->ar_name[1] != '/')){ - member_name_offset = strtoul(ar_hdr->ar_name + 1, NULL, 10); + member_name_offset = + (uint32_t)strtoul(ar_hdr->ar_name + 1, NULL, 10); if(member_name_offset < ofile->sysv_ar_strtab_size){ ar_name = ofile->sysv_ar_strtab + member_name_offset; i = 0; @@ -2316,7 +2511,7 @@ struct ofile *ofile) else if(strncmp(ar_hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){ #ifdef OTOOL - if(check_extend_format_1(ofile, ar_hdr, size - offset, + if(check_extend_format_1(ofile, ar_hdr, (uint32_t)(size-offset), &ar_name_size) == CHECK_BAD){ i = size_ar_name(ar_hdr); ar_name = ar_hdr->ar_name; @@ -2325,7 +2520,8 @@ struct ofile *ofile) else #endif /* OTOOL */ { - i = strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1,NULL,10); + i = (uint32_t) + strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1,NULL,10); ar_name = ar_hdr->ar_name + sizeof(struct ar_hdr); ar_name_size = i; } @@ -2341,8 +2537,8 @@ struct ofile *ofile) ofile->member_name_size = i; ofile->member_offset = offset + ar_name_size; ofile->member_addr = addr + offset + ar_name_size; - ofile->member_size = strtoul(ar_hdr->ar_size, NULL, 10) - - ar_name_size; + ofile->member_size = + (uint32_t)strtoul(ar_hdr->ar_size, NULL, 10) - ar_name_size; ofile->member_ar_hdr = ar_hdr; ofile->member_type = OFILE_UNKNOWN; @@ -2352,10 +2548,11 @@ struct ofile *ofile) memcpy(&magic, addr + offset + ar_name_size, sizeof(uint32_t)); #ifdef __BIG_ENDIAN__ - if(magic == FAT_MAGIC) + if(magic == FAT_MAGIC || magic == FAT_MAGIC_64) #endif /* __BIG_ENDIAN__ */ #ifdef __LITTLE_ENDIAN__ - if(magic == SWAP_INT(FAT_MAGIC)) + if(magic == SWAP_INT(FAT_MAGIC) || + magic == SWAP_INT(FAT_MAGIC_64)) #endif /* __LITTLE_ENDIAN__ */ { ofile->member_type = OFILE_FAT; @@ -2364,22 +2561,43 @@ struct ofile *ofile) #ifdef __LITTLE_ENDIAN__ swap_fat_header(ofile->fat_header, host_byte_sex); #endif /* __LITTLE_ENDIAN__ */ - if(sizeof(struct fat_header) + - ofile->fat_header->nfat_arch * - sizeof(struct fat_arch) > ofile->member_size){ + if(ofile->fat_header->magic == FAT_MAGIC_64) + sizeof_fat_archs = ofile->fat_header->nfat_arch * + sizeof(struct fat_arch_64); + else + sizeof_fat_archs = ofile->fat_header->nfat_arch * + sizeof(struct fat_arch); + if(sizeof(struct fat_header) + sizeof_fat_archs > + ofile->member_size){ archive_member_error(ofile, "fat file truncated or " - "malformed (fat_arch structs would extend " - "past the end of the archive member)"); + "malformed (fat_arch%s structs would extend" + " past the end of the archive member)", + ofile->fat_header->magic == FAT_MAGIC_64 ? + "_64" : ""); goto fatcleanup; } - ofile->fat_archs = - (struct fat_arch *)(addr + offset + ar_name_size + + if(ofile->fat_header->magic == FAT_MAGIC_64){ + ofile->fat_archs64 = + (struct fat_arch_64 *) + (addr + offset + ar_name_size + sizeof(struct fat_header)); #ifdef __LITTLE_ENDIAN__ - swap_fat_arch(ofile->fat_archs, - ofile->fat_header->nfat_arch, - host_byte_sex); + swap_fat_arch_64(ofile->fat_archs64, + ofile->fat_header->nfat_arch, + host_byte_sex); #endif /* __LITTLE_ENDIAN__ */ + } + else{ + ofile->fat_archs = + (struct fat_arch *) + (addr + offset + ar_name_size + + sizeof(struct fat_header)); +#ifdef __LITTLE_ENDIAN__ + swap_fat_arch(ofile->fat_archs, + ofile->fat_header->nfat_arch, + host_byte_sex); +#endif /* __LITTLE_ENDIAN__ */ + } if(check_fat_object_in_archive(ofile) == FALSE) goto fatcleanup; } @@ -2460,6 +2678,7 @@ struct ofile *ofile) fatcleanup: ofile->fat_header = NULL; ofile->fat_archs = NULL; + ofile->fat_archs64 = NULL; cleanup: ofile->member_offset = 0; ofile->member_addr = NULL; @@ -2643,9 +2862,11 @@ struct ofile *ofile) } if(ofile->mh != NULL) - module_index = (ofile->dylib_module + 1) - ofile->modtab; + module_index = + (uint32_t)((ofile->dylib_module + 1) - ofile->modtab); else - module_index = (ofile->dylib_module64 + 1) - ofile->modtab64; + module_index = + (uint32_t)((ofile->dylib_module64 + 1) - ofile->modtab64); if(module_index >= ofile->nmodtab) return(FALSE); @@ -2818,6 +3039,7 @@ struct ofile *ofile) printf("file_type = 0x%x\n", (unsigned int)ofile->file_type); printf("fat_header = 0x%x\n", (unsigned int)ofile->fat_header); printf("fat_archs = 0x%x\n", (unsigned int)ofile->fat_archs); + printf("fat_archs64 = 0x%x\n", (unsigned int)ofile->fat_archs64); printf("narch = 0x%x\n", (unsigned int)ofile->narch); printf("arch_type = 0x%x\n", (unsigned int)ofile->arch_type); printf("arch_flag.name = %s\n", ofile->arch_flag.name); @@ -2846,7 +3068,7 @@ struct ofile *ofile) /* * check_fat() checks the fat ofile for correctness (the fat_header and - * fat_archs are assumed to be in the host byte sex). + * fat_archs or fat_archs64 are assumed to be in the host byte sex). */ static enum check_type @@ -2859,6 +3081,11 @@ struct ofile *ofile) uint32_t i, j; uint64_t big_size; + cpu_type_t cputype; + cpu_subtype_t cpusubtype; + uint64_t offset; + uint64_t size; + uint32_t align; if(ofile->file_type != OFILE_FAT){ error("internal error. check_fat() call and file type of: %s is " @@ -2871,47 +3098,73 @@ struct ofile *ofile) return(CHECK_BAD); } for(i = 0; i < ofile->fat_header->nfat_arch; i++){ - big_size = ofile->fat_archs[i].offset; - big_size += ofile->fat_archs[i].size; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + cputype = ofile->fat_archs64[i].cputype; + cpusubtype = ofile->fat_archs64[i].cpusubtype; + offset = ofile->fat_archs64[i].offset; + size = ofile->fat_archs64[i].size; + align = ofile->fat_archs64[i].align; + } + else{ + cputype = ofile->fat_archs[i].cputype; + cpusubtype = ofile->fat_archs[i].cpusubtype; + offset = ofile->fat_archs[i].offset; + size = ofile->fat_archs[i].size; + align = ofile->fat_archs[i].align; + } + big_size = offset; + big_size += size; if(big_size > ofile->file_size){ error("fat file: %s truncated or malformed (offset plus size " "of cputype (%d) cpusubtype (%d) extends past the " "end of the file)", ofile->file_name, - ofile->fat_archs[i].cputype, - ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); + cputype, cpusubtype & ~CPU_SUBTYPE_MASK); return(CHECK_BAD); } - if(ofile->fat_archs[i].align > MAXSECTALIGN){ + if(align > MAXSECTALIGN){ error("fat file: %s align (2^%u) too large for cputype (%d) " "cpusubtype (%d) (maximum 2^%d)", ofile->file_name, - ofile->fat_archs[i].align, ofile->fat_archs[i].cputype, - ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK, + align, cputype, cpusubtype & ~CPU_SUBTYPE_MASK, MAXSECTALIGN); return(CHECK_BAD); } - if(ofile->fat_archs[i].offset % - (1 << ofile->fat_archs[i].align) != 0){ - error("fat file: %s offset: %u for cputype (%d) cpusubtype " + if(offset % + (1 << align) != 0){ + error("fat file: %s offset: %llu for cputype (%d) cpusubtype " "(%d)) not aligned on it's alignment (2^%u)", - ofile->file_name, - ofile->fat_archs[i].offset, - ofile->fat_archs[i].cputype, - ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK, - ofile->fat_archs[i].align); + ofile->file_name, offset, cputype, + cpusubtype & ~CPU_SUBTYPE_MASK, align); return(CHECK_BAD); } } for(i = 0; i < ofile->fat_header->nfat_arch; i++){ for(j = i + 1; j < ofile->fat_header->nfat_arch; j++){ - if(ofile->fat_archs[i].cputype == - ofile->fat_archs[j].cputype && - (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == - (ofile->fat_archs[j].cpusubtype & ~CPU_SUBTYPE_MASK)){ - error("fat file: %s contains two of the same " - "architecture (cputype (%d) cpusubtype (%d))", - ofile->file_name, ofile->fat_archs[i].cputype, - ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); - return(CHECK_BAD); + if(ofile->fat_header->magic == FAT_MAGIC_64){ + if(ofile->fat_archs64[i].cputype == + ofile->fat_archs64[j].cputype && + (ofile->fat_archs64[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + (ofile->fat_archs64[j].cpusubtype & + ~CPU_SUBTYPE_MASK)){ + error("fat file: %s contains two of the same " + "architecture (cputype (%d) cpusubtype (%d))", + ofile->file_name, ofile->fat_archs64[i].cputype, + ofile->fat_archs64[i].cpusubtype & + ~CPU_SUBTYPE_MASK); + return(CHECK_BAD); + } + } + else{ + if(ofile->fat_archs[i].cputype == + ofile->fat_archs[j].cputype && + (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + (ofile->fat_archs[j].cpusubtype & ~CPU_SUBTYPE_MASK)){ + error("fat file: %s contains two of the same " + "architecture (cputype (%d) cpusubtype (%d))", + ofile->file_name, ofile->fat_archs[i].cputype, + ofile->fat_archs[i].cpusubtype & + ~CPU_SUBTYPE_MASK); + return(CHECK_BAD); + } } } } @@ -2921,9 +3174,10 @@ struct ofile *ofile) /* * check_fat_object_in_archive() checks the fat object file which is a member - * of a thin archive for correctness (the fat_header and fat_archs are assumed - * to be in the host byte sex). This is not a legal form but allowed when - * archives_with_fat_objects is TRUE when ofile_map() is called. + * of a thin archive for correctness (the fat_header and fat_archs or + * fat_archs64 are assumed to be in the host byte sex). This is not a legal + * form but allowed when archives_with_fat_objects is TRUE when ofile_map() is + * called. */ static enum check_type @@ -2932,6 +3186,11 @@ struct ofile *ofile) { uint32_t i, j; uint32_t magic; + cpu_type_t cputype; + cpu_subtype_t cpusubtype; + uint64_t offset; + uint64_t size; + uint32_t align; if(ofile->file_type != OFILE_ARCHIVE){ error("internal error. check_fat_object_in_archive() called and " @@ -2944,31 +3203,39 @@ struct ofile *ofile) return(CHECK_BAD); } for(i = 0; i < ofile->fat_header->nfat_arch; i++){ - if(ofile->fat_archs[i].offset + ofile->fat_archs[i].size > - ofile->member_size){ + if(ofile->fat_header->magic == FAT_MAGIC_64){ + cputype = ofile->fat_archs64[i].cputype; + cpusubtype = ofile->fat_archs64[i].cpusubtype; + offset = ofile->fat_archs64[i].offset; + size = ofile->fat_archs64[i].size; + align = ofile->fat_archs64[i].align; + } + else{ + cputype = ofile->fat_archs[i].cputype; + cpusubtype = ofile->fat_archs[i].cpusubtype; + offset = ofile->fat_archs[i].offset; + size = ofile->fat_archs[i].size; + align = ofile->fat_archs[i].align; + } + if(offset + size > ofile->member_size){ archive_member_error(ofile, "fat file truncated or malformed " "(offset plus size of cputype (%d) cpusubtype (%d) " "extends past the end of the file)", - ofile->fat_archs[i].cputype, - ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); + cputype, cpusubtype & ~CPU_SUBTYPE_MASK); return(CHECK_BAD); } - if(ofile->fat_archs[i].align > MAXSECTALIGN){ + if(align > MAXSECTALIGN){ archive_member_error(ofile, "fat file's align (2^%u) too " "large for cputype (%d) cpusubtype (%d) (maximum 2^%d)", - ofile->fat_archs[i].align, ofile->fat_archs[i].cputype, - ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK, + align, cputype, cpusubtype & ~CPU_SUBTYPE_MASK, MAXSECTALIGN); return(CHECK_BAD); } - if(ofile->fat_archs[i].offset % - (1 << ofile->fat_archs[i].align) != 0){ - archive_member_error(ofile, "fat file's offset: %u for " + if(offset % (1 << align) != 0){ + archive_member_error(ofile, "fat file's offset: %llu for " "cputype (%d) cpusubtype (%d) not aligned on it's " - "alignment (2^%u)", ofile->fat_archs[i].offset, - ofile->fat_archs[i].cputype, - ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK, - ofile->fat_archs[i].align); + "alignment (2^%u)", offset, cputype, + cpusubtype & ~CPU_SUBTYPE_MASK, align); return(CHECK_BAD); } @@ -2976,20 +3243,20 @@ struct ofile *ofile) * The only supported format where fat files are allowed to appear * in archives is when the fat file contains only object files. */ - if(ofile->fat_archs[i].size < sizeof(struct mach_header)){ + if(size < sizeof(struct mach_header)){ archive_member_error(ofile, "fat file for cputype (%d) " "cpusubtype (%d) is not an object file (size too small " - "to be an object file)", ofile->fat_archs[i].cputype, - ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); + "to be an object file)", cputype, + cpusubtype & ~CPU_SUBTYPE_MASK); return(CHECK_BAD); } memcpy(&magic, ofile->file_addr + ofile->member_offset + - ofile->fat_archs[i].offset, + offset, sizeof(uint32_t)); if(magic == MH_MAGIC || magic == SWAP_INT(MH_MAGIC)){ #ifdef ALIGNMENT_CHECKS - if((ofile->member_offset + ofile->fat_archs[i].offset) % + if((ofile->member_offset + offset) % 4 != 0){ archive_member_error(ofile, "fat object file's offset in " "archive not a multiple of 4) (must be since " @@ -3001,7 +3268,7 @@ struct ofile *ofile) else if(magic == MH_MAGIC_64 || magic == SWAP_INT(MH_MAGIC_64)){ #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT if(archive_64_bit_align_warning == FALSE && - (ofile->member_offset + ofile->fat_archs[i].offset) % + (ofile->member_offset + offset) % 8 != 0){ temporary_archive_member_warning(ofile, "fat object file's " "offset in archive not a multiple of 8) (must be since " @@ -3014,11 +3281,11 @@ struct ofile *ofile) else{ #ifdef LTO_SUPPORT if(is_llvm_bitcode(ofile, ofile->file_addr + - ofile->member_offset + ofile->fat_archs[i].offset, - ofile->fat_archs[i].size) == TRUE){ + ofile->member_offset + offset, + size) == TRUE){ #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT if(archive_64_bit_align_warning == FALSE && - (ofile->member_offset + ofile->fat_archs[i].offset) % + (ofile->member_offset + offset) % 8 != 0){ temporary_archive_member_warning(ofile, "fat object " "file's offset in archive not a multiple of 8) " @@ -3033,23 +3300,40 @@ struct ofile *ofile) { archive_member_error(ofile, "fat file for cputype (%d) " "cpusubtype (%d) is not an object file (bad magic " - "number)", ofile->fat_archs[i].cputype, - ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); + "number)", cputype, + cpusubtype & ~CPU_SUBTYPE_MASK); return(CHECK_BAD); } } } for(i = 0; i < ofile->fat_header->nfat_arch; i++){ for(j = i + 1; j < ofile->fat_header->nfat_arch; j++){ - if(ofile->fat_archs[i].cputype == - ofile->fat_archs[j].cputype && - (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == - (ofile->fat_archs[j].cpusubtype & ~CPU_SUBTYPE_MASK)){ - archive_member_error(ofile, "fat file contains two of the " - "same architecture (cputype (%d) cpusubtype (%d))", - ofile->fat_archs[i].cputype, - ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); - return(CHECK_BAD); + if(ofile->fat_header->magic == FAT_MAGIC_64){ + if(ofile->fat_archs64[i].cputype == + ofile->fat_archs64[j].cputype && + (ofile->fat_archs64[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + (ofile->fat_archs64[j].cpusubtype & + ~CPU_SUBTYPE_MASK)){ + error("fat file: %s contains two of the same " + "architecture (cputype (%d) cpusubtype (%d))", + ofile->file_name, ofile->fat_archs64[i].cputype, + ofile->fat_archs64[i].cpusubtype & + ~CPU_SUBTYPE_MASK); + return(CHECK_BAD); + } + } + else{ + if(ofile->fat_archs[i].cputype == + ofile->fat_archs[j].cputype && + (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + (ofile->fat_archs[j].cpusubtype & ~CPU_SUBTYPE_MASK)){ + error("fat file: %s contains two of the same " + "architecture (cputype (%d) cpusubtype (%d))", + ofile->file_name, ofile->fat_archs[i].cputype, + ofile->fat_archs[i].cpusubtype & + ~CPU_SUBTYPE_MASK); + return(CHECK_BAD); + } } } } @@ -3065,9 +3349,6 @@ check_archive( struct ofile *ofile, enum bool archives_with_fat_objects) { -#ifdef OTOOL - return(CHECK_GOOD); -#else /* !defined OTOOL */ char *addr; uint64_t size, offset; uint64_t big_size; @@ -3084,11 +3365,22 @@ enum bool archives_with_fat_objects) * cpusubtype if known) and make sure it is an archive. */ if(ofile->file_type == OFILE_FAT){ - addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset; - size = ofile->fat_archs[ofile->narch].size; - ofile->archive_cputype = ofile->fat_archs[ofile->narch].cputype; - ofile->archive_cpusubtype = - ofile->fat_archs[ofile->narch].cpusubtype; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + addr = ofile->file_addr + + ofile->fat_archs64[ofile->narch].offset; + size = ofile->fat_archs64[ofile->narch].size; + ofile->archive_cputype = + ofile->fat_archs64[ofile->narch].cputype; + ofile->archive_cpusubtype = + ofile->fat_archs64[ofile->narch].cpusubtype; + } + else{ + addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset; + size = ofile->fat_archs[ofile->narch].size; + ofile->archive_cputype = ofile->fat_archs[ofile->narch].cputype; + ofile->archive_cpusubtype = + ofile->fat_archs[ofile->narch].cpusubtype; + } } else if(ofile->file_type == OFILE_ARCHIVE){ addr = ofile->file_addr; @@ -3125,7 +3417,7 @@ enum bool archives_with_fat_objects) ar_hdr = (struct ar_hdr *)(addr + offset); ofile->member_offset = offset; ofile->member_addr = addr + offset; - ofile->member_size = strtoul(ar_hdr->ar_size, NULL, 10); + ofile->member_size = (uint32_t)strtoul(ar_hdr->ar_size, NULL, 10); ofile->member_ar_hdr = ar_hdr; ofile->member_name = ar_hdr->ar_name; ofile->member_name_size = size_ar_name(ofile->member_ar_hdr); @@ -3137,8 +3429,9 @@ enum bool archives_with_fat_objects) */ ar_name_size = 0; if(strncmp(ofile->member_name,AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){ - if(check_extend_format_1(ofile, ar_hdr, size - offset, - &ar_name_size) == CHECK_BAD) + if(check_extend_format_1(ofile, ar_hdr, + (uint32_t)(size - offset), + &ar_name_size) == CHECK_BAD) return(CHECK_BAD); ofile->member_name = ar_hdr->ar_name + sizeof(struct ar_hdr); ofile->member_name_size = ar_name_size; @@ -3147,6 +3440,7 @@ enum bool archives_with_fat_objects) ofile->member_addr += ar_name_size; ofile->member_size -= ar_name_size; } +#ifndef OTOOL big_size = rnd(ofile->member_size, sizeof(short)); big_size += offset; if(big_size > size){ @@ -3154,13 +3448,15 @@ enum bool archives_with_fat_objects) "member extends past the end of the file)"); return(CHECK_BAD); } +#endif /* !defined(OTOOL) */ if(size - offset > sizeof(uint32_t)){ memcpy(&magic, addr + offset, sizeof(uint32_t)); #ifdef __BIG_ENDIAN__ - if(magic == FAT_MAGIC) + if(magic == FAT_MAGIC || magic == FAT_MAGIC_64) #endif /* __BIG_ENDIAN__ */ #ifdef __LITTLE_ENDIAN__ - if(magic == SWAP_INT(FAT_MAGIC)) + if(magic == SWAP_INT(FAT_MAGIC) || + magic == SWAP_INT(FAT_MAGIC_64)) #endif /* __LITTLE_ENDIAN__ */ { if(archives_with_fat_objects == FALSE || @@ -3198,28 +3494,41 @@ enum bool archives_with_fat_objects) ofile->archive_cputype = mh.cputype; ofile->archive_cpusubtype = mh.cpusubtype; } +#ifndef OTOOL else if(ofile->archive_cputype != mh.cputype){ archive_member_error(ofile, "cputype (%d) does not " "match previous archive members cputype (%d) " "(all members must match)", mh.cputype, ofile->archive_cputype); } +#endif /* !defined(OTOOL) */ } else if(magic == MH_MAGIC_64){ if(ofile->archive_cputype == 0){ ofile->archive_cputype = mh64.cputype; ofile->archive_cpusubtype = mh64.cpusubtype; } +#ifndef OTOOL else if(ofile->archive_cputype != mh64.cputype){ archive_member_error(ofile, "cputype (%d) does not " "match previous archive members cputype (%d) " "(all members must match)", mh64.cputype, ofile->archive_cputype); } +#endif /* !defined(OTOOL) */ } } } +#ifdef OTOOL + big_size = rnd(ofile->member_size, sizeof(short)); + big_size += offset; + if(big_size > size) + offset = size; + else + offset += rnd(ofile->member_size, sizeof(short)); +#else offset += rnd(ofile->member_size, sizeof(short)); +#endif /* !defined(OTOOL) */ } ofile->member_offset = 0; ofile->member_addr = NULL; @@ -3228,7 +3537,6 @@ enum bool archives_with_fat_objects) ofile->member_name = NULL; ofile->member_name_size = 0; return(CHECK_GOOD); -#endif /* OTOOL */ } /* @@ -3256,7 +3564,7 @@ uint32_t *member_name_size) (int)sizeof(ar_hdr->ar_name), ar_hdr->ar_name); return(CHECK_BAD); } - ar_name_size = strtoul(p, &endp, 10); + ar_name_size = (uint32_t)strtoul(p, &endp, 10); if(ar_name_size == UINT_MAX && errno == ERANGE){ archive_error(ofile, "malformed (size in ar_name: %.*s for " "archive extend format #1 overflows uint32_t)", @@ -3294,12 +3602,30 @@ enum check_type check_archive_toc( struct ofile *ofile) { - uint32_t i, symdef_length, offset, nranlibs, strsize; + uint32_t symdef_length, nranlibs, strsize; + uint64_t i, n, offset, ran_off, nranlibs64, strsize64; enum byte_sex host_byte_sex, toc_byte_sex; struct ranlib *ranlibs; + struct ranlib_64 *ranlibs64; char *strings; + enum bool toc_is_32bit; + /* cctools-port start */ + ranlibs = NULL; + ranlibs64 = NULL; + /* cctools-port end */ + + /* silence clang warnings */ + nranlibs = 0; + nranlibs64 = 0; + strsize = 0; + strsize64 = 0; + ranlibs = NULL; + ranlibs64 = NULL; + + ofile->toc_is_32bit = TRUE; ofile->toc_ranlibs = NULL; + ofile->toc_ranlibs64 = NULL; ofile->toc_nranlibs = 0; ofile->toc_strings = NULL; ofile->toc_strsize = 0; @@ -3311,23 +3637,51 @@ struct ofile *ofile) return(CHECK_GOOD); symdef_length = ofile->toc_size; - /* - * The contents of a __.SYMDEF file is begins with a 32-bit word giving - * the size in bytes of ranlib structures which immediately follow, and - * then continues with a string table consisting of a 32-bit word giving - * the number of bytes of strings which follow and then the strings - * themselves. So the smallest valid size is two 32-bit words long. - */ - if(symdef_length < 2 * sizeof(uint32_t)){ + if(strncmp(ofile->member_name, SYMDEF_64_SORTED, + ofile->member_name_size) == 0 || + strncmp(ofile->member_name, SYMDEF_64, + ofile->member_name_size) == 0) + toc_is_32bit = FALSE; + else + toc_is_32bit = TRUE; + if(toc_is_32bit == TRUE){ /* - * Size of table of contents for archive too small to be a valid - * table of contents. + * The contents of a __.SYMDEF file is begins with a 32-bit word + * giving the size in bytes of ranlib structures which immediately + * follow, and then continues with a string table consisting of a + * 32-bit word giving the number of bytes of strings which follow + * and then the strings themselves. So the smallest valid size is + * two 32-bit words long. */ - ofile->toc_bad = TRUE; - return(CHECK_GOOD); - } + if(symdef_length < 2 * sizeof(uint32_t)){ + /* + * Size of table of contents for archive too small to be a valid + * table of contents. + */ + ofile->toc_bad = TRUE; + return(CHECK_GOOD); + } + } else { + /* + * The contents of a __.SYMDEF_64 file is begins with a 64-bit word + * giving the size in bytes of ranlib structures which immediately + * follow, and then continues with a string table consisting of a + * 64-bit word giving the number of bytes of strings which follow + * and then the strings themselves. So the smallest valid size is + * two 64-bit words long. + */ + if(symdef_length < 2 * sizeof(uint64_t)){ + /* + * Size of table of contents for archive too small to be a valid + * table of contents. + */ + ofile->toc_bad = TRUE; + return(CHECK_GOOD); + } + } host_byte_sex = get_host_byte_sex(); - toc_byte_sex = get_toc_byte_sex(ofile->file_addr, ofile->file_size); + toc_byte_sex = get_toc_byte_sex(ofile->file_addr, + (uint32_t)ofile->file_size); if(toc_byte_sex == UNKNOWN_BYTE_SEX){ /* * Can't determine the byte order of table of contents as it @@ -3337,62 +3691,134 @@ struct ofile *ofile) return(CHECK_GOOD); } offset = 0; - nranlibs = *((uint32_t *)(ofile->toc_addr + offset)); - if(toc_byte_sex != host_byte_sex) - nranlibs = SWAP_INT(nranlibs); - nranlibs = nranlibs / sizeof(struct ranlib); - offset += sizeof(uint32_t); - ranlibs = (struct ranlib *)(ofile->toc_addr + offset); - offset += sizeof(struct ranlib) * nranlibs; - if(nranlibs == 0) - return(CHECK_GOOD); - if(offset - (2 * sizeof(uint32_t)) > symdef_length){ - /* - * Truncated or malformed archive. The ranlib structures in table - * of contents extends past the end of the table of contents. - */ - ofile->toc_bad = TRUE; - return(CHECK_GOOD); + if(toc_is_32bit == TRUE){ + nranlibs = *((uint32_t *)(ofile->toc_addr + offset)); + if(toc_byte_sex != host_byte_sex) + nranlibs = SWAP_INT(nranlibs); + nranlibs = nranlibs / sizeof(struct ranlib); + n = nranlibs; + offset += sizeof(uint32_t); + + ranlibs = (struct ranlib *)(ofile->toc_addr + offset); + offset += sizeof(struct ranlib) * nranlibs; + if(nranlibs == 0) + return(CHECK_GOOD); + if(offset - (2 * sizeof(uint32_t)) > symdef_length){ + /* + * Truncated or malformed archive. The ranlib structures in + * table of contents extends past the end of the table of + * contents. + */ + ofile->toc_bad = TRUE; + return(CHECK_GOOD); + } + + strsize = *((uint32_t *)(ofile->toc_addr + offset)); + if(toc_byte_sex != host_byte_sex) + strsize = SWAP_INT(strsize); + offset += sizeof(uint32_t); + + strings = ofile->toc_addr + offset; + offset += strsize; + if(offset - (2 * sizeof(uint32_t)) > symdef_length){ + /* + * Truncated or malformed archive. The ranlib strings in table + * of contents extends past the end of the table of contents. + */ + ofile->toc_bad = TRUE; + return(CHECK_GOOD); + } + if(symdef_length == 2 * sizeof(uint32_t)) + return(CHECK_GOOD); + } else { + nranlibs64 = *((uint64_t *)(ofile->toc_addr + offset)); + if(toc_byte_sex != host_byte_sex) + nranlibs64 = SWAP_LONG_LONG(nranlibs64); + nranlibs64 = nranlibs64 / sizeof(struct ranlib_64); + n = nranlibs64; + offset += sizeof(uint64_t); + + ranlibs64 = (struct ranlib_64 *)(ofile->toc_addr + offset); + offset += sizeof(struct ranlib_64) * nranlibs64; + if(nranlibs64 == 0) + return(CHECK_GOOD); + if(offset - (2 * sizeof(uint64_t)) > symdef_length){ + /* + * Truncated or malformed archive. The ranlib structures in + * table of contents extends past the end of the table of + * contents. + */ + ofile->toc_bad = TRUE; + return(CHECK_GOOD); + } + + strsize64 = *((uint64_t *)(ofile->toc_addr + offset)); + if(toc_byte_sex != host_byte_sex) + strsize64 = SWAP_LONG_LONG(strsize64); + offset += sizeof(uint64_t); + + strings = ofile->toc_addr + offset; + offset += strsize64; + if(offset - (2 * sizeof(uint64_t)) > symdef_length){ + /* + * Truncated or malformed archive. The ranlib strings in table + * of contents extends past the end of the table of contents. + */ + ofile->toc_bad = TRUE; + return(CHECK_GOOD); + } + if(symdef_length == 2 * sizeof(uint64_t)) + return(CHECK_GOOD); } - strsize = *((uint32_t *)(ofile->toc_addr + offset)); - if(toc_byte_sex != host_byte_sex) - strsize = SWAP_INT(strsize); - offset += sizeof(uint32_t); - strings = ofile->toc_addr + offset; - offset += strsize; - if(offset - (2 * sizeof(uint32_t)) > symdef_length){ - /* - * Truncated or malformed archive. The ranlib strings in table of - * contents extends past the end of the table of contents. - */ - ofile->toc_bad = TRUE; - return(CHECK_GOOD); - } - if(symdef_length == 2 * sizeof(uint32_t)) - return(CHECK_GOOD); /* * Check the string offset and the member offsets of the ranlib structs. */ - if(toc_byte_sex != host_byte_sex) - swap_ranlib(ranlibs, nranlibs, host_byte_sex); - for(i = 0; i < nranlibs; i++){ - if(ranlibs[i].ran_un.ran_strx >= strsize){ - /* - * Malformed table of contents. The ranlib struct at this index - * has a bad string index field. - */ - ofile->toc_bad = TRUE; - return(CHECK_GOOD); - } - if(ranlibs[i].ran_off >= ofile->file_size){ - /* - * Malformed table of contents. The ranlib struct at this index - * has a bad library member offset field. - */ - ofile->toc_bad = TRUE; - return(CHECK_GOOD); + if(toc_byte_sex != host_byte_sex){ + if(toc_is_32bit == TRUE) + swap_ranlib(ranlibs, nranlibs, host_byte_sex); + else + swap_ranlib_64(ranlibs64, nranlibs64, host_byte_sex); + } + for(i = 0; i < n; i++){ + if(toc_is_32bit == TRUE){ + if(ranlibs[i].ran_un.ran_strx >= strsize){ + /* + * Malformed table of contents. The ranlib struct at this + * index has a bad string index field. + */ + ofile->toc_bad = TRUE; + return(CHECK_GOOD); + } + if(ranlibs[i].ran_off >= ofile->file_size){ + /* + * Malformed table of contents. The ranlib struct at this + * index has a bad library member offset field. + */ + ofile->toc_bad = TRUE; + return(CHECK_GOOD); + } + ran_off = ranlibs[i].ran_off; + } else { + if(ranlibs64[i].ran_un.ran_strx >= strsize64){ + /* + * Malformed table of contents. The ranlib struct at this + * index has a bad string index field. + */ + ofile->toc_bad = TRUE; + return(CHECK_GOOD); + } + if(ranlibs64[i].ran_off >= ofile->file_size){ + /* + * Malformed table of contents. The ranlib struct at this + * index has a bad library member offset field. + */ + ofile->toc_bad = TRUE; + return(CHECK_GOOD); + } + ran_off = ranlibs64[i].ran_off; } + /* * These should be on 4 byte boundaries because the maximum * alignment of the header structures and relocation are 4 bytes. @@ -3402,7 +3828,7 @@ struct ofile *ofile) * machine. */ #if defined(mc68000) || defined(__i386__) - if(ranlibs[i].ran_off % sizeof(short) != 0){ + if(ran_off % sizeof(short) != 0){ /* * Malformed table of contents. This ranlib struct library * member offset not a multiple 2 bytes. @@ -3411,20 +3837,38 @@ struct ofile *ofile) return(CHECK_GOOD); } #else - if(ranlibs[i].ran_off % sizeof(uint32_t) != 0){ - /* - * Malformed table of contents. This ranlib struct library - * member offset not a multiple of 4 bytes. - */ - ofile->toc_bad = TRUE; - return(CHECK_GOOD); + if(toc_is_32bit == TRUE){ + if(ran_off % sizeof(uint32_t) != 0){ + /* + * Malformed table of contents. This ranlib struct library + * member offset not a multiple of 4 bytes. + */ + ofile->toc_bad = TRUE; + return(CHECK_GOOD); + } + } else { + if(ran_off % sizeof(uint64_t) != 0){ + /* + * Malformed table of contents. This ranlib struct library + * member offset not a multiple of 8 bytes. + */ + ofile->toc_bad = TRUE; + return(CHECK_GOOD); + } } #endif } + ofile->toc_is_32bit = toc_is_32bit; ofile->toc_ranlibs = ranlibs; - ofile->toc_nranlibs = nranlibs; + ofile->toc_ranlibs64 = ranlibs64; ofile->toc_strings = strings; - ofile->toc_strsize = strsize; + if(toc_is_32bit == TRUE){ + ofile->toc_nranlibs = nranlibs; + ofile->toc_strsize = strsize; + } else { + ofile->toc_nranlibs = nranlibs64; + ofile->toc_strsize = strsize64; + } return(CHECK_GOOD); } @@ -3448,6 +3892,7 @@ struct ofile *ofile) enum bool swapped; struct mach_header *mh; struct mach_header_64 *mh64; + uint32_t mh_flags; struct load_command *load_commands, *lc, l; struct segment_command *sg; struct segment_command_64 *sg64; @@ -3470,9 +3915,12 @@ struct ofile *ofile) struct routines_command_64 *rc64; struct twolevel_hints_command *hints; struct linkedit_data_command *code_sig, *split_info, *func_starts, - *data_in_code, *code_sign_drs, *linkedit_data; + *data_in_code, *code_sign_drs, *linkedit_data, + *exports_trie, *chained_fixups; struct linkedit_data_command *link_opt_hint; struct version_min_command *vers; + struct build_version_command *bv, *bv1, *bv2; + struct build_tool_version *btv; struct prebind_cksum_command *cs; struct encryption_info_command *encrypt_info; struct encryption_info_command_64 *encrypt_info64; @@ -3482,12 +3930,14 @@ struct ofile *ofile) struct rpath_command *rpath; struct entry_point_command *ep; struct source_version_command *sv; + struct note_command *nc; uint32_t flavor, count, nflavor; char *p, *state; uint32_t sizeof_nlist, sizeof_dylib_module; char *struct_dylib_module_name, *struct_nlist_name; uint64_t big_size, big_end, big_load_end; struct element elements; + cpu_type_t fat_cputype; elements.offset = 0; elements.size = 0; @@ -3512,13 +3962,14 @@ struct ofile *ofile) "commands extend past the end of the file)"); return(CHECK_BAD); } - sizeofhdrs = big_size; + sizeofhdrs = (uint32_t)big_size; ofile->mh_cputype = mh->cputype; ofile->mh_cpusubtype = mh->cpusubtype; ofile->mh_filetype = mh->filetype; ncmds = mh->ncmds; sizeofcmds = mh->sizeofcmds; cputype = mh->cputype; + mh_flags = mh->flags; load_command_multiple = 4; sizeof_nlist = sizeof(struct nlist); struct_nlist_name = "struct nlist"; @@ -3535,13 +3986,14 @@ struct ofile *ofile) "commands extend past the end of the file)"); return(CHECK_BAD); } - sizeofhdrs = big_size; + sizeofhdrs = (uint32_t)big_size; ofile->mh_cputype = mh64->cputype; ofile->mh_cpusubtype = mh64->cpusubtype; ofile->mh_filetype = mh64->filetype; ncmds = mh64->ncmds; sizeofcmds = mh64->sizeofcmds; cputype = mh64->cputype; + mh_flags = mh64->flags; load_command_multiple = 8; sizeof_nlist = sizeof(struct nlist_64); struct_nlist_name = "struct nlist_64"; @@ -3552,7 +4004,11 @@ struct ofile *ofile) "Mach-O headers") == CHECK_BAD) goto return_bad; if(ofile->file_type == OFILE_FAT){ - if(ofile->fat_archs[ofile->narch].cputype != ofile->mh_cputype){ + if(ofile->fat_header->magic == FAT_MAGIC_64) + fat_cputype = ofile->fat_archs64[ofile->narch].cputype; + else + fat_cputype = ofile->fat_archs[ofile->narch].cputype; + if(fat_cputype != ofile->mh_cputype){ Mach_O_error(ofile, "malformed fat file (fat header " "architecture: %u's cputype does not match " "object file's mach header)", ofile->narch); @@ -3574,12 +4030,17 @@ struct ofile *ofile) data_in_code = NULL; code_sign_drs = NULL; link_opt_hint = NULL; + exports_trie = NULL; + chained_fixups = NULL; split_info = NULL; cs = NULL; uuid = NULL; encrypt_info = NULL; dyld_info = NULL; vers = NULL; + bv = NULL; + bv1 = NULL; + bv2 = NULL; big_load_end = 0; for(i = 0, lc = load_commands; i < ncmds; i++){ if(big_load_end + sizeof(struct load_command) > sizeofcmds){ @@ -3841,7 +4302,7 @@ struct ofile *ofile) s64->flags != S_ZEROFILL && s64->flags != S_THREAD_LOCAL_ZEROFILL && check_overlaping_element(ofile, &elements, s64->offset, - s64->size, "section contents") == CHECK_BAD) + (uint32_t)s64->size, "section contents")==CHECK_BAD) goto return_bad; if(s64->reloff > size){ Mach_O_error(ofile, "truncated or malformed object " @@ -4185,7 +4646,7 @@ struct ofile *ofile) case LC_DATA_IN_CODE: cmd_name = "LC_DATA_IN_CODE"; - element_name = "date in code info"; + element_name = "data in code info"; if(data_in_code != NULL){ Mach_O_error(ofile, "malformed object (more than one " "%s command)", cmd_name); @@ -4196,7 +4657,7 @@ struct ofile *ofile) case LC_DYLIB_CODE_SIGN_DRS: cmd_name = "LC_DYLIB_CODE_SIGN_DRS"; - element_name = "code signing RDs data"; + element_name = "dylib codesign designated requirements data"; if(code_sign_drs != NULL){ Mach_O_error(ofile, "malformed object (more than one " "%s command)", cmd_name); @@ -4216,6 +4677,28 @@ struct ofile *ofile) link_opt_hint = (struct linkedit_data_command *)lc; goto check_linkedit_data_command; + case LC_DYLD_EXPORTS_TRIE: + cmd_name = "LC_DYLD_EXPORTS_TRIE"; + element_name = "exports trie"; + if(exports_trie != NULL){ + Mach_O_error(ofile, "malformed object (more than one " + "%s command)", cmd_name); + goto return_bad; + } + exports_trie = (struct linkedit_data_command *)lc; + goto check_linkedit_data_command; + + case LC_DYLD_CHAINED_FIXUPS: + cmd_name = "LC_DYLD_CHAINED_FIXUPS"; + element_name = "chained fixups"; + if(chained_fixups != NULL){ + Mach_O_error(ofile, "malformed object (more than one " + "%s command)", cmd_name); + goto return_bad; + } + chained_fixups = (struct linkedit_data_command *)lc; + goto check_linkedit_data_command; + check_linkedit_data_command: if(l.cmdsize < sizeof(struct linkedit_data_command)){ Mach_O_error(ofile, "malformed object (%s cmdsize too " @@ -4260,8 +4743,9 @@ check_linkedit_data_command: } if(vers != NULL){ Mach_O_error(ofile, "malformed object (more than one " - "LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_MACOSX " - "command)"); + "LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, " + "LC_VERSION_MIN_TVOS or LC_VERSION_MIN_WATCHOS " + "load command)"); goto return_bad; } vers = (struct version_min_command *)lc; @@ -4272,6 +4756,15 @@ check_linkedit_data_command: "MACOSX command %u has too small cmdsize field)", i); goto return_bad; } + if (bv1 != NULL) { + if (bv1->platform == PLATFORM_MACOS) { + Mach_O_error(ofile, "malformed object (the " + "LC_VERSION_MIN_MACOSX command %u " + "is not allowed when an LC_BUILD_VERSION " + "command for MACOS is present)", i); + goto return_bad; + } + } break; case LC_VERSION_MIN_IPHONEOS: @@ -4282,10 +4775,17 @@ check_linkedit_data_command: } if(vers != NULL){ Mach_O_error(ofile, "malformed object (more than one " - "LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_MACOSX " - "command)"); + "LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, " + "LC_VERSION_MIN_TVOS or LC_VERSION_MIN_WATCHOS " + "load command)"); goto return_bad; } + if (bv1) { + Mach_O_error(ofile, "malformed object " + "(LC_VERSION_MIN_IPHONEOS and some " + "LC_BUILD_VERSION load command also found)"); + goto return_bad; + } vers = (struct version_min_command *)lc; if(swapped) swap_version_min_command(vers, host_byte_sex); @@ -4298,20 +4798,28 @@ check_linkedit_data_command: case LC_VERSION_MIN_TVOS: if(l.cmdsize < sizeof(struct version_min_command)){ - Mach_O_error(ofile, "malformed object (LC_VERSION_MIN_" + Mach_O_error(ofile, "malformed object (LC_VERSION_MIN_TVOS" " cmdsize too small) in command %u",i); goto return_bad; } if(vers != NULL){ Mach_O_error(ofile, "malformed object (more than one " - "LC_VERSION_MIN_ command)"); + "LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, " + "LC_VERSION_MIN_TVOS or LC_VERSION_MIN_WATCHOS " + "load command)"); goto return_bad; } + if (bv1) { + Mach_O_error(ofile, "malformed object " + "(LC_VERSION_MIN_TVOS and some " + "LC_BUILD_VERSION load command also found)"); + goto return_bad; + } vers = (struct version_min_command *)lc; if(swapped) swap_version_min_command(vers, host_byte_sex); if(vers->cmdsize < sizeof(struct version_min_command)){ - Mach_O_error(ofile, "malformed object (LC_VERSION_MIN_" + Mach_O_error(ofile, "malformed object (LC_VERSION_MIN_TVOS" " command %u has too small cmdsize field)", i); goto return_bad; } @@ -4325,10 +4833,17 @@ check_linkedit_data_command: } if(vers != NULL){ Mach_O_error(ofile, "malformed object (more than one " - "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_MACOSX or " - "LC_VERSION_MIN_WATCHOS command)"); + "LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, " + "LC_VERSION_MIN_TVOS or LC_VERSION_MIN_WATCHOS " + "command)"); goto return_bad; } + if (bv1) { + Mach_O_error(ofile, "malformed object " + "(LC_VERSION_MIN_WATCHOS and some " + "LC_BUILD_VERSION load command also found)"); + goto return_bad; + } vers = (struct version_min_command *)lc; if(swapped) swap_version_min_command(vers, host_byte_sex); @@ -4339,6 +4854,87 @@ check_linkedit_data_command: } break; + case LC_BUILD_VERSION: + /* check load command size */ + if(l.cmdsize < sizeof(struct build_version_command)){ + Mach_O_error(ofile, "malformed object (LC_BUILD_VERSION" + "cmdsize too small) in command %u",i); + goto return_bad; + } + if(vers != NULL && (vers->cmd != LC_VERSION_MIN_MACOSX)){ + Mach_O_error(ofile, "malformed object (LC_BUILD_VERSION " + "and some LC_VERSION_MIN load command also found)"); + goto return_bad; + } + if(bv1 != NULL && bv2 != NULL && + (mh_flags & MH_SIM_SUPPORT) == 0){ + Mach_O_error(ofile, "malformed object (more than two " + "LC_BUILD_VERSION load commands)"); + } + bv = (struct build_version_command *)lc; + if(swapped) + swap_build_version_command(bv, host_byte_sex); + if(bv->cmdsize < sizeof(struct build_version_command) + + bv->ntools * sizeof(struct build_tool_version)){ + Mach_O_error(ofile, "malformed object (LC_BUILD_VERSION" + "command %u has too small cmdsize field)", i); + goto return_bad; + } + btv = (struct build_tool_version *) + ((char *)bv + sizeof(struct build_version_command)); + if(swapped) + swap_build_tool_version(btv, bv->ntools, host_byte_sex); + if (vers != NULL) { + if (vers->cmd == LC_VERSION_MIN_MACOSX && + bv->platform != PLATFORM_MACCATALYST) { + Mach_O_error(ofile, "malformed object " + "(LC_VERSION_MIN_MACOSX is set but the " + "LC_BUILD_VERSION load command is not for " + "MACCATALYST)"); + goto return_bad; + } + } + if(bv1 == NULL) { + bv1 = bv; + if (((mh_flags & MH_SIM_SUPPORT) != 0) && + (bv1->platform != PLATFORM_MACOS && + bv1->platform != PLATFORM_MACCATALYST && + bv1->platform != PLATFORM_IOSSIMULATOR && + bv1->platform != PLATFORM_TVOSSIMULATOR && + bv1->platform != PLATFORM_WATCHOSSIMULATOR)) + Mach_O_error(ofile, "malformed object (the " + "LC_BUILD_VERSION, command %u, platform value is " + "not allowed when the mach header flag " + "MH_SIM_SUPPORT is set)", i); + } + else { + bv2 = bv; + if ((bv1->platform != PLATFORM_MACOS && + bv1->platform != PLATFORM_MACCATALYST) || + ((bv1->platform == PLATFORM_MACOS && + bv2->platform != PLATFORM_MACCATALYST) || + (bv1->platform == PLATFORM_MACCATALYST && + bv2->platform != PLATFORM_MACOS))) { + if ((mh_flags & MH_SIM_SUPPORT) == 0) { + Mach_O_error(ofile, "malformed object (the two " + "LC_BUILD_VERSION load commands are not for " + "MACOS and MACCATALYST)"); + } + else{ + if(bv2->platform != PLATFORM_MACOS && + bv2->platform != PLATFORM_MACCATALYST && + bv2->platform != PLATFORM_IOSSIMULATOR && + bv2->platform != PLATFORM_TVOSSIMULATOR && + bv2->platform != PLATFORM_WATCHOSSIMULATOR) + Mach_O_error(ofile, "malformed object (the " + "LC_BUILD_VERSION, command %u, platform value " + "is not allowed when the mach header flag " + "MH_SIM_SUPPORT is set)", i); + } + } + } + break; + case LC_ENCRYPTION_INFO: if(l.cmdsize < sizeof(struct encryption_info_command)){ Mach_O_error(ofile, "malformed object (LC_ENCRYPTION_INFO " @@ -4434,7 +5030,7 @@ check_linkedit_data_command: swap_dyld_info_command(dyld_info, host_byte_sex); if(dyld_info->cmdsize != sizeof(struct dyld_info_command)){ - Mach_O_error(ofile, "malformed object (LC_DYLD_INFO" + Mach_O_error(ofile, "malformed object (LC_DYLD_INFO " "command %u has incorrect cmdsize)", i); goto return_bad; } @@ -5968,7 +6564,7 @@ check_dylinker_command: } break; } - if(cputype == CPU_TYPE_ARM64){ + if(cputype == CPU_TYPE_ARM64 || cputype == CPU_TYPE_ARM64_32){ arm_thread_state64_t *cpu; nflavor = 0; @@ -6111,6 +6707,31 @@ check_dylinker_command: goto return_bad; } break; + case LC_NOTE: + if(l.cmdsize != sizeof(struct note_command)){ + Mach_O_error(ofile, "malformed object (LC_NOTE: cmdsize " + "incorrect) in command %u", i); + goto return_bad; + } + nc = (struct note_command *)lc; + if(swapped) + swap_note_command(nc, host_byte_sex); + if(nc->offset > size){ + Mach_O_error(ofile, "truncated or malformed object (" + "LC_NOTE command %u offset field " + "extends past the end of the file)", i); + goto return_bad; + } + big_size = nc->offset; + big_size += nc->size; + if(big_size > size){ + Mach_O_error(ofile, "truncated or malformed object (" + "LC_NOTE command %u offset field " + "plus size field extends past the end of " + "the file)", i); + goto return_bad; + } + break; #ifndef OFI default: diff --git a/cctools/libstuff/port.c b/cctools/libstuff/port.c index 1137dc8..94f9610 100644 --- a/cctools/libstuff/port.c +++ b/cctools/libstuff/port.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -37,6 +38,51 @@ char *find_clang() } #endif /* ! DISABLE_CLANG_AS */ +#ifndef HAVE_UTIMENS +/* + * utimens utility to set file times with sub-second resolution when available. + * This is done by using utimensat if available at compile time. + * + * macOS is special cased: utimensat is only visible at compile time when + * building for macOS >= 10.13, but with proper runtime checks we can make + * builds targeted at older versions also work with sub-second resolution when + * available. This is especially important because APFS introduces sub-second + * timestamp resolution. + */ +#include + +#ifdef HAVE_UTIMENSAT +#include +#endif + +#if defined(__APPLE__) && defined(HAVE_UTIMENSAT) +#pragma weak utimensat +#endif + +int utimens(const char *path, const struct timespec times[2]) +{ +#ifdef HAVE_UTIMENSAT +#ifdef __APPLE__ + if (utimensat != NULL) +#endif + return utimensat(AT_FDCWD, path, times, 0); +#endif + + /* Fall back to truncating the timestamp to 1s resolution. */ +#ifndef __OPENSTEP__ + struct utimbuf timep; + timep.actime = times[0].tv_sec; + timep.modtime = times[1].tv_sec; + return utime(path, &timep); +#else + time_t timep[2]; + timep[0] = times[0].tv_sec; + timep[1] = times[1].tv_sec; + return utime(path, timep); +#endif +} +#endif /* HAVE_UTIMENS */ + #ifndef __APPLE__ #include @@ -58,7 +104,6 @@ char *find_clang() #include #endif - int _NSGetExecutablePath(char *epath, unsigned int *size) { #if defined(__FreeBSD__) || defined(__DragonFly__) @@ -401,4 +446,49 @@ size_t strlcpy(char *dst, const char *src, size_t siz) return(s - src - 1); /* count does not include NUL */ } -#endif /* __APPLE__ */ +#ifndef HAVE_REALLOCF +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 1998 M. Warner Losh + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +void *reallocf(void *ptr, size_t size) +{ + void *nptr; + + nptr = realloc(ptr, size); + + /* + * When the System V compatibility option (malloc "V" flag) is + * in effect, realloc(ptr, 0) frees the memory and returns NULL. + * So, to avoid double free, call free() only when size != 0. + * realloc(ptr, 0) can't fail when ptr != NULL. + */ + if (!nptr && ptr && size != 0) + free(ptr); + return (nptr); +} +#endif /* !HAVE_REALLOCF */ + +#endif /* !__APPLE__ */ diff --git a/cctools/libstuff/reloc.c b/cctools/libstuff/reloc.c index 9d9c76c..62ef47d 100644 --- a/cctools/libstuff/reloc.c +++ b/cctools/libstuff/reloc.c @@ -74,9 +74,10 @@ cpu_type_t cputype) return(ARM_RELOC_PAIR); break; case CPU_TYPE_ARM64: + case CPU_TYPE_ARM64_32: /* - * We should never hit this case for arm64, so drop down to the - * fatal error below. + * We should never hit this case for arm64 or arm64_32, so drop down + * to the fatal error below. */ break; } @@ -160,6 +161,7 @@ uint32_t r_type) return(TRUE); break; case CPU_TYPE_ARM64: + case CPU_TYPE_ARM64_32: return(FALSE); default: fatal("internal error: reloc_has_pair() called with unknown " @@ -226,7 +228,8 @@ uint32_t r_type) return(TRUE); break; case CPU_TYPE_ARM64: - /* No sectdiff relocs for arm64. */ + case CPU_TYPE_ARM64_32: + /* No sectdiff relocs for arm64 or arm64_32. */ return(FALSE); break; default: diff --git a/cctools/libstuff/rnd.c b/cctools/libstuff/rnd.c index 95ba994..597acae 100644 --- a/cctools/libstuff/rnd.c +++ b/cctools/libstuff/rnd.c @@ -27,17 +27,27 @@ */ #include #include "stuff/rnd.h" + /* * rnd() rounds v to a multiple of r. */ -__private_extern__ -uint64_t -rnd( -uint64_t v, -uint64_t r) +__private_extern__ uint64_t rnd(uint64_t v, uint64_t r) { - r--; - v += r; - v &= ~(int64_t)r; - return(v); + return rnd64(v, r); +} + +__private_extern__ uint64_t rnd64(uint64_t v, uint64_t r) +{ + r--; + v += r; + v &= ~(int64_t)r; + return(v); +} + +__private_extern__ uint32_t rnd32(uint32_t v, uint32_t r) +{ + r--; + v += r; + v &= ~(uint32_t)r; + return(v); } diff --git a/cctools/libstuff/seg_addr_table.c b/cctools/libstuff/seg_addr_table.c index 44afe51..14b5125 100644 --- a/cctools/libstuff/seg_addr_table.c +++ b/cctools/libstuff/seg_addr_table.c @@ -20,6 +20,8 @@ * * @APPLE_LICENSE_HEADER_END@ */ +/* NOTE: This is no longer compiled into libstuff as of 2/27/2019 */ +/* cctools-port: We still use this. */ #ifndef RLD #include #include @@ -96,20 +98,26 @@ uint32_t *table_size) file_name, flag, argument); /* * For some reason mapping files with zero size fails - * so it has to be handled specially. + * so it has to be handled specially. Also, deal with files that are + * too large to be valid seg_addr tables. */ file_addr = NULL; - if(stat_buf.st_size != 0){ + if (stat_buf.st_size > 0xFFFFFFFF) { + fatal("File too large (%llu): %s for %s %s", stat_buf.st_size, + file_name, flag, argument); + } + else if (stat_buf.st_size == 0) { + fatal("Empty file: %s for %s %s", file_name, flag, argument); + } + else { file_addr = mmap(0, stat_buf.st_size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0); if((intptr_t)file_addr == -1) system_error("can't map file: %s for %s %s", file_name, flag, argument); } - else - fatal("Empty file: %s for %s %s", file_name, flag, argument); close(fd); - file_size = stat_buf.st_size; + file_size = (uint32_t)stat_buf.st_size; /* * Got the file mapped now parse it. @@ -145,11 +153,11 @@ uint32_t *table_size) continue; } new_seg_addr_table[k].seg1addr = - strtoul(file_addr + j, &endp, 16); + (uint32_t)strtoul(file_addr + j, &endp, 16); if(endp == NULL) fatal("improper hexadecimal number on line %u in " "file: %s for %s %s", j, file_name, flag, argument); - j = endp - file_addr; + j = (uint32_t)(endp - file_addr); if(j == file_size) fatal("missing library install name on line %u in file: " "%s for %s %s", j, file_name, flag, argument); @@ -164,13 +172,13 @@ uint32_t *table_size) "%s for %s %s", j, file_name, flag, argument); new_seg_addr_table[k].segs_read_write_addr = - strtoul(file_addr + j, &endp, 16); + (uint32_t)strtoul(file_addr + j, &endp, 16); if(endp == NULL || endp == file_addr + j){ new_seg_addr_table[k].split = FALSE; new_seg_addr_table[k].segs_read_write_addr = UINT_MAX; } else{ - j = endp - file_addr; + j = (uint32_t)(endp - file_addr); new_seg_addr_table[k].split = TRUE; new_seg_addr_table[k].segs_read_only_addr = new_seg_addr_table[k].seg1addr; @@ -240,29 +248,31 @@ void *cookie) { int fd; struct stat stat_buf; - uint32_t i, file_size, line, comment_prefix_length; + uint32_t i, file_size, line; + size_t comment_prefix_length; char *file_addr, *endp; struct seg_addr_table entry; - file_addr = NULL; if((fd = open(file_name, O_RDONLY, 0)) == -1) system_fatal("can't open file: %s", file_name); if(fstat(fd, &stat_buf) == -1) system_fatal("can't stat file: %s", file_name); - /* - * For some reason mapping files with zero size fails - * so it has to be handled specially. - */ - if(stat_buf.st_size != 0){ + file_addr = NULL; + if (stat_buf.st_size > 0xFFFFFFFF) { + fatal("File too large (%llu): %s", stat_buf.st_size, + file_name); + } + else if (stat_buf.st_size == 0) { + fatal("Empty file: %s", file_name); + } + else { file_addr = mmap(0, stat_buf.st_size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0); if((intptr_t)file_addr == -1) system_error("can't map file: %s", file_name); } - else - fatal("empty file: %s ", file_name); close(fd); - file_size = stat_buf.st_size; + file_size = (uint32_t)stat_buf.st_size; /* * Got the file mapped now parse and process it. @@ -305,11 +315,11 @@ void *cookie) line++; continue; } - entry.seg1addr = strtoul(file_addr + i, &endp, 16); + entry.seg1addr = (uint32_t)strtoul(file_addr + i, &endp, 16); if(endp == NULL) fatal("improper hexadecimal number on line %u in file: %s", line, file_name); - i = endp - file_addr; + i = (uint32_t)(endp - file_addr); if(i == file_size) fatal("missing library install name on line %u in file: %s", line, file_name); @@ -323,13 +333,13 @@ void *cookie) fatal("missing library install name on line %u in file: %s", line, file_name); - entry.segs_read_write_addr = strtoul(file_addr + i, &endp, 16); + entry.segs_read_write_addr = (uint32_t)strtoul(file_addr + i, &endp, 16); if(endp == NULL || endp == file_addr + i){ entry.split = FALSE; entry.segs_read_write_addr = UINT_MAX; } else{ - i = endp - file_addr; + i = (uint32_t)(endp - file_addr); entry.split = TRUE; entry.segs_read_only_addr = entry.seg1addr; entry.seg1addr = UINT_MAX; diff --git a/cctools/libstuff/swap_headers.c b/cctools/libstuff/swap_headers.c index cb0f4e3..a3e7395 100644 --- a/cctools/libstuff/swap_headers.c +++ b/cctools/libstuff/swap_headers.c @@ -101,6 +101,9 @@ struct load_command *load_commands) struct linker_option_command *lo; struct dyld_info_command *dc; struct version_min_command *vc; + struct build_version_command *bv; + struct build_tool_version *btv; + struct note_command *nc; uint32_t flavor, count; unsigned long nflavor; char *p, *state, *cmd_name; @@ -1031,6 +1034,18 @@ check_dylinker_command: } break; + case LC_NOTE: + nc = (struct note_command *)lc; + if((char *)nc + nc->cmdsize > + (char *)load_commands + sizeofcmds){ + error("in swap_object_headers(): truncated or malformed " + "load commands (cmdsize field of LC_NOTE " + "command %lu extends past the end of the load " + "commands)", i); + return(FALSE); + } + break; + case LC_IDENT: id = (struct ident_command *)lc; if((char *)id + id->cmdsize > @@ -1191,6 +1206,17 @@ check_dylinker_command: } break; + case LC_BUILD_VERSION: + bv = (struct build_version_command *)lc; + if(bv->cmdsize != sizeof(struct build_version_command) + + bv->ntools * sizeof(struct build_tool_version)){ + error("in swap_object_headers(): malformed load commands " + "(LC_BUILD_VERSION command %lu has incorrect " + "cmdsize", i); + return(FALSE); + } + break; + case LC_RPATH: rpath = (struct rpath_command *)lc; if(rpath->cmdsize < sizeof(struct rpath_command)){ @@ -1700,6 +1726,11 @@ check_dylinker_command: swap_source_version_command(sv, target_byte_sex); break; + case LC_NOTE: + nc = (struct note_command *)lc; + swap_note_command(nc, target_byte_sex); + break; + case LC_IDENT: id = (struct ident_command *)lc; swap_ident_command(id, target_byte_sex); @@ -1736,6 +1767,8 @@ check_dylinker_command: case LC_DATA_IN_CODE: case LC_DYLIB_CODE_SIGN_DRS: case LC_LINKER_OPTIMIZATION_HINT: + case LC_DYLD_EXPORTS_TRIE: + case LC_DYLD_CHAINED_FIXUPS: ld = (struct linkedit_data_command *)lc; swap_linkedit_data_command(ld, target_byte_sex); break; @@ -1773,6 +1806,13 @@ check_dylinker_command: vc = (struct version_min_command *)lc; swap_version_min_command(vc, target_byte_sex); break; + + case LC_BUILD_VERSION: + bv = (struct build_version_command *)lc; + btv = (struct build_tool_version *) + ((char *)bv + sizeof(struct build_version_command)); + swap_build_tool_version(btv, bv->ntools, target_byte_sex); + swap_build_version_command(bv, target_byte_sex); } lc = (struct load_command *)((char *)lc + l.cmdsize); diff --git a/cctools/libstuff/symbol_list.c b/cctools/libstuff/symbol_list.c index 613bc1a..d11b7c8 100644 --- a/cctools/libstuff/symbol_list.c +++ b/cctools/libstuff/symbol_list.c @@ -21,6 +21,7 @@ * @APPLE_LICENSE_HEADER_END@ */ #ifndef RLD +#include #include #include #include @@ -52,7 +53,8 @@ struct symbol_list **list, uint32_t *size) { int fd; - uint32_t i, j, len, strings_size; + uint32_t i, j, strings_size; + size_t len; struct stat stat_buf; char *strings, *p, *line; @@ -65,7 +67,7 @@ uint32_t *size) close(fd); return; } - strings_size = stat_buf.st_size; + strings_size = (uint32_t)stat_buf.st_size; strings = (char *)allocate(strings_size + 2); strings[strings_size] = '\n'; strings[strings_size + 1] = '\0'; @@ -116,7 +118,7 @@ uint32_t *size) (*list)[i].seen = FALSE; i++; len = strlen(line); - j = len - 1; + j = (uint32_t)(len - 1); while(j > 0 && isspace(line[j])){ j--; } @@ -151,7 +153,7 @@ uint32_t *size) #ifdef DEBUG printf("symbol list:\n"); for(i = 0; i < (*size); i++){ - printf("0x%x name = %s\n", &((*list)[i]),(*list)[i].name); + printf("0x%p name = %s\n", &((*list)[i]),(*list)[i].name); } #endif /* DEBUG */ } diff --git a/cctools/libstuff/version_number.c b/cctools/libstuff/version_number.c index 9a0384c..baf018b 100644 --- a/cctools/libstuff/version_number.c +++ b/cctools/libstuff/version_number.c @@ -38,8 +38,8 @@ __private_extern__ enum bool get_version_number( -char *flag, -char *argument, +const char *flag, +const char *argument, uint32_t *value) { char *p, *x, *y, *z, *dot, *endp; @@ -71,7 +71,7 @@ uint32_t *value) Y = 0; Z = 0; - X = strtoul(x, &endp, 10); + X = (uint32_t)strtoul(x, &endp, 10); if(*endp != '\0'){ error("first field (%s) in argument for: %s %s not a proper " "unsigned number", x, flag, argument); @@ -83,7 +83,7 @@ uint32_t *value) goto fail; } if(y != NULL){ - Y = strtoul(y, &endp, 10); + Y = (uint32_t)strtoul(y, &endp, 10); if(*endp != '\0'){ error("second field (%s) in argument for: %s %s not a proper " "unsigned number", y, flag, argument); @@ -95,7 +95,7 @@ uint32_t *value) goto fail; } if(z != NULL){ - Z = strtoul(z, &endp, 10); + Z = (uint32_t)strtoul(z, &endp, 10); if(*endp != '\0'){ error("third field (%s) in argument for: %s %s not a " "proper unsigned number", z, flag, argument); diff --git a/cctools/libstuff/write64.c b/cctools/libstuff/write64.c new file mode 100644 index 0000000..1de8dba --- /dev/null +++ b/cctools/libstuff/write64.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef HAVE_WRITE64 /* cctools-port */ + +#include "stuff/write64.h" + +ssize_t write64(int fildes, const void *buf, size_t nbyte) +{ + unsigned char* uchars = (unsigned char*)buf; + ssize_t total = 0; + + while (nbyte) + { + /* + * If we were writing socket- or stream-safe code we'd chuck the + * entire buf to write(2) and then gracefully re-request bytes that + * didn't get written. But write(2) will return EINVAL if you ask it to + * write more than 2^31-1 bytes. So instead we actually need to throttle + * the input to write. + * + * Historically code using write(2) to write to disk will assert that + * that all of the requested bytes were written. It seems harmless to + * re-request bytes as one does when writing to streams, with the + * compromise that we will return immediately when write(2) returns 0 + * bytes written. + */ + size_t limit = 0x7FFFFFFF; + size_t towrite = nbyte < limit ? nbyte : limit; + ssize_t wrote = write(fildes, uchars, towrite); + if (-1 == wrote) + { + return -1; + } + else if (0 == wrote) + { + break; + } + else + { + nbyte -= wrote; + uchars += wrote; + total += wrote; + } + } + + return total; +} + +#endif /* ! HAVE_WRITE64 */ diff --git a/cctools/libstuff/writeout.c b/cctools/libstuff/writeout.c index 16f7354..10f164a 100644 --- a/cctools/libstuff/writeout.c +++ b/cctools/libstuff/writeout.c @@ -26,6 +26,7 @@ #include "stuff/openstep_mach.h" #include #ifndef __OPENSTEP__ +#include #include #endif #include "stuff/ofile.h" @@ -36,6 +37,7 @@ #ifdef LTO_SUPPORT #include "stuff/lto.h" #endif /* LTO_SUPPORT */ +#include "stuff/write64.h" static void copy_new_symbol_info( char *p, @@ -52,6 +54,7 @@ static void make_table_of_contents( time_t toc_time, enum bool sort_toc, enum bool commons_in_toc, + enum bool force_64bit_toc, enum bool library_warnings); static enum bool toc_symbol( @@ -100,7 +103,12 @@ static void warn_member( * a new table of contents is created and is sorted if sort_toc is TRUE and * commons symbols are included in the table of contents if commons_in_toc is * TRUE. The normal use will have sort_toc == TRUE and commons_in_toc == FALSE. - * If warnings about unusual libraries are printed if library_warnings == TRUE. + * For testing force_64bit_toc can be set to TRUE but it should normally be set + * to FALSE. If the output contains archive members that have archive offsets + * greater than 32-bits then a 64-bit toc will be used. If warnings about + * unusual libraries are printed if library_warnings == TRUE. If throttle is + * not NULL it is set to a value of bytes per second to limiting the writes to + * in order to not eat all I/O bandwidth. */ __private_extern__ void @@ -111,29 +119,67 @@ char *output, unsigned short mode, enum bool sort_toc, enum bool commons_in_toc, +enum bool force_64bit_toc, enum bool library_warnings, uint32_t *throttle) { uint32_t fsync; int fd; #ifndef __OPENSTEP__ - struct utimbuf timep; + struct timeval toc_timeval; + struct timespec toc_timespec; #else time_t timep[2]; + time_t toc_time; #endif mach_port_t my_mach_host_self; char *file, *p; - uint32_t file_size; - time_t toc_time; + uint64_t file_size; enum bool seen_archive; kern_return_t r; - - seen_archive = FALSE; - toc_time = time(0); + int time_result; - writeout_to_mem(archs, narchs, output, (void **)&file, &file_size, - sort_toc, commons_in_toc, library_warnings, - &seen_archive); + seen_archive = FALSE; + +#ifndef __OPENSTEP__ + /* cctools-port: replaced __builtin_available */ +#if 0 + if (__builtin_available(macOS 10.12, *)) { +#endif /* 0 */ +#ifdef HAVE_CLOCK_GETTIME + if (clock_gettime(CLOCK_REALTIME, &toc_timespec)) { + system_error("clock_gettime failed"); + return; + } +#endif /* HAVE_CLOCK_GETTIME */ +#if 0 + } else { +#endif /* 0 */ +#ifndef HAVE_CLOCK_GETTIME + if (gettimeofday(&toc_timeval, NULL)) { + system_error("gettimeofday failed"); + return; + } +#endif /* !HAVE_CLOCK_GETTIME */ +#if 0 + } +#endif /* 0 */ +#else + /* + * The environment variable ZERO_AR_DATE is used here and other + * places that write archives to allow testing and comparing + * things for exact binary equality. + */ + if (getenv("ZERO_AR_DATE") == NULL) { + toc_time = time(NULL); + } else { + toc_time = 0; + } +#endif /* !defined(__OPENSTEP__) */ + + writeout_to_mem(archs, narchs, output, (void **)&file, &file_size, + sort_toc, commons_in_toc, force_64bit_toc, + library_warnings, &seen_archive); /* * Create the output file. The unlink() is done to handle the problem @@ -186,10 +232,11 @@ uint32_t *throttle) #undef THROTTLE_DEBUG do { if((file + file_size) - p < WRITE_SIZE) - write_size = (file + file_size) - p; + write_size = (uint32_t)((file + file_size) - p); else write_size = WRITE_SIZE; - if(write(fd, p, write_size) != (int)write_size){ + /* MDT: write(2) is OK here, write_size is less than 2^31-1 */ + if(write(fd, p, write_size) != (ssize_t)write_size){ system_error("can't write output file: %s", output); goto cleanup; } @@ -238,7 +285,7 @@ uint32_t *throttle) } else{ no_throttle: - if(write(fd, file, file_size) != (int)file_size){ + if(write64(fd, file, file_size) != (ssize_t)file_size){ system_error("can't write output file: %s", output); goto cleanup; } @@ -249,15 +296,41 @@ no_throttle: } if(seen_archive == TRUE){ #ifndef __OPENSTEP__ - timep.actime = toc_time - 5; - timep.modtime = toc_time - 5; - if(utime(output, &timep) == -1) + /* + * If ZERO_AR_DATE is set here, writeout_to_mem has zeroed the + * SYMDEF mod time; the other ar content objects are assumed to + * have been zeroed out when the library was created. writeout + * will not zero out the modification time in the filesystem. + */ + /* cctools-port: replaced __builtin_available */ +#if 0 + if (__builtin_available(macOS 10.12, *)) { +#endif /* 0 */ +#ifdef HAVE_UTIMESAT + struct timespec times[2] = {0}; + memcpy(×[0], &toc_timespec, sizeof(struct timespec)); + memcpy(×[1], &toc_timespec, sizeof(struct timespec)); + time_result = utimensat(AT_FDCWD, output, times, 0); +#endif /* HAVE_UTIMESAT */ +#if 0 + } + else { +#endif /* 0 */ +#ifndef HAVE_UTIMESAT + struct timeval times[2] = {0}; + memcpy(×[0], &toc_timeval, sizeof(struct timeval)); + memcpy(×[1], &toc_timeval, sizeof(struct timeval)); + time_result = utimes(output, times); +#endif /* !HAVE_UTIMESAT */ +#if 0 + } +#endif /* 0 */ #else - timep[0] = toc_time - 5; - timep[1] = toc_time - 5; - if(utime(output, timep) == -1) + timep[0] = toc_time; + timep[1] = toc_time; + time_result = utime(output, timep); #endif - { + if (time_result) { system_fatal("can't set the modifiy times in output file: %s", output); goto cleanup; @@ -271,7 +344,6 @@ cleanup: } } - /* * writeout_to_mem() creates an ofile in memory from the data structure pointed * to by archs (of narchs size). Upon successful return, *outputbuf will point @@ -281,9 +353,13 @@ cleanup: * - if filename is NULL, a dummy file name is used. If there are libraries in * the data structures a new table of contents is created and is sorted if * sort_toc is TRUE and commons symbols are included in the table of contents - * if commons_in_toc is TRUE. The normal use will have sort_toc == TRUE and - * commons_in_toc == FALSE. If warnings about unusual libraries are printed if - * library_warnings == TRUE. + * if commons_in_toc is TRUE. The normal use will have sort_toc == TRUE and + * commons_in_toc == FALSE. For testing force_64bit_toc can be set to TRUE but + * it should normally be set to FALSE. If the output contains archive members + * that have archive offsets greater than 32-bits then a 64-bit toc will be + * used. If warnings about unusual libraries are printed if library_warnings + * == TRUE. If an archive is in the output then *seen_archive will be set to + * TRUE else FALSE. */ __private_extern__ void @@ -292,19 +368,23 @@ struct arch *archs, uint32_t narchs, char *filename, void **outputbuf, -uint32_t *length, +uint64_t *length, enum bool sort_toc, enum bool commons_in_toc, +enum bool force_64bit_toc, enum bool library_warnings, enum bool *seen_archive) { - uint32_t i, j, k, file_size, offset, pad, size; + uint32_t i, j, k, pad, size; + uint64_t file_size, offset; uint32_t i32; + uint64_t i64; enum byte_sex target_byte_sex, host_byte_sex; char *file, *p; kern_return_t r; struct fat_header *fat_header; struct fat_arch *fat_arch; + struct fat_arch_64 *fat_arch64; struct dysymtab_command dyst; struct twolevel_hints_command hints_cmd; struct load_command lc, *lcp; @@ -325,9 +405,18 @@ enum bool *seen_archive) * modification time of the output file to be set to. */ *seen_archive = FALSE; - toc_time = time(0); + /* + * The environment variable ZERO_AR_DATE is used here and other + * places that write archives to allow testing and comparing + * things for exact binary equality. + */ + if (getenv("ZERO_AR_DATE") != NULL) + toc_time = 0; + else + toc_time = time(0) + 5; fat_arch = NULL; /* here to quite compiler maybe warning message */ + fat_arch64 = NULL; fat_header = NULL; if(narchs == 0){ @@ -341,43 +430,81 @@ enum bool *seen_archive) * Calculate the total size of the file and the final size of each * architecture. */ - if(narchs > 1 || archs[0].fat_arch != NULL) - file_size = sizeof(struct fat_header) + - sizeof(struct fat_arch) * narchs; + if(narchs > 1 || + archs[0].fat_arch != NULL || archs[0].fat_arch64 != NULL){ + file_size = sizeof(struct fat_header); + if(archs[0].fat_arch64 != NULL) + file_size += sizeof(struct fat_arch_64) * narchs; + else + file_size += sizeof(struct fat_arch) * narchs; + } else file_size = 0; for(i = 0; i < narchs; i++){ /* * For each arch that is an archive recreate the table of contents. + * + * Remember, for historical reasons the table of contents is + * time-shifted 5 seconds into the future. This 5 second offset is + * not applied when zeroing out ar dates. */ if(archs[i].type == OFILE_ARCHIVE){ *seen_archive = TRUE; make_table_of_contents(archs + i, filename, toc_time, sort_toc, - commons_in_toc, library_warnings); + commons_in_toc, force_64bit_toc, + library_warnings); archs[i].library_size += SARMAG + archs[i].toc_size; - if(archs[i].fat_arch != NULL) + if(archs[i].fat_arch64 != NULL) + file_size = rnd(file_size, 1 << archs[i].fat_arch64->align); + else if(archs[i].fat_arch != NULL) file_size = rnd(file_size, 1 << archs[i].fat_arch->align); file_size += archs[i].library_size; - if(archs[i].fat_arch != NULL) - archs[i].fat_arch->size = archs[i].library_size; + if(archs[i].fat_arch64 != NULL) + archs[i].fat_arch64->size = archs[i].library_size; + else if(archs[i].fat_arch != NULL) { + if (archs[i].library_size > 0xFFFFFFFF) { + error("file too large to create as a fat file because " + "size field in struct fat_arch is only 32-bits " + "and library_size (%llu) of file %s exceeds that", + archs[i].unknown_size, archs[i].file_name); + return; + } + archs[i].fat_arch->size = (uint32_t)archs[i].library_size; + } } else if(archs[i].type == OFILE_Mach_O){ size = archs[i].object->object_size - archs[i].object->input_sym_info_size + archs[i].object->output_new_content_size + archs[i].object->output_sym_info_size; - if(archs[i].fat_arch != NULL) + if(archs[i].fat_arch64 != NULL) + file_size = rnd(file_size, 1 << archs[i].fat_arch64->align); + else if(archs[i].fat_arch != NULL) file_size = rnd(file_size, 1 << archs[i].fat_arch->align); file_size += size; - if(archs[i].fat_arch != NULL) + if(archs[i].fat_arch64 != NULL) + archs[i].fat_arch64->size = size; + else if(archs[i].fat_arch != NULL) archs[i].fat_arch->size = size; } else{ /* archs[i].type == OFILE_UNKNOWN */ - if(archs[i].fat_arch != NULL) + if(archs[i].fat_arch64 != NULL) + file_size = rnd(file_size, 1 << archs[i].fat_arch64->align); + else if(archs[i].fat_arch != NULL) file_size = rnd(file_size, 1 << archs[i].fat_arch->align); file_size += archs[i].unknown_size; - if(archs[i].fat_arch != NULL) - archs[i].fat_arch->size = archs[i].unknown_size; + if(archs[i].fat_arch64 != NULL) + archs[i].fat_arch64->size = archs[i].unknown_size; + else if(archs[i].fat_arch != NULL) { + if (archs[i].unknown_size > 0xFFFFFFFF) { + error("file too large to create as a fat file because " + "size field in struct fat_arch is only 32-bits " + "and unknown_size (%llu) of file %s exceeds that", + archs[i].unknown_size, archs[i].file_name); + return; + } + archs[i].fat_arch->size = (uint32_t)archs[i].unknown_size; + } } } @@ -388,27 +515,63 @@ enum bool *seen_archive) if((r = vm_allocate(mach_task_self(), (vm_address_t *)&file, file_size, TRUE)) != KERN_SUCCESS) mach_fatal(r, "can't vm_allocate() buffer for output file: %s of " - "size %u", filename, file_size); + "size %llu", filename, file_size); /* * If there is more than one architecture then fill in the fat file - * header and the fat_arch structures in the buffer. + * header and the fat_arch or fat_arch64 structures in the buffer. */ - if(narchs > 1 || archs[0].fat_arch != NULL){ + if(narchs > 1 || + archs[0].fat_arch != NULL || archs[0].fat_arch64 != NULL){ fat_header = (struct fat_header *)file; - fat_header->magic = FAT_MAGIC; + if(archs[0].fat_arch64 != NULL) + fat_header->magic = FAT_MAGIC_64; + else + fat_header->magic = FAT_MAGIC; fat_header->nfat_arch = narchs; - offset = sizeof(struct fat_header) + - sizeof(struct fat_arch) * narchs; - fat_arch = (struct fat_arch *)(file + sizeof(struct fat_header)); + offset = sizeof(struct fat_header); + if(archs[0].fat_arch64 != NULL){ + offset += sizeof(struct fat_arch_64) * narchs; + fat_arch64 = (struct fat_arch_64 *) + (file + sizeof(struct fat_header)); + fat_arch = NULL; + } + else{ + offset += sizeof(struct fat_arch) * narchs; + fat_arch = (struct fat_arch *) + (file + sizeof(struct fat_header)); + fat_arch64 = NULL; + } for(i = 0; i < narchs; i++){ - fat_arch[i].cputype = archs[i].fat_arch->cputype; - fat_arch[i].cpusubtype = archs[i].fat_arch->cpusubtype; - offset = rnd(offset, 1 << archs[i].fat_arch->align); - fat_arch[i].offset = offset; - fat_arch[i].size = archs[i].fat_arch->size; - fat_arch[i].align = archs[i].fat_arch->align; - offset += archs[i].fat_arch->size; + if(archs[i].fat_arch64 != NULL){ + fat_arch64[i].cputype = archs[i].fat_arch64->cputype; + fat_arch64[i].cpusubtype = archs[i].fat_arch64->cpusubtype; + } + else{ + fat_arch[i].cputype = archs[i].fat_arch->cputype; + fat_arch[i].cpusubtype = archs[i].fat_arch->cpusubtype; + } + if(offset > UINT32_MAX && archs[i].fat_arch64 == NULL){ + error("file too large to create as a fat file because " + "offset field in struct fat_arch is only 32-bits and " + "offset (%llu) to architecture %s exceeds that", + offset, archs[i].fat_arch_name); + return; + } + if(archs[i].fat_arch64 != NULL){ + offset = rnd(offset, 1 << archs[i].fat_arch64->align); + fat_arch64[i].offset = offset; + fat_arch64[i].size = archs[i].fat_arch64->size; + fat_arch64[i].align = archs[i].fat_arch64->align; + offset += archs[i].fat_arch64->size; + } + else{ + offset = rnd(offset, 1 << archs[i].fat_arch->align); + fat_arch[i].offset = (uint32_t)offset; + fat_arch[i].size = archs[i].fat_arch->size; + fat_arch[i].align = archs[i].fat_arch->align; + offset += archs[i].fat_arch->size; + } } } @@ -416,8 +579,12 @@ enum bool *seen_archive) * Now put each arch in the buffer. */ for(i = 0; i < narchs; i++){ - if(archs[i].fat_arch != NULL) - p = file + fat_arch[i].offset; + if(archs[i].fat_arch != NULL || archs[i].fat_arch64 != NULL){ + if(archs[i].fat_arch64 != NULL) + p = file + fat_arch64[i].offset; + else + p = file + fat_arch[i].offset; + } else p = file; @@ -442,7 +609,8 @@ enum bool *seen_archive) * bsd4.3 ranlib(1) implementation. */ if(library_warnings == TRUE && archs[i].ntocs == 0){ - if(narchs > 1 || archs[i].fat_arch != NULL) + if(narchs > 1 || + archs[i].fat_arch != NULL || archs[i].fat_arch64 != NULL) warning("warning library: %s for architecture: %s the " "table of contents is empty (no object file " "members in the library)", filename, @@ -468,12 +636,21 @@ enum bool *seen_archive) target_byte_sex = host_byte_sex; /* - * Put in the table of contents member: - * the archive header - * a 32-bit for the number of bytes of the ranlib structs - * the ranlib structs - * a 32-bit for the number of bytes of the ranlib strings - * the strings for the ranlib structs + * Put in the table of contents member, which can be either a + * 32-bit toc or a 64-bit toc: + * Both forms start with: + * the archive header + * the archive member name (if using a long name) + * then for a 32-bit toc the rest is this: + * a 32-bit for the number of bytes of the ranlib structs + * the ranlib structs + * a 32-bit for the number of bytes of the ranlib strings + * the strings for the ranlib structs + * and for a 64-bit toc the rest is this: + * a 64-bit for the number of bytes of the ranlib_64 structs + * the ranlib_64 structs + * a 64-bit for the number of bytes of the ranlib strings + * the strings for the ranlib structs */ memcpy(p, (char *)(&archs[i].toc_ar_hdr),sizeof(struct ar_hdr)); p += sizeof(struct ar_hdr); @@ -485,24 +662,69 @@ enum bool *seen_archive) sizeof(struct ar_hdr)); } - i32 = archs[i].ntocs * sizeof(struct ranlib); - if(target_byte_sex != host_byte_sex) - i32 = SWAP_INT(i32); - memcpy(p, (char *)&i32, sizeof(uint32_t)); - p += sizeof(uint32_t); + if(archs[i].using_64toc == FALSE){ + if (archs[i].ntocs > 0xFFFFFFFF) { + error("file too large to create because there are more " + "than 2^32 entries (%llu) in the toc for file %s", + archs[i].ntocs, archs[i].file_name); + return; + } + if (archs[i].ntocs * sizeof(struct ranlib) > 0xFFFFFFFF) { + error("file too large to create because the library " + "toc size is only 32-bits and the required toc " + "size (%llu) for file %s exceeds that", + archs[i].ntocs * sizeof(struct ranlib), + archs[i].file_name); + return; + } + if (archs[i].toc_strsize > 0xFFFFFFFF) { + error("file too large to create because toc symbol " + "name length is only 32-bits and the required " + "toc symbol name length (%llu) for file %s " + "exceeds that", + archs[i].toc_strsize, archs[i].file_name); + return; + } + i32 = (uint32_t)(archs[i].ntocs * sizeof(struct ranlib)); + if(target_byte_sex != host_byte_sex) + i32 = SWAP_INT(i32); + memcpy(p, (char *)&i32, sizeof(uint32_t)); + p += sizeof(uint32_t); - if(target_byte_sex != host_byte_sex) - swap_ranlib(archs[i].toc_ranlibs, archs[i].ntocs, - target_byte_sex); - memcpy(p, (char *)archs[i].toc_ranlibs, - archs[i].ntocs * sizeof(struct ranlib)); - p += archs[i].ntocs * sizeof(struct ranlib); + if(target_byte_sex != host_byte_sex) + swap_ranlib(archs[i].toc_ranlibs, + (uint32_t)archs[i].ntocs, + target_byte_sex); + memcpy(p, (char *)archs[i].toc_ranlibs, + archs[i].ntocs * sizeof(struct ranlib)); + p += archs[i].ntocs * sizeof(struct ranlib); - i32 = archs[i].toc_strsize; - if(target_byte_sex != host_byte_sex) - i32 = SWAP_INT(i32); - memcpy(p, (char *)&i32, sizeof(uint32_t)); - p += sizeof(uint32_t); + i32 = (uint32_t)archs[i].toc_strsize; + if(target_byte_sex != host_byte_sex) + i32 = SWAP_INT(i32); + memcpy(p, (char *)&i32, sizeof(uint32_t)); + p += sizeof(uint32_t); + } + else{ + i64 = archs[i].ntocs * sizeof(struct ranlib_64); + if(target_byte_sex != host_byte_sex) + i64 = SWAP_LONG_LONG(i64); + memcpy(p, (char *)&i64, sizeof(uint64_t)); + p += sizeof(uint64_t); + + if(target_byte_sex != host_byte_sex) + swap_ranlib_64(archs[i].toc_ranlibs64, archs[i].ntocs, + target_byte_sex); + memcpy(p, (char *)archs[i].toc_ranlibs64, + archs[i].ntocs * sizeof(struct ranlib_64)); + p += archs[i].ntocs * sizeof(struct ranlib_64); + + i64 = archs[i].toc_strsize; + if(target_byte_sex != host_byte_sex) + i64 = SWAP_LONG_LONG(i64); + memcpy(p, (char *)&i64, sizeof(uint64_t)); + p += sizeof(uint64_t); + } memcpy(p, (char *)archs[i].toc_strings, archs[i].toc_strsize); p += archs[i].toc_strsize; @@ -593,14 +815,15 @@ enum bool *seen_archive) archs[i].members[j].object); } p += size; - pad = rnd(size, 8) - size; + pad = (uint32_t)rnd(size, 8) - size; } else{ memcpy(p, archs[i].members[j].unknown_addr, archs[i].members[j].unknown_size); p += archs[i].members[j].unknown_size; - pad = rnd(archs[i].members[j].unknown_size, 8) - - archs[i].members[j].unknown_size; + pad = (uint32_t) + (rnd(archs[i].members[j].unknown_size, 8) - + archs[i].members[j].unknown_size); } /* as with the UNIX ar(1) program pad with '\n' chars */ for(k = 0; k < pad; k++) @@ -652,7 +875,7 @@ enum bool *seen_archive) } } if(timestamp == 0) - timestamp = toc_time; + timestamp = (uint32_t)toc_time; lcp = archs[i].object->load_commands; if(archs[i].object->mh != NULL) ncmds = archs[i].object->mh->ncmds; @@ -717,9 +940,13 @@ enum bool *seen_archive) } } #ifdef __LITTLE_ENDIAN__ - if(narchs > 1 || archs[0].fat_arch != NULL){ + if(narchs > 1 || + archs[0].fat_arch != NULL || archs[0].fat_arch64 != NULL){ swap_fat_header(fat_header, BIG_ENDIAN_BYTE_SEX); - swap_fat_arch(fat_arch, narchs, BIG_ENDIAN_BYTE_SEX); + if(archs[0].fat_arch64 != NULL) + swap_fat_arch_64(fat_arch64, narchs, BIG_ENDIAN_BYTE_SEX); + else + swap_fat_arch(fat_arch, narchs, BIG_ENDIAN_BYTE_SEX); } #endif /* __LITTLE_ENDIAN__ */ *outputbuf = file; @@ -748,6 +975,18 @@ struct object *object) object->output_dyld_info_size); *size += object->output_dyld_info_size; } + if(object->output_dyld_chained_fixups_data_size != 0){ + if(object->output_dyld_chained_fixups_data != NULL) + memcpy(p + *size, object->output_dyld_chained_fixups_data, + object->output_dyld_chained_fixups_data_size); + *size += object->output_dyld_chained_fixups_data_size; + } + if(object->output_dyld_exports_trie_data_size != 0){ + if(object->output_dyld_exports_trie_data != NULL) + memcpy(p + *size, object->output_dyld_exports_trie_data, + object->output_dyld_exports_trie_data_size); + *size += object->output_dyld_exports_trie_data_size; + } memcpy(p + *size, object->output_loc_relocs, dyst->nlocrel * sizeof(struct relocation_info)); *size += dyst->nlocrel * @@ -831,8 +1070,10 @@ struct object *object) memcpy(p + *size, object->output_strings, object->output_strings_size); *size += object->output_strings_size; + memset(p + *size, '\0', object->output_strings_size_pad); + *size += object->output_strings_size_pad; if(object->output_code_sig_data_size != 0){ - *size = rnd(*size, 16); + *size = (uint32_t)rnd(*size, 16); if(object->output_code_sig_data != NULL) memcpy(p + *size, object->output_code_sig_data, object->output_code_sig_data_size); @@ -873,8 +1114,10 @@ struct object *object) memcpy(p + *size, object->output_strings, object->output_strings_size); *size += object->output_strings_size; + memset(p + *size, '\0', object->output_strings_size_pad); + *size += object->output_strings_size_pad; if(object->output_code_sig_data_size != 0){ - *size = rnd(*size, 16); + *size = (uint32_t)rnd(*size, 16); if(object->output_code_sig_data != NULL) memcpy(p + *size, object->output_code_sig_data, object->output_code_sig_data_size); @@ -896,6 +1139,7 @@ char *output, time_t toc_time, enum bool sort_toc, enum bool commons_in_toc, +enum bool force_64bit_toc, enum bool library_warnings) { uint32_t i, j, k, r, s, nsects; @@ -1057,6 +1301,8 @@ enum bool library_warnings) arch->toc_ranlibs = allocate(sizeof(struct ranlib) * arch->ntocs); arch->toc_strsize = rnd(arch->toc_strsize, 8); arch->toc_strings = allocate(arch->toc_strsize); + if(arch->toc_strsize >= 8) + memset(arch->toc_strings + arch->toc_strsize - 7, '\0', 7); /* * Second pass over the members to fill in the toc_entry structs and @@ -1222,22 +1468,106 @@ enum bool library_warnings) arch->toc_name_size = 16; arch->toc_name = SYMDEF "\0\0\0\0\0\0\0"; } - arch->toc_size = sizeof(struct ar_hdr) + - sizeof(uint32_t) + - arch->ntocs * sizeof(struct ranlib) + - sizeof(uint32_t) + - arch->toc_strsize; + arch->toc_size = (uint32_t) + (sizeof(struct ar_hdr) + + sizeof(uint32_t) + + arch->ntocs * sizeof(struct ranlib) + + sizeof(uint32_t) + + arch->toc_strsize); if(arch->toc_long_name == TRUE) arch->toc_size += arch->toc_name_size + (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr)); + /* + * Now with the size of the 32-bit toc known we can now see if it will + * work or if we have offsets to members that are more than 32-bits and + * we need to switch to the 64-bit toc, or switch to that if we are + * forcing a 64-bit toc. + */ + if(force_64bit_toc == TRUE) + arch->using_64toc = TRUE; + else{ + arch->using_64toc = FALSE; + for(i = 0; i < arch->nmembers; i++){ + if(arch->members[i].offset + SARMAG + arch->toc_size > + UINT32_MAX){ + arch->using_64toc = TRUE; + break; + } + } + } + if(arch->using_64toc){ + /* it is already checked above that arch->toc_long_name == TRUE */ + if(sorted == FALSE){ + /* + * This assumes that "__.SYMDEF_64\0\0\0\0" is 16 bytes + * and + * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr) + * is 4 bytes. + */ + ar_name = AR_EFMT1 "20"; + arch->toc_name_size = 16; + arch->toc_name = SYMDEF_64 "\0\0\0\0"; + } + else{ + arch->toc_name = SYMDEF_64_SORTED; + arch->toc_name_size = sizeof(SYMDEF_64_SORTED) - 1; + /* + * This assumes that "__.SYMDEF_64 SORTED\0\0\0\0\0" is 24 bytes + * and + * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr) + * is 4 bytes. + */ + ar_name = AR_EFMT1 "28"; + arch->toc_name_size = 24; + arch->toc_name = SYMDEF_64_SORTED "\0\0\0\0\0"; + } + /* + * Free the space for the 32-bit ranlib structs and allocate space + * for the 64-bit ranlib structs. + */ + free(arch->toc_ranlibs); + arch->toc_ranlibs = NULL; + arch->toc_ranlibs64 = allocate(sizeof(struct ranlib_64) * + arch->ntocs); + /* + * Now the size of the toc member when it is a 64-bit toc can be + * set. It is made up of the sizeof an archive header struct (the + * size of the name which is always a long name to get 8-byte + * alignment then the toc which is (as defined in ranlib.h): + * a uint64_t for the number of bytes of the ranlib_64 structs + * the ranlib_64 structures + * a uint64_t for the number of bytes of the strings + * the strings + */ + arch->toc_size = (uint32_t) + (sizeof(struct ar_hdr) + + sizeof(uint64_t) + + arch->ntocs * sizeof(struct ranlib_64) + + sizeof(uint64_t) + + arch->toc_strsize); + /* add the size of the name as a long name is always used */ + arch->toc_size += arch->toc_name_size + + (rnd(sizeof(struct ar_hdr), 8) - + sizeof(struct ar_hdr)); + } + for(i = 0; i < arch->nmembers; i++) arch->members[i].offset += SARMAG + arch->toc_size; + for(i = 0; i < arch->ntocs; i++){ - arch->toc_ranlibs[i].ran_un.ran_strx = - arch->toc_entries[i].symbol_name - arch->toc_strings; - arch->toc_ranlibs[i].ran_off = - arch->members[arch->toc_entries[i].member_index - 1].offset; + if(arch->using_64toc){ + arch->toc_ranlibs64[i].ran_un.ran_strx = + arch->toc_entries[i].symbol_name - arch->toc_strings; + arch->toc_ranlibs64[i].ran_off = + arch->members[arch->toc_entries[i].member_index - 1].offset; + } + else{ + arch->toc_ranlibs[i].ran_un.ran_strx = (uint32_t) + (arch->toc_entries[i].symbol_name - arch->toc_strings); + arch->toc_ranlibs[i].ran_off = (uint32_t) + arch->members[arch->toc_entries[i].member_index - 1].offset; + } } numask = 0; @@ -1393,7 +1723,7 @@ enum bool library_warnings) return(FALSE); fprintf(stderr, "%s: same symbol defined in more than one " "member ", progname); - if(arch->fat_arch != NULL) + if(arch->fat_arch != NULL || arch->fat_arch64 != NULL) fprintf(stderr, "for architecture: %s ", arch->fat_arch_name); fprintf(stderr, "in: %s (table of contents will not be " @@ -1444,7 +1774,7 @@ const char *format, ...) va_list ap; fprintf(stderr, "%s: ", progname); - if(arch->fat_arch != NULL) + if(arch->fat_arch != NULL || arch->fat_arch64 != NULL) fprintf(stderr, "for architecture: %s ", arch->fat_arch_name); if(member->input_ar_hdr != NULL){ diff --git a/cctools/ltmain.sh b/cctools/ltmain.sh new file mode 100644 index 0000000..48cea9b --- /dev/null +++ b/cctools/ltmain.sh @@ -0,0 +1,11369 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2018-07-24.06 + +# libtool (GNU libtool) 2.4.6.42-b88ce-dirty +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996-2018 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4.6.42-b88ce-dirty +package_revision=2.4.6.42 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2018-07-24.06; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# This is free software. There is NO warranty; not even for +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Copyright (C) 2004-2018 Bootstrap Authors +# +# This file is dual licensed under the terms of the MIT license +# , and GPL version 3 or later +# . You must apply one of +# these licenses when using or redistributing this software or any of +# the files within it. See the URLs above, or the file `LICENSE` +# included in the Bootstrap distribution for the full license texts. + +# Please report bugs or propose patches to: +# + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac +fi + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# func_unset VAR +# -------------- +# Portably unset VAR. +# In some shells, an 'unset VAR' statement leaves a non-zero return +# status if VAR is already unset, which might be problematic if the +# statement is used at the end of a function (thus poisoning its return +# value) or when 'set -e' is active (causing even a spurious abort of +# the script in this case). +func_unset () +{ + { eval $1=; (eval unset $1) >/dev/null 2>&1 && eval unset $1 || : ; } +} + + +# Make sure CDPATH doesn't cause `cd` commands to output the target dir. +func_unset CDPATH + +# Make sure ${,E,F}GREP behave sanely. +func_unset GREP_OPTIONS + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed "$PATH:/usr/xpg4/bin" + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep "$PATH:/usr/xpg4/bin" + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_arg pretty "$2" + eval "$1+=\\ \$func_quote_arg_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_arg pretty "$2" + eval "$1=\$$1\\ \$func_quote_arg_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_portable EVAL ARG +# ---------------------------- +# Internal function to portably implement func_quote_arg. Note that we still +# keep attention to performance here so we as much as possible try to avoid +# calling sed binary (so far O(N) complexity as long as func_append is O(1)). +func_quote_portable () +{ + $debug_cmd + + func_quote_portable_result=$2 + + # one-time-loop (easy break) + while true + do + if $1; then + func_quote_portable_result=`$ECHO "$2" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` + break + fi + + # Quote for eval. + case $func_quote_portable_result in + *[\\\`\"\$]*) + case $func_quote_portable_result in + *[\[\*\?]*) + func_quote_portable_result=`$ECHO "$func_quote_portable_result" \ + | $SED "$sed_quote_subst"` + break + ;; + esac + + func_quote_portable_old_IFS=$IFS + for _G_char in '\' '`' '"' '$' + do + # STATE($1) PREV($2) SEPARATOR($3) + set start "" "" + func_quote_portable_result=dummy"$_G_char$func_quote_portable_result$_G_char"dummy + IFS=$_G_char + for _G_part in $func_quote_portable_result + do + case $1 in + quote) + func_append func_quote_portable_result "$3$2" + set quote "$_G_part" "\\$_G_char" + ;; + start) + set first "" "" + func_quote_portable_result= + ;; + first) + set quote "$_G_part" "" + ;; + esac + done + done + IFS=$func_quote_portable_old_IFS + ;; + *) ;; + esac + break + done + + func_quote_portable_unquoted_result=$func_quote_portable_result + case $func_quote_portable_result in + # double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # many bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_portable_result=\"$func_quote_portable_result\" + ;; + esac +} + + +# func_quotefast_eval ARG +# ----------------------- +# Quote one ARG (internal). This is equivalent to 'func_quote_arg eval ARG', +# but optimized for speed. Result is stored in $func_quotefast_eval. +if test xyes = `(x=; printf -v x %q yes; echo x"$x") 2>/dev/null`; then + printf -v _GL_test_printf_tilde %q '~' + if test '\~' = "$_GL_test_printf_tilde"; then + func_quotefast_eval () + { + printf -v func_quotefast_eval_result %q "$1" + } + else + # Broken older Bash implementations. Make those faster too if possible. + func_quotefast_eval () + { + case $1 in + '~'*) + func_quote_portable false "$1" + func_quotefast_eval_result=$func_quote_portable_result + ;; + *) + printf -v func_quotefast_eval_result %q "$1" + ;; + esac + } + fi +else + func_quotefast_eval () + { + func_quote_portable false "$1" + func_quotefast_eval_result=$func_quote_portable_result + } +fi + + +# func_quote_arg MODEs ARG +# ------------------------ +# Quote one ARG to be evaled later. MODEs argument may contain zero or more +# specifiers listed below separated by ',' character. This function returns two +# values: +# i) func_quote_arg_result +# double-quoted (when needed), suitable for a subsequent eval +# ii) func_quote_arg_unquoted_result +# has all characters that are still active within double +# quotes backslashified. Available only if 'unquoted' is specified. +# +# Available modes: +# ---------------- +# 'eval' (default) +# - escape shell special characters +# 'expand' +# - the same as 'eval'; but do not quote variable references +# 'pretty' +# - request aesthetic output, i.e. '"a b"' instead of 'a\ b'. This might +# be used later in func_quote to get output like: 'echo "a b"' instead +# of 'echo a\ b'. This is slower than default on some shells. +# 'unquoted' +# - produce also $func_quote_arg_unquoted_result which does not contain +# wrapping double-quotes. +# +# Examples for 'func_quote_arg pretty,unquoted string': +# +# string | *_result | *_unquoted_result +# ------------+-----------------------+------------------- +# " | \" | \" +# a b | "a b" | a b +# "a b" | "\"a b\"" | \"a b\" +# * | "*" | * +# z="${x-$y}" | "z=\"\${x-\$y}\"" | z=\"\${x-\$y}\" +# +# Examples for 'func_quote_arg pretty,unquoted,expand string': +# +# string | *_result | *_unquoted_result +# --------------+---------------------+-------------------- +# z="${x-$y}" | "z=\"${x-$y}\"" | z=\"${x-$y}\" +func_quote_arg () +{ + _G_quote_expand=false + case ,$1, in + *,expand,*) + _G_quote_expand=: + ;; + esac + + case ,$1, in + *,pretty,*|*,expand,*|*,unquoted,*) + func_quote_portable $_G_quote_expand "$2" + func_quote_arg_result=$func_quote_portable_result + func_quote_arg_unquoted_result=$func_quote_portable_unquoted_result + ;; + *) + # Faster quote-for-eval for some shells. + func_quotefast_eval "$2" + func_quote_arg_result=$func_quotefast_eval_result + ;; + esac +} + + +# func_quote MODEs ARGs... +# ------------------------ +# Quote all ARGs to be evaled later and join them into single command. See +# func_quote_arg's description for more info. +func_quote () +{ + $debug_cmd + _G_func_quote_mode=$1 ; shift + func_quote_result= + while test 0 -lt $#; do + func_quote_arg "$_G_func_quote_mode" "$1" + if test -n "$func_quote_result"; then + func_append func_quote_result " $func_quote_arg_result" + else + func_append func_quote_result "$func_quote_arg_result" + fi + shift + done +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_arg pretty,expand "$_G_cmd" + eval "func_notquiet $func_quote_arg_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_arg expand,pretty "$_G_cmd" + eval "func_echo $func_quote_arg_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# This is free software. There is NO warranty; not even for +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Copyright (C) 2010-2018 Bootstrap Authors +# +# This file is dual licensed under the terms of the MIT license +# , and GPL version 3 or later +# . You must apply one of +# these licenses when using or redistributing this software or any of +# the files within it. See the URLs above, or the file `LICENSE` +# included in the Bootstrap distribution for the full license texts. + +# Please report bugs or propose patches to: +# + +# Set a version string for this script. +scriptversion=2018-07-24.06; # UTC + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# Copyright'. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug in processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# in the main code. A hook is just a list of function names that can be +# run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of hook functions to be called by +# FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_propagate_result FUNC_NAME_A FUNC_NAME_B +# --------------------------------------------- +# If the *_result variable of FUNC_NAME_A _is set_, assign its value to +# *_result variable of FUNC_NAME_B. +func_propagate_result () +{ + $debug_cmd + + func_propagate_result_result=: + if eval "test \"\${${1}_result+set}\" = set" + then + eval "${2}_result=\$${1}_result" + else + func_propagate_result_result=false + fi +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It's assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook functions." ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + func_unset "${_G_hook}_result" + eval $_G_hook '${1+"$@"}' + func_propagate_result $_G_hook func_run_hooks + if $func_propagate_result_result; then + eval set dummy "$func_run_hooks_result"; shift + fi + done +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list from your hook function. You may remove +# or edit any options that you action, and then pass back the remaining +# unprocessed options in '_result', escaped +# suitably for 'eval'. +# +# The '_result' variable is automatically unset +# before your hook gets called; for best performance, only set the +# *_result variable when necessary (i.e. don't call the 'func_quote' +# function unnecessarily because it can be an expensive operation on some +# machines). +# +# Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# # No change in '$@' (ignored completely by this hook). Leave +# # my_options_prep_result variable intact. +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# args_changed=false +# +# # Note that, for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: +# args_changed=: +# ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# args_changed=: +# ;; +# *) # Make sure the first unrecognised option "$_G_opt" +# # is added back to "$@" in case we need it later, +# # if $args_changed was set to 'true'. +# set dummy "$_G_opt" ${1+"$@"}; shift; break ;; +# esac +# done +# +# # Only call 'func_quote' here if we processed at least one argument. +# if $args_changed; then +# func_quote eval ${1+"$@"} +# my_silent_option_result=$func_quote_result +# fi +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll also need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options_finish [ARG]... +# ---------------------------- +# Finishing the option parse loop (call 'func_options' hooks ATM). +func_options_finish () +{ + $debug_cmd + + func_run_hooks func_options ${1+"$@"} + func_propagate_result func_run_hooks func_options_finish +} + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + _G_options_quoted=false + + for my_func in options_prep parse_options validate_options options_finish + do + func_unset func_${my_func}_result + func_unset func_run_hooks_result + eval func_$my_func '${1+"$@"}' + func_propagate_result func_$my_func func_options + if $func_propagate_result_result; then + eval set dummy "$func_options_result"; shift + _G_options_quoted=: + fi + done + + $_G_options_quoted || { + # As we (func_options) are top-level options-parser function and + # nobody quoted "$@" for us yet, we need to do it explicitly for + # caller. + func_quote eval ${1+"$@"} + func_options_result=$func_quote_result + } +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propagate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before returning. +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + func_run_hooks func_options_prep ${1+"$@"} + func_propagate_result func_run_hooks func_options_prep +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + _G_parse_options_requote=false + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + func_run_hooks func_parse_options ${1+"$@"} + func_propagate_result func_run_hooks func_parse_options + if $func_propagate_result_result; then + eval set dummy "$func_parse_options_result"; shift + # Even though we may have changed "$@", we passed the "$@" array + # down into the hook and it quoted it for us (because we are in + # this if-branch). No need to quote it again. + _G_parse_options_requote=false + fi + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + # We expect that one of the options parsed in this function matches + # and thus we remove _G_opt from "$@" and need to re-quote. + _G_match_parse_options=: + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" >&2 + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + if test $# = 0 && func_missing_arg $_G_opt; then + _G_parse_options_requote=: + break + fi + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) _G_parse_options_requote=: ; break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift + _G_match_parse_options=false + break + ;; + esac + + if $_G_match_parse_options; then + _G_parse_options_requote=: + fi + done + + if $_G_parse_options_requote; then + # save modified positional parameters for caller + func_quote eval ${1+"$@"} + func_parse_options_result=$func_quote_result + fi +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + func_run_hooks func_validate_options ${1+"$@"} + func_propagate_result func_run_hooks func_validate_options + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables +# after splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + if test "x$func_split_equals_lhs" = "x$1"; then + func_split_equals_rhs= + fi + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +# The version message is extracted from the calling file's header +# comments, with leading '# ' stripped: +# 1. First display the progname and version +# 2. Followed by the header comment line matching /^# Written by / +# 3. Then a blank line followed by the first following line matching +# /^# Copyright / +# 4. Immediately followed by any lines between the previous matches, +# except lines preceding the intervening completely blank line. +# For example, see the header comments of this file. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /^# Written by /!b + s|^# ||; p; n + + :fwd2blnk + /./ { + n + b fwd2blnk + } + p; n + + :holdwrnt + s|^# || + s|^# *$|| + /^Copyright /!{ + /./H + n + b holdwrnt + } + + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + G + s|\(\n\)\n*|\1|g + p; q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "30/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6.42-b88ce-dirty' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname (GNU libtool) 2.4.6.42-b88ce-dirty + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func_fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + _G_rc_lt_options_prep=: + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + *) + _G_rc_lt_options_prep=false + ;; + esac + + if $_G_rc_lt_options_prep; then + # Pass back the list of options. + func_quote eval ${1+"$@"} + libtool_options_prep_result=$func_quote_result + fi +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + _G_rc_lt_parse_options=false + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_match_lt_parse_options=: + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"} ; shift + _G_match_lt_parse_options=false + break + ;; + esac + $_G_match_lt_parse_options && _G_rc_lt_parse_options=: + done + + if $_G_rc_lt_parse_options; then + # save modified positional parameters for caller + func_quote eval ${1+"$@"} + libtool_parse_options_result=$func_quote_result + fi +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote eval ${1+"$@"} + libtool_validate_options_result=$func_quote_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_arg pretty "$libobj" + test "X$libobj" != "X$func_quote_arg_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_arg pretty "$srcfile" + qsrcfile=$func_quote_arg_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_arg pretty "$nonopt" + install_prog="$func_quote_arg_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_arg pretty "$arg" + func_append install_prog "$func_quote_arg_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_arg pretty "$arg" + func_append install_prog " $func_quote_arg_result" + if test -n "$arg2"; then + func_quote_arg pretty "$arg2" + fi + func_append install_shared_prog " $func_quote_arg_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_arg pretty "$install_override_mode" + func_append install_shared_prog " -m $func_quote_arg_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_arg expand,pretty "$relink_command" + eval "func_echo $func_quote_arg_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + func_quote_arg pretty "$ECHO" + qECHO=$func_quote_arg_result + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=$qECHO + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_arg pretty,unquoted "$arg" + qarg=$func_quote_arg_unquoted_result + func_append libtool_args " $func_quote_arg_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_arg pretty "$flag" + func_append arg " $func_quote_arg_result" + func_append compiler_flags " $func_quote_arg_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_arg pretty "$flag" + func_append arg " $wl$func_quote_arg_result" + func_append compiler_flags " $wl$func_quote_arg_result" + func_append linker_flags " $func_quote_arg_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -specs=* GCC specs files + # -stdlib=* select c++ std lib with clang + # -fsanitize=* Clang/GCC memory and address sanitizer + # -fuse-ld=* Linker select flags for GCC + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ + -specs=*|-fsanitize=*|-fuse-ld=*) + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_arg expand,pretty "$cmd" + eval "func_echo $func_quote_arg_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_arg expand,pretty "$cmd" + eval "func_echo $func_quote_arg_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_arg pretty "$var_value" + relink_command="$var=$func_quote_arg_result; export $var; $relink_command" + fi + done + func_quote eval cd "`pwd`" + func_quote_arg pretty,unquoted "($func_quote_result; $relink_command)" + relink_command=$func_quote_arg_unquoted_result + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_arg pretty,unquoted "$var_value" + relink_command="$var=$func_quote_arg_unquoted_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + func_quote eval cd "`pwd`" + relink_command="($func_quote_result; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + func_quote_arg pretty,unquoted "$relink_command" + relink_command=$func_quote_arg_unquoted_result + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/cctools/m4/llvm.m4 b/cctools/m4/llvm.m4 index cfdb165..a69f9a6 100644 --- a/cctools/m4/llvm.m4 +++ b/cctools/m4/llvm.m4 @@ -11,43 +11,55 @@ AC_DEFUN([CHECK_LLVM], [LLVM_CONFIG=$with_llvm_config], [LLVM_CONFIG=no]) if test "x$enable_lto_support" = "xyes"; then - if test "x$LLVM_CONFIG" = "xno"; then - AC_PATH_PROGS(LLVM_CONFIG, - [llvm-config \ - llvm-config-3.9 llvm-config-3.8 llvm-config-3.7 \ - llvm-config-3.6 llvm-config-3.5 llvm-config-3.4 \ - llvm-config-3.3 llvm-config-3.2 llvm-config-3.1 \ - llvm-config39 llvm-config38 llvm-config37 llvm-config36 \ - llvm-config35 llvm-config34 llvm-config33 llvm-config32 \ - llvm-config31], - no) - fi + if test "x$LLVM_CONFIG" = "xno"; then + AC_PATH_PROGS(LLVM_CONFIG, + [llvm-config \ + llvm-config-9.0 llvm-config-8.0 \ + llvm-config-7.0 llvm-config-6.0 \ + llvm-config-5.0 llvm-config-4.0 \ + llvm-config-3.9 llvm-config-3.8 llvm-config-3.7 \ + llvm-config-3.6 llvm-config-3.5 llvm-config-3.4 \ + llvm-config-3.3 llvm-config-3.2 llvm-config-3.1 \ + llvm-config90 llvm-config80 \ + llvm-config70 llvm-config60 \ + llvm-config50 llvm-config40 \ + llvm-config39 llvm-config38 llvm-config37 llvm-config36 \ + llvm-config35 llvm-config34 llvm-config33 llvm-config32 \ + llvm-config31], + no) + fi - if test "x$LLVM_CONFIG" != "xno"; then - LLVM_INCLUDE_DIR="`${LLVM_CONFIG} --includedir`" - LLVM_LIB_DIR="`${LLVM_CONFIG} --libdir`" + if test "x$LLVM_CONFIG" != "xno"; then + LLVM_INCLUDE_DIR="`${LLVM_CONFIG} --includedir`" + LLVM_LIB_DIR="`${LLVM_CONFIG} --libdir`" - ORIGLDFLAGS=$LDFLAGS - LDFLAGS="$LDFLAGS -L${LLVM_LIB_DIR}" + ORIGLDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -L${LLVM_LIB_DIR}" - AC_CHECK_LIB([LTO],[lto_get_version], - [ LTO_LIB="-L${LLVM_LIB_DIR} -lLTO" - if test "x$rpathlink" = "xyes"; then - LTO_RPATH="-Wl,-rpath,$LLVM_LIB_DIR,--enable-new-dtags" - LTO_LIB="$LTO_LIB" - fi - LTO_DEF=-DLTO_SUPPORT - # DO NOT include the LLVM include dir directly, - # it may cause the build to fail. - cp -f $LLVM_INCLUDE_DIR/llvm-c/lto.h `dirname ${0}`/include/llvm-c/lto.h - AC_SUBST([LTO_DEF]) - AC_SUBST([LTO_RPATH]) - AC_SUBST([LTO_LIB]) ]) + AC_CHECK_LIB([LTO],[lto_get_version], [ + LTO_LIB="-L${LLVM_LIB_DIR} -lLTO" + if test "x$rpathlink" = "xyes"; then + LTO_RPATH="-Wl,-rpath,$LLVM_LIB_DIR,--enable-new-dtags" + fi + if test "x$isdarwin" = "xyes"; then + LTO_RPATH="-Wl,-rpath,$LLVM_LIB_DIR" + fi + LTO_DEF=-DLTO_SUPPORT + # DO NOT include the LLVM include dir directly, + # it may cause the build to fail. + cp -f $LLVM_INCLUDE_DIR/llvm-c/lto.h `dirname ${0}`/include/llvm-c + if test -e $LLVM_INCLUDE_DIR/llvm-c/ExternC.h; then + cp -f $LLVM_INCLUDE_DIR/llvm-c/ExternC.h `dirname ${0}`/include/llvm-c + fi + AC_SUBST([LTO_DEF]) + AC_SUBST([LTO_RPATH]) + AC_SUBST([LTO_LIB]) + ]) - LDFLAGS=$ORIGLDFLAGS - else - AC_MSG_WARN([llvm-config not found, disabling LTO support]) - fi + LDFLAGS=$ORIGLDFLAGS + else + AC_MSG_WARN([llvm-config not found, disabling LTO support]) + fi fi AC_SUBST(LLVM_CONFIG) diff --git a/cctools/man/Mach-O.5 b/cctools/man/Mach-O.5 index 7808984..149c6c3 100644 --- a/cctools/man/Mach-O.5 +++ b/cctools/man/Mach-O.5 @@ -51,7 +51,7 @@ mapped in with the use of the link editor's option which creates a segment that contains these parts. These parts can be stripped down with the .B \-S -option to +option to .IR ld (1) or various options to .IR strip (1). diff --git a/cctools/man/Makefile b/cctools/man/Makefile deleted file mode 100644 index 1f75496..0000000 --- a/cctools/man/Makefile +++ /dev/null @@ -1,80 +0,0 @@ -ifneq "" "$(wildcard /bin/mkdirs)" - MKDIRS = /bin/mkdirs -else - MKDIRS = /bin/mkdir -p -endif - -DYLD_MAN1 = dyld.1 -OS_MAN1 = strings.1 lipo.1 -COMMON_MAN1 = as.1 nm.1 otool.1 ranlib.1 segedit.1 size.1 \ - strip.1 libtool.1 cmpdylib.1 pagestuff.1 \ - redo_prebinding.1 nmedit.1 install_name_tool.1 \ - codesign_allocate.1 ctf_insert.1 bitcode_strip.1 \ - llvm-otool.1 nm-classic.1 size-classic.1 otool-classic.1 -DEAD = gprof.1 - -DYLD_MAN3 = dyld.3 NSModule.3 NSObjectFileImage.3 dyld_debug.3 -MAN3 = kld.3 arch.3 get_end.3 end.3 getsectbyname.3 \ - getsectbynamefromheader.3 getsectdata.3 getsectdatafromheader.3 \ - getsegbyname.3 - -MAN5 = Mach-O.5 a.out.5 ranlib.5 stab.5 - -MANL = indr.1 checksyms.1 seg_addr_table.1 check_dylib.1 - -EFI1 = mtoc.1 - -DYLD_MANL3 = NSObjectFileImage_priv.3 -MANL3 = libsyminfo.3 redo_prebinding.3 - -INSTALL_FILES = Makefile $(OS_MAN1) $(COMMON_MAN1) $(MAN3) $(MAN5) $(MANL) \ - $(MANL3) $(DYLD_MAN1) $(DYLD_MAN3) $(DYLD_MANL3) $(EFI1) notes - -MANDIR = /usr/share/man -LOCMANDIR = /usr/local/man -EFIMANDIR = /usr/local/efi/share/man -DSTDIRS_MAN1 = $(DSTROOT)$(MANDIR)/man1 -DSTDIRS = $(DSTROOT)$(MANDIR)/man3 \ - $(DSTROOT)$(MANDIR)/man5 $(DSTROOT)$(LOCMANDIR)/man1 \ - $(DSTROOT)$(LOCMANDIR)/man3 $(DSTROOT)$(EFIMANDIR)/man1 - -install_os_tools: $(DSTDIRS_MAN1) $(OS_MAN1) - install -c -m 444 $(OS_MAN1) $(DSTROOT)$(MANDIR)/man1 - -install: $(DSTDIRS) $(DSTDIRS_MAN1) $(COMMON_MAN1) $(MAN3) $(MAN5) $(MANL) \ - $(RC_OS) $(MANL3) install_os_tools - install -c -m 444 $(COMMON_MAN1) $(DSTROOT)$(MANDIR)/man1 - if [ $(OLD_DYLD_STUFF) ]; \ - then \ - install -c -m 444 $(DYLD_MAN1) $(DSTROOT)$(MANDIR)/man1 ; \ - fi - install -c -m 444 $(MAN3) $(DSTROOT)$(MANDIR)/man3 - if [ $(OLD_DYLD_STUFF) ]; \ - then \ - install -c -m 444 $(DYLD_MAN3) $(DSTROOT)$(MANDIR)/man3 ; \ - fi - install -c -m 444 $(MAN5) $(DSTROOT)$(MANDIR)/man5 - install -c -m 444 $(MANL) $(DSTROOT)$(LOCMANDIR)/man1 - install -c -m 444 $(MANL3) $(DSTROOT)$(LOCMANDIR)/man3 - install -c -m 444 $(EFI1) $(DSTROOT)$(EFIMANDIR)/man1 - if [ $(OLD_DYLD_STUFF) ]; \ - then \ - install -c -m 444 $(DYLD_MANL3) $(DSTROOT)$(LOCMANDIR)/man3;\ - fi - -teflon macos: - -nextstep: - -installsrc: - $(MKDIRS) $(SRCROOT) - chmod 755 $(SRCROOT) - gnutar cf - $(INSTALL_FILES) | (cd $(SRCROOT); gnutar xf -) - chmod 444 $(SRCROOT)/* - -$(DSTDIRS) $(DSTDIRS_MAN1): - $(MKDIRS) $@ - -clean shlib_clean: - -all: diff --git a/cctools/man/Makefile.am b/cctools/man/Makefile.am new file mode 100644 index 0000000..3834c81 --- /dev/null +++ b/cctools/man/Makefile.am @@ -0,0 +1,50 @@ +dist_man_MANS = +dist_man_MANS += dyld.1 +dist_man_MANS += strings.1 +dist_man_MANS += lipo.1 +dist_man_MANS += as.1 +dist_man_MANS += nm.1 +dist_man_MANS += otool.1 +dist_man_MANS += ranlib.1 +dist_man_MANS += segedit.1 +dist_man_MANS += size.1 +dist_man_MANS += strip.1 +dist_man_MANS += libtool.1 +dist_man_MANS += cmpdylib.1 +dist_man_MANS += pagestuff.1 +dist_man_MANS += redo_prebinding.1 +dist_man_MANS += nmedit.1 +dist_man_MANS += install_name_tool.1 +dist_man_MANS += codesign_allocate.1 +dist_man_MANS += ctf_insert.1 +dist_man_MANS += bitcode_strip.1 +dist_man_MANS += llvm-otool.1 +dist_man_MANS += nm-classic.1 +dist_man_MANS += size-classic.1 +dist_man_MANS += otool-classic.1 +# dist_man_MANS += gprof.1 +dist_man_MANS += dyld.3 +dist_man_MANS += NSModule.3 +dist_man_MANS += NSObjectFileImage.3 +dist_man_MANS += dyld_debug.3 +dist_man_MANS += kld.3 +dist_man_MANS += arch.3 +dist_man_MANS += get_end.3 +dist_man_MANS += end.3 +dist_man_MANS += getsectbyname.3 +dist_man_MANS += getsectbynamefromheader.3 +dist_man_MANS += getsectdata.3 +dist_man_MANS += getsectdatafromheader.3 +dist_man_MANS += getsegbyname.3 +dist_man_MANS += Mach-O.5 +dist_man_MANS += a.out.5 +dist_man_MANS += ranlib.5 +dist_man_MANS += stab.5 +dist_man_MANS += indr.1 +dist_man_MANS += checksyms.1 +dist_man_MANS += seg_addr_table.1 +dist_man_MANS += check_dylib.1 +dist_man_MANS += mtoc.1 +dist_man_MANS += NSObjectFileImage_priv.3 +dist_man_MANS += libsyminfo.3 +dist_man_MANS += redo_prebinding.3 diff --git a/cctools/man/Makefile.in b/cctools/man/Makefile.in new file mode 100644 index 0000000..f279eb4 --- /dev/null +++ b/cctools/man/Makefile.in @@ -0,0 +1,656 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = man +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +depcomp = +am__maybe_remake_depfiles = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man1dir = $(mandir)/man1 +am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man3dir)" \ + "$(DESTDIR)$(man5dir)" +man3dir = $(mandir)/man3 +man5dir = $(mandir)/man5 +NROFF = nroff +MANS = $(dist_man_MANS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +# dist_man_MANS += gprof.1 +dist_man_MANS = dyld.1 strings.1 lipo.1 as.1 nm.1 otool.1 ranlib.1 \ + segedit.1 size.1 strip.1 libtool.1 cmpdylib.1 pagestuff.1 \ + redo_prebinding.1 nmedit.1 install_name_tool.1 \ + codesign_allocate.1 ctf_insert.1 bitcode_strip.1 llvm-otool.1 \ + nm-classic.1 size-classic.1 otool-classic.1 dyld.3 NSModule.3 \ + NSObjectFileImage.3 dyld_debug.3 kld.3 arch.3 get_end.3 end.3 \ + getsectbyname.3 getsectbynamefromheader.3 getsectdata.3 \ + getsectdatafromheader.3 getsegbyname.3 Mach-O.5 a.out.5 \ + ranlib.5 stab.5 indr.1 checksyms.1 seg_addr_table.1 \ + check_dylib.1 mtoc.1 NSObjectFileImage_priv.3 libsyminfo.3 \ + redo_prebinding.3 +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps man/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps man/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man1: $(dist_man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(dist_man_MANS)'; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.1[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.1[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) +install-man3: $(dist_man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(dist_man_MANS)'; \ + test -n "$(man3dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man3dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man3dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.3[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ + done; } + +uninstall-man3: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man3dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.3[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man3dir)'; $(am__uninstall_files_from_dir) +install-man5: $(dist_man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(dist_man_MANS)'; \ + test -n "$(man5dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.5[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ + done; } + +uninstall-man5: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man5dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.5[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(MANS) +installdirs: + for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(man5dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man1 install-man3 install-man5 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man + +uninstall-man: uninstall-man1 uninstall-man3 uninstall-man5 + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-man1 install-man3 install-man5 install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-man uninstall-man1 uninstall-man3 \ + uninstall-man5 + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/man/NSModule.3 b/cctools/man/NSModule.3 index ab5a5bc..5088455 100644 --- a/cctools/man/NSModule.3 +++ b/cctools/man/NSModule.3 @@ -9,16 +9,16 @@ NSModule \- programmatic interface for working with modules and symbols typedef void * NSModule; .sp .5 extern NSModule NSLinkModule( - NSObjectFileImage objectFileImage, + NSObjectFileImage objectFileImage, const char *moduleName, unsigned long options); .sp .5 extern enum DYLD_BOOL NSUnLinkModule( - NSModule module, + NSModule module, unsigned long options); .sp .5 extern const char * NSNameOfModule( - NSModule m); + NSModule m); .sp .5 extern const char * NSLibraryNameForModule( NSModule m); @@ -31,7 +31,7 @@ extern enum DYLD_BOOL NSIsSymbolNameDefined( extern enum DYLD_BOOL NSIsSymbolNameDefinedWithHint( const char *symbolName const char *libraryNameHint); -.sp .5 +.sp .5 extern enum DYLD_BOOL NSIsSymbolNameDefinedInImage( const struct mach_header *image, const char *symbolName); @@ -86,7 +86,7 @@ extern void NSInstallLinkEditErrorHandlers( .sp .5 extern void NSLinkEditError( NSLinkEditErrors *c, - int *errorNumber, + int *errorNumber, const char **fileName, const char **errorString); .if @@ -95,7 +95,7 @@ extern void NSLinkEditError( .PP extern NSModule NSReplaceModule( NSModule moduleToReplace, - NSObjectFileImage newObjectFileImage, + NSObjectFileImage newObjectFileImage, unsigned long options); .fi .PP @@ -129,7 +129,7 @@ are used for plugins. A module name is specified when a module is linked so that later .I NSNameOfModule can be used with the module handle and to do things like report errors. -If you want +If you want .IR gdb (1) to be able to debug your module, when calling .I NSLinkModule @@ -183,7 +183,7 @@ name of the object file tailing after the NULL character of the logical name. This is only useful to the zero-link implementation. .PP .I NSUnLinkModule -unlinks the specified module handle from the program. Currently the +unlinks the specified module handle from the program. Currently the implementation is limited to only allow modules linked with .I NSLinkModule to be unlinked. The parameter, @@ -255,7 +255,7 @@ If the program was built with the flag or executed with the environment variable .SM DYLD_FORCE_FLAT_NAMESPACE set and the pointer to a mach_header structure is not of a bundle loaded with -the +the .B NSLINKMODULE_OPTION_PRIVATE option of .IR NSLinkModule (3) @@ -277,7 +277,7 @@ Also the .IR dyld (3) routine .IR _dyld_get_image_header (3) -and the mach_header pointer arguments to the call back routines called from +and the mach_header pointer arguments to the call back routines called from .IR _dyld_register_func_for_add_image (3) routines can also be used. .PP @@ -318,7 +318,7 @@ If the program was built with the flag or executed with the environment variable .SM DYLD_FORCE_FLAT_NAMESPACE set and the pointer to a mach_header structure is not of a bundle loaded with -the +the .B NSLINKMODULE_OPTION_PRIVATE option of .IR NSLinkModule (3) @@ -476,7 +476,7 @@ functions are given in the following typedef: .nf typedef struct { void (*undefined)(const char *symbolName); - NSModule (*multiple)(NSSymbol s, NSModule oldModule, NSModule newModule); + NSModule (*multiple)(NSSymbol s, NSModule oldModule, NSModule newModule); void (*linkEdit)(NSLinkEditErrors errorClass, int errorNumber, const char *fileName, const char *errorString); } NSLinkEditErrorHandlers; @@ -534,7 +534,7 @@ further link editing, either the .I oldModule or the .I newModule. -It may also record one of the module handles to later take action after the +It may also record one of the module handles to later take action after the runtime linking process has completed (for example later unlink the module). The dynamic link editor updates the references to the symbol if the handler specifies the new symbol is to be used. @@ -584,7 +584,7 @@ parameter will be a one of the following values: .RS .nf typedef enum { - NSOtherErrorRelocation, + NSOtherErrorRelocation, NSOtherErrorLazyBind, NSOtherErrorIndrLoop, NSOtherErrorLazyInit, @@ -601,7 +601,7 @@ In those cases the parameter will be .sm NULL. .PP -For file access errors and file format errors, an attempt to return a file name +For file access errors and file format errors, an attempt to return a file name will also be passed, and if that is not possible the .I filename parameter will be diff --git a/cctools/man/NSObjectFileImage.3 b/cctools/man/NSObjectFileImage.3 index c235960..65a6b27 100644 --- a/cctools/man/NSObjectFileImage.3 +++ b/cctools/man/NSObjectFileImage.3 @@ -12,7 +12,7 @@ extern NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile( .sp .5 extern NSObjectFileImageReturnCode NSCreateObjectFileImageFromMemory( void *address, - unsigned long size, + unsigned long size, NSObjectFileImage *objectFileImage); .sp .5 extern NSObjectFileImageReturnCode NSCreateCoreFileImageFromFile( @@ -89,29 +89,29 @@ task with to determine what libraries were loaded and which modules were linked. .PP .I NSSymbolDefinitionCountInObjectFileImage -returns the number of symbol definitions in the NSObjectFileImage. +returns the number of symbol definitions in the NSObjectFileImage. .PP .I NSSymbolDefinitionNameInObjectFileImage -returns the name of the i'th symbol definitions in the NSObjectFileImage. +returns the name of the i'th symbol definitions in the NSObjectFileImage. The 'C' string returned should not be freed. If the ordinal specified is outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will be -returned. +returned. .PP .I NSSymbolReferenceCountInObjectFileImage -returns the number of references to undefined symbols the NSObjectFileImage. +returns the number of references to undefined symbols the NSObjectFileImage. .PP .I NSSymbolReferenceNameInObjectFileImage -returns the name of the i'th undefined symbol in the NSObjectFileImage. +returns the name of the i'th undefined symbol in the NSObjectFileImage. The 'C' string returned should not be freed. If the ordinal specified is outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be -returned. +returned. .PP .I NSIsSymbolDefinedInObjectFileImage returns TRUE if the specified symbol name has a definition in the -NSObjectFileImage. +NSObjectFileImage. .PP .I NSGetSectionDataInObjectFileImage -returns the address of the data for the named section in the named segment in +returns the address of the data for the named section in the named segment in the NSObjectFileImage. If the parameter size is not NULL, the size of the section is returned in size. If the section cannot be found or a zerofill section, NULL is returned and the size returned is zero. @@ -130,7 +130,7 @@ the host machine's cpu architecture. .TP .B NSObjectFileImageFailure Indicates the API failed and no NSObjectFileImage was returned. If this is -returned an error message is printed on stderr as to the reason for the +returned an error message is printed on stderr as to the reason for the failure. .TP .B NSObjectFileImageInappropriateFile diff --git a/cctools/man/NSObjectFileImage_priv.3 b/cctools/man/NSObjectFileImage_priv.3 index aeddd1c..749e424 100644 --- a/cctools/man/NSObjectFileImage_priv.3 +++ b/cctools/man/NSObjectFileImage_priv.3 @@ -6,15 +6,15 @@ NSObjectFileImage_priv \- programmatic interface for working with Mach-O files .PP #include .sp .5 -extern enum DYLD_BOOL +extern enum DYLD_BOOL NSFindSectionAndOffsetInObjectFileImage( - NSObjectFileImage objectFileImage, + NSObjectFileImage objectFileImage, unsigned long imageOffset, const char** segmentName, /* can be NULL */ const char** sectionName, /* can be NULL */ unsigned long* sectionOffset) /* can be NULL */ .sp .5 -extern enum DYLD_BOOL +extern enum DYLD_BOOL NSHasModInitObjectFileImage( NSObjectFileImage objectFileImage); .fi @@ -28,9 +28,9 @@ machine's cpu architecture. .PP .PP .I NSFindSectionAndOffsetInObjectFileImage -is supplied an imageOffset into an ObjectFileImage and returns +is supplied an imageOffset into an ObjectFileImage and returns via parameters the segment/section name and offset into that section of -that imageOffset. It returns FALSE if the imageOffset is not +that imageOffset. It returns FALSE if the imageOffset is not in any section, otherwise TRUE. You can used the resulting sectionOffset to index into the data returned by NSGetSectionDataInObjectFileImage. .PP diff --git a/cctools/man/arch.3 b/cctools/man/arch.3 index 360cb7a..74a2496 100644 --- a/cctools/man/arch.3 +++ b/cctools/man/arch.3 @@ -1,10 +1,11 @@ -.Dd September 13, 2013 +.Dd June 8, 2016 .Dt ARCH 3 .Sh NAME .Nm NXGetAllArchInfos , .Nm NXGetLocalArchInfo , .Nm NXGetArchInfoFromName , .Nm NXGetArchInfoFromCpuType , +.Nm NXFreeArchInfo , .Nm NXFindBestFatArch , .Nm NXCombineCpuSubtypes .Nd get architecture information @@ -18,8 +19,12 @@ .Fn NXGetArchInfoFromName "const char *name" .Ft extern const NXArchInfo * .Fn NXGetArchInfoFromCpuType "cpu_type_t cputype" "cpu_subtype_t cpusubtype" +.Ft extern void +.Fn NXFreeArchInfo "NXArchInfo *x" .Ft extern struct fat_arch * .Fn NXFindBestFatArch "cpu_type_t cputype" "cpu_subtype_t cpusubtype" "struct fat_arch *fat_archs" "uint32_t nfat_archs" +.Ft extern struct fat_arch_64 * +.Fn NXFindBestFatArch_64 "cpu_type_t cputype" "cpu_subtype_t cpusubtype" "struct fat_arch_64 *fat_archs64" "uint32_t nfat_archs" .Ft extern cpu_subtype_t .Fn NXCombineCpuSubtypes "cpu_type_t cputype" "cpu_subtype_t cpusubtype1" "cpu_subtype_t cpusubtype2" .Sh DESCRIPTION @@ -48,12 +53,14 @@ It is used to hold the name of the architecture and the corresponding CPU type and CPU subtype, together with the architecture's byte order and a brief description string. .Pp The currently known architectures are: -.Bl -column hppa7100LC CPU_TYPE_POWERPC CPU_SUBTYPE_MC68030_ONLY +.Bl -column hppa7100LC CPU_TYPE_POWERPC64 CPU_SUBTYPE_MC68030_ONLY .It Em Name Ta Em "CPU Type" Ta Em "CPU Subtype" Ta Em Description .It x86_64 Ta CPU_TYPE_X86_64 Ta CPU_SUBTYPE_X86_64_ALL Ta Intel x86-64 .It i386 Ta CPU_TYPE_I386 Ta CPU_SUBTYPE_I386_ALL Ta Intel 80x86 .It arm Ta CPU_TYPE_ARM Ta CPU_SUBTYPE_ARM_ALL Ta ARM .It arm64 Ta CPU_TYPE_ARM64 Ta CPU_SUBTYPE_ARM64_ALL Ta ARM64 +.It arm64e Ta CPU_TYPE_ARM64 Ta CPU_SUBTYPE_ARM64E Ta ARM64E +.It arm64_32 Ta CPU_TYPE_ARM64_32 Ta CPU_SUBTYPE_ARM64_32_V8 Ta ARM64_32 .It ppc Ta CPU_TYPE_POWERPC Ta CPU_SUBTYPE_POWERPC_ALL Ta PowerPC .It ppc64 Ta CPU_TYPE_POWERPC64 Ta CPU_SUBTYPE_POWERPC64_ALL Ta PowerPC 64-bit .It m68k Ta CPU_TYPE_MC680x0 Ta CPU_SUBTYPE_MC680x0_ALL Ta Motorola 68K @@ -105,7 +112,7 @@ returns a pointer to an array of all known NXArchInfo structures. The last NXArchInfo is marked by a NULL name. .Pp .Fn NXGetLocalArchInfo -returns the NXArchInfo for the local host, or NULL if none is known. +returns the NXArchInfo for the local host, or NULL if none is known. .Pp .Fn NXGetArchInfoFromName and @@ -116,6 +123,43 @@ A CPU subtype of CPU_SUBTYPE_MULTIPLE can be used to request the most general NXArchInfo known for the given CPU type. NULL is returned if no matching NXArchInfo can be found. .Pp +.Fn NXFreeArchInfo +is passed a pointer to an NXArchInfo returned by the above interfaces and if +not in the array returned in +.Fn NXGetAllArchInfos +will +.Xr free 3 +the description field and then the NXArchInfo pointer. +.Pp +The above interfaces that return pointers to NXArchInfo structs in normal +cases returns a pointer from the array returned in +.Fn NXGetAllArchInfos . +In some cases when the cputype is CPU_TYPE_I386 or CPU_TYPE_POWERPC it will +return a malloc(3)'ed NXArchInfo struct which contains a string in the +description field also a malloc(3)'ed pointer. To allow programs not to +leak memory they can call +.Fn NXFreeArchInfo +on pointers returned from the above interfaces. Since this is a new API on +older systems can use the code below. Going forward the above interfaces will +only return pointers from the array returned in +.Fn NXGetAllArchInfos . +.Bd -literal -offset indent +static void NXFreeArchInfo( +const NXArchInfo *x) +{ + const NXArchInfo *p; + + p = NXGetAllArchInfos(); + while(p->name != NULL){ + if(x == p) + return; + p++; + } + free((char *)x->description); + free((NXArchInfo *)x); +} +.Ed +.Pp .Fn NXFindBestFatArch is passed a CPU type and CPU subtype and a set of fat_arch structs. It selects the best one that matches (if any), and returns a pointer to that @@ -127,6 +171,11 @@ are added and an old version of this routine is used. But if there is an exact match between the CPU type and CPU subtype and one of the fat_arch structs, this routine will always succeed. .Pp +.Fn NXFindBestFatArch_64 +is the same as +.Fn NXFindBestFatArch +but returns and takes fat_arch_64 structs. +.Pp .Fn NXCombineCpuSubtypes returns the resulting CPU subtype when combining two different CPU subtypes for the specified CPU type. diff --git a/cctools/man/as.1 b/cctools/man/as.1 index d3eb31f..d595e7b 100644 --- a/cctools/man/as.1 +++ b/cctools/man/as.1 @@ -3,30 +3,30 @@ as \- Mac OS X Mach-O GNU-based assemblers .SH SYNOPSIS .B as -[ +[ .I "option \&..." -] [ +] [ .I "file \&..." -] +] .SH DESCRIPTION The .I as -command translates assembly code in the named files to object code. If no files are specified, +command translates assembly code in the named files to object code. If no files are specified, .I as -reads from +reads from .BR stdin . All undefined symbols in the assembly are treated as global. The output of the assembly is left in the file .B a.out by default. .PP -The program -.B /usr/bin/as +The program +.B /usr/bin/as is actually a driver that executes assemblers for specific target -architectures. If no target architecture is specified, it defaults to the +architectures. If no target architecture is specified, it defaults to the architecture of the host it is running on. .SH OPTIONS -.TP +.TP .BI \-o " name" Name the output file .I name @@ -43,8 +43,8 @@ or .BI /usr/local/libexec/gcc/darwin/ arch_type /as . There is only one assembler for an architecture family. If the specified target architecture is a machine-specific implementation, -the assembler for that architecture family is executed (e.g., -.B /usr/libexec/gcc/darwin/ppc/as +the assembler for that architecture family is executed (e.g., +.B /usr/libexec/gcc/darwin/ppc/as for .BR "\-arch ppc604e" ). See @@ -60,14 +60,14 @@ and the architecture (from the flag), to distinguish which architecture the error messages refer to. When the .IR cc (1) -driver program +driver program is run with multiple -.B \-arch +.B \-arch flags, it invokes .I as -with the +with the .B \-arch_multiple -option. +option. .TP .BI \-force_cpusubtype_ALL By default, the assembler will produce the CPU subtype ALL for the object file @@ -82,10 +82,10 @@ the ALL subtype. If the target architecture specified is a machine-specific implementation (e.g., .BR "\-arch ppc603" , -.BR "\-arch i486" ), +.BR "\-arch i486" ), the assembler will flag as errors instructions that are not supported on that architecture, and it will produce an object -file with the CPU subtype for that specific implementation (even if no +file with the CPU subtype for that specific implementation (even if no implementation-specific instructions are used). The .B \-force_cpusubtype_ALL @@ -96,19 +96,19 @@ Enables dynamic linking features. This is the default. .TP .B \-static -Causes the assembler to treat as an error any features for dynamic +Causes the assembler to treat as an error any features for dynamic linking. Also causes the .text directive to not include the pure_instructions section attribute. .TP .B \-\|\- -Use -.B stdin +Use +.B stdin for the assembly source input. .TP .B \-n -Instructs the assembler not to assume that the assembly file starts -with a -.B \.text +Instructs the assembler not to assume that the assembly file starts +with a +.B \.text directive. Use this option when an output file is not to contain a (_\|_TEXT,_\|_text) section or this section is not to be first one in the output file. @@ -118,8 +118,8 @@ Fast; no need for the assembler preprocessor (``app''). The assembler preprocessor can also be turned off by starting the assembly file with "#NO_APP\\n". This is intended for use by compilers which produce assembly code in a strict "clean" format that specifies exactly where whitespace -can go. The assembler preprocessor needs to be run on hand-written assembly -files and/or files that have been preprocessed by the C preprocessor +can go. The assembler preprocessor needs to be run on hand-written assembly +files and/or files that have been preprocessed by the C preprocessor .B cpp. This is typically needed when assembler files are assembled through the use of the @@ -127,22 +127,22 @@ the command, which automatically runs the C preprocessor on assembly source files. The assembler preprocessor strips out excess spaces, turns single-quoted characters into a decimal constants, and turns -# +# into .line ;.file pairs. When the assembler preprocessor has been turned off by a "#NO_APP\\n" at the start of a file, it can be turned back on and off again with pairs of "#APP\\n" and "#NO_APP\\n" at the beginnings of lines. This is used by the compiler to wrap -assembly statements produced from -.B asm() +assembly statements produced from +.B asm() statements. .TP .B \-g Produce debugging information for the symbolic debugger .IR gdb (1) -so that the assembly source can be debugged symbolically. The debugger depends on correct use of the C preprocessor's #include directive +so that the assembly source can be debugged symbolically. The debugger depends on correct use of the C preprocessor's #include directive or the assembler's .include directive: Any include file -that produces instructions in the (_\|_TEXT,_\|_text) section must be included -while a .text directive is in +that produces instructions in the (_\|_TEXT,_\|_text) section must be included +while a .text directive is in effect. In other words, there must be a .text directive before the include, and the .text directive must still be in effect at the end of the include file. Otherwise, the debugger will get confused when in that assembly file. @@ -161,7 +161,7 @@ Add the directory to the list of directories to search for files included with the .include directive. The default place to search is the current directory. .TP -.B \-W +.B \-W Suppress warnings. .TP .B \-L diff --git a/cctools/man/bitcode_strip.1 b/cctools/man/bitcode_strip.1 index f50c800..f11ea2e 100644 --- a/cctools/man/bitcode_strip.1 +++ b/cctools/man/bitcode_strip.1 @@ -1,4 +1,4 @@ -.TH BITCODE_STRIP 1 "June 8, 2015" "Apple, Inc." +.TH BITCODE_STRIP 1 "July 12, 2016" "Apple, Inc." .SH NAME bitcode_strip \- remove or leave the bitcode segment in a Mach-O file .SH SYNOPSIS @@ -9,7 +9,7 @@ input [ \-r | \-m | \-l ] \-o output edits the input Mach-O file and with the \-r option removes the bitcode segment, the segment named __LLVM and its section. With the \-m option removes the bitcode segment but leaves a marker. Or with the -l option leaves only the bitcode segment -in the Mach-O file. If the Mach-O file, or slice of a universal file, does not have a +in the Mach-O file an the (__TEXT,__info_plist) section. If the Mach-O file, or slice of a universal file, does not have a bitcode segment, it is left essentially unchanged. .TP .BI input @@ -26,4 +26,5 @@ specifies the bitcode segment is to be removed. specifies the bitcode segment is to be removed and a marker is left. .TP .BI \-l -specifies that only the bitcode segment is to be left in the Mach-O file. +specifies that only the bitcode segment and the (__TEXT,__info_plist) section +is to be left in the Mach-O file. diff --git a/cctools/man/checksyms.1 b/cctools/man/checksyms.1 index 95acd50..bd62a19 100644 --- a/cctools/man/checksyms.1 +++ b/cctools/man/checksyms.1 @@ -1,4 +1,4 @@ -.TH CHECKSYMS 1 "September 10, 2000" "Apple Computer, Inc." +.TH CHECKSYMS 1 "February 28, 2019" "Apple Computer, Inc." .SH NAME checksyms \- check Mach-O production binary for proper conventions .SH SYNOPSIS @@ -21,7 +21,7 @@ proper stripping of symbols for the file type (and whether is is using the dynamic linker), if the file is a dynamic library then it checks for the preferred linked address, setting of compatibility and -current versions, +current versions, proper prebinding and objcunique if is uses the dynamic linker, and proper code generation if a dynamic binary so that there are no relocation entries in read-only sections. @@ -48,7 +48,7 @@ Allow all symbols except debugging symbols (those created by the compiler's option). .TP .B \-b -Check the binaries that use the dynamic linker to see that they do not have +Check the binaries that use the dynamic linker to see that they do not have relocation entries in read-only sections, are prebound and had objcunique run on them. This is now the default. .TP @@ -61,7 +61,7 @@ Specifies the architecture, .I arch_type, in the file to check. More than one .BI \-arch " arch_type" -can be specified. The default is +can be specified. The default is .BI \-arch " all" which checks all architectures in the file. See .IR arch (3) @@ -69,15 +69,19 @@ for the currently known .IR arch_type s. .TP .BI \-dylib_table " filename" -This specifies the filename of the table of dynamic libraries and their -addresses. If not specified the default is ~rc/Data/DylibTable. The format -of the table is lines of a dynamic library name and an address in hex separated -by spaces and or tabs. +This option has been removed. In previous versions of +.B checksyms +it specifies the filename of the table of dynamic libraries and their addresses. +If not specified the default is ~rc/Data/DylibTable. +The format of the table is lines of a dynamic library name and an address in hex +separated by spaces and / or tabs. .TP .BI \-seg_addr_table " filename" -This specifies the filename of the segment address table of dynamic library -install names and their addresses. The format of this table is lines of two -forms. +This option has been removed. In previous versions of +.B checksyms +it specifies the filename of the segment address table of dynamic library +install names and their addresses. +The format of this table is lines of two forms. The entries in the table are lines containing either a single hex address and an install name or two hex addresses and an install name. In the first form the single hex address is used for ``flat'' libraries and is the @@ -101,7 +105,9 @@ is set it is also used instead of the table specified with the option. .TP .BI "\-seg_addr_table_filename" " pathname" -Use +This option has been removed. In previous versions it instructs +.B checksyms +to use .B pathname instead of the install name of the library for matching an entry in the segment address table. diff --git a/cctools/man/codesign_allocate.1 b/cctools/man/codesign_allocate.1 index 78bdea0..6a335f3 100644 --- a/cctools/man/codesign_allocate.1 +++ b/cctools/man/codesign_allocate.1 @@ -1,4 +1,4 @@ -.TH CODESIGN_ALLOCATE 1 "March 16, 2009" "Apple, Inc." +.TH CODESIGN_ALLOCATE 1 "April 17, 2017" "Apple, Inc." .SH NAME codesign_allocate \- add code signing data to a Mach-O file .SH SYNOPSIS @@ -6,7 +6,7 @@ codesign_allocate \- add code signing data to a Mach-O file \-i oldfile [ \-a arch size ]... [ \-A cputype cpusubtype size ]... \-o newfile .SH DESCRIPTION .I codesign_allocate -sets up a Mach-O file used by the dynamic linker so space for code signing data +sets up a Mach-O file used by the dynamic linker so space for code signing data of the specified size for the specified architecture is embedded in the Mach-O file. The program must be passed one \-a argument or one \-A argument for each architecture in a universal file, or exactly one \-a or \-A for a thin file. @@ -28,10 +28,26 @@ The value of .I size must be a multiple of 16. .TP -.BI \-a " cputype cpusubtype size" +.BI \-A " cputype cpusubtype size" specifies for the architecture as a pair of decimal integers for the cputype and cpusubtype that the size of the code signing data is to be .I size. The value of .I size must be a multiple of 16. +.TP +.BI \-r +remove the code signature data and the LC_CODE_SIGNATURE load command. This +is the same as specifiying the +.B -a +or +.B -A +option with a +.I size +of zero. +.TP +.BI \-p +page align the code signature data by padding string table and changing its +size. This is not the default as +.IR codesign (1) +currently can't use this option. diff --git a/cctools/man/ctf_insert.1 b/cctools/man/ctf_insert.1 index 881f4ba..fcfca23 100644 --- a/cctools/man/ctf_insert.1 +++ b/cctools/man/ctf_insert.1 @@ -1,15 +1,21 @@ -.TH CODESIGN_ALLOCATE 1 "March 2, 2010" "Apple, Inc." +.TH CTF_INSERT 1 "December 13, 2018" "Apple, Inc." .SH NAME -ctf_insert \- insert the (__CTF,__ctf) section data into the mach_kernel file +ctf_insert \- insert Compact C Type Format data into a mach_kernel file .SH SYNOPSIS .B ctf_insert input [ \-arch arch file ]... \-o output .SH DESCRIPTION .I ctf_insert -inserts the cft (Compact File Type) data into a mach_kernel creating -(__CTF,__ctf) sections. The input must not have this section or it is an error. -And the program must be passed one \-arch argument for each architecture in a -universal file, or exactly one \-arch for a thin file. +inserts CTF (Compact C Type Format) data into a mach_kernel binary, storing the +data in a newly created (__CTF,__ctf) section. This section must not be +present in the input file. +.IR ctf_insert (1) +must be passed one +.B \-arch +argument for each architecture in a universal file, or +exactly one +.B \-arch +for a thin file. .TP .BI input specifies the input mach_kernel. @@ -18,7 +24,7 @@ specifies the input mach_kernel. specifies the output file. .TP .BI \-arch " arch file" -specifies for the file containing the cft (Compact File Type) data to be used -for the specified +specifies a file of CTF data to be used for the specified .I arch -whos content will be the section's data. +in a Mach-O or universal file. The file's content will be stored in a newly +created (__CTF,__ctf) section. \ No newline at end of file diff --git a/cctools/man/dyld.1 b/cctools/man/dyld.1 index 7e978bd..2a016a6 100644 --- a/cctools/man/dyld.1 +++ b/cctools/man/dyld.1 @@ -49,12 +49,12 @@ XXX.framework/Versions/YYY/XXX or XXX.framework/XXX, where XXX and YYY are any name.) .IP For each framework that a program uses, the dynamic linker looks for the -framework in each directory in +framework in each directory in .SM DYLD_FRAMEWORK_PATH in turn. If it looks in all the directories and can't find the framework, it -searches the directories in +searches the directories in .SM DYLD_LIBRARY_PATH -in turn. If it still can't find the framework, it then searches +in turn. If it still can't find the framework, it then searches .SM DYLD_FALLBACK_FRAMEWORK_PATH and .SM DYLD_FALLBACK_LIBRARY_PATH @@ -62,7 +62,7 @@ in turn. .IP Use the .B \-L -option to +option to .IR otool (1). to discover the frameworks and shared libraries that the executable is linked against. @@ -80,12 +80,12 @@ $(HOME)/Library/Frameworks:/Library/Frameworks:/Network/Library/Frameworks: This is a colon separated list of directories that contain libraries. The dynamic linker searches these directories before it searches the default locations for libraries. It allows you to test new versions of existing -libraries. +libraries. .IP For each library that a program uses, the dynamic linker looks for it in each -directory in +directory in .SM DYLD_LIBRARY_PATH -in turn. If it still can't find the library, it then searches +in turn. If it still can't find the library, it then searches .SM DYLD_FALLBACK_FRAMEWORK_PATH and .SM DYLD_FALLBACK_LIBRARY_PATH @@ -93,7 +93,7 @@ in turn. .IP Use the .B \-L -option to +option to .IR otool (1). to discover the frameworks and shared libraries that the executable is linked against. @@ -164,7 +164,7 @@ This lets you attach a debugger to the process instead of letting the process exit. .TP .B DYLD_PREBIND_DEBUG -When this is set, the dynamic linker prints diagnostics about +When this is set, the dynamic linker prints diagnostics about launching prebound programs and libraries. This lets you determine why a program is not being launched prebound. You can view the recorded library time stamps with the @@ -187,7 +187,7 @@ variables. This is so that if a program is .IR exec (2)'ed from a secure program too will not have it's libraries searched for, as well. For statically linked secure programs that -.IR exec (2) +.IR exec (2) other programs that might use the dynamic linker, they too should clear out the values of the dyld path and insertion environment variables. .TP diff --git a/cctools/man/dyld.3 b/cctools/man/dyld.3 index 8af3ae2..6eb10d6 100644 --- a/cctools/man/dyld.3 +++ b/cctools/man/dyld.3 @@ -53,7 +53,7 @@ int _dyld_func_lookup( .sp .5 extern void _dyld_bind_objc_module( void *objc_module); -.sp .5 +.sp .5 extern void _dyld_get_objc_module_sect_for_module( NSModule module, void **objc_module, diff --git a/cctools/man/dyld_debug.3 b/cctools/man/dyld_debug.3 index 76ff27d..1a26e7e 100644 --- a/cctools/man/dyld_debug.3 +++ b/cctools/man/dyld_debug.3 @@ -180,17 +180,17 @@ adds the .I subscriber port to the list of event ports that dyld event messages are sent to. This is just a different interface to get dynamic link events on a mach port rather -than using +than using .I _dyld_debug_subscribe_to_events which creates a new thread. .PP .I _dyld_event_server is the mig generated routine to dispatch dyld event messages that can be used if -the +the .I _dyld_debug_add_event_subscriber interface is used. This routine will call the routine .I _dyld_event_server_callback -which must be provided if +which must be provided if .I _dyld_event_server is used. .PP @@ -221,7 +221,7 @@ struct dyld_debug_error_data { .RE .PP The local_error field is a unique number for each possible error condition -in the source code in that makes up the dyld debug APIs. +in the source code in that makes up the dyld debug APIs. The file_name and line_number fields are filled in with the the source file name and line number for the files in the Darwin cctools project in the libdyld sub-directory which is where the dyld debug APIs are implemented. @@ -327,7 +327,7 @@ NSUnLinkModule call (without the option specified) done by the target task. For this event only the arg[0] field of the dyld_event structure is used to identify the module being removed. .SH RETURN CODES -.TP +.TP .SM DYLD_SUCCESS Indicates the operation and the communication with the target task was successful. diff --git a/cctools/man/get_end.3 b/cctools/man/get_end.3 index d5bc836..e2a0656 100644 --- a/cctools/man/get_end.3 +++ b/cctools/man/get_end.3 @@ -17,7 +17,7 @@ link-editor defined symbols. Use of these routines is very strongly discouraged. The problem is that any program that is using .SM UNIX link editor defined symbols (_end, _etext or _edata) is making assumptions that -the program has the memory layout of a UNIX program. +the program has the memory layout of a UNIX program. .PP This is an incorrect assumption for a program built by the Mach-O link editor. The reason that these routines are provided is that if very minimal diff --git a/cctools/man/getsectbyname.3 b/cctools/man/getsectbyname.3 index 8e18301..be10c12 100644 --- a/cctools/man/getsectbyname.3 +++ b/cctools/man/getsectbyname.3 @@ -45,7 +45,7 @@ field in the section structure will have to have added to it to make it a valid pointer. .PP .I Getsectbyname -is the same as +is the same as .I getsectbynamefromheader with its first argument being the link editor defined symbol .I _mh_execute_header. @@ -64,7 +64,7 @@ the address to the data returned will have to have added to it to make it a valid pointer. .PP .I Getsectdata -is the same as +is the same as .I getsectdatafromheader with its first argument being the link editor defined symbol .I _mh_execute_header. diff --git a/cctools/man/kld.3 b/cctools/man/kld.3 index bc3fd87..8d2300a 100644 --- a/cctools/man/kld.3 +++ b/cctools/man/kld.3 @@ -144,7 +144,7 @@ has been compiled for debugging (for example), it can take orders of magnitude longer. .PP Since the objects loaded with -.I kld_load +.I kld_load or .I kld_load_from_memory can only use symbols that appear in the executable program, @@ -181,25 +181,25 @@ This file can be used with the .IR gdb (1) .I add-file command to debug the code in the dynamically loaded object. -The +The +.I kld_load +function returns 1 for success and 0 for failure. If a fatal system error +(out of memory, etc.) occurs, all future calls to .I kld_load -function returns 1 for success and 0 for failure. If a fatal system error -(out of memory, etc.) occurs, all future calls to -.I kld_load and the other routines described here will fail. .PP .I kld_load_from_memory() is similar to .IR kld_load() , -but works on memory rather than a file. The argument -.I object_name +but works on memory rather than a file. The argument +.I object_name is the name associated with the memory and is used for messages. (It must not be NULL.) The -arguments -.I object_addr -and -.I object_size -are the memory address and size of the object file. +arguments +.I object_addr +and +.I object_size +are the memory address and size of the object file. .I kld_load_from_memory() only allows one thin object file (not an archive or ``universal'' file) to be loaded. @@ -226,11 +226,11 @@ routine (For this routine, only internal errors can result.) clears out all allocated data structures used by these routines. If the parameter .I deallocate_sets -is non-zero, the function also unloads all objects that were loaded. +is non-zero, the function also unloads all objects that were loaded. If .I deallocate_sets is zero the object sets aren't unloaded, and the program can continue to use -the code and data loaded. However, further calls to the routines +the code and data loaded. However, further calls to the routines described here will no longer know about the symbols in those objects. If objects aren't to be allowed access to each other's symbols, an @@ -253,19 +253,19 @@ basis for subsequent .IR kld_load_basefile_from_memory is an alternate interface that allows mapped ``thin'' object image to be specified rather than a file. The base file may be a ``universal'' file, and -must contain an architecture that would execute on the host; -otherwise, it is an error. +must contain an architecture that would execute on the host; +otherwise, it is an error. If the file is a universal file, the ``best'' architecture (as defined by -what the kernel -.IR exec (2) +what the kernel +.IR exec (2) would select) is used as the base file. .I kld_load_basefile -must be invoked before any call to +must be invoked before any call to .I kld_load. Alternatively, it can be called after .IR kld_unload_all , which unloads the base file. This call is intended to be used when a program -is dynamically loading object sets into a program other than itself, where +is dynamically loading object sets into a program other than itself, where .I base_filename contains the symbol table of the target program. The routine .IR kld_address_func , @@ -287,7 +287,7 @@ calculation of The function specified by .I func -should return the address where the output is to be link edited. +should return the address where the output is to be link edited. .I kld_address_func is intended to be used when a program is dynamically loading objects into a @@ -299,12 +299,12 @@ is passed a mask of options, .IR link_options , that are used to control some aspects of the following .I kld_load -operations. Passing +operations. Passing .I KLD_STRIP_NONE will stop kld from stripping symbols from the output in all cases. By default -all symbols are stripped for kernel loads and when +all symbols are stripped for kernel loads and when .I output_filename -is NULL for +is NULL for .I kld_load() and .I kld_load_from_memory() @@ -327,7 +327,7 @@ symbols have been merged, has to allocate storage for these symbols for the code to run without error. The problem occurs if, on a later call to .IR kld_load , -one of the common symbols that +one of the common symbols that .I kld_load allocated appears in an object file as a defining symbol (not a common or undefined symbol). In this case, diff --git a/cctools/man/libsyminfo.3 b/cctools/man/libsyminfo.3 index 5d793a1..ca69385 100644 --- a/cctools/man/libsyminfo.3 +++ b/cctools/man/libsyminfo.3 @@ -136,13 +136,13 @@ .\" ====================================================================== .\" .IX Title "libsyminfo 3" -.TH libsyminfo 3 +.TH libsyminfo 3 .UC .SH "NAME" libsyminfo \- Library for accessing symbol information .SH "DESCRIPTION" .IX Header "DESCRIPTION" -Typically access to symbol information from a mach-o is done via the command line tool nm. This data can be examined and processed to determine what a binary exports or imports. With the advent of Symdex(A symbol index used by Mac OS X Build & Integration), there was desire to avoid constant invocations to a command line tool. libsyminfo gives a object oriented approach written in C to allow clients to extract import and export information from a mach-o binary. +Typically access to symbol information from a mach-o is done via the command line tool nm. This data can be examined and processed to determine what a binary exports or imports. With the advent of Symdex(A symbol index used by Mac OS X Build & Integration), there was desire to avoid constant invocations to a command line tool. libsyminfo gives a object oriented approach written in C to allow clients to extract import and export information from a mach-o binary. .SH "API" .IX Header "API" @@ -222,8 +222,8 @@ Function used to create NMSymbols. .B NMDependencies NMCreateDependencies(char **subUmbrellas, char **subFrameworks, int nSubUmbrellas,int nSubFrameworks) -Function used to create NMDependencies. +Function used to create NMDependencies. -.SH "SEE ALSO" +.SH "SEE ALSO" .IX Header "SEE ALSO" nm(1) diff --git a/cctools/man/libtool.1 b/cctools/man/libtool.1 index 2aa4860..526f5f4 100644 --- a/cctools/man/libtool.1 +++ b/cctools/man/libtool.1 @@ -8,17 +8,17 @@ ranlib \- add or update the table of contents of archive libraries .B \-static .BI \-o " output" [ -.B \-sacLT +.B \-sacLTD ] [ .B \- -] +] [ .BI -arch_only " arch_type" ] [ .B \-no_warning_for_no_symbols -] +] .IR file ... [-filelist listfile[,dirname]] .br @@ -37,22 +37,22 @@ ranlib \- add or update the table of contents of archive libraries ] [ .I "link editor flags" -] +] [ .B \-v -] +] [ .B \-noall_load ] [ .B \- -] +] [ .BI -arch_only " arch_type" ] [ .B \-V -] +] .IR file ... [-filelist listfile[,dirname]] .br @@ -63,22 +63,22 @@ ranlib \- add or update the table of contents of archive libraries ] [ .B \- -] +] .IR archive ... .SH DESCRIPTION The .I libtool -command takes the specified input object files and creates a library for +command takes the specified input object files and creates a library for use with the link editor, -.IR ld (1). +.IR ld (1). The library's name is specified by .I output (the argument -to the -.B \-o +to the +.B \-o flag). The input object files may be in any correct format that contains object files (``universal'' files, archives, -object files). +object files). .I Libtool will not put any non-object input file into the output library (unlike @@ -113,7 +113,7 @@ in more than one object file and no common symbol can be used. To maximize sharing of a dynamically linked shared library the objects should be compiled with the .B \-dynamic -flag of +flag of .IR cc (1) to produce indirect undefined references and position-independent code. To build a dynamically linked library, @@ -128,9 +128,9 @@ to create a universal file if needed. .SH "ARCHIVE (or statically linked) LIBRARIES" .PP .I Libtool -with +with .B \-static -is intended to replace +is intended to replace .IR ar (5) and .IR ranlib . @@ -170,12 +170,30 @@ These are explained below, under the and .B \-a options. +.\" OPTIONS .SH OPTIONS -.PP +.PP The following options pertain to .I libtool only. .TP +.BI @ file +Arguments beginning with +.B @ +are replaced by arguments read from the specified +.I file, +as an alternative to listing those arguments on the command line. The files +simply contain libtool options and files separated by whitespace: spaces, tabs, +and newlines. Characters can be escaped with a backslash (\\), including +whitespace characters and other backslashes. Also, arguments that include +whitespace can be enclosed, wholly or in part, by single- or double-quote +charcters. These files may contain +.I @file +references to additional files, although libtool will error on include cycles. +If a file cannot be found, the original +.I @file +argument will remain in the argument list. +.TP .B \-static Produce a statically linked (archive) library from the input files. This is the default. @@ -212,8 +230,8 @@ value of 0 and no checking is done when the library is used. .TP .BI \-current_version " number" For dynamic shared library files this specifies the current version number -of the library. The program using the library can obtain the -current version of the library programmatically to determine exactly +of the library. The program using the library can obtain the +current version of the library programmatically to determine exactly which version of the library it is using. The format of .I number @@ -263,7 +281,7 @@ flags are accepted and passed through: .B \-sectcreate, .B \-sectorder, .B \-sectorder_detail, -.B \-sectalign, +.B \-sectalign, .B \-undefined, .B \-read_only_relocs, .B \-prebind, @@ -341,7 +359,7 @@ only by newlines (spaces and tabs are assumed to be part of the file name). If the optional directory name, .I dirname is specified then it is prepended to each name in the list file. -.TP +.TP .BI \-arch_only " arch_type" This option causes libtool to build a library only for the specified .I arch_type @@ -357,7 +375,7 @@ argument to as the .B \-arch flag so that the output is tagged with that cpusubtype. -.PP +.PP The following options pertain to the table of contents for an archive library, and apply to both .IB libtool " \-static" @@ -406,20 +424,26 @@ will no longer be able to operate on it. .TP .B \-q Do nothing if a universal file would be created. +.TP +.B \-D +When building a static library, set archive contents' user ids, group ids, +dates, and file modes to reasonable defaults. This allows libraries created +with identical input to be identical to each other, regardless of time of day, +user, group, umask, and other aspects of the environment. .PP -For compatibility, the following +For compatibility, the following .I ranlib option is accepted (but ignored): .TP .B \-t -This option used to request that +This option used to request that .I ranlib only ``touch'' the archives instead of modifying them. The option is now ignored, and the table of contents is rebuilt. .PP One other option applies to both .I libtool -and +and .IR ranlib : .TP .B \- @@ -431,15 +455,15 @@ Don't warn about file that have no symbols. .SH "SEE ALSO" ld(1), ar(1), otool(1), make(1), redo_prebinding(1), ar(5) .SH BUGS -With the way libraries used to be created, errors were possible if the library +With the way libraries used to be created, errors were possible if the library was modified with .IR ar (1) and the table of contents was not updated by rerunning .IR ranlib (1). So previously the link editor, .IR ld (1), -generated an error when the modification date of a library was more recent than -the creation date of its table of contents. Unfortunately, this meant that +generated an error when the modification date of a library was more recent than +the creation date of its table of contents. Unfortunately, this meant that you got the error even if you only copy the library. Since this error was found to be too much of a nuisance it was removed. So now it is possible again to get link errors if the library is modified and the table of contents is diff --git a/cctools/man/lipo.1 b/cctools/man/lipo.1 index b7ee463..84411e2 100644 --- a/cctools/man/lipo.1 +++ b/cctools/man/lipo.1 @@ -1,148 +1,161 @@ -.TH LIPO 1 "September 12, 2006" "Apple Computer, Inc." +.TH LIPO 1 "August 31, 2018" "Apple Computer, Inc." .SH NAME lipo \- create or operate on universal files .SH SYNOPSIS .B lipo -[\-info] -[\-detailed_info] -[\-arch -.IR "arch_type input_file" "] ..." -[ -.IR input_file "] ..." -[\-arch_blank -.IR arch_type ] -[\-create] -[\-thin -.IR arch_type ] -[\-replace -.IR "arch_type filename" "] ..." -[\-remove -.IR arch_type "] ..." -[\-extract -.IR arch_type "] ..." -[\-extract_family -.IR arch_type "] ..." -[\-verify_arch -.IR arch_type " ...] " -[\-output -.IR output_file ] -[\-segalign -.IR "arch_type value" "] ..." +.IR input_file +.IR command +.IR [option ...] .SH DESCRIPTION The -.I lipo -command creates or operates on ``universal'' (multi-architecture) files. -It only ever produces one output file, -and never alters the input file. The operations that -.I lipo -performs are: -listing the architecture types in a universal file; -creating a single universal file from one or more input files; -thinning out a single universal file to one specified architecture type; -and extracting, replacing, and/or removing architectures -types from the input file to create a single new universal output file. +.B lipo +tool creates or operates on ``universal'' (multi-architecture) files. Generally, +.B lipo +reads a single input file and writes to a single output file, although some +commands and options accept multiple input files. +.B lipo +will only ever write to a single output file, and input files are never +modified in place. +.PP +.B lipo +supports a number of commands for creating universal files from +single-architecture files, extracting single-architecture files from universal +files, and displaying architecture information. +.B lipo +can only perform one such command at a time, although some command flags may appear more than once. Some commands support additional options that can be +used with that command. In addition, there are global options that are +supported by multiple commands. .PP -Only one option can be specified, -with the exception of -.BR \-arch , -.BR \-arch_blank , -.BR \-output , -and -.BR \-segalign , -which are used in combination with other options. The -.I input_file -argument is required, and only the -.B \-create -option allows more than one -.I input_file -to be specified. -The -.B \-output -flag must be used, except with the -.BI \-info -and -.BI \-detailed_info -flags. -.PP -The -.I arch_type +.I arch_type arguments may be any of the supported architecture names listed in the man page .IR arch (3). -.SH OPTIONS -.TP -.BI \-info -Briefly list the architecture types in the input universal file -(just the names of each architecture). +.SH COMMANDS +.TP +.B \-archs +Display only the architecture names present in a single input file. Each +architecture name is a single word, making this option suitable for shell +scripting. Unknown architectures will be represented by "unknown" along with +the numeric CPU type and CPU subtype values as a single word. +.TP +.BI \-create " [\-arch_blank arch_type ...]" +Create one universal output file from one or more input files. When input files +specified on the command-line, all of the architectures in each file will be +copied into the output file, whereas when input files are included using the +global +.B \-arch +option, only the specified architecture will be copied from that input file. +The +.B \-arch_blank +option specifies that the output for the specified +.I arch_type +will be an MH_DYLIB_STUB file. This command requires the +.B \-output +option. .TP .BI \-detailed_info -Display a detailed list of the architecture types in the input universal file +Display a detailed list of the architecture types in the input universal file (all the the information in the universal header, for each architecture in the file). .TP -.BI \-arch " arch_type input_file" -Tells -.I lipo -that -.I input_file -contains the specified architecture type. -The -.BI \-arch " arch_type" -specification is unnecessary if -.I input_file -is an -object file, a universal file, or some other file whose architecture(s) -.I lipo -can figure out. -.TP -.BI \-arch_blank " arch_type" -Specifies that the output for the specified -.IR arch_type -will be an MH_DYLIB_STUB file. This flag may not be used with any operation -other than -.BR \-create . -.TP -.BI \-output " output_file" -Specifies its argument to be the output file. -.TP -.B \-create -Take the input files (or file) and create one universal output file from them. -.TP -.BI \-thin " arch_type" -Take one input file and create a thin output file with the specified -.IR arch_type . -.TP -.BI \-replace " arch_type file_name" -Take one universal input file; in the output file, replace the -.I arch_type -contents of the input file with the contents of the specified -.IR file_name . -.TP -.BI \-remove " arch_type" -Take one universal input file and remove the -.I arch_type -from that universal file, placing the result in the output file. -.TP -.BI \-extract " arch_type" +.BI \-extract " arch_type [\-extract arch_type...]" Take one universal input file and copy the .I arch_type from that universal file into a universal output file containing -only that architecture. +only that architecture. This command requires the +.B \-output +option. .TP -.BI \-extract_family " arch_type" -Take one universal input file and copy all of the +.BI \-extract_family " arch_type [\-extract_family arch_type...]" +Take one universal input file and copy all of the .IR arch_type s for the family that .I arch_type is in from that universal file into an output file containing only those architectures. The file will be thin if only one architecture is -found or universal otherwise. +found or universal otherwise. This command requires the +.B \-output +option. +.TP +.BI \-info +Display a brief description of each input file along with the names of each +architecture type in that input file. +.TP +.BI \-remove " arch_type [\-remove arch_type ...]" +Take one universal input file and remove the +.I arch_type +from that universal file, placing the result in the output file. This command requires the +.B \-output +option. +.TP +.BI \-replace " arch_type file_name [\-replace arch_type file_name...]" +Take one universal input file; in the output file, replace the +.I arch_type +contents of the input file with the contents of the specified +.IR file_name . +This command requires the +.B \-output +option. +.TP +.BI \-thin " arch_type" +Take one input file and create a thin output file with the specified arch_type. +This command requires the +.B \-output +option. .TP .BI \-verify_arch " arch_type ..." Take one input file and verify the specified .IR arch_type s are present in the file. If so then exit with a status of 0 else exit with a -status of 1. +status of 1. Because more than one +.I arch_type +can be verified at once, all of the input files must appear before the +.B \-verify_arch +flag on the command-line. +.SH OPTIONS +.TP +.BI \-arch " arch_type input_file" +Tells +.B lipo +that +.I input_file +contains the specified architecture type. +The +.BI \-arch " arch_type" +specification is unnecessary if +.I input_file +is an +object file, a universal file, or some other file whose architecture(s) +.B lipo +can figure out. +.TP +.BI \-hideARM64 +When creating a universal binary including both 32-bit and 64-bit ARM files, +this option will ask +.B lipo +to add the 64-bit files at the end and not include them in the count of +architectures present in the file. The files must be executable files (Mach-O +filetype MH_EXECUTE). This option has no effect if neither 32-bit ARM nor 64-bit ARM +files are present, and no other files may be hidden in this way. This option only works with the +.B \-create, +.B \-remove, +and +.B \-replace, +commands, and is only intended for tools and workflows testing a workaround on +older systems. +.TP +.BI \-output " output_file" +Commands that create new files write to the output file specified by the +.B \-output +flag. This option is required for the +.B \-create, +.B \-extract, +.B \-extract_family, +.B \-remove, +.B \-replace, +and +.B \-thin +commands. .TP .BI \-segalign " arch_type value" Set the segment alignment of the specified @@ -151,13 +164,13 @@ when creating a universal file containing that architecture. .I value is a hexadecimal number that must be an integral power of 2. This is only needed when -.I lipo -can't figure out the alignment of an input file +.B lipo +can't figure out the alignment of an input file (currently not an object file), or when it guesses at the alignment too conservatively. The default for files unknown to -.I lipo -is 0 (2^0, or an alignment of one byte), +.B lipo +is 0 (2^0, or an alignment of one byte), and the default alignment for archives is 4 (2^2, or 4-byte alignment). .SH "SEE ALSO" diff --git a/cctools/man/llvm-otool.1 b/cctools/man/llvm-otool.1 index ae2ca46..9885e8e 100644 --- a/cctools/man/llvm-otool.1 +++ b/cctools/man/llvm-otool.1 @@ -1,29 +1,35 @@ -.TH LLVM-OTOOL 1 "January 13, 2016" "Apple Inc." +.TH LLVM-OTOOL 1 "July 31, 2018" "Apple Inc." +.\" NAME .SH NAME -llvm-otool \- the temporary command line shim for otool to objdump command line translation +llvm-otool \- the otool-compatible command line parser for llvm-objdump +.\" SYNOPSIS .SH SYNOPSIS .B llvm-otool -[ +[ .I "option \&..." -] [ +] [ .I "file \&..." -] +] +.\" DESCRIPTION .SH DESCRIPTION -The temporary command line shim +The command line shim .I llvm-otool -takes all the same options as the command +takes all the same options as the original .IR otool (1) -and executes an equivalent +command and executes an equivalent .IR objdump (1) command. Its use is to ease the change over -of the use of +of the original use of .IR otool (1) -which will be obsoleted, to the llvm based open source +to the llvm based open source .IR objdump (1) -command with the similar functionality. It is a temporary tool that will -removed when the +command with the similar functionality. +.PP +The original implementation of .IR otool (1) -command line tool is removed. +can now be found as +.IR otool-classic (1) +and typically will be run by using "xcrun otool-classic". .TP .B \-show-objdump-command Print the @@ -31,33 +37,30 @@ Print the command that .IR llvm-otool (1) will execute. - +.\" "NOTES FOR SPECIFIC OPTIONS" .SH "NOTES FOR SPECIFIC OPTIONS" .TP .B \-l -This also always implies the +This always implies the .B \-h option, as the .IR objdump (1) -option used is +option .B \-private-headers prints both the mach header and load commands. .TP -.B \-r -The format for the printing of the relocation information is different with -.IR objdump (1). -.TP .B \-S To display the contents of the `\_\^\_.SYMDEF' archive file, use .IR llvm-nm (1) -with the +with the .B \-print-armap option. - +.\" "GENERAL NOTES" .SH "GENERAL NOTES" -.PP -Many of the older options in otool(1) are obsolete as they print parts of the -object file that are no longer in use. When used with +Many of the older options in +.IR otool(1) +are obsolete as they print parts of the object file that are no longer in use. +When used with .IR llvm-otool (1) a line is printed that states the option and the functionality is obsolete. If no valid equivalent options are given then usage message from @@ -87,9 +90,8 @@ commands in some cases. As the command is not meant to produce the exact same output as .IR otool (1) in all cases where the functionality is very similar. - +.\" "SPECIFIC TRANSLATIONS OF OPTIONS" .SH "SPECIFIC TRANSLATIONS OF OPTIONS" -.PP Below is the list of .IR otool (1) options and the specific @@ -128,7 +130,7 @@ There is no option to display the contents of the `\_\^\_.SYMDEF' file, if the file is an archive. For that use .IR llvm-nm (1) -with the +with the .B \-print-armap option. .TP @@ -199,6 +201,29 @@ options will do. If this is not wanted then the .B \-no-symbolic-operands option can be used. .TP +.B \-x +The +.IR objdump (1) +option to display the contents of every \_\^\_text section defined in a Mach-O +file is +.BI \-section " ,\_\^\_text" . +Note that an empty segment name means all segments. If disassembly is wanted as +with the +.B \-xv +.IR otool (1) +options then +.IR objdump (1) +.B \-disassemble-all +is used. By default +.IR objdump (1) +also symbolically disassembles the operands as the +.IR otool (1) +.B \-xV +options will do. If this is not wanted then the +.IR objdump (1) +.B \-no-symbolic-operands +option can be used. +.TP .B \-d The .IR objdump (1) @@ -219,8 +244,19 @@ The .IR objdump (1) option to display the relocation entries is .BR \-r . -The format for the printing of the relocation information is different with -.IR objdump (1). +Note that the default relocation entry format is different between +.IR objdump (1) +and +.IR otool (1). +When +.BR \-r +is combined with the +.BR \-macho +option, +.IR objdump (1) +will display the relocation entries in the classic +.IR otool (1) +format. .TP .B \-I The @@ -309,7 +345,6 @@ version information and the version information is .BR \-version (with one leading dash). - .SH "OBSOLETE OPTIONS" .TP .B \-c @@ -375,3 +410,6 @@ syntax as that is the default. And the .I archive(member) syntax is not supported as file arguments with .IR objdump (1). +.SH "SEE ALSO" +.IR otool-classic (1), +.IR llvm-objdump (1) \ No newline at end of file diff --git a/cctools/man/mtoc.1 b/cctools/man/mtoc.1 index 3e5c3b2..54c0ef1 100644 --- a/cctools/man/mtoc.1 +++ b/cctools/man/mtoc.1 @@ -1,9 +1,9 @@ -.TH MTOC 1 "September 12, 2008" "Apple, Inc." +.TH MTOC 1 "July 21, 2017" "Apple, Inc." .SH NAME mtoc \- convert a Mach-O file to a PECOFF file .SH SYNOPSIS .B mtoc -[ \-subsystem type ] [ \-section_alignment value ] [ \-align value ] [ \-d filename ] input output +[ \-subsystem type ] [ \-section_alignment value ] [ \-align value ] [ \-version major.minor ] [ \-d filename ] input output .SH DESCRIPTION .I mtoc converts the @@ -40,5 +40,12 @@ The default is 400 hex. This value should match the value used for .B "\-segalign" when linking the Mach-O file. .TP +.BI "\-version" " major.minor" +Specifies the PECOFF +.I major +and +.I minor +versions for the MajorImageVersion and MinorImageVersion fields. +.TP .BI "\-d " filename" Specifies the filename to be used to create a debug directory entry with. diff --git a/cctools/man/nm.1 b/cctools/man/nm.1 index f459b10..2053167 100644 --- a/cctools/man/nm.1 +++ b/cctools/man/nm.1 @@ -1,12 +1,29 @@ -.TH NM 1 "May 27, 2015" "Apple, Inc." +.TH NM 1 "December 13, 2018" "Apple, Inc." +.\" NAME .SH NAME nm \- display name list (symbol table) .SH SYNOPSIS -.B nm +.B llvm-nm +[ +.B \-agnoprumxjlPA +] [ +.B \- +] [ +.BI \-t " format" +] [[ +.BI \-arch " arch_flag +]...] [ +.IR file " ... ]" +[ +.B \-s +.I segname sectname +] +.PP +.B nm-classic [ .B \-agnoprumxjlfPA [ -.B s +.B s .I segname sectname ]] [ @@ -17,20 +34,51 @@ nm \- display name list (symbol table) .BI \-arch " arch_flag ]...] [ .IR file " ... ]" +.\" DESCRIPTION .SH DESCRIPTION -.I Nm -displays the name list (symbol table) of each object +As of Xcode 8.0 the default +.IR nm (1) +tool is +.IR llvm-nm (1). +For the most part +.IR nm (1) +and +.IR llvm-nm (1) +have the same options; notable exceptions include +.B \-f, +.B \-s, +and +.B \-L +as described below. This document explains options common between the two +commands as well as some historically relevant options supported by +.IR nm-classic (1) . +More help on options for +.IR llvm-nm (1) +is provided when running it with the +.B \-\-help +option. +.PP +.I nm +displays the name list (symbol table of nlist structures) of each object .I file -in the argument list. If an argument is an archive, a listing for each object -file in the archive will be produced. +in the argument list. In some cases, as with an object that has had +.IR strip (1) +with its +.B \-T +option used on the object, that can be different than the dyld information. +For that information use +.IR dyldinfo (1). +.PP +If an argument is an archive, a listing for each object +file in the archive will be produced. .I File can be of the form libx.a(x.o), in which case only symbols from that member of the -object file are listed. +object file are listed. (The parentheses have to be quoted to get by the shell.) If no .I file -is given, the symbols in -.I a.out +is given, the symbols in +.I a.out are listed. .PP Each symbol name is preceded by its value (blanks if undefined). @@ -75,7 +123,7 @@ lowercase letter. A lower case in a dynamic shared library indicates a undefined reference to a private external in another module in the same library. .PP -If the symbol is a Objective C method, the symbol name is +If the symbol is a Objective-C method, the symbol name is .BI \(+-[ "Class_name(category_name)" " " "method:name:" "]\fR," where `+' is for class methods, `\-' is for instance methods, and @@ -87,7 +135,7 @@ The output is sorted alphabetically by default. Options are: .TP .B \-a -Display all symbol table entries, +Display all symbol table entries, including those inserted for use by debuggers. .TP .B \-g @@ -97,7 +145,7 @@ Display only global (external) symbols. Sort numerically rather than alphabetically. .TP .B \-o -Prepend file or archive element name to each output line, +Prepend file or archive element name to each output line, rather than only once. .TP .B \-p @@ -126,7 +174,14 @@ Undefined, common, absolute and indirect symbols get displayed as .IR (absolute) , and .IR (indirect) , -respectively. +respectively. Other symbol details are displayed in a human-friendly manner, +such as "[no dead strip]". +.IR nm +will display the referenced symbol for indirect symbols and will display the +name of the library expected to provide an undefined symbol. See +.IR nlist (3) +and + for more information on the nlist structure. .TP .B \-x Display the symbol table entry's fields in hexadecimal, @@ -138,11 +193,14 @@ Just display the symbol names (no value or type). .BI \-s " segname sectname" List only those symbols in the section .I (segname,sectname). +For +.IR llvm-nm (1) +this option must be last on the command line, and after the files. .TP .B \-l List a pseudo symbol .I ".section_start" -if no symbol has as its value the starting address of the section. +if no symbol has as its value the starting address of the section. (This is used with the .B \-s option above.) @@ -164,9 +222,17 @@ if the file contains it; otherwise, symbols for all architectures in the file are displayed. .TP +.B \-f " format" +For +.IR llvm-nm (1) +this specifies the output format. Where format can be bsd, sysv, posix or +darwin. +.TP .B \-f -Display the symbol table of a dynamic library flat (as one file not separate -modules). +For +.IR nm-classic (1) +this displays the symbol table of a dynamic library flat (as one file not separate modules). This is obsolete and not supported with +.IR llvm-nm(1). .TP .B \-A Write the pathname or library name of an object on each line. @@ -191,14 +257,17 @@ The value shall be written in hexadecimal. .TP .B \-L Display the symbols in the bitcode files in the (\_\^\_LLVM,\_\^\_bundle) -section if present instead of the object's symbol table. This is the default -if the object has no symbol table and there is an (\_\^\_LLVM,\_\^\_bundle) -section. +section if present instead of the object's symbol table. For +.IR nm-classic (1) +this is the default if the object has no symbol table and an +(\_\^\_LLVM,\_\^\_bundle) section exists. This option is not supported by +.IR llvm-nm (1) +where displaying llvm bitcode symbols is the default behavior. .SH SEE ALSO -ar(1), ar(5), Mach-O(5), stab(5), nlist(3) +ar(1), ar(5), Mach-O(5), stab(5), nlist(3), dyldinfo(1) .SH BUGS Displaying Mach-O symbols with .B \-m -is too verbose. Without the +is too verbose. Without the .BR \-m , -symbols in the Objective C sections get displayed as an `s'. +symbols in the Objective-C sections get displayed as an `s'. diff --git a/cctools/man/nmedit.1 b/cctools/man/nmedit.1 index 4ebff3e..2c10141 100644 --- a/cctools/man/nmedit.1 +++ b/cctools/man/nmedit.1 @@ -75,15 +75,15 @@ white space. .BI \-R " filename" Change the symbol table entries for the global symbols listed in .I filename -into static symbols. This file has the same format as the +into static symbols. This file has the same format as the .B \-s .I filename option above. -If the +If the .BI \-R " filename" option is specified without the .BI \-s " filename" -option, then all symbols not listed in the +option, then all symbols not listed in the .BI \-R " filename" option's filename are left as globals. If both a diff --git a/cctools/man/otool-classic.1 b/cctools/man/otool-classic.1 index e1b3b23..158afd0 100644 --- a/cctools/man/otool-classic.1 +++ b/cctools/man/otool-classic.1 @@ -1 +1,215 @@ -.so man1/otool.1 +.TH OTOOL-CLASSIC 1 "June 22, 2017" "Apple Inc." +.\# NAME +.SH NAME +otool-classic \- object file displaying tool +.SH SYNOPSIS +.B otool +[ +.I "option \&..." +] [ +.I "file \&..." +] +.\# DESCRIPTION +.SH DESCRIPTION +The +.I otool-classic +command displays specified parts of object files or libraries. It is now +obsolete and the command line shim, +.IR otool (1) +executes +.IR llvm-obdump (1) +as the default tool. +.PP +If the +.B \-m +option is not used the file +arguments may be of the form +.IR "libx.a(foo.o)" , +to request information about only that object file and not +the entire library. (Typically this argument must be quoted, +.I ``libx.a(foo.o)'', +to get it past the shell.) +.I Otool-classic +understands both Mach-O (Mach object) files and universal file formats. +.I Otool-classic +can display the specified information in either its raw (numeric) form +(without the +.B \-v +flag), or in a symbolic form using macro names of constants, etc. (with the +.B \-v +or +.B \-V +flag). +.PP +At least one of the following options must be specified: +.TP +.B \-a +Display the archive header, if the file is an archive. +.TP +.B \-S +Display the contents of the `\_\^\_.SYMDEF' file, if the file is an archive. +.TP +.B \-f +Display the universal headers. +.TP +.B \-h +Display the Mach header. +.TP +.B \-l +Display the load commands. +.TP +.B \-L +Display the names and version numbers of the shared libraries that the object +file uses, as well as the shared library ID if the file is a shared library. +.TP +.B \-D +Display just the install name of a shared library. See +.IR install_name_tool (1) +for more info. +.TP +.BI \-s " segname sectname" +Display the contents of the section +.RI ( segname,sectname ). +If the +.B \-v +flag is specified, the section is displayed as its type, unless the type is +zero (the section header flags). Also the sections +(\_\^\_OBJC,\_\^\_protocol), +(\_\^\_OBJC,__string_object) and (\_\^\_OBJC,\_\^\_runtime_setup) are displayed +symbolically if the +.B \-v +flag is specified. +.TP +.B \-t +Display the contents of the (\_\^\_TEXT,\_\^\_text) section. With the +.B \-v +flag, this disassembles the text. With the +.B \-V +flag, it also symbolically disassembles the operands. +.TP +.B \-x +Display the contents of every \_\^\_text section found in the file. This is +useful when looking at the Mach kernel and other files with \_\^\_text sections +in more than one segment, or where the \_\^\_text section is somewhere other +than \_\^\_TEXT. When used with the +.B \-v +flag, this disassembles the text. When used with the +.B \-V +flag, it also symbolically disassembles the operands. +.TP +.B \-d +Display the contents of the (\_\^\_DATA,\_\^\_data) section. +.TP +.B \-o +Display the contents of the \_\^\_OBJC segment used by the Objective-C run-time +system. +.TP +.B \-r +Display the relocation entries. +.TP +.B \-c +Display the argument strings (argv[] and envp[]) from a core file. +.TP +.B \-I +Display the indirect symbol table. +.TP +.B \-T +Display the table of contents for a dynamically linked shared library. +.TP +.B \-R +Display the reference table of a dynamically linked shared library. +.TP +.B \-M +Display the module table of a dynamically linked shared library. +.TP +.B \-H +Display the two-level namespace hints table. +.TP +.B \-G +Display the data in code table. +.TP +.B \-C +Display the linker optimization hints (-v for verbose mode can also be added). +.TP +.B \-P +Print the info plist section, (\_\^\_TEXT,\_\^\_info\_plist), as strings. +.PP +The following options may also be given: +.TP +.BI "\-p " name +Used with the +.B \-t +and +.B \-v +or +.B \-V +options to start the disassembly from symbol +.I name +and continue to the end of the (\_\^\_TEXT,\_\^\_text) section. This option +can also be used with the +.B \-x +option to begin disassembly from symbol +.I name +in any segment where a \_\^\_text section is found. +.TP +.B \-v +Display verbosely (symbolically) when possible. +.TP +.B \-V +Display the disassembled operands symbolically (this implies the +.B \-v +option). This is useful with the +.B \-t +and +.B \-x +options. +.TP +.B \-X +Don't print leading addresses or headers with disassembly of sections. +.TP +.B \-q +Use the llvm disassembler when doing disassembly; this is available for the x86 +and arm architectures. This is the default. +.TP +.BI \-mcpu= arg +When doing disassembly using the llvm disassembler use the cpu +.I arg. +.TP +.B \-function_offsets +When doing disassembly print the decimal offset from the last label printed. +.TP +.B \-j +When doing disassembly print the opcode bytes of the instructions. +.TP +.B \-Q +Use +.IR otool-classic (1)'s +disassembler when doing disassembly. +.TP +.BI \-arch " arch_type" +Specifies the architecture, +.I arch_type, +of the file for +.IR otool-classic (1) +to operate on when the file is a universal file (aka a file with multiple +architectures). (See +.IR arch (3) +for the currently known +.IR arch_type s.) +The +.I arch_type +can be "all" to operate on all architectures in the file. +The default is to display only the host architecture, if the file contains it; +otherwise, all architectures in the file are shown. +.TP +.B \-m +The object file names are not assumed to be in the archive(member) syntax, +which allows file names containing parenthesis. +.TP +.B \-\-version +Print the +.IR otool-classic (1) +version information. +.\# "SEE ALSO" +.SH "SEE ALSO" +llvm-otool(1), install_name_tool(1), dyld(1) and libtool(1) diff --git a/cctools/man/otool.1 b/cctools/man/otool.1 index b659573..7809c7e 100644 --- a/cctools/man/otool.1 +++ b/cctools/man/otool.1 @@ -1,189 +1 @@ -.TH OTOOL 1 "March 19, 2015" "Apple Inc." -.SH NAME -otool \- object file displaying tool -.SH SYNOPSIS -.B otool -[ -.I "option \&..." -] [ -.I "file \&..." -] -.SH DESCRIPTION -The -.I otool -command displays specified parts of object files or libraries. If the -.B \-m -option is not used the file -arguments may be of the form -.IR "libx.a(foo.o)" , -to request information about only that object file and not -the entire library. (Typically this argument must be quoted, -.I ``libx.a(foo.o)'', -to get it past the shell.) -.I Otool -understands both Mach-O (Mach object) files and universal file formats. -.I Otool -can display the specified information in either its raw (numeric) form -(without the -.B \-v -flag), or in a symbolic form using macro names of constants, etc. (with the -.B \-v -or -.B \-V -flag). -.PP -At least one of the following options must be specified: -.TP -.B \-a -Display the archive header, if the file is an archive. -.TP -.B \-S -Display the contents of the `\_\^\_.SYMDEF' file, if the file is an archive. -.TP -.B \-f -Display the universal headers. -.TP -.B \-h -Display the Mach header. -.TP -.B \-l -Display the load commands. -.TP -.B \-L -Display the names and version numbers of the shared libraries that the object -file uses, as well as the shared library ID if the file is a shared library. -.TP -.B \-D -Display just the install name of a shared library. See -.IR install_name_tool (1) -for more info. -.TP -.BI \-s " segname sectname" -Display the contents of the section -.RI ( segname,sectname ). -If the -.B \-v -flag is specified, the section is displayed as its type, unless the type is -zero (the section header flags). Also the sections -(\_\^\_OBJC,\_\^\_protocol), -(\_\^\_OBJC,__string_object) and (\_\^\_OBJC,\_\^\_runtime_setup) are displayed -symbolically if the -.B \-v -flag is specified. -.TP -.B \-t -Display the contents of the (\_\^\_TEXT,\_\^\_text) section. With the -.B \-v -flag, this disassembles the text. With the -.B \-V -flag, it also symbolically disassembles the operands. -.TP -.B \-d -Display the contents of the (\_\^\_DATA,\_\^\_data) section. -.TP -.B \-o -Display the contents of the \_\^\_OBJC segment used by the Objective-C run-time -system. -.TP -.B \-r -Display the relocation entries. -.TP -.B \-c -Display the argument strings (argv[] and envp[]) from a core file. -.TP -.B \-I -Display the indirect symbol table. -.TP -.B \-T -Display the table of contents for a dynamically linked shared library. -.TP -.B \-R -Display the reference table of a dynamically linked shared library. -.TP -.B \-M -Display the module table of a dynamically linked shared library. -.TP -.B \-H -Display the two-level namespace hints table. -.TP -.B \-G -Display the data in code table. -.TP -.B \-C -Display the linker optimization hints (-v for verbose mode can also be added). -.TP -.B \-P -Print the info plist section, (\_\^\_TEXT,\_\^\_info\_plist), as strings. - -.PP -The following options may also be given: -.TP -.BI "\-p " name -Used with the -.B \-t -and -.B \-v -or -.B \-V -options to start the disassembly from symbol -.I name -and continue to the end of the (\_\^\_TEXT,\_\^\_text) section. -.TP -.B \-v -Display verbosely (symbolically) when possible. -.TP -.B \-V -Display the disassembled operands symbolically (this implies the -.B \-v -option). This is useful with the -.B \-t -option. -.TP -.B \-X -Don't print leading addresses or headers with disassembly of sections. -.TP -.B \-q -Use the llvm disassembler when doing disassembly; this is available for the x86 -and arm architectures. This is the default. -.TP -.BI \-mcpu= arg -When doing disassembly using the llvm disassembler use the cpu -.I arg. -.TP -.B \-function_offsets -When doing disassembly print the decimal offset from the last label printed. -.TP -.B \-j -When doing disassembly print the opcode bytes of the instructions. -.TP -.B \-Q -Use -.IR otool (1)'s -disassembler when doing disassembly. -.TP -.BI \-arch " arch_type" -Specifies the architecture, -.I arch_type, -of the file for -.IR otool (1) -to operate on when the file is a universal file (aka a file with multiple -architectures). (See -.IR arch (3) -for the currently known -.IR arch_type s.) -The -.I arch_type -can be "all" to operate on all architectures in the file. -The default is to display only the host architecture, if the file contains it; -otherwise, all architectures in the file are shown. -.TP -.B \-m -The object file names are not assumed to be in the archive(member) syntax, -which allows file names containing parenthesis. -.TP -.B \-\-version -Print the -.IR otool (1) -version information. -.SH "SEE ALSO" -install_name_tool(1), dyld(1) and libtool(1) +.so man1/llvm-otool.1 diff --git a/cctools/man/pagestuff.1 b/cctools/man/pagestuff.1 index bc70974..b8d6743 100644 --- a/cctools/man/pagestuff.1 +++ b/cctools/man/pagestuff.1 @@ -1,14 +1,13 @@ -.TH PAGESTUFF 1 "November 2, 2010" "Apple, Inc." +.TH PAGESTUFF 1 "February 10, 2017" "Apple, Inc." .SH NAME pagestuff \- Mach-O file page analysis tool .SH SYNOPSIS -pagestuff file [-arch arch_flag] [-a] [-p] [pagenumber...] +pagestuff file [-arch arch_flag] [[-a] [-p] | [pagenumber...]] .SH DESCRIPTION pagestuff displays information about the specified logical pages of a file conforming to the Mach-O executable format. For each specified page of code, symbols (function and static data structure names) are -displayed. If no pages are specified, symbols for all pages in the -__TEXT, __text section are displayed. +displayed. .PP The options to .IR pagestuff (1) diff --git a/cctools/man/redo_prebinding.1 b/cctools/man/redo_prebinding.1 index 47df802..1b16dff 100644 --- a/cctools/man/redo_prebinding.1 +++ b/cctools/man/redo_prebinding.1 @@ -21,7 +21,7 @@ not be prebound. .PP The options allow for different types of checking for use in shell scripts. Only one of \-c, \-p or \-d can be used at a time. -If +If .I redo_prebinding redoes the prebinding on an input file it will run /usr/bin/objcunique if it exists on the result. @@ -50,12 +50,12 @@ ignore non-prebound files (useful when running on all types of files). zero out the prebind check sum in the output if it has one. .TP .B \-u -unprebind, rather than reprebind (-c, -p, -d, -e ignored). +unprebind, rather than reprebind (-c, -p, -d, -e ignored). Resets or removes prebinding-specific information from the input file. -As unprebinding is intended to produce a canonical Mach-O -binary, bundles and non-prebound executables and dylibs are acceptable -as input. For these files, the unprebind operation will zero library time -stamps and version numbers and zero entries in the two-level hints +As unprebinding is intended to produce a canonical Mach-O +binary, bundles and non-prebound executables and dylibs are acceptable +as input. For these files, the unprebind operation will zero library time +stamps and version numbers and zero entries in the two-level hints table. .TP .BI "\-e " executable_path diff --git a/cctools/man/redo_prebinding.3 b/cctools/man/redo_prebinding.3 index 256f203..0f41190 100644 --- a/cctools/man/redo_prebinding.3 +++ b/cctools/man/redo_prebinding.3 @@ -82,7 +82,7 @@ buffer with a .SM NULL terminated string with the error message. For all functions when they return they release all resources (memory, open file descriptors, -etc). +etc). .PP The file_name parameter for these functions may be of the form .I foo(bar) @@ -99,13 +99,13 @@ it is used for any dependent library has a path that starts with Then .I @executable_path is replaced with -.I executable_path. +.I executable_path. .PP If the .I root_dir parameter is not .SM NULL -it is prepended to all the rooted dependent library paths. +it is prepended to all the rooted dependent library paths. .PP .IR dependent_libs () takes a @@ -161,7 +161,7 @@ is successful it returns .SM REDO_PREBINDING_SUCCESS otherwise it returns .SM REDO_PREBINDING_FAILURE. -If the +If the .I slide_to_address parameter is non-zero and the binary is a dynamic library it is relocated to have that has its prefered address. @@ -173,7 +173,7 @@ nothing is done and this returns If the parameter .I allow_missing_architectures is non-zero then only problems with missing architectures for the architecure -of the cputype specified by +of the cputype specified by .I allow_missing_architectures will cause this call to fail. Other architectures that could not be prebound due to missing architectures in depending libraries will not have their @@ -201,7 +201,7 @@ tools and never set by the .IR update_prebinding (1) command). If -.I throttle +.I throttle is non-NULL it points to a value of the maximum bytes per second to use for writting the output. If the value is ULONG_MAX then the actual bytes per second is returned indirectly through *throttle. @@ -223,9 +223,9 @@ is successful it returns .SM REDO_PREBINDING_SUCCESS otherwise it returns .SM REDO_PREBINDING_FAILURE. -If the binary is already unprebound (it has the +If the binary is already unprebound (it has the .SM MH_PREBINDABLE -flag set) then +flag set) then .SM REDO_PREBINDING_NOT_NEEDED is returned. If .I zero_out_prebind_checksum @@ -236,22 +236,22 @@ load command (if any) is set to zero on output, otherwise it is left alone are the same - minus prebinding - the unprebinding process produces binaries that are identical). Unprebinding slides dynamic libraries to address zero, resets prebound symbols -to address zero and type undefined, resets symbol pointers, removes +to address zero and type undefined, resets symbol pointers, removes .SM LC_PREBOUND_DYLIB -commands, resets library timestamps, resets two-level hints, and updates -relocation entries if necessary. Unprebound binaries have the +commands, resets library timestamps, resets two-level hints, and updates +relocation entries if necessary. Unprebound binaries have the .SM MH_PREBINDABLE -flag set, but not +flag set, but not .SM MH_PREBOUND. It will also set the the .SM MH_ALLMODSBOUND flag if all two-level libraries were used and all modules were found to be bound in the .SM LC_PREBOUND_DYLIB -commands. As unprebinding is intended to produce a canonical Mach-O -binary, bundles and non-prebound executables and dylibs are acceptable -as input. For these files, the unprebind operation will zero library time -stamps and version numbers and zero entries in the two-level hints +commands. As unprebinding is intended to produce a canonical Mach-O +binary, bundles and non-prebound executables and dylibs are acceptable +as input. For these files, the unprebind operation will zero library time +stamps and version numbers and zero entries in the two-level hints table. These files will not gain the .SM MH_PREBINDABLE flag. All resulting binaries successfully processed by unprebind() will have diff --git a/cctools/man/seg_addr_table.1 b/cctools/man/seg_addr_table.1 index 3e7ebb6..c73c1d0 100644 --- a/cctools/man/seg_addr_table.1 +++ b/cctools/man/seg_addr_table.1 @@ -12,7 +12,7 @@ operation with out problems exits with zero status. Else it exits with a non-zero status and prints an error message about the problem. .PP -The Apple Build and Integration team uses the segment address table in +The Apple Build and Integration team uses the segment address table in /AppleInternal/Developer/seg_addr_table to set the preferred addresses of dynamic libraries. See the .IR ld (1) @@ -67,14 +67,14 @@ assignment is based on the special entries in the table for the next addresses to assign. .TP .B \-update_overlaps -Detects overlaps in the table and reassigns the lower of the two addresses. The address +Detects overlaps in the table and reassigns the lower of the two addresses. The address assignment is based on the special entries in the table for the next addresses to assign. This action is similar to detecting overlaps with -checkonly, setting -the overlapping library to 0x00000000 and running with -update. +the overlapping library to 0x00000000 and running with -update. .TP .B \-relayout_nonsplit Similar to relayout except it only causes all the non split libraries to -re-laied out and all non-split dynamic libraries to be assigned addresses. The +re-laied out and all non-split dynamic libraries to be assigned addresses. The addresses are assigned in order specified and the space given to each is based on the libraries virtual address sizes. .TP @@ -171,7 +171,7 @@ Specifies the architecture, .I arch_type, in the files to use for the sizes. More than one .BI \-arch " arch_type" -can be specified. The default is +can be specified. The default is .BI \-arch " all" which uses all architectures in the file. See .IR arch (3) diff --git a/cctools/man/segedit.1 b/cctools/man/segedit.1 index 7257038..ad8dc84 100644 --- a/cctools/man/segedit.1 +++ b/cctools/man/segedit.1 @@ -1,62 +1,69 @@ -.TH SEGEDIT 1 "October 23, 1997" "Apple Computer, Inc." +.TH SEGEDIT 1 "June 25, 2018" "Apple, Inc." .SH NAME segedit \- extract and replace sections from object files .SH SYNOPSIS -.B segedit -[ option ] name ... -.I input_file -[\-extract -.IR "segname sectname filename" "] ..." -[[\-replace -.IR "segname sectname filename" "] ..." -\-output -.IR output_file ] +\fBsegedit\fR \fIinput_file\fR [\fB-extract\fR \fIseg_name\fR \fIsect_name\fR +\fIdata_file\fR] ... +.br +\fBsegedit\fR \fIinput_file\fR [\fB-replace\fR \fIseg_name\fR \fIsect_name\fR +\fIdata_file\fR] ... \fB-output\fR \fIoutput_file\fR +.br .SH DESCRIPTION -.I Segedit -extracts and or replaces the named sections from the -.I input_file -and creates an -.I output_file -(if replacing a section). The segment and section names are -the same as specified to -.IR ld (1) +.B segedit +extracts or replaces named sections from the \fIinput_file\fR. When extracting +sections, +.B segedit +will write the contents of each requested section into \fIdata_file\fR. When +replacing sections, +.B segedit +will write a new \fIoutput_file\fR formed from the \fIinput_file\fR and the +requested replacement section content from \fIdata_file\fR. The segment and +section names are the same as those given to +.BR ld (1) with the -.B \-segcreate +.I \-sectcreate option. The segment and section names of an object file can be examined with the -.B \-l -option to -.IR otool (1). -Only sections in segments that have no relocation to or for them can be -replaced (marked with the +.I \-l +option to +.BR otool (1). +Only sections in segments that have no relocation to or from them (i.e., segments +marked with the .SM SG_NORELOC -segment flag) but all sections can be -extracted. +flag) can be replaced but all sections can be extracted. .PP The options to -.IR segedit (1): +.BR segedit (1): .TP -.BI \-extract " segname sectname filename" -Extracts the section specified by the segment name section name pair and places -the contents in the specified -.I filename. +.BI \-extract " seg_name sect_name data_file" +Extracts each section specified by the segment and section names and places +the contents in the specified \fIdata_file\fR. .TP -.BI \-replace " segname sectname filename" -Will replace the section specified by the segment name section name pair and -places and take the new contents for the section from the specified -.I filename. -The -.BI \-output " filename" -option must also be specified. -The resulting size of the section will be rounded to a multiple of 4 bytes and -padded with zero bytes if necessary. +.BI \-replace " seg_name sect_name data_file" +Replaces each section specified by the segment and section names and takes the +new section content from the specified \fIdata_file\fR. The +.BI \-output " output_file" +option must also be specified. The resulting size of the section will be rounded +to a multiple of 4 bytes and padded with zero bytes if necessary. .TP .BI \-output " output_file" -Specifies the output file to create when replacing sections. +Specifies the new file to create when replacing sections. .SH "SEE ALSO" -ld(1), otool(1) +ld(1), otool(1), lipo(1) .SH "LIMITATIONS" -Only mach-O format files that are laid out in a contiguous address space -and with their contents ordered in the order of increasing address can have -their segments replaced by this program. This layout is what the link editor +Only Mach-O format files that are laid out in a contiguous address space +and with their segments in increasing address order can have their segments +replaced by this program. This layout is what +.BR ld (1) produces by default. +.PP +Only sections in segments that have no relocation to or from them (i.e., segments +marked with the +.SM SG_NORELOC +flag) can be replaced. +.PP +.B segedit +will not extract or replace sections from universal files. If necessary, use +.BR lipo (1) +to extract the desired Mach-O files from a universal file before running +.B segedit. diff --git a/cctools/man/size.1 b/cctools/man/size.1 index 8a997c3..e5c70b7 100644 --- a/cctools/man/size.1 +++ b/cctools/man/size.1 @@ -2,7 +2,7 @@ .SH NAME size \- print the size of the sections in an object file .SH SYNOPSIS -.B size +.B size [ option ... ] [ object ... ] .SH DESCRIPTION .I Size @@ -10,7 +10,7 @@ size \- print the size of the sections in an object file .B \-m option) prints the (decimal) number of bytes required by the \_\^\_TEXT, \_\^\_DATA and \_\^\_OBJC segments. All other segments are totaled and -that size is listed in the `others' column. The final two columns is +that size is listed in the `others' column. The final two columns is the sum in decimal and hexadecimal. If no file is specified, .B a.out diff --git a/cctools/man/stab.5 b/cctools/man/stab.5 index 2f7ff3e..a2884e2 100644 --- a/cctools/man/stab.5 +++ b/cctools/man/stab.5 @@ -173,7 +173,7 @@ and .Fa n_value fields of the given -.Fa n_type . +.Fa n_type . .Em Sdb uses the .Fa n_desc diff --git a/cctools/man/strings.1 b/cctools/man/strings.1 index 08c9f1b..4924745 100644 --- a/cctools/man/strings.1 +++ b/cctools/man/strings.1 @@ -34,7 +34,7 @@ .\" .\" @(#)strings.1 8.1 (Berkeley) 6/6/93 .\" -.TH STRINGS 1 "September 11, 2006" "Apple Computer, Inc." +.TH STRINGS 1 "June 7, 2016" "Apple, Inc." .SH NAME strings \- find the printable strings in a object, or other binary, file .SH SYNOPSIS @@ -59,9 +59,8 @@ strings \- find the printable strings in a object, or other binary, file looks for ASCII strings in a binary file or standard input. .I Strings is useful for identifying random object files and many other things. -A string is any -sequence of 4 (the default) or more printing characters ending with a newline -or a null. Unless the +A string is any sequence of 4 (the default) or more printing characters +[ending at, but not including, any other character or EOF]. Unless the .B \- flag is given, .I strings diff --git a/cctools/man/strip.1 b/cctools/man/strip.1 index c353453..8c25ba0 100644 --- a/cctools/man/strip.1 +++ b/cctools/man/strip.1 @@ -1,4 +1,4 @@ -.TH STRIP 1 "August 4, 2006" "Apple Computer, Inc." +.TH STRIP 1 "January 17, 2018" "Apple Inc." .SH NAME strip \- remove symbols .SH SYNOPSIS @@ -10,11 +10,11 @@ removes or modifies the symbol table attached to the output of the assembler and link editor. This is useful to save space after a program has been debugged and to limit dynamically bound symbols. .PP -.I strip +.I strip no longer removes relocation entries under any condition. Instead, it updates the external relocation entries (and indirect symbol table entries) to reflect the resulting symbol table. -.I strip +.I strip prints an error message for those symbols not in the resulting symbol table that are needed by an external relocation entry or an indirect symbol table. The link editor @@ -22,10 +22,10 @@ The link editor is the only program that can strip relocation entries and know if it is safe to do so. .PP -When +When .I strip is used with no options on an executable file, it checks that file to see if it uses the dynamic link editor. -If it does, the effect of the +If it does, the effect of the .I strip command is the same as using the .B \-u @@ -33,9 +33,9 @@ and .B \-r options. If the file does not use the dynamic link editor, the effect of .I strip -without any options is the same as using the +without any options is the same as using the .B \-s -option of +option of .IR ld (1). The options .B \-S, @@ -47,12 +47,12 @@ have the same effect as the options. The options to .IR strip (1) -can be combined to trim the symbol table to just what is desired. +can be combined to trim the symbol table to just what is desired. .PP You should trim the symbol table of files used with dynamic linking so that only those symbols intended to be external interfaces are saved. Files used with dynamic linking include executables, objects that are -loaded (usually bundles), and dynamic shared libraries. +loaded (usually bundles), and dynamic shared libraries. Only global symbols are used by the dynamic linking process. You should strip all non-global symbols. .PP @@ -79,7 +79,7 @@ where the file would contain only those global symbols from the executable that the executable wants the loaded objects to have access to. .PP -For objects that will be loaded into an executable, you should trim the symbol table +For objects that will be loaded into an executable, you should trim the symbol table to limit the global symbols the executable will see. This would be done with: .RS @@ -153,7 +153,7 @@ white space. .BI \-R " filename" Remove the symbol table entries for the global symbols listed in .I filename. -This file has the same format as the +This file has the same format as the .B \-s .I filename option above. @@ -179,7 +179,9 @@ The source file names listed in .I filename must be one per line with no other white space in the file except the newlines on the end of each line. And they must be just the base name of the source file -without any leading directories. +without any leading directories. This option works only with the +.IR stab (5) +debugging format, it has no affect when using the DWARF debugging format. .TP .B \-A Save all global absolute symbols except those with a value of zero, and save @@ -191,8 +193,8 @@ at runtime and want the loaded code to use symbols from the shared libraries .TP .B \-n Save all N_SECT global symbols. This is intended for use with executable -programs in combination with -.B \-A +programs in combination with +.B \-A to remove the symbols needed for correct static link editing which are not needed for use with runtime loading interfaces where using the @@ -207,13 +209,23 @@ These options specify symbols to be removed from the resulting output file. .B \-S Remove the debugging symbol table entries (those created by the .B \-g -option to +option to .IR cc (1) and other compilers). .TP .B \-X Remove the local symbols whose names begin with `L'. -.TP +.TP +.B \-T +The intent of this flag is to remove Swift symbols. It removes the +symbols whose names begin with `\_$S' or `\_$s' only when it finds +an \_\^\_objc_imageinfo section with and it has a non-zero swift version. +The future the implementation of this flag may change to match the intent. +.TP +.B \-N +In binaries that use the dynamic linker remove all nlist symbols and the string +table. Setting the environment variable STRIP_NLISTS has the same effect. +.TP .B \-x Remove all local symbols (saving only global symbols). .TP @@ -233,6 +245,12 @@ Write the result into the file .B \-no_uuid Remove any LC_UUID load commands. .TP +.B \-no_split_info +Remove the LC_SEGMENT_SPLIT_INFO load command and its payload load. +.TP +.B \-no_code_signature_warning +Don't warn when the code signature would be invalid in the output. +.TP .BI \-arch " arch_type" Specifies the architecture, .I arch_type, @@ -251,11 +269,11 @@ ld(1), cc(1) .PP When creating a stub library the .B \-c -and +and .B \-x are typically used: .IP strip -x -c libfoo -o libfoo.stripped .SH LIMITATIONS -Not every layout of a Mach-O file can be stripped by this program. But all +Not every layout of a Mach-O file can be stripped by this program. But all layouts produced by the Apple compiler system can be stripped. diff --git a/cctools/misc/Makefile.am b/cctools/misc/Makefile.am index 5256aa2..d0c0b5e 100644 --- a/cctools/misc/Makefile.am +++ b/cctools/misc/Makefile.am @@ -20,12 +20,16 @@ bin_PROGRAMS = \ ctf_insert \ check_dylib \ cmpdylib \ - inout + inout \ + vtool LDADD = \ + $(top_builddir)/libmacho/libmacho.la \ $(top_builddir)/libstuff/libstuff.la \ $(DL_LIB) \ - $(LTO_RPATH) + $(LTO_RPATH) \ + $(MATH_LIB) \ + $(REALLOCF_LIB) AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -I$(top_srcdir)/libstuff $(WARNINGS) $(LTO_DEF) -D__DARWIN_UNIX03 $(ENDIAN_FLAG) @@ -54,3 +58,4 @@ ctf_insert_SOURCES= ctf_insert.c check_dylib_SOURCES= check_dylib.c cmpdylib_SOURCES= cmpdylib.c inout_SOURCES= inout.c +vtool_SOURCES= vtool.c diff --git a/cctools/misc/Makefile.in b/cctools/misc/Makefile.in new file mode 100644 index 0000000..e2bdc58 --- /dev/null +++ b/cctools/misc/Makefile.in @@ -0,0 +1,977 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = checksyms$(EXEEXT) lipo$(EXEEXT) size$(EXEEXT) \ + strings$(EXEEXT) nm$(EXEEXT) libtool$(EXEEXT) \ + redo_prebinding$(EXEEXT) seg_addr_table$(EXEEXT) \ + seg_hack$(EXEEXT) install_name_tool$(EXEEXT) indr$(EXEEXT) \ + strip$(EXEEXT) nmedit$(EXEEXT) segedit$(EXEEXT) \ + pagestuff$(EXEEXT) ranlib$(EXEEXT) codesign_allocate$(EXEEXT) \ + bitcode_strip$(EXEEXT) ctf_insert$(EXEEXT) \ + check_dylib$(EXEEXT) cmpdylib$(EXEEXT) inout$(EXEEXT) \ + vtool$(EXEEXT) +subdir = misc +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_bitcode_strip_OBJECTS = bitcode_strip-bitcode_strip.$(OBJEXT) +bitcode_strip_OBJECTS = $(am_bitcode_strip_OBJECTS) +bitcode_strip_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +bitcode_strip_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +bitcode_strip_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(bitcode_strip_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am_check_dylib_OBJECTS = check_dylib.$(OBJEXT) +check_dylib_OBJECTS = $(am_check_dylib_OBJECTS) +check_dylib_LDADD = $(LDADD) +check_dylib_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_checksyms_OBJECTS = checksyms.$(OBJEXT) +checksyms_OBJECTS = $(am_checksyms_OBJECTS) +checksyms_LDADD = $(LDADD) +checksyms_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_cmpdylib_OBJECTS = cmpdylib.$(OBJEXT) +cmpdylib_OBJECTS = $(am_cmpdylib_OBJECTS) +cmpdylib_LDADD = $(LDADD) +cmpdylib_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_codesign_allocate_OBJECTS = codesign_allocate.$(OBJEXT) +codesign_allocate_OBJECTS = $(am_codesign_allocate_OBJECTS) +codesign_allocate_LDADD = $(LDADD) +codesign_allocate_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_ctf_insert_OBJECTS = ctf_insert.$(OBJEXT) +ctf_insert_OBJECTS = $(am_ctf_insert_OBJECTS) +ctf_insert_LDADD = $(LDADD) +ctf_insert_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_indr_OBJECTS = indr.$(OBJEXT) +indr_OBJECTS = $(am_indr_OBJECTS) +indr_LDADD = $(LDADD) +indr_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_inout_OBJECTS = inout.$(OBJEXT) +inout_OBJECTS = $(am_inout_OBJECTS) +inout_LDADD = $(LDADD) +inout_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_install_name_tool_OBJECTS = install_name_tool.$(OBJEXT) +install_name_tool_OBJECTS = $(am_install_name_tool_OBJECTS) +install_name_tool_LDADD = $(LDADD) +install_name_tool_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_libtool_OBJECTS = libtool.$(OBJEXT) +libtool_OBJECTS = $(am_libtool_OBJECTS) +libtool_LDADD = $(LDADD) +libtool_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_lipo_OBJECTS = lipo.$(OBJEXT) +lipo_OBJECTS = $(am_lipo_OBJECTS) +lipo_LDADD = $(LDADD) +lipo_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_nm_OBJECTS = nm.$(OBJEXT) +nm_OBJECTS = $(am_nm_OBJECTS) +nm_LDADD = $(LDADD) +nm_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_nmedit_OBJECTS = nmedit-strip.$(OBJEXT) +nmedit_OBJECTS = $(am_nmedit_OBJECTS) +nmedit_LDADD = $(LDADD) +nmedit_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +nmedit_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(nmedit_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am_pagestuff_OBJECTS = pagestuff.$(OBJEXT) +pagestuff_OBJECTS = $(am_pagestuff_OBJECTS) +pagestuff_LDADD = $(LDADD) +pagestuff_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_ranlib_OBJECTS = ranlib-libtool.$(OBJEXT) +ranlib_OBJECTS = $(am_ranlib_OBJECTS) +ranlib_LDADD = $(LDADD) +ranlib_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +ranlib_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ranlib_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am_redo_prebinding_OBJECTS = redo_prebinding.$(OBJEXT) +redo_prebinding_OBJECTS = $(am_redo_prebinding_OBJECTS) +redo_prebinding_LDADD = $(LDADD) +redo_prebinding_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_seg_addr_table_OBJECTS = seg_addr_table.$(OBJEXT) +seg_addr_table_OBJECTS = $(am_seg_addr_table_OBJECTS) +seg_addr_table_LDADD = $(LDADD) +seg_addr_table_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_seg_hack_OBJECTS = seg_hack.$(OBJEXT) +seg_hack_OBJECTS = $(am_seg_hack_OBJECTS) +seg_hack_LDADD = $(LDADD) +seg_hack_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_segedit_OBJECTS = segedit.$(OBJEXT) +segedit_OBJECTS = $(am_segedit_OBJECTS) +segedit_LDADD = $(LDADD) +segedit_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_size_OBJECTS = size.$(OBJEXT) +size_OBJECTS = $(am_size_OBJECTS) +size_LDADD = $(LDADD) +size_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_strings_OBJECTS = strings.$(OBJEXT) +strings_OBJECTS = $(am_strings_OBJECTS) +strings_LDADD = $(LDADD) +strings_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_strip_OBJECTS = strip.$(OBJEXT) +strip_OBJECTS = $(am_strip_OBJECTS) +strip_LDADD = $(LDADD) +strip_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_vtool_OBJECTS = vtool.$(OBJEXT) +vtool_OBJECTS = $(am_vtool_OBJECTS) +vtool_LDADD = $(LDADD) +vtool_DEPENDENCIES = $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(bitcode_strip_SOURCES) $(check_dylib_SOURCES) \ + $(checksyms_SOURCES) $(cmpdylib_SOURCES) \ + $(codesign_allocate_SOURCES) $(ctf_insert_SOURCES) \ + $(indr_SOURCES) $(inout_SOURCES) $(install_name_tool_SOURCES) \ + $(libtool_SOURCES) $(lipo_SOURCES) $(nm_SOURCES) \ + $(nmedit_SOURCES) $(pagestuff_SOURCES) $(ranlib_SOURCES) \ + $(redo_prebinding_SOURCES) $(seg_addr_table_SOURCES) \ + $(seg_hack_SOURCES) $(segedit_SOURCES) $(size_SOURCES) \ + $(strings_SOURCES) $(strip_SOURCES) $(vtool_SOURCES) +DIST_SOURCES = $(bitcode_strip_SOURCES) $(check_dylib_SOURCES) \ + $(checksyms_SOURCES) $(cmpdylib_SOURCES) \ + $(codesign_allocate_SOURCES) $(ctf_insert_SOURCES) \ + $(indr_SOURCES) $(inout_SOURCES) $(install_name_tool_SOURCES) \ + $(libtool_SOURCES) $(lipo_SOURCES) $(nm_SOURCES) \ + $(nmedit_SOURCES) $(pagestuff_SOURCES) $(ranlib_SOURCES) \ + $(redo_prebinding_SOURCES) $(seg_addr_table_SOURCES) \ + $(seg_hack_SOURCES) $(segedit_SOURCES) $(size_SOURCES) \ + $(strings_SOURCES) $(strip_SOURCES) $(vtool_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +LDADD = \ + $(top_builddir)/libmacho/libmacho.la \ + $(top_builddir)/libstuff/libstuff.la \ + $(DL_LIB) \ + $(LTO_RPATH) \ + $(MATH_LIB) \ + $(REALLOCF_LIB) + +AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -I$(top_srcdir)/libstuff $(WARNINGS) $(LTO_DEF) -D__DARWIN_UNIX03 $(ENDIAN_FLAG) +checksyms_SOURCES = checksyms.c +lipo_SOURCES = lipo.c +size_SOURCES = size.c +strings_SOURCES = strings.c +nm_SOURCES = nm.c +libtool_SOURCES = libtool.c +redo_prebinding_SOURCES = redo_prebinding.c +seg_addr_table_SOURCES = seg_addr_table.c +seg_hack_SOURCES = seg_hack.c +install_name_tool_SOURCES = install_name_tool.c +indr_SOURCES = indr.c +strip_SOURCES = strip.c +nmedit_SOURCES = strip.c +nmedit_CFLAGS = -DNMEDIT $(AM_CFLAGS) +segedit_SOURCES = segedit.c +pagestuff_SOURCES = pagestuff.c +ranlib_SOURCES = libtool.c +ranlib_CFLAGS = -DRANLIB $(AM_CFLAGS) +codesign_allocate_SOURCES = codesign_allocate.c +bitcode_strip_SOURCES = bitcode_strip.c +bitcode_strip_CFLAGS = -DALLOW_ARCHIVES $(AM_CFLAGS) +ctf_insert_SOURCES = ctf_insert.c +check_dylib_SOURCES = check_dylib.c +cmpdylib_SOURCES = cmpdylib.c +inout_SOURCES = inout.c +vtool_SOURCES = vtool.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps misc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps misc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +bitcode_strip$(EXEEXT): $(bitcode_strip_OBJECTS) $(bitcode_strip_DEPENDENCIES) $(EXTRA_bitcode_strip_DEPENDENCIES) + @rm -f bitcode_strip$(EXEEXT) + $(AM_V_CCLD)$(bitcode_strip_LINK) $(bitcode_strip_OBJECTS) $(bitcode_strip_LDADD) $(LIBS) + +check_dylib$(EXEEXT): $(check_dylib_OBJECTS) $(check_dylib_DEPENDENCIES) $(EXTRA_check_dylib_DEPENDENCIES) + @rm -f check_dylib$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(check_dylib_OBJECTS) $(check_dylib_LDADD) $(LIBS) + +checksyms$(EXEEXT): $(checksyms_OBJECTS) $(checksyms_DEPENDENCIES) $(EXTRA_checksyms_DEPENDENCIES) + @rm -f checksyms$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(checksyms_OBJECTS) $(checksyms_LDADD) $(LIBS) + +cmpdylib$(EXEEXT): $(cmpdylib_OBJECTS) $(cmpdylib_DEPENDENCIES) $(EXTRA_cmpdylib_DEPENDENCIES) + @rm -f cmpdylib$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cmpdylib_OBJECTS) $(cmpdylib_LDADD) $(LIBS) + +codesign_allocate$(EXEEXT): $(codesign_allocate_OBJECTS) $(codesign_allocate_DEPENDENCIES) $(EXTRA_codesign_allocate_DEPENDENCIES) + @rm -f codesign_allocate$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(codesign_allocate_OBJECTS) $(codesign_allocate_LDADD) $(LIBS) + +ctf_insert$(EXEEXT): $(ctf_insert_OBJECTS) $(ctf_insert_DEPENDENCIES) $(EXTRA_ctf_insert_DEPENDENCIES) + @rm -f ctf_insert$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(ctf_insert_OBJECTS) $(ctf_insert_LDADD) $(LIBS) + +indr$(EXEEXT): $(indr_OBJECTS) $(indr_DEPENDENCIES) $(EXTRA_indr_DEPENDENCIES) + @rm -f indr$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(indr_OBJECTS) $(indr_LDADD) $(LIBS) + +inout$(EXEEXT): $(inout_OBJECTS) $(inout_DEPENDENCIES) $(EXTRA_inout_DEPENDENCIES) + @rm -f inout$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(inout_OBJECTS) $(inout_LDADD) $(LIBS) + +install_name_tool$(EXEEXT): $(install_name_tool_OBJECTS) $(install_name_tool_DEPENDENCIES) $(EXTRA_install_name_tool_DEPENDENCIES) + @rm -f install_name_tool$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(install_name_tool_OBJECTS) $(install_name_tool_LDADD) $(LIBS) + +libtool$(EXEEXT): $(libtool_OBJECTS) $(libtool_DEPENDENCIES) $(EXTRA_libtool_DEPENDENCIES) + @rm -f libtool$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libtool_OBJECTS) $(libtool_LDADD) $(LIBS) + +lipo$(EXEEXT): $(lipo_OBJECTS) $(lipo_DEPENDENCIES) $(EXTRA_lipo_DEPENDENCIES) + @rm -f lipo$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lipo_OBJECTS) $(lipo_LDADD) $(LIBS) + +nm$(EXEEXT): $(nm_OBJECTS) $(nm_DEPENDENCIES) $(EXTRA_nm_DEPENDENCIES) + @rm -f nm$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nm_OBJECTS) $(nm_LDADD) $(LIBS) + +nmedit$(EXEEXT): $(nmedit_OBJECTS) $(nmedit_DEPENDENCIES) $(EXTRA_nmedit_DEPENDENCIES) + @rm -f nmedit$(EXEEXT) + $(AM_V_CCLD)$(nmedit_LINK) $(nmedit_OBJECTS) $(nmedit_LDADD) $(LIBS) + +pagestuff$(EXEEXT): $(pagestuff_OBJECTS) $(pagestuff_DEPENDENCIES) $(EXTRA_pagestuff_DEPENDENCIES) + @rm -f pagestuff$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pagestuff_OBJECTS) $(pagestuff_LDADD) $(LIBS) + +ranlib$(EXEEXT): $(ranlib_OBJECTS) $(ranlib_DEPENDENCIES) $(EXTRA_ranlib_DEPENDENCIES) + @rm -f ranlib$(EXEEXT) + $(AM_V_CCLD)$(ranlib_LINK) $(ranlib_OBJECTS) $(ranlib_LDADD) $(LIBS) + +redo_prebinding$(EXEEXT): $(redo_prebinding_OBJECTS) $(redo_prebinding_DEPENDENCIES) $(EXTRA_redo_prebinding_DEPENDENCIES) + @rm -f redo_prebinding$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(redo_prebinding_OBJECTS) $(redo_prebinding_LDADD) $(LIBS) + +seg_addr_table$(EXEEXT): $(seg_addr_table_OBJECTS) $(seg_addr_table_DEPENDENCIES) $(EXTRA_seg_addr_table_DEPENDENCIES) + @rm -f seg_addr_table$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(seg_addr_table_OBJECTS) $(seg_addr_table_LDADD) $(LIBS) + +seg_hack$(EXEEXT): $(seg_hack_OBJECTS) $(seg_hack_DEPENDENCIES) $(EXTRA_seg_hack_DEPENDENCIES) + @rm -f seg_hack$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(seg_hack_OBJECTS) $(seg_hack_LDADD) $(LIBS) + +segedit$(EXEEXT): $(segedit_OBJECTS) $(segedit_DEPENDENCIES) $(EXTRA_segedit_DEPENDENCIES) + @rm -f segedit$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(segedit_OBJECTS) $(segedit_LDADD) $(LIBS) + +size$(EXEEXT): $(size_OBJECTS) $(size_DEPENDENCIES) $(EXTRA_size_DEPENDENCIES) + @rm -f size$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(size_OBJECTS) $(size_LDADD) $(LIBS) + +strings$(EXEEXT): $(strings_OBJECTS) $(strings_DEPENDENCIES) $(EXTRA_strings_DEPENDENCIES) + @rm -f strings$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(strings_OBJECTS) $(strings_LDADD) $(LIBS) + +strip$(EXEEXT): $(strip_OBJECTS) $(strip_DEPENDENCIES) $(EXTRA_strip_DEPENDENCIES) + @rm -f strip$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(strip_OBJECTS) $(strip_LDADD) $(LIBS) + +vtool$(EXEEXT): $(vtool_OBJECTS) $(vtool_DEPENDENCIES) $(EXTRA_vtool_DEPENDENCIES) + @rm -f vtool$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(vtool_OBJECTS) $(vtool_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +bitcode_strip-bitcode_strip.o: bitcode_strip.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(bitcode_strip_CFLAGS) $(CFLAGS) -c -o bitcode_strip-bitcode_strip.o `test -f 'bitcode_strip.c' || echo '$(srcdir)/'`bitcode_strip.c + +bitcode_strip-bitcode_strip.obj: bitcode_strip.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(bitcode_strip_CFLAGS) $(CFLAGS) -c -o bitcode_strip-bitcode_strip.obj `if test -f 'bitcode_strip.c'; then $(CYGPATH_W) 'bitcode_strip.c'; else $(CYGPATH_W) '$(srcdir)/bitcode_strip.c'; fi` + +nmedit-strip.o: strip.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(nmedit_CFLAGS) $(CFLAGS) -c -o nmedit-strip.o `test -f 'strip.c' || echo '$(srcdir)/'`strip.c + +nmedit-strip.obj: strip.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(nmedit_CFLAGS) $(CFLAGS) -c -o nmedit-strip.obj `if test -f 'strip.c'; then $(CYGPATH_W) 'strip.c'; else $(CYGPATH_W) '$(srcdir)/strip.c'; fi` + +ranlib-libtool.o: libtool.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ranlib_CFLAGS) $(CFLAGS) -c -o ranlib-libtool.o `test -f 'libtool.c' || echo '$(srcdir)/'`libtool.c + +ranlib-libtool.obj: libtool.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ranlib_CFLAGS) $(CFLAGS) -c -o ranlib-libtool.obj `if test -f 'libtool.c'; then $(CYGPATH_W) 'libtool.c'; else $(CYGPATH_W) '$(srcdir)/libtool.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-binPROGRAMS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/misc/bitcode_strip.c b/cctools/misc/bitcode_strip.c index e418dc2..b2aa425 100644 --- a/cctools/misc/bitcode_strip.c +++ b/cctools/misc/bitcode_strip.c @@ -30,6 +30,7 @@ #include "stuff/allocate.h" #include "stuff/rnd.h" #include "stuff/execute.h" +#include "stuff/write64.h" /* used by error routines as the name of the program */ char *progname = NULL; @@ -75,7 +76,8 @@ static void strip_bitcode_from_load_commands( static void leave_only_bitcode_load_commands( struct arch *arch, - struct object *object); + struct object *object, + enum bool keeping_plist); static void reset_pointers_for_object_load_commands( struct arch *arch, @@ -201,7 +203,7 @@ char **envp) return(EXIT_SUCCESS); } - writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, NULL); + writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, FALSE, NULL); if(errors) return(EXIT_FAILURE); @@ -267,10 +269,10 @@ uint32_t narchs) archs[i].members[j].offset = offset; size = 0; if(archs[i].members[j].member_long_name == TRUE){ - size = rnd(archs[i].members[j].member_name_size, + size = rnd32(archs[i].members[j].member_name_size, sizeof(int64_t)); - size = rnd(archs[i].members[j].member_name_size, 8) + - (rnd(sizeof(struct ar_hdr), 8) - + size = rnd32(archs[i].members[j].member_name_size, 8) + + (rnd32(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr)); archs[i].toc_long_name = TRUE; } @@ -373,7 +375,7 @@ struct object *object) */ if(object->seg_bitcode != NULL || object->seg_bitcode64 != NULL){ section_ordinal = 1; - first_bitcode_section_ordinal = 0; + first_bitcode_section_ordinal = last_bitcode_section_ordinal = 0; lc = object->load_commands; for(i = 0; i < mh_ncmds && first_bitcode_section_ordinal == 0; i++){ if(lc->cmd == LC_SEGMENT){ @@ -515,13 +517,15 @@ struct object *object) * If we are removing the bitcode segment and leaving just a marker * calculate a minimum sized segment contents with all zeros which * usually will be the segment alignment. + * + * In practice we will assume 16K alignment (arm) unless the arch + * flag specifies otherwise. */ + segalign = 0x4000; /* 16K */ if(mflag){ arch_flag = get_arch_family_from_cputype(object->mh_cputype); if(arch_flag != NULL) segalign = get_segalign_from_flag(arch_flag); - else - segalign = 0x4000; /* 16K */ } /* @@ -601,8 +605,9 @@ struct object *object) object->seg_linkedit64->fileoff -= object->seg_bitcode64->filesize; } - object->input_sym_info_size = object->seg_linkedit64->filesize; - start_offset = object->seg_linkedit64->fileoff; + object->input_sym_info_size = + (uint32_t)object->seg_linkedit64->filesize; + start_offset = (uint32_t)object->seg_linkedit64->fileoff; /* * If we have bitcode and are replacing it with just a marker @@ -614,7 +619,8 @@ struct object *object) if(object->seg_bitcode64->filesize >= segalign) bitcode_marker_size = segalign; else - bitcode_marker_size = object->seg_bitcode64->filesize; + bitcode_marker_size = + (uint32_t)object->seg_bitcode64->filesize; object->output_new_content = allocate(bitcode_marker_size); memset(object->output_new_content, '\0', bitcode_marker_size); object->output_new_content_size = bitcode_marker_size; @@ -623,7 +629,7 @@ struct object *object) object->seg_bitcode64->fileoff = start_offset; /* Note we are leaving the vmsize unchanged */ - sect_offset = object->seg_bitcode64->fileoff; + sect_offset = (uint32_t)object->seg_bitcode64->fileoff; s64 = (struct section_64 *)((char *)object->seg_bitcode64 + sizeof(struct segment_command_64)); if(object->seg_bitcode64->nsects > 0){ @@ -723,6 +729,24 @@ struct object *object) offset += object->dyld_info->export_size; } } + + if (object->dyld_chained_fixups != NULL) { + object->output_dyld_chained_fixups_data = + object->object_addr + object->dyld_chained_fixups->dataoff; + object->output_dyld_chained_fixups_data_size = + object->dyld_chained_fixups->datasize; + object->dyld_chained_fixups->dataoff = offset; + offset += object->dyld_chained_fixups->datasize; + } + + if (object->dyld_exports_trie != NULL) { + object->output_dyld_exports_trie_data = + object->object_addr + object->dyld_exports_trie->dataoff; + object->output_dyld_exports_trie_data_size = + object->dyld_exports_trie->datasize; + object->dyld_exports_trie->dataoff = offset; + offset += object->dyld_exports_trie->datasize; + } /* Local relocation entries are next in the output. */ if(object->dyst != NULL){ @@ -958,7 +982,7 @@ struct object *object) object->code_sig_cmd->dataoff; object->output_code_sig_data_size = object->code_sig_cmd->datasize; - offset = rnd(offset, 16); + offset = rnd32(offset, 16); object->code_sig_cmd->dataoff = offset; offset += object->code_sig_cmd->datasize; } @@ -980,7 +1004,9 @@ static char fake_string_table[8]; * leave_just_bitcode_segment() is only called when there is a bitcode segment, * and removes everything but that segment contents but leaving the load * commands intact but zeros out the sizes and counts to make the resulting - * Mach-O file valid. + * Mach-O file valid. With the exception of if there is an + * (__TEXT,__info_plist) section then that is kept which is a hack to make + * code signing work. */ static void @@ -989,12 +1015,12 @@ struct arch *arch, struct member *member, struct object *object) { - uint32_t i, start_offset, offset, sect_offset; + uint32_t i, j, start_offset, offset, sect_offset; struct load_command *lc; - struct segment_command *sg; - struct segment_command_64 *sg64; - struct section *s; - struct section_64 *s64; + struct segment_command *sg, *text; + struct segment_command_64 *sg64, *text64; + struct section *s, *plist; + struct section_64 *s64, *plist64; /* * For MH_OBJECT files, .o files there is no static link editor @@ -1016,7 +1042,8 @@ struct object *object) * Which is just the size of the old load commands. * * To get the bit code segment into the output file we use the - * output_new_content and output_new_content_size. + * output_new_content and output_new_content_size. And we also use + * this if we have a (__TEXT,__info_plist) section. * * Lastly to fake up the output symbolic information will have a 8-byte * string table of zeros and set the size of all the counts to zero @@ -1024,8 +1051,13 @@ struct object *object) * * Also adjust the file offset of the link edit information which is * where the new fake output symbolic information will start in the - * output file. Which will be right after the load commands. + * output file. Which will be right after the load commands or right + * after the (__TEXT,__info_plist) section. */ + text = NULL; + text64 = NULL; + plist = NULL; + plist64 = NULL; if(object->mh != NULL){ start_offset = 0; lc = object->load_commands; @@ -1035,8 +1067,18 @@ struct object *object) if(sg->filesize != 0 && sg->fileoff == 0){ s = (struct section *)((char *)sg + sizeof(struct segment_command)); - if(sg->nsects > 0) + if(sg->nsects > 0){ start_offset = s->offset; + for(j = 0; j < sg->nsects; j++){ + if(strcmp(s->segname, SEG_TEXT) == 0 && + strcmp(s->sectname, "__info_plist") == 0 && + s->size != 0 && plist == NULL){ + plist = s; + text = sg; + } + s++; + } + } } } lc = (struct load_command *)((char *)lc + lc->cmdsize); @@ -1048,9 +1090,29 @@ struct object *object) object->object_size -= (object->seg_linkedit->fileoff - start_offset); - object->output_new_content = object->object_addr + - object->seg_bitcode->fileoff; - object->output_new_content_size = object->seg_bitcode->filesize; + if(plist != NULL) { + object->output_new_content = object->object_addr + + object->seg_bitcode->fileoff; + object->output_new_content_size = + object->seg_bitcode->filesize + plist->size; + object->output_new_content = + allocate(object->output_new_content_size); + memcpy(object->output_new_content, + object->object_addr + plist->offset, + plist->size); + memcpy(object->output_new_content + plist->size, + object->object_addr + object->seg_bitcode->fileoff, + object->seg_bitcode->filesize); + plist->offset = start_offset; + text->fileoff = plist->offset; + text->filesize = plist->size; + start_offset += plist->size; + } + else { + object->output_new_content = object->object_addr + + object->seg_bitcode->fileoff; + object->output_new_content_size = object->seg_bitcode->filesize; + } object->seg_bitcode->fileoff = start_offset; sect_offset = object->seg_bitcode->fileoff; @@ -1075,8 +1137,18 @@ struct object *object) if(sg64->filesize != 0 && sg64->fileoff == 0){ s64 = (struct section_64 *)((char *)sg64 + sizeof(struct segment_command_64)); - if(sg64->nsects > 0) + if(sg64->nsects > 0){ start_offset = s64->offset; + for(j = 0; j < sg64->nsects; j++){ + if(strcmp(s64->segname, SEG_TEXT) == 0 && + strcmp(s64->sectname, "__info_plist") == 0 && + s64->size != 0 && plist64 == NULL){ + plist64 = s64; + text64 = sg64; + } + s64++; + } + } } } lc = (struct load_command *)((char *)lc + lc->cmdsize); @@ -1088,12 +1160,33 @@ struct object *object) object->object_size -= (object->seg_linkedit64->fileoff - start_offset); - object->output_new_content = object->object_addr + - object->seg_bitcode64->fileoff; - object->output_new_content_size = object->seg_bitcode64->filesize; + if(plist64 != NULL) { + object->output_new_content = object->object_addr + + object->seg_bitcode64->fileoff; + object->output_new_content_size = (uint32_t) + (object->seg_bitcode64->filesize + plist64->size); + object->output_new_content = + allocate(object->output_new_content_size); + memcpy(object->output_new_content, + object->object_addr + plist64->offset, + plist64->size); + memcpy(object->output_new_content + plist64->size, + object->object_addr + object->seg_bitcode64->fileoff, + object->seg_bitcode64->filesize); + plist64->offset = start_offset; + text64->fileoff = plist64->offset; + text64->filesize = plist64->size; + start_offset += plist64->size; + } + else { + object->output_new_content = object->object_addr + + object->seg_bitcode64->fileoff; + object->output_new_content_size = + (uint32_t)object->seg_bitcode64->filesize; + } object->seg_bitcode64->fileoff = start_offset; - sect_offset = object->seg_bitcode64->fileoff; + sect_offset = (uint32_t)object->seg_bitcode64->fileoff; s64 = (struct section_64 *)((char *)object->seg_bitcode64 + sizeof(struct segment_command_64)); for(i = 0; i < object->seg_bitcode64->nsects; i++){ @@ -1103,7 +1196,8 @@ struct object *object) } start_offset += object->seg_bitcode64->filesize; - object->input_sym_info_size = object->seg_linkedit64->filesize; + object->input_sym_info_size = + (uint32_t)object->seg_linkedit64->filesize; object->seg_linkedit64->fileoff = start_offset; } @@ -1133,6 +1227,20 @@ struct object *object) object->dyld_info->export_off = 0; object->dyld_info->export_size = 0; } + + if(object->dyld_chained_fixups != NULL){ + object->output_dyld_chained_fixups_data = NULL; + object->output_dyld_chained_fixups_data_size = 0; + object->dyld_chained_fixups->dataoff = 0; + object->dyld_chained_fixups->datasize = 0; + } + + if(object->dyld_exports_trie != NULL){ + object->output_dyld_exports_trie_data = NULL; + object->output_dyld_exports_trie_data_size = 0; + object->dyld_exports_trie->dataoff = 0; + object->dyld_exports_trie->datasize = 0; + } /* Local relocation entries are next in the output. */ if(object->dyst != NULL){ @@ -1248,7 +1356,8 @@ struct object *object) else object->seg_linkedit64->filesize = object->output_sym_info_size; - leave_only_bitcode_load_commands(arch, object); + leave_only_bitcode_load_commands(arch, object, + plist != NULL || plist64 != NULL); } /* @@ -1363,13 +1472,17 @@ struct object *object) * the LC_SEGMENT or LC_SEGMENT_64 load command from the object's load commands * for the bitcode segment. It only removes the LC_CODE_SIGNATURE and * LC_DYLIB_CODE_SIGN_DRS load commands. And zeros out all the fields of - * other load commands to make them valid in the Mach-O file. + * other load commands to make them valid in the Mach-O file. If keeping_plist + * is TRUE, then the (__TEXT,__info_plist) section is kept and the caller has + * adjusted the __TEXT segment's values and the __info_plist section values, + * so they are not changed here. */ static void leave_only_bitcode_load_commands( struct arch *arch, -struct object *object) +struct object *object, +enum bool keeping_plist) { uint32_t i, j, mh_ncmds, new_ncmds, mh_sizeofcmds, new_sizeofcmds; struct load_command *lc1, *lc2, *new_load_commands; @@ -1378,6 +1491,8 @@ struct object *object) struct section *s; struct section_64 *s64; struct entry_point_command *ep; + struct encryption_info_command *encrypt_info; + struct encryption_info_command_64 *encrypt_info64; /* * Allocate space for the new load commands and zero it out so any holes @@ -1408,19 +1523,26 @@ struct object *object) sg = (struct segment_command *)lc1; if(strcmp(sg->segname, "__LLVM") != 0 && strcmp(sg->segname, SEG_LINKEDIT) != 0){ - sg->vmaddr = 0; - sg->vmsize = 0; - sg->fileoff = 0; - sg->filesize = 0; + if(keeping_plist == FALSE || + strcmp(sg->segname, SEG_TEXT) != 0){ + sg->vmaddr = 0; + sg->vmsize = 0; + sg->fileoff = 0; + sg->filesize = 0; + } s = (struct section *)((char *)sg + sizeof(struct segment_command)); for(j = 0; j < sg->nsects; j++){ - s->addr = 0; - s->size = 0; - s->offset = 0; - s->reloff = 0; - s->nreloc = 0; - s->reserved1 = 0; + if(keeping_plist == FALSE || + strcmp(s->segname, SEG_TEXT) != 0 || + strcmp(s->sectname, "__info_plist") != 0){ + s->addr = 0; + s->size = 0; + s->offset = 0; + s->reloff = 0; + s->nreloc = 0; + s->reserved1 = 0; + } s++; } } @@ -1433,19 +1555,26 @@ struct object *object) sg64 = (struct segment_command_64 *)lc1; if(strcmp(sg64->segname, "__LLVM") != 0 && strcmp(sg64->segname, SEG_LINKEDIT) != 0){ - sg64->vmaddr = 0; - sg64->vmsize = 0; - sg64->fileoff = 0; - sg64->filesize = 0; + if(keeping_plist == FALSE || + strcmp(sg64->segname, SEG_TEXT) != 0){ + sg64->vmaddr = 0; + sg64->vmsize = 0; + sg64->fileoff = 0; + sg64->filesize = 0; + } s64 = (struct section_64 *)((char *)sg64 + sizeof(struct segment_command_64)); for(j = 0; j < sg64->nsects; j++){ - s64->addr = 0; - s64->size = 0; - s64->offset = 0; - s64->reloff = 0; - s64->nreloc = 0; - s64->reserved1 = 0; + if(keeping_plist == FALSE || + strcmp(s64->segname, SEG_TEXT) != 0 || + strcmp(s64->sectname, "__info_plist") != 0){ + s64->addr = 0; + s64->size = 0; + s64->offset = 0; + s64->reloff = 0; + s64->nreloc = 0; + s64->reserved1 = 0; + } s64++; } } @@ -1460,6 +1589,16 @@ struct object *object) ep = (struct entry_point_command *)lc1; ep->entryoff = 0; } + else if(lc1->cmd == LC_ENCRYPTION_INFO){ + encrypt_info = (struct encryption_info_command *)lc1; + encrypt_info->cryptoff = 0; + encrypt_info->cryptsize = 0; + } + else if(lc1->cmd == LC_ENCRYPTION_INFO_64){ + encrypt_info64 = (struct encryption_info_command_64 *)lc1; + encrypt_info64->cryptoff = 0; + encrypt_info64->cryptsize = 0; + } memcpy(lc2, lc1, lc1->cmdsize); new_ncmds++; new_sizeofcmds += lc2->cmdsize; @@ -1571,6 +1710,13 @@ struct object *object) case LC_CODE_SIGNATURE: object->code_sig_cmd = (struct linkedit_data_command *)lc; break; + case LC_DYLD_CHAINED_FIXUPS: + object->dyld_chained_fixups = + (struct linkedit_data_command *)lc; + break; + case LC_DYLD_EXPORTS_TRIE: + object->dyld_exports_trie = (struct linkedit_data_command *)lc; + break; } lc = (struct load_command *)((char *)lc + lc->cmdsize); } @@ -1651,8 +1797,8 @@ struct object *object) if((fd = open(input_file, O_WRONLY|O_CREAT, 0600)) < 0) system_fatal("can't open temporary file: %s", input_file); - if(write(fd, object->object_addr, object->object_size) != - object->object_size) + if(write64(fd, object->object_addr, object->object_size) != + (ssize_t)object->object_size) system_fatal("can't write temporary file: %s", input_file); if(close(fd) == -1) @@ -1823,6 +1969,14 @@ struct object *object) fatal_arch(arch, member, "malformed MH_OBJECT should not contain a " "dyld info"); + if(object->dyld_chained_fixups != NULL) + fatal_arch(arch, member, "malformed MH_OBJECT should not contain " + "dyld chained fixups"); + + if(object->dyld_exports_trie != NULL) + fatal_arch(arch, member, "malformed MH_OBJECT should not contain a " + "dyld exports trie"); + /* Local relocation entries off the dynamic symbol table would next in the output, but there are not in .o files */ diff --git a/cctools/misc/checksyms.c b/cctools/misc/checksyms.c index cba2445..ae17fc8 100644 --- a/cctools/misc/checksyms.c +++ b/cctools/misc/checksyms.c @@ -37,8 +37,6 @@ #include "stuff/symbol.h" #include "stuff/errors.h" #include "stuff/allocate.h" -#include "stuff/dylib_table.h" -#include "stuff/seg_addr_table.h" #include "stuff/guess_short_name.h" #include "stuff/macosx_deployment_target.h" @@ -81,14 +79,12 @@ static void check_dylib( /* * The dylib table. This is specified with the -dylib_table option. */ -static struct dylib_table *dylib_table = NULL; static char *dylib_table_name = NULL; /* * The segment address table. This is specified with the -seg_addr_table * option. */ -static struct seg_addr_table *seg_addr_table = NULL; static char *seg_addr_table_name = NULL; static enum bool seg_addr_table_specified = FALSE; /* @@ -110,7 +106,7 @@ char **envp) { int i; struct cmd_flags cmd_flags; - uint32_t j, table_size; + uint32_t j; struct arch_flag *arch_flags; uint32_t narch_flags; enum bool all_archs; @@ -169,8 +165,7 @@ char **envp) usage(); } dylib_table_name = argv[i+1]; - dylib_table = parse_dylib_table(argv[i+1], argv[i], - argv[i+1]); + printf("warning: -dylib_table is no longer used.\n"); i++; } else if(strcmp(argv[i], "-seg_addr_table") == 0){ @@ -184,8 +179,7 @@ char **envp) } seg_addr_table_specified = TRUE; seg_addr_table_name = argv[i+1]; - seg_addr_table = parse_seg_addr_table(argv[i+1], - argv[i], argv[i+1], &table_size); + printf("warning: -seg_addr_table is no longer used.\n"); i++; } else if(strcmp(argv[i], "-seg_addr_table_filename") == 0){ @@ -198,6 +192,8 @@ char **envp) usage(); } seg_addr_table_filename = argv[i+1]; + printf("warning: -seg_addr_table_filename is no longer " + "used.\n"); i++; } else{ @@ -293,8 +289,11 @@ void *cookie) mh_flags = ofile->mh64->flags; mh_ncmds = ofile->mh64->ncmds; } - else + else { + printf("internal error: no mach header\n"); + exit_status = EXIT_FAILURE; return; + } debug = FALSE; cmd_flags = (struct cmd_flags *)cookie; diff --git a/cctools/misc/codesign_allocate.c b/cctools/misc/codesign_allocate.c index 467b902..eda66c6 100644 --- a/cctools/misc/codesign_allocate.c +++ b/cctools/misc/codesign_allocate.c @@ -41,6 +41,9 @@ struct arch_sign { struct arch_sign *arch_signs; uint32_t narch_signs = 0; +enum bool rflag = FALSE; +enum bool pflag = FALSE; + /* used by error routines as the name of the program */ char *progname = NULL; @@ -62,14 +65,21 @@ static struct linkedit_data_command *add_code_sig_load_command( struct member *member, struct object *object); +static void strip_LC_CODE_SIGNATURE_commands( + struct arch *arch, + struct member *member, + struct object *object); + /* apple_version is created by the libstuff/Makefile */ extern char apple_version[]; char *version = apple_version; +static enum bool cs_alloc_debug; + /* * The codesign_allocate(1) tool has the following usage: * - * codesign_allocate -i oldfile -a arch size ... -o newfile + * codesign_allocate -i oldfile [-a arch size ...] | [-r] -o newfile * * Where the oldfile is a Mach-O file that is input for the dynamic linker * and it creates or adds an @@ -85,11 +95,31 @@ char **envp) struct arch *archs; uint32_t narchs; + /* if CS_ALLOC_DEBUG is set print the complete arguments to stderr */ + cs_alloc_debug = (NULL != getenv("CS_ALLOC_DEBUG")); + if (cs_alloc_debug) { + for (i = 0; i < argc; ++i) { + if (i < (argc-1)) { + fprintf(stderr, "%s ", argv[i]); + } else { + fprintf(stderr, "%s\n", argv[i]); + } + } + } + progname = argv[0]; input = NULL; output = NULL; archs = NULL; narchs = 0; + /* + * If this is being run via the symbolic link named codesign_allocate-p + * then set the pflag. + */ + i = (uint32_t)strlen(argv[0]); + if(i >= sizeof("codesign_allocate-p") - 1 && + strcmp(argv[0] + i-2, "-p") == 0) + pflag = TRUE; for(i = 1; i < argc; i++){ if(strcmp(argv[i], "-i") == 0){ if(i + 1 == argc){ @@ -131,7 +161,7 @@ char **envp) usage(); } arch_signs[narch_signs].datasize = - strtoul(argv[i+2], &endp, 0); + (uint32_t)strtoul(argv[i+2], &endp, 0); if(*endp != '\0') fatal("size for '-a %s %s' not a proper number", argv[i+1], argv[i+2]); @@ -153,13 +183,13 @@ char **envp) (narch_signs + 1) * sizeof(struct arch_sign)); arch_signs[narch_signs].arch_flag.cputype = - strtoul(argv[i+1], &endp, 0); + (uint32_t)strtoul(argv[i+1], &endp, 0); if(*endp != '\0') fatal("cputype for '-A %s %s %s' not a proper number", argv[i+1], argv[i+2], argv[i+3]); arch_signs[narch_signs].arch_flag.cpusubtype = - strtoul(argv[i+2], &endp, 0); + (uint32_t)strtoul(argv[i+2], &endp, 0); if(*endp != '\0') fatal("cpusubtype for '-A %s %s %s' not a proper " "number", argv[i+1], argv[i+2], argv[i+3]); @@ -170,7 +200,7 @@ char **envp) arch_signs[narch_signs].arch_flag.cpusubtype); arch_signs[narch_signs].datasize = - strtoul(argv[i+3], &endp, 0); + (uint32_t)strtoul(argv[i+3], &endp, 0); if(*endp != '\0') fatal("size for '-A %s %s %s' not a proper number", argv[i+1], argv[i+2], argv[i+3]); @@ -183,13 +213,24 @@ char **envp) i += 3; } } + else if(strcmp(argv[i], "-r") == 0){ + rflag = TRUE; + } + else if(strcmp(argv[i], "-p") == 0){ + pflag = TRUE; + } else{ error("unknown flag: %s", argv[i]); usage(); } } - if(input == NULL || output == NULL || narch_signs == 0) + if(input == NULL || output == NULL || + (narch_signs == 0 && rflag == FALSE)) usage(); + if(rflag && narch_signs != 0){ + error("-r flag can't be specified with -a or -A flags"); + usage(); + } breakout(input, &archs, &narchs, FALSE); if(errors) @@ -206,7 +247,7 @@ char **envp) arch_signs[i].arch_flag.name, arch_signs[i].datasize); } - writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, NULL); + writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, FALSE, NULL); if(errors) return(EXIT_FAILURE); @@ -222,8 +263,8 @@ void usage( void) { - fprintf(stderr, "Usage: %s -i input [-a ]... " - "[-A ]... -o output\n", + fprintf(stderr, "Usage: %s -i input [[-a ]... " + "[-A ]... | -r] [-p] -o output\n", progname); exit(EXIT_FAILURE); } @@ -265,7 +306,7 @@ uint32_t narchs) archs[i].members[j].offset = offset; size = 0; if(archs[i].members[j].member_long_name == TRUE){ - size = rnd(archs[i].members[j].member_name_size, + size = rnd32(archs[i].members[j].member_name_size, sizeof(long)); archs[i].toc_long_name = TRUE; } @@ -297,9 +338,10 @@ uint32_t narchs) } /* - * setup_code_signature() does the work to add or update the needed + * setup_code_signature() does the work to add or update (or remove) the needed * LC_CODE_SIGNATURE load command for the specified broken out ofile if it - * is of one of the architecures specifed with a -a command line options. + * is of one of the architecures specifed with a -a command line options. Or + * removes the LC_CODE_SIGNATURE load command if the -r flag is specified. */ static void @@ -308,15 +350,29 @@ struct arch *arch, struct member *member, struct object *object) { - uint32_t i; + uint32_t i, filetype; cpu_type_t cputype; cpu_subtype_t cpusubtype; - uint32_t flags, linkedit_end; + uint32_t flags, linkedit_end, input_sym_info_size_before_code_sig_rnd; uint32_t dyld_info_start; uint32_t dyld_info_end; - uint32_t align_delta; + uint32_t align_delta, old_align_delta; + uint32_t dataoff, rnd_dataoff; linkedit_end = 0; + input_sym_info_size_before_code_sig_rnd = 0; + if(object->mh != NULL){ + cputype = object->mh->cputype; + cpusubtype = object->mh->cpusubtype & ~CPU_SUBTYPE_MASK; + filetype = object->mh->filetype; + flags = object->mh->flags; + } + else{ + cputype = object->mh64->cputype; + cpusubtype = object->mh64->cpusubtype & ~CPU_SUBTYPE_MASK; + filetype = object->mh64->filetype; + flags = object->mh64->flags; + } /* * First set up all the pointers and sizes of the symbolic info. */ @@ -435,6 +491,18 @@ struct object *object) object->output_link_opt_hint_info_data_size = object->link_opt_hint_cmd->datasize; } + if(object->dyld_chained_fixups != NULL){ + object->output_dyld_chained_fixups_data = + (object->object_addr + object->dyld_chained_fixups->dataoff); + object->output_dyld_chained_fixups_data_size = + object->dyld_chained_fixups->datasize; + } + if(object->dyld_exports_trie != NULL){ + object->output_dyld_exports_trie_data = + (object->object_addr + object->dyld_exports_trie->dataoff); + object->output_dyld_exports_trie_data_size = + object->dyld_exports_trie->datasize; + } object->output_ext_relocs = (struct relocation_info *) (object->object_addr + object->dyst->extreloff); object->output_tocs = @@ -490,6 +558,12 @@ struct object *object) if(object->link_opt_hint_cmd != NULL) object->input_sym_info_size += object->link_opt_hint_cmd->datasize; + if(object->dyld_chained_fixups != NULL) + object->input_sym_info_size += + object->dyld_chained_fixups->datasize; + if(object->dyld_exports_trie != NULL) + object->input_sym_info_size += + object->dyld_exports_trie->datasize; if(object->mh != NULL){ object->input_sym_info_size += object->dyst->nmodtab * @@ -512,30 +586,78 @@ struct object *object) } } object->output_sym_info_size = object->input_sym_info_size; + input_sym_info_size_before_code_sig_rnd = object->input_sym_info_size; if(object->code_sig_cmd != NULL){ - object->input_sym_info_size = rnd(object->input_sym_info_size, - 16); + /* + * An MH_OBJECT filetype will not have any padding to get the offset + * of an existing code signture to a 16 byte boundary. To get the + * offset to a specific byte boundary in an MH_OBJECT file the + * string table size before it is adjusted and there is no padding. + */ + if(filetype != MH_OBJECT) + object->input_sym_info_size = rnd32(object->input_sym_info_size, + 16); object->input_sym_info_size += object->code_sig_cmd->datasize; } /* * Now see if one of the -a flags matches this object. */ - if(object->mh != NULL){ - cputype = object->mh->cputype; - cpusubtype = object->mh->cpusubtype & ~CPU_SUBTYPE_MASK; - flags = object->mh->flags; - } - else{ - cputype = object->mh64->cputype; - cpusubtype = object->mh64->cpusubtype & ~CPU_SUBTYPE_MASK; - flags = object->mh64->flags; - } for(i = 0; i < narch_signs; i++){ if(arch_signs[i].arch_flag.cputype == cputype && arch_signs[i].arch_flag.cpusubtype == cpusubtype) break; } + + /* + * If the -r flag is specified we remove the code signature and the + * LC_CODE_SIGNATURE load command if any. We also do this if we have + * an -a flag for this arch and the size is zero. + */ + if(rflag || (i < narch_signs && arch_signs[i].datasize == 0)){ + struct arch_flag arch_flag; + const char *arch_name; + arch_name = get_arch_name_from_types(cputype, cpusubtype); + (void)get_arch_from_flag((char *)arch_name, &arch_flag); + if(i < narch_signs) + arch_signs[i].found = TRUE; + /* + * If this has a code signature load command reduce the linkedit by + * the size of that data and the old alignment. But do not use the + * old data. + */ + if(object->code_sig_cmd != NULL){ + dataoff = object->object_size - object->input_sym_info_size + + input_sym_info_size_before_code_sig_rnd; + + old_align_delta = object->code_sig_cmd->dataoff - dataoff; + if(object->seg_linkedit != NULL){ + object->seg_linkedit->filesize -= + (old_align_delta + object->code_sig_cmd->datasize); + if(object->seg_linkedit->filesize > + object->seg_linkedit->vmsize) + object->seg_linkedit->vmsize = + rnd32(object->seg_linkedit->filesize, + get_segalign_from_flag(&arch_flag)); + } + else if(object->seg_linkedit64 != NULL){ + object->seg_linkedit64->filesize -= + old_align_delta; + object->seg_linkedit64->filesize -= + object->code_sig_cmd->datasize; + if(object->seg_linkedit64->filesize > + object->seg_linkedit64->vmsize) + object->seg_linkedit64->vmsize = + rnd(object->seg_linkedit64->filesize, + get_segalign_from_flag(&arch_flag)); + } + } + object->output_code_sig_data_size = 0; + object->output_code_sig_data = NULL; + strip_LC_CODE_SIGNATURE_commands(arch, member, object); + return; + } + /* * If we didn't find a matching -a flag then just use the existing * code signature if any. @@ -566,20 +688,55 @@ struct object *object) * the size of that data. But do not use the old data. */ if(object->code_sig_cmd != NULL){ + /* + * To get the code signature data to be page aligned we have to + * determine the old padding incase it was just 16 byte aligned. + * Then determine the new padding alignment and change the string + * table size to add the new padding. + * + * If there is no string table then we just use the existing + * alignment of the old code signature data. + */ + old_align_delta = 0; + align_delta = 0; + if(object->st != NULL) { + dataoff = object->object_size - object->input_sym_info_size + + input_sym_info_size_before_code_sig_rnd; + + old_align_delta = object->code_sig_cmd->dataoff - dataoff; + + if(pflag) + rnd_dataoff = rnd32(dataoff, + get_segalign_from_flag(&arch_signs[i].arch_flag)); + else + rnd_dataoff = rnd32(dataoff, 16); + align_delta = rnd_dataoff - dataoff; + + object->code_sig_cmd->dataoff = rnd_dataoff; + if(pflag) { + object->output_strings_size_pad = align_delta; + object->st->strsize += object->output_strings_size_pad; + } + } if(object->seg_linkedit != NULL){ object->seg_linkedit->filesize += - arch_signs[i].datasize - object->code_sig_cmd->datasize; + align_delta + arch_signs[i].datasize + - (old_align_delta + object->code_sig_cmd->datasize); if(object->seg_linkedit->filesize > object->seg_linkedit->vmsize) object->seg_linkedit->vmsize = - rnd(object->seg_linkedit->filesize, + rnd32(object->seg_linkedit->filesize, get_segalign_from_flag(&arch_signs[i].arch_flag)); } else if(object->seg_linkedit64 != NULL){ - object->seg_linkedit64->filesize += - arch_signs[i].datasize; + object->seg_linkedit64->filesize -= + old_align_delta; object->seg_linkedit64->filesize -= object->code_sig_cmd->datasize; + object->seg_linkedit64->filesize += + align_delta; + object->seg_linkedit64->filesize += + arch_signs[i].datasize; if(object->seg_linkedit64->filesize > object->seg_linkedit64->vmsize) object->seg_linkedit64->vmsize = @@ -591,9 +748,8 @@ struct object *object) object->output_code_sig_data_size = arch_signs[i].datasize; object->output_code_sig_data = NULL; - object->output_sym_info_size = rnd(object->output_sym_info_size, - 16); - object->output_sym_info_size += object->code_sig_cmd->datasize; + object->output_sym_info_size += align_delta + + object->code_sig_cmd->datasize; } /* * The object does not have a code signature load command we add one. @@ -610,8 +766,8 @@ struct object *object) linkedit_end = object->seg_linkedit->fileoff + object->seg_linkedit->filesize; else if(object->seg_linkedit64 != NULL) - linkedit_end = object->seg_linkedit64->fileoff + - object->seg_linkedit64->filesize; + linkedit_end = (uint32_t)(object->seg_linkedit64->fileoff + + object->seg_linkedit64->filesize); else if(object->mh_filetype == MH_OBJECT) linkedit_end = object->object_size; else @@ -620,10 +776,25 @@ struct object *object) SEG_LINKEDIT " segment", arch->file_name, arch_signs[i].arch_flag.name); - object->code_sig_cmd->dataoff = rnd(linkedit_end, 16); + /* + * If we have a string table and we are padding it so the code + * signature is page aligned determine the string table padding and + * adjust the string table size. If not just pad to the older 16 + * byte alignment. + */ + if(object->st != NULL && pflag) { + object->code_sig_cmd->dataoff = rnd32(linkedit_end, + get_segalign_from_flag(&arch_signs[i].arch_flag)); + object->output_strings_size_pad = + object->code_sig_cmd->dataoff - linkedit_end; + object->st->strsize += object->output_strings_size_pad; + } + else { + object->code_sig_cmd->dataoff = rnd32(linkedit_end, 16); + } + align_delta = object->code_sig_cmd->dataoff - linkedit_end; object->output_code_sig_data_size = arch_signs[i].datasize; object->output_code_sig_data = NULL; - align_delta = object->code_sig_cmd->dataoff - linkedit_end; object->output_sym_info_size = align_delta + object->output_sym_info_size; @@ -636,7 +807,7 @@ struct object *object) if(object->seg_linkedit->filesize > object->seg_linkedit->vmsize) object->seg_linkedit->vmsize = - rnd(object->seg_linkedit->filesize, + rnd32(object->seg_linkedit->filesize, get_segalign_from_flag(&arch_signs[i].arch_flag)); } else if(object->seg_linkedit64 != NULL){ @@ -691,7 +862,10 @@ struct object *object) * The size of the new load commands that includes the added code * signature load command is larger than the existing load commands, so * see if they can be fitted in before the contents of the first section - * (or segment in the case of a LINKEDIT segment only file). + * (or segment in the case of a LINKEDIT segment only file, in that case + * the fileoff is non-zero, as with MH_KEXTBUNDLE it may have a __TEXT + * segment with no sections just mapping the headers as those sections + * would be in the __TEXT_EXEC segment). */ low_fileoff = UINT_MAX; lc = object->load_commands; @@ -708,11 +882,12 @@ struct object *object) S_THREAD_LOCAL_ZEROFILL && s->offset < low_fileoff) low_fileoff = s->offset; - s++; + s++; } } else{ - if(sg->filesize != 0 && sg->fileoff < low_fileoff) + if(sg->fileoff != 0 && sg->filesize != 0 && + sg->fileoff < low_fileoff) low_fileoff = sg->fileoff; } } @@ -732,8 +907,9 @@ struct object *object) } } else{ - if(sg64->filesize != 0 && sg64->fileoff < low_fileoff) - low_fileoff = sg64->fileoff; + if(sg64->fileoff != 0 && sg64->filesize != 0 && + sg64->fileoff < low_fileoff) + low_fileoff = (uint32_t)sg64->fileoff; } } lc = (struct load_command *)((char *)lc + lc->cmdsize); @@ -776,3 +952,136 @@ struct object *object) } return(code_sig); } + +/* + * strip_LC_CODE_SIGNATURE_commands() is called when -r is specified to remove + * any LC_CODE_SIGNATURE load commands from the object's load commands. + */ +static +void +strip_LC_CODE_SIGNATURE_commands( +struct arch *arch, +struct member *member, +struct object *object) +{ + uint32_t i, ncmds, mh_sizeofcmds, sizeofcmds; + struct load_command *lc1, *lc2, *new_load_commands; + struct segment_command *sg; + + /* + * See if there is an LC_CODE_SIGNATURE load command and if no command + * just return. + */ + if(object->code_sig_cmd == NULL) + return; + + /* + * Allocate space for the new load commands and zero it out so any holes + * will be zero bytes. + */ + if(arch->object->mh != NULL){ + ncmds = arch->object->mh->ncmds; + mh_sizeofcmds = arch->object->mh->sizeofcmds; + } + else{ + ncmds = arch->object->mh64->ncmds; + mh_sizeofcmds = arch->object->mh64->sizeofcmds; + } + new_load_commands = allocate(mh_sizeofcmds); + memset(new_load_commands, '\0', mh_sizeofcmds); + + /* + * Copy all the load commands except the LC_CODE_SIGNATURE load commands + * into the allocated space for the new load commands. + */ + lc1 = arch->object->load_commands; + lc2 = new_load_commands; + sizeofcmds = 0; + for(i = 0; i < ncmds; i++){ + if(lc1->cmd != LC_CODE_SIGNATURE){ + memcpy(lc2, lc1, lc1->cmdsize); + sizeofcmds += lc2->cmdsize; + lc2 = (struct load_command *)((char *)lc2 + lc2->cmdsize); + } + lc1 = (struct load_command *)((char *)lc1 + lc1->cmdsize); + } + + /* + * Finally copy the updated load commands over the existing load + * commands. + */ + memcpy(arch->object->load_commands, new_load_commands, sizeofcmds); + if(mh_sizeofcmds > sizeofcmds){ + memset((char *)arch->object->load_commands + sizeofcmds, '\0', + (mh_sizeofcmds - sizeofcmds)); + } + ncmds -= 1; + if(arch->object->mh != NULL) { + arch->object->mh->sizeofcmds = sizeofcmds; + arch->object->mh->ncmds = ncmds; + } else { + arch->object->mh64->sizeofcmds = sizeofcmds; + arch->object->mh64->ncmds = ncmds; + } + free(new_load_commands); + + /* + * reset the pointers into the load commands + * + * Recall that the LC_CODE_SIGNATURE load command can be anywhere in + * the load command array. We've just removed LC_CODE_SIGNATURE and + * compacted the array, and if any of the following load commands + * followed the code signature cmd their pointers are invalid. + */ + object->code_sig_cmd = NULL; + lc1 = arch->object->load_commands; + for(i = 0; i < ncmds; i++){ + switch(lc1->cmd){ + case LC_SYMTAB: + arch->object->st = (struct symtab_command *)lc1; + break; + case LC_DYSYMTAB: + arch->object->dyst = (struct dysymtab_command *)lc1; + break; + case LC_TWOLEVEL_HINTS: + arch->object->hints_cmd = (struct twolevel_hints_command *)lc1; + break; + case LC_PREBIND_CKSUM: + arch->object->cs = (struct prebind_cksum_command *)lc1; + break; + case LC_SEGMENT: + sg = (struct segment_command *)lc1; + if(strcmp(sg->segname, SEG_LINKEDIT) == 0) + arch->object->seg_linkedit = sg; + break; + case LC_SEGMENT_SPLIT_INFO: + object->split_info_cmd = (struct linkedit_data_command *)lc1; + break; + case LC_FUNCTION_STARTS: + object->func_starts_info_cmd = + (struct linkedit_data_command *)lc1; + break; + case LC_DATA_IN_CODE: + object->data_in_code_cmd = + (struct linkedit_data_command *)lc1; + break; + case LC_DYLIB_CODE_SIGN_DRS: + object->code_sign_drs_cmd = + (struct linkedit_data_command *)lc1; + break; + case LC_LINKER_OPTIMIZATION_HINT: + object->link_opt_hint_cmd = + (struct linkedit_data_command *)lc1; + break; + case LC_DYLD_EXPORTS_TRIE: + object->dyld_exports_trie = + (struct linkedit_data_command *)lc1; + break; + case LC_DYLD_CHAINED_FIXUPS: + object->dyld_chained_fixups = + (struct linkedit_data_command *)lc1; + break; + } + lc1 = (struct load_command *)((char *)lc1 + lc1->cmdsize); + } +} diff --git a/cctools/misc/ctf_insert.c b/cctools/misc/ctf_insert.c index a6bc3bb..c0de184 100644 --- a/cctools/misc/ctf_insert.c +++ b/cctools/misc/ctf_insert.c @@ -145,7 +145,7 @@ char **envp) } arch_ctfs[narch_ctfs].filename = argv[i+2]; arch_ctfs[narch_ctfs].contents = contents; - arch_ctfs[narch_ctfs].size = stat_buf.st_size; + arch_ctfs[narch_ctfs].size = (uint32_t)stat_buf.st_size; arch_ctfs[narch_ctfs].arch_found = FALSE; narch_ctfs++; i += 2; @@ -178,7 +178,7 @@ char **envp) arch_ctfs[i].arch_flag.name, arch_ctfs[i].filename); } - writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, NULL); + writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, FALSE, NULL); if(errors) return(EXIT_FAILURE); @@ -247,7 +247,7 @@ struct object *object) cputype = object->mh64->cputype; cpusubtype = object->mh64->cpusubtype & ~CPU_SUBTYPE_MASK; flags = object->mh64->flags; - offset = object->seg_linkedit64->fileoff; + offset = (uint32_t)object->seg_linkedit64->fileoff; addr = object->seg_linkedit64->vmaddr; } @@ -414,11 +414,11 @@ struct object *object) * rounded to the load command size for this arch. */ if(object->mh != NULL){ - move_size = rnd(arch_ctfs[i].size, sizeof(uint32_t)); + move_size = rnd32(arch_ctfs[i].size, sizeof(uint32_t)); object->seg_linkedit->fileoff += move_size; } else{ - move_size = rnd(arch_ctfs[i].size, sizeof(uint64_t)); + move_size = rnd32(arch_ctfs[i].size, sizeof(uint64_t)); object->seg_linkedit64->fileoff += move_size; } if(object->st != NULL && object->st->nsyms != 0){ @@ -545,7 +545,7 @@ uint32_t size) } else{ if(sg64->filesize != 0 && sg64->fileoff < low_fileoff) - low_fileoff = sg64->fileoff; + low_fileoff = (uint32_t)sg64->fileoff; } } lc = (struct load_command *)((char *)lc + lc->cmdsize); @@ -571,7 +571,7 @@ printf("space available = %d\n", low_fileoff - (sizeofcmds + mach_header_size)); sg_CTF->cmdsize = sizeof(struct segment_command) + sizeof(struct section); strcpy(sg_CTF->segname, "__CTF"); - sg_CTF->vmaddr = addr; + sg_CTF->vmaddr = (uint32_t)addr; sg_CTF->vmsize = 0; sg_CTF->fileoff = offset; sg_CTF->filesize = size; @@ -584,7 +584,7 @@ printf("space available = %d\n", low_fileoff - (sizeofcmds + mach_header_size)); memset(s_ctf, '\0', sizeof(struct section)); strcpy(s_ctf->sectname, "__ctf"); strcpy(s_ctf->segname, "__CTF"); - s_ctf->addr = addr; + s_ctf->addr = (uint32_t)addr; s_ctf->size = size; s_ctf->offset = offset; s_ctf->align = 0; diff --git a/cctools/misc/indr.c b/cctools/misc/indr.c index a363b39..745dac1 100644 --- a/cctools/misc/indr.c +++ b/cctools/misc/indr.c @@ -352,7 +352,7 @@ char *envp[]) if(stat(input_file, &stat_buf) == -1) system_error("can't stat input file: %s", input_file); writeout(archs, narchs, output_file, stat_buf.st_mode & 0777, TRUE, - FALSE, FALSE, NULL); + FALSE, FALSE, FALSE, NULL); if(errors) return(EXIT_FAILURE); @@ -389,7 +389,8 @@ enum bool nflag) { FILE *list; char buf[BUFSIZ], *symbol_name, *_symbol_name, *membername; - int32_t i, len, symbol_number; + int32_t i, symbol_number; + size_t len; struct indr_object *io; /* @@ -482,6 +483,10 @@ enum bool nflag) cputype = archs[i].object->mh_cputype; cpusubtype = archs[i].object->mh_cpusubtype; } + else if(archs[i].fat_arch64 != NULL){ + cputype = archs[i].fat_arch64->cputype; + cpusubtype = archs[i].fat_arch64->cpusubtype; + } else if(archs[i].fat_arch != NULL){ cputype = archs[i].fat_arch->cputype; cpusubtype = archs[i].fat_arch->cpusubtype; @@ -544,7 +549,7 @@ enum bool nflag) archs[i].members[j].offset = offset; size = 0; if(archs[i].members[j].member_long_name == TRUE){ - size = rnd(archs[i].members[j].member_name_size, + size = rnd32(archs[i].members[j].member_name_size, sizeof(int32_t)); archs[i].toc_long_name = TRUE; } @@ -808,8 +813,9 @@ struct object *object) { enum byte_sex host_byte_sex; uint32_t i, inew_syms, inew_undefsyms, inew_mods, indr_iextdefsym; - uint32_t new_ext_strsize, len, offset; + uint32_t new_ext_strsize, offset; uint32_t *map; + size_t len; struct symbol *sp; char *p, *q; struct scattered_relocation_info *sreloc; @@ -1014,7 +1020,7 @@ struct object *object) * Second pass, create the new tables. */ new_symbols =(struct nlist *)allocate(new_nsyms * sizeof(struct nlist)); - new_strsize = rnd(new_strsize, sizeof(int32_t)); + new_strsize = rnd32(new_strsize, sizeof(int32_t)); new_strings = (char *)allocate(new_strsize); new_strings[new_strsize - 3] = '\0'; new_strings[new_strsize - 2] = '\0'; @@ -1042,7 +1048,8 @@ struct object *object) new_symbols[inew_syms] = symbols[i]; if(symbols[i].n_un.n_strx != 0){ strcpy(q, strings + symbols[i].n_un.n_strx); - new_symbols[inew_syms].n_un.n_strx = q - new_strings; + new_symbols[inew_syms].n_un.n_strx = + (uint32_t)(q - new_strings); q += strlen(q) + 1; } map[i] = inew_syms; @@ -1061,13 +1068,15 @@ struct object *object) strcpy(p, sp->indr); else strcpy(p, strings + symbols[i].n_un.n_strx); - new_symbols[inew_syms].n_un.n_strx = p - new_strings; + new_symbols[inew_syms].n_un.n_strx = + (uint32_t)(p - new_strings); p += strlen(p) + 1; } if((symbols[i].n_type & N_TYPE) == N_INDR){ if(symbols[i].n_value != 0){ strcpy(p, strings + symbols[i].n_value); - new_symbols[inew_syms].n_value = p - new_strings; + new_symbols[inew_syms].n_value = + (uint32_t)(p - new_strings); p += strlen(p) + 1; } } @@ -1078,7 +1087,7 @@ struct object *object) indr_iextdefsym = inew_syms; for(i = 0; i < indr_list.used; i++){ /* loop for new defined symbols*/ strcpy(p, indr_list.list[i]->indr); - new_symbols[inew_syms].n_un.n_strx = p - new_strings; + new_symbols[inew_syms].n_un.n_strx = (uint32_t)(p - new_strings); p += strlen(p) + 1; new_symbols[inew_syms].n_type = N_INDR | N_EXT; new_symbols[inew_syms].n_desc = 0; @@ -1086,7 +1095,7 @@ struct object *object) /* Note this name is used below for the undefined */ strcpy(p, indr_list.list[i]->undef); indr_list.list[i]->undef = p; - new_symbols[inew_syms].n_value = p - new_strings; + new_symbols[inew_syms].n_value = (uint32_t)(p - new_strings); p += strlen(p) + 1; inew_syms++; } @@ -1102,7 +1111,7 @@ struct object *object) if(indr_list.list[i]->existing_symbol == FALSE){ /* Note this name is used from above for the undefined */ undef_map[inew_undefsyms].symbol.n_un.n_strx = - indr_list.list[i]->undef - new_strings; + (uint32_t)(indr_list.list[i]->undef - new_strings); undef_map[inew_undefsyms].symbol.n_type = N_UNDF | N_EXT; undef_map[inew_undefsyms].symbol.n_desc = 0; undef_map[inew_undefsyms].symbol.n_sect = NO_SECT; @@ -1124,7 +1133,7 @@ struct object *object) else strcpy(p, strings + symbols[i].n_un.n_strx); undef_map[inew_undefsyms].symbol.n_un.n_strx = - p - new_strings; + (uint32_t)(p - new_strings); p += strlen(p) + 1; } undef_map[inew_undefsyms].old_symbol = TRUE; @@ -1158,14 +1167,14 @@ struct object *object) for(i = 0; i < nmodtab; i++){ new_mods[inew_mods] = mods[i]; strcpy(p, strings + mods[i].module_name); - new_mods[inew_mods].module_name = p - new_strings; + new_mods[inew_mods].module_name = (uint32_t)(p - new_strings); p += strlen(p) + 1; inew_mods++; } for(i = 0; i < indr_list.used; i++){ memset(new_mods + inew_mods, '\0', sizeof(struct dylib_module)); strcpy(p, indr_list.list[i]->membername); - new_mods[inew_mods].module_name = p - new_strings; + new_mods[inew_mods].module_name = (uint32_t)(p - new_strings); p += strlen(p) + 1; new_mods[inew_mods].iextdefsym = indr_iextdefsym + i; new_mods[inew_mods].nextdefsym = 1; @@ -1323,11 +1332,11 @@ struct object *object) if(object->code_sig_cmd != NULL){ object->input_sym_info_size = - rnd(object->input_sym_info_size, 16); + rnd32(object->input_sym_info_size, 16); object->input_sym_info_size += object->code_sig_cmd->datasize; object->output_sym_info_size = - rnd(object->output_sym_info_size, 16); + rnd32(object->output_sym_info_size, 16); object->output_sym_info_size += object->code_sig_cmd->datasize; } @@ -1483,7 +1492,7 @@ struct object *object) offset += object->st->strsize; } if(object->code_sig_cmd != NULL){ - offset = rnd(offset, 16); + offset = rnd32(offset, 16); object->code_sig_cmd->dataoff = offset; offset += object->code_sig_cmd->datasize; } @@ -1578,7 +1587,7 @@ struct arch *arch) * Now loop through the indr list creating the objects for each indirect * symbol to be added to this archive. */ - indr_time = time(0); + indr_time = (uint32_t)time(0); oumask = umask(0); indr_mode = S_IFREG | (0666 & ~oumask); (void)umask(oumask); @@ -1790,7 +1799,8 @@ int32_t add_to_string_table( char *p) { - int32_t len, index; + size_t len; + uint32_t index; len = strlen(p) + 1; if(string_table.size < string_table.index + len){ @@ -1814,7 +1824,7 @@ end_string_table() { uint32_t length; - length = rnd(string_table.index, sizeof(uint32_t)); + length = rnd32(string_table.index, sizeof(uint32_t)); memset(string_table.strings + string_table.index, '\0', length - string_table.index); string_table.index = length; diff --git a/cctools/misc/inout.c b/cctools/misc/inout.c index 7c5465c..bdb74a4 100644 --- a/cctools/misc/inout.c +++ b/cctools/misc/inout.c @@ -89,7 +89,7 @@ char **envp) process(archs, narchs); - writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, NULL); + writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, FALSE, NULL); if(errors) return(EXIT_FAILURE); diff --git a/cctools/misc/install_name_tool.c b/cctools/misc/install_name_tool.c index 70b4916..34d063d 100644 --- a/cctools/misc/install_name_tool.c +++ b/cctools/misc/install_name_tool.c @@ -30,6 +30,7 @@ #include "stuff/breakout.h" #include "stuff/rnd.h" #include "stuff/allocate.h" +#include "stuff/write64.h" /* used by error routines as the name of the program */ char *progname = NULL; @@ -46,9 +47,6 @@ static void write_on_input( uint32_t narchs, char *input); -static void setup_object_symbolic_info( - struct object *object); - static void update_load_commands( struct arch *arch, uint32_t *header_size); @@ -95,13 +93,6 @@ static uint32_t ndelete_rpaths = 0; */ static uint32_t *arch_header_sizes = NULL; -/* - * The -o output option is not enabled as it is not needed and has the - * unintended side effect of changing the time stamps in LC_ID_DYLIB commands - * which is not the desired functionality of this command. - */ -#undef OUTPUT_OPTION - /* apple_version is created by the libstuff/Makefile */ extern char apple_version[]; char *version = apple_version; @@ -147,21 +138,6 @@ char **envp) archs = NULL; narchs = 0; for(i = 1; i < argc; i++){ -#ifdef OUTPUT_OPTION - if(strcmp(argv[i], "-o") == 0){ - if(i + 1 == argc){ - error("missing argument to: %s option", argv[i]); - usage(); - } - if(output != NULL){ - error("more than one: %s option specified", argv[i]); - usage(); - } - output = argv[i+1]; - i++; - } - else -#endif /* OUTPUT_OPTION */ if(strcmp(argv[i], "-id") == 0){ if(i + 1 == argc){ error("missing argument to: %s option", argv[i]); @@ -337,7 +313,8 @@ char **envp) exit(EXIT_FAILURE); if(output != NULL) - writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, NULL); + writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, FALSE, + NULL); else write_on_input(archs, narchs, input); @@ -358,9 +335,6 @@ void) fprintf(stderr, "Usage: %s [-change old new] ... [-rpath old new] ... " "[-add_rpath new] ... [-delete_rpath old] ... " "[-id name] input" -#ifdef OUTPUT_OPTION - " [-o output]" -#endif /* OUTPUT_OPTION */ "\n", progname); exit(EXIT_FAILURE); } @@ -380,7 +354,6 @@ uint32_t narchs) if(object->mh_filetype == MH_DYLIB_STUB) fatal("input file: %s is Mach-O dynamic shared library stub" " file and can't be changed", archs[i].file_name); - setup_object_symbolic_info(object); update_load_commands(archs + i, arch_header_sizes + i); } else{ @@ -402,7 +375,8 @@ uint32_t narchs, char *input) { int fd; - uint32_t i, offset, size, headers_size; + uint32_t i, size, headers_size; + off_t offset; char *headers; struct mach_header *mh; struct mach_header_64 *mh64; @@ -416,12 +390,14 @@ char *input) system_error("can't open input file: %s for writing", input); for(i = 0; i < narchs; i++){ - if(archs[i].fat_arch != NULL) + if(archs[i].fat_arch64 != NULL) + offset = archs[i].fat_arch64->offset; + else if(archs[i].fat_arch != NULL) offset = archs[i].fat_arch->offset; else offset = 0; if(lseek(fd, offset, SEEK_SET) == -1) - system_error("can't lseek to offset: %u in file: %s for " + system_error("can't lseek to offset: %lld in file: %s for " "writing", offset, input); /* * Since the new headers may be smaller than the old headers and @@ -466,7 +442,7 @@ char *input) fatal("internal error: swap_object_headers() failed"); } - if(write(fd, headers, size) != (int)size) + if(write64(fd, headers, size) != (ssize_t)size) system_error("can't write new headers in file: %s", input); free(headers); @@ -475,165 +451,6 @@ char *input) system_error("can't close written on input file: %s", input); } -static -void -setup_object_symbolic_info( -struct object *object) -{ -#ifdef OUTPUT_OPTION - if(object->st != NULL && object->st->nsyms != 0){ - object->output_symbols = (struct nlist *) - (object->object_addr + object->st->symoff); - if(object->object_byte_sex != get_host_byte_sex()) - swap_nlist(object->output_symbols, - object->st->nsyms, - get_host_byte_sex()); - object->output_nsymbols = object->st->nsyms; - object->output_strings = - object->object_addr + object->st->stroff; - object->output_strings_size = object->st->strsize; - object->input_sym_info_size = - object->st->nsyms * sizeof(struct nlist) + - object->st->strsize; - object->output_sym_info_size = - object->input_sym_info_size; - } - if(object->dyst != NULL){ - object->output_ilocalsym = object->dyst->ilocalsym; - object->output_nlocalsym = object->dyst->nlocalsym; - object->output_iextdefsym = object->dyst->iextdefsym; - object->output_nextdefsym = object->dyst->nextdefsym; - object->output_iundefsym = object->dyst->iundefsym; - object->output_nundefsym = object->dyst->nundefsym; - - object->output_loc_relocs = (struct relocation_info *) - (object->object_addr + object->dyst->locreloff); - object->output_ext_relocs = (struct relocation_info *) - (object->object_addr + object->dyst->extreloff); - object->output_indirect_symtab = (uint32_t *) - (object->object_addr + object->dyst->indirectsymoff); - object->output_tocs = - (struct dylib_table_of_contents *) - (object->object_addr + object->dyst->tocoff); - object->output_ntoc = object->dyst->ntoc; - object->output_mods = (struct dylib_module *) - (object->object_addr + object->dyst->modtaboff); - object->output_nmodtab = object->dyst->nmodtab; - object->output_refs = (struct dylib_reference *) - (object->object_addr + object->dyst->extrefsymoff); - object->output_nextrefsyms = object->dyst->nextrefsyms; - if(object->dyld_info != NULL){ - object->input_sym_info_size += object->dyld_info->rebase_size - + object->dyld_info->bind_size - + object->dyld_info->weak_bind_size - + object->dyld_info->lazy_bind_size - + object->dyld_info->export_size; - } - object->input_sym_info_size += - object->dyst->nlocrel * - sizeof(struct relocation_info) + - object->dyst->nextrel * - sizeof(struct relocation_info) + - object->dyst->nindirectsyms * - sizeof(uint32_t) + - object->dyst->ntoc * - sizeof(struct dylib_table_of_contents)+ - object->dyst->nmodtab * - sizeof(struct dylib_module) + - object->dyst->nextrefsyms * - sizeof(struct dylib_reference); - object->output_sym_info_size += - object->dyst->nlocrel * - sizeof(struct relocation_info) + - object->dyst->nextrel * - sizeof(struct relocation_info) + - object->dyst->nindirectsyms * - sizeof(uint32_t) + - object->dyst->ntoc * - sizeof(struct dylib_table_of_contents)+ - object->dyst->nmodtab * - sizeof(struct dylib_module) + - object->dyst->nextrefsyms * - sizeof(struct dylib_reference); - if(object->split_info_cmd != NULL){ - object->output_split_info_data = - (object->object_addr + object->split_info_cmd->dataoff); - object->output_split_info_data_size = - object->split_info_cmd->datasize; - object->input_sym_info_size += - object->split_info_cmd->datasize; - object->output_sym_info_size += - object->split_info_cmd->datasize; - } - if(object->func_starts_info_cmd != NULL){ - object->output_func_start_info_data = - (object->object_addr + object->func_starts_info_cmd->dataoff); - object->output_func_start_info_data_size = - object->func_starts_info_cmd->datasize; - object->input_sym_info_size += - object->func_starts_info_cmd->datasize; - object->output_sym_info_size += - object->func_starts_info_cmd->datasize; - } - if(object->data_in_code_cmd != NULL){ - object->output_data_in_code_info_data = - (object->object_addr + object->data_in_code_cmd->dataoff); - object->output_data_in_code_info_data_size = - object->data_in_code_cmd->datasize; - object->input_sym_info_size += - object->data_in_code_cmd->datasize; - object->output_sym_info_size += - object->data_in_code_cmd->datasize; - } - if(object->code_sign_drs_cmd != NULL){ - object->output_code_sign_drs_info_data = - (object->object_addr + object->code_sign_drs_cmd->dataoff); - object->output_code_sign_drs_info_data_size = - object->code_sign_drs_cmd->datasize; - object->input_sym_info_size += - object->code_sign_drs_cmd->datasize; - object->output_sym_info_size += - object->code_sign_drs_cmd->datasize; - } - if(object->link_opt_hint_cmd != NULL){ - object->output_link_opt_hint_info_data = - (object->object_addr + object->link_opt_hint_cmd->dataoff); - object->output_link_opt_hint_info_data_size = - object->link_opt_hint_cmd->datasize; - object->input_sym_info_size += - object->link_opt_hint_cmd->datasize; - object->output_sym_info_size += - object->link_opt_hint_cmd->datasize; - } - if(object->hints_cmd != NULL){ - object->output_hints = (struct twolevel_hint *) - (object->object_addr + - object->hints_cmd->offset); - object->input_sym_info_size += - object->hints_cmd->nhints * - sizeof(struct twolevel_hint); - object->output_sym_info_size += - object->hints_cmd->nhints * - sizeof(struct twolevel_hint); - } - if(object->code_sig_cmd != NULL){ - object->output_code_sig_data = object->object_addr + - object->code_sig_cmd->dataoff; - object->output_code_sig_data_size = - object->code_sig_cmd->datasize; - object->input_sym_info_size = - rnd(object->input_sym_info_size, 16); - object->input_sym_info_size += - object->code_sig_cmd->datasize; - object->output_sym_info_size = - rnd(object->output_sym_info_size, 16); - object->output_sym_info_size += - object->code_sig_cmd->datasize; - } - } -#endif /* OUTPUT_OPTION */ -} - /* * update_load_commands() changes the install names the LC_LOAD_DYLIB, * LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_LOAD_UPWARD_DYLIB and @@ -699,7 +516,7 @@ uint32_t *header_size) dylib_name1 = (char *)dl_id1 + dl_id1->dylib.name.offset; if(id != NULL){ new_size = sizeof(struct dylib_command) + - rnd(strlen(id) + 1, cmd_round); + rnd32((uint32_t)strlen(id) + 1, cmd_round); new_sizeofcmds += (new_size - dl_id1->cmdsize); } break; @@ -714,7 +531,7 @@ uint32_t *header_size) for(j = 0; j < nchanges; j++){ if(strcmp(changes[j].old, dylib_name1) == 0){ new_size = sizeof(struct dylib_command) + - rnd(strlen(changes[j].new) + 1, + rnd32((int)strlen(changes[j].new) + 1, cmd_round); new_sizeofcmds += (new_size - dl_load1->cmdsize); break; @@ -729,9 +546,9 @@ uint32_t *header_size) if(strcmp(changes[j].old, dylib_name1) == 0){ linked_modules_size = pbdylib1->cmdsize - ( sizeof(struct prebound_dylib_command) + - rnd(strlen(dylib_name1) + 1, cmd_round)); + rnd32((int)strlen(dylib_name1) + 1, cmd_round)); new_size = sizeof(struct prebound_dylib_command) + - rnd(strlen(changes[j].new) + 1, + rnd32((int)strlen(changes[j].new) + 1, cmd_round) + linked_modules_size; new_sizeofcmds += (new_size - pbdylib1->cmdsize); @@ -798,8 +615,8 @@ uint32_t *header_size) if(rpaths[j].found == TRUE) break; rpaths[j].found = TRUE; - new_size = rnd(sizeof(struct rpath_command) + - strlen(rpaths[j].new) + 1, + new_size = rnd32(sizeof(struct rpath_command) + + (int)strlen(rpaths[j].new) + 1, cmd_round); new_sizeofcmds += (new_size - rpath1->cmdsize); break; @@ -839,8 +656,8 @@ uint32_t *header_size) } for(i = 0; i < nadd_rpaths; i++){ - new_size = rnd(sizeof(struct rpath_command) + - strlen(add_rpaths[i].new) + 1, cmd_round); + new_size = rnd32(sizeof(struct rpath_command) + + (int)strlen(add_rpaths[i].new) + 1, cmd_round); new_sizeofcmds += new_size; } @@ -875,7 +692,7 @@ uint32_t *header_size) memcpy(lc2, lc1, sizeof(struct dylib_command)); dl_id2 = (struct dylib_command *)lc2; dl_id2->cmdsize = sizeof(struct dylib_command) + - rnd(strlen(id) + 1, cmd_round); + rnd32((int)strlen(id) + 1, cmd_round); dl_id2->dylib.name.offset = sizeof(struct dylib_command); dylib_name2 = (char *)dl_id2 + dl_id2->dylib.name.offset; strcpy(dylib_name2, id); @@ -897,7 +714,7 @@ uint32_t *header_size) memcpy(lc2, lc1, sizeof(struct dylib_command)); dl_load2 = (struct dylib_command *)lc2; dl_load2->cmdsize = sizeof(struct dylib_command) + - rnd(strlen(changes[j].new) + 1, + rnd32((int)strlen(changes[j].new)+1, cmd_round); dl_load2->dylib.name.offset = sizeof(struct dylib_command); @@ -921,10 +738,10 @@ uint32_t *header_size) pbdylib2 = (struct prebound_dylib_command *)lc2; linked_modules_size = pbdylib1->cmdsize - ( sizeof(struct prebound_dylib_command) + - rnd(strlen(dylib_name1) + 1, cmd_round)); + rnd32((int)strlen(dylib_name1) + 1, cmd_round)); pbdylib2->cmdsize = sizeof(struct prebound_dylib_command) + - rnd(strlen(changes[j].new) + 1, cmd_round) + + rnd32((int)strlen(changes[j].new) + 1, cmd_round) + linked_modules_size; pbdylib2->name.offset = @@ -935,7 +752,7 @@ uint32_t *header_size) pbdylib2->linked_modules.offset = sizeof(struct prebound_dylib_command) + - rnd(strlen(changes[j].new) + 1, cmd_round); + rnd32((int)strlen(changes[j].new) + 1, cmd_round); linked_modules1 = (char *)pbdylib1 + pbdylib1->linked_modules.offset; linked_modules2 = (char *)pbdylib2 + @@ -973,8 +790,8 @@ uint32_t *header_size) rpaths[j].found = TRUE; memcpy(lc2, lc1, sizeof(struct rpath_command)); rpath2 = (struct rpath_command *)lc2; - rpath2->cmdsize = rnd(sizeof(struct rpath_command) + - strlen(rpaths[j].new) + 1, + rpath2->cmdsize = rnd32(sizeof(struct rpath_command) + + (int)strlen(rpaths[j].new) + 1, cmd_round); rpath2->path.offset = sizeof(struct rpath_command); path2 = (char *)rpath2 + rpath2->path.offset; @@ -1001,8 +818,8 @@ uint32_t *header_size) for(i = 0; i < nadd_rpaths; i++){ rpath2 = (struct rpath_command *)lc2; rpath2->cmd = LC_RPATH; - rpath2->cmdsize = rnd(sizeof(struct rpath_command) + - strlen(add_rpaths[i].new) + 1, + rpath2->cmdsize = rnd32(sizeof(struct rpath_command) + + (int)strlen(add_rpaths[i].new) + 1, cmd_round); rpath2->path.offset = sizeof(struct rpath_command); path2 = (char *)rpath2 + rpath2->path.offset; @@ -1095,6 +912,14 @@ uint32_t *header_size) arch->object->link_opt_hint_cmd = (struct linkedit_data_command *)lc1; break; + case LC_DYLD_CHAINED_FIXUPS: + arch->object->dyld_chained_fixups = + (struct linkedit_data_command *)lc1; + break; + case LC_DYLD_EXPORTS_TRIE: + arch->object->dyld_exports_trie = + (struct linkedit_data_command *)lc1; + break; } lc1 = (struct load_command *)((char *)lc1 + lc1->cmdsize); } diff --git a/cctools/misc/libtool.c b/cctools/misc/libtool.c index 5238a50..24436ba 100644 --- a/cctools/misc/libtool.c +++ b/cctools/misc/libtool.c @@ -29,6 +29,7 @@ #include "stuff/openstep_mach.h" #include #ifndef __OPENSTEP__ +#include #include #endif #include @@ -40,6 +41,9 @@ #include #include #include +#include /* cctools-port: gettimeofday() */ +#include +#include "stuff/args.h" #include "stuff/bool.h" #include "stuff/ofile.h" #include "stuff/rnd.h" @@ -48,6 +52,8 @@ #include "stuff/execute.h" #include "stuff/version_number.h" #include "stuff/unix_standard_mode.h" +#include "stuff/write64.h" +#include "stuff/port.h" /* cctools-port */ #ifdef LTO_SUPPORT #include "stuff/lto.h" #endif /* LTO_SUPPORT */ @@ -59,15 +65,13 @@ #include #endif -/* cctools-port */ -int asprintf(char **strp, const char *fmt, ...); /* * This is used internally to build the table of contents. */ struct toc { char *name; /* symbol defined by */ - int32_t index1; /* library member at this index plus 1 */ + int64_t index1; /* library member at this index plus 1 */ }; /* used by error routines as the name of the program */ @@ -77,10 +81,32 @@ char *progname = NULL; static enum byte_sex host_byte_sex = UNKNOWN_BYTE_SEX; /* - * The time the table of contents' are set to and the time to base the - * modification time of the output file to be set to. + * toc_time holds the time_t value the archive contents + * + * toc_timeval, and toc_timespec hold the time value the archive contents are + * set to, as well as the modification of the output file. Which value is used + * depends on the deployment operating system. For modern macOS systems (e.g.) + * nanosecond-precise toc_timespec will be used, whereas older macOS systems + * will use microsecond-precise toc_timeval; toc_time will be used for + * historical OS versions. + * + * toc_uid, toc_gid, and toc_mode similarly hold the the uid, gid, and file mode + * values for the archive contents. + * + * all of these values are initialized to reasonable defaults for deterministic + * archives: archives that are consistent regardless of user, time, or umask + * differences. Ordinarily, these values and will be set to more specific + * ones when building new archives, but that can be suppressed using the + * '-D' option or the ZERO_AR_DATE environment variable. */ static time_t toc_time = 0; +#ifndef __OPENSTEP__ +static struct timeval toc_timeval; +static struct timespec toc_timespec; +#endif /* !defined(__OPENSTEP__) */ +static uid_t toc_uid = 0; +static gid_t toc_gid = 0; +static u_short toc_mode = 0100644; /* * The environment variable ZERO_AR_DATE is used here and other places that @@ -89,11 +115,6 @@ static time_t toc_time = 0; */ static enum bool zero_ar_date = FALSE; -/* - * The mode of the table of contents member (S_IFREG | (0666 & ~umask)) - */ -static u_short toc_mode = 0; - /* flags set from the command line arguments */ struct cmd_flags { char **files; /* array of file name arguments */ @@ -109,6 +130,7 @@ struct cmd_flags { enum bool t; /* just "touch" the archives to get the date right */ enum bool f; /* warn if the output archive is fat,used by ar(1) -s */ enum bool q; /* only write archive if NOT fat, used by ar(1) */ + enum bool D; /* write deterministic archive files */ char *output; /* the output file specified by -o */ enum bool final_output_specified; /* if -final_output is specified */ enum bool dynamic; /* create a dynamic shared library, static by default */ @@ -141,9 +163,16 @@ struct cmd_flags { enum bool /* set with -L (the default) off with -T, for -static */ use_long_names; /* use 4.4bsd extended format 1 for long names */ enum bool L_or_T_specified; - enum bool /* set if the environ var LD_TRACE_ARCHIVES is set */ + enum bool /* set if the environ var LD_TRACE_ARCHIVES or */ + /* RC_TRACE_ARCHIVES is set */ ld_trace_archives; - const char * /* LD_TRACE_FILE if set and LD_TRACE_ARCHIVES is set, or NULL */ + enum bool /* set if the environ var LD_TRACE_DEPENDENTS is set. */ + /* Note that this value will take precedence over */ + /* ld_trace_archives. */ + ld_trace_dependents; + const char * /* LD_TRACE_FILE if set and one of LD_TRACE_ARCHIVES, */ + /* RC_TRACE_ARCHIVES, or LD_TRACE_DEPENDENTS is set, */ + /* or NULL. */ trace_file_path; enum bool /* set if -search_paths_first is specified */ search_paths_first; @@ -152,6 +181,9 @@ struct cmd_flags { uint32_t debug; /* debug value to debug output_flush() routine */ enum bool /* don't warn if members have no symbols */ no_warning_for_no_symbols; + enum bool toc64; /* force the use of the 64-bit toc */ + enum bool fat64; /* force the use of 64-bit fat files + when a fat is to be created */ }; static struct cmd_flags cmd_flags = { 0 }; @@ -186,10 +218,12 @@ struct arch { char *toc_name; /* name of toc member */ uint32_t toc_name_size;/* size of name of toc member */ struct toc *tocs; /* internal table of contents */ - struct ranlib *toc_ranlibs; /* ranlib structs for output */ - uint32_t toc_nranlibs;/* number of ranlib structs */ + enum bool using_64toc; /* TRUE if we are using a 64-bit toc */ + struct ranlib *toc_ranlibs; /* 32-bit ranlib structs for output */ + struct ranlib_64 *toc_ranlibs64; /* 64-bit ranlib structs for output */ + uint64_t toc_nranlibs;/* number of ranlib structs */ char *toc_strings; /* strings of symbol names for ranlib structs */ - uint32_t toc_strsize; /* number of bytes for the strings above */ + uint64_t toc_strsize; /* number of bytes for the strings above */ /* the members of this architecture in the library */ struct member *members; /* the members of the library for this arch */ @@ -231,6 +265,15 @@ struct member { uint64_t input_member_offset; /* if from a thin archive */ }; +/* + * trace_buffer points to a C string that will be written to the trace file, and + * trace_buflen records the current length of the trace data string, but without + * including the ASCII zero terminator. trace data will be written to the trace + * file only when processing concludes. + */ +static char* trace_buffer = NULL; +static int trace_buflen = 0; + static void usage( void); static void process( @@ -304,8 +347,10 @@ static void warn_member( struct arch *arch, struct member *member, const char *format, ...) __attribute__ ((format (printf, 3, 4))); -static void ld_trace( - const char *format, ...) __attribute__ ((format (printf, 1, 2))); +static void ld_trace_archive(const char* path); +static void ld_trace_close(void); +static void ld_trace_append( + const char *format, ...) __attribute__ ((format (printf, 1, 2))); /* * This structure is used to describe blocks of the output file that are flushed @@ -335,9 +380,9 @@ static void print_block_list(void); static struct block *get_block(void); static void remove_block( struct block *block); -static uint32_t trnc( - uint32_t v, - uint32_t r); +static uint64_t trnc64( + uint64_t v, + uint64_t r); /* apple_version is in vers.c which is created by the libstuff/Makefile */ extern char apple_version[]; @@ -354,33 +399,13 @@ char **envp) uint32_t j, nfiles, maxfiles; uint32_t temp; int oumask, numask; - enum bool lflags_seen, bad_flag_seen, Vflag; + enum bool bad_flag_seen, Vflag; - lflags_seen = FALSE; Vflag = FALSE; progname = argv[0]; host_byte_sex = get_host_byte_sex(); - /* - * The environment variable ZERO_AR_DATE is used here and other - * places that write archives to allow testing and comparing - * things for exact binary equality. - */ - if(getenv("ZERO_AR_DATE") == NULL) - zero_ar_date = FALSE; - else - zero_ar_date = TRUE; - if(zero_ar_date == FALSE) - toc_time = time(0); - else - toc_time = 0; - - numask = 0; - oumask = umask(numask); - toc_mode = S_IFREG | (0666 & ~oumask); - (void)umask(oumask); - /* see if this is being run as ranlib */ /* cctools-port start*/ #if 0 /* old code */ @@ -400,6 +425,11 @@ char **envp) /* The default is to used long names */ cmd_flags.use_long_names = TRUE; + /* expand @file references in the options list */ + if (FALSE == cmd_flags.ranlib) + if (args_expand_at(&argc, &argv)) + exit(EXIT_FAILURE); + /* process the command line arguments and collect the files */ maxfiles = argc; cmd_flags.files = allocate(sizeof(char *) * maxfiles); @@ -619,7 +649,7 @@ char **envp) error("more than one: %s option specified", argv[i]); usage(); } - temp = strtoul(argv[i + 1], &endp, 16); + temp = (uint32_t)strtoul(argv[i + 1], &endp, 16); if(*endp != '\0'){ error("address for -seg1addr %s not a proper " "hexadecimal number", argv[i+1]); @@ -641,7 +671,7 @@ char **envp) error("more than one: %s option specified", argv[i]); usage(); } - temp = strtoul(argv[i + 1], &endp, 16); + temp = (uint32_t)strtoul(argv[i + 1], &endp, 16); if(*endp != '\0'){ error("address for -segs_read_only_addr %s not a " "proper hexadecimal number", argv[i+1]); @@ -663,7 +693,7 @@ char **envp) error("more than one: %s option specified", argv[i]); usage(); } - temp = strtoul(argv[i + 1], &endp, 16); + temp = (uint32_t)strtoul(argv[i + 1], &endp, 16); if(*endp != '\0'){ error("address for -segs_read_write_addr %s not a " "proper hexadecimal number", argv[i+1]); @@ -917,7 +947,6 @@ char **envp) usage(); } cmd_flags.files[cmd_flags.nfiles++] = argv[i]; - lflags_seen = TRUE; } else if(strncmp(argv[i], "-weak-l", 7) == 0){ if(cmd_flags.ranlib == TRUE){ @@ -929,7 +958,6 @@ char **envp) usage(); } cmd_flags.files[cmd_flags.nfiles++] = argv[i]; - lflags_seen = TRUE; } else if(strcmp(argv[i], "-framework") == 0 || strcmp(argv[i], "-weak_framework") == 0 || @@ -944,7 +972,6 @@ char **envp) } cmd_flags.files[cmd_flags.nfiles++] = argv[i]; cmd_flags.files[cmd_flags.nfiles++] = argv[i+1]; - lflags_seen = TRUE; i += 1; } else if(strcmp(argv[i], "-T") == 0){ @@ -1006,6 +1033,12 @@ char **envp) else if(strcmp(argv[i], "-no_warning_for_no_symbols") == 0){ cmd_flags.no_warning_for_no_symbols = TRUE; } + else if(strcmp(argv[i], "-toc64") == 0){ + cmd_flags.toc64 = TRUE; + } + else if(strcmp(argv[i], "-fat64") == 0){ + cmd_flags.fat64 = TRUE; + } #ifdef DEBUG else if(strcmp(argv[i], "-debug") == 0){ if(i + 1 >= argc){ @@ -1076,6 +1109,9 @@ char **envp) argv[i][j], argv[i]); usage(); } + case 'D': + cmd_flags.D = TRUE; + break; default: error("unknown option character `%c' in: %s", argv[i][j], argv[i]); @@ -1087,14 +1123,37 @@ char **envp) else cmd_flags.files[cmd_flags.nfiles++] = argv[i]; } + /* - * Test to see if the environment variable LD_TRACE_ARCHIVES is set. + * Test to see if one of the following trace environment variables are + * set: + * + * LC_TRACE_DEPENDENTS + * RC_TRACE_ARCHIVES + * LC_TRACE_ARCHIVES + * + * If so, also get the LD_TRACE_FILE. */ - if((getenv("RC_TRACE_ARCHIVES") != NULL) || - (getenv("LD_TRACE_ARCHIVES") != NULL)) { - cmd_flags.ld_trace_archives = TRUE; - cmd_flags.trace_file_path = getenv("LD_TRACE_FILE"); - } + if (getenv("LD_TRACE_DEPENDENTS") != NULL) { + cmd_flags.ld_trace_dependents = TRUE; + cmd_flags.ld_trace_archives = TRUE; + cmd_flags.trace_file_path = getenv("LD_TRACE_FILE"); + } + else if ((getenv("RC_TRACE_ARCHIVES") != NULL) || + (getenv("LD_TRACE_ARCHIVES") != NULL)) { + cmd_flags.ld_trace_archives = TRUE; + cmd_flags.trace_file_path = getenv("LD_TRACE_FILE"); + } + + /* + * The environment variable ZERO_AR_DATE is used here and other + * places that write archives to allow testing and comparing + * things for exact binary equality. + */ + if(getenv("ZERO_AR_DATE") == NULL) + zero_ar_date = FALSE; + else + zero_ar_date = TRUE; /* * If either -syslibroot or the environment variable NEXT_ROOT is set @@ -1273,6 +1332,47 @@ char **envp) if(cmd_flags.a == FALSE) cmd_flags.s = TRUE; /* sort table of contents by default */ + /* remember common values used in the archive table of contents */ + if (cmd_flags.D == FALSE && zero_ar_date == FALSE) { +#ifndef __OPENSTEP__ + /* cctools-port: replaced __builtin_available */ +#if 0 + if (__builtin_available(macOS 10.12, *)) { +#endif /* 0*/ +#ifdef HAVE_CLOCK_GETTIME + if (clock_gettime(CLOCK_REALTIME, &toc_timespec)) { + system_fatal("clock_gettime failed"); + return(EXIT_FAILURE); + } + toc_time = toc_timespec.tv_sec; +#endif /* HAVE_CLOCK_GETTIME */ +#if 0 + } else { +#endif /* 0 */ +#ifndef HAVE_CLOCK_GETTIME + if (gettimeofday(&toc_timeval, NULL)) { + system_fatal("gettimeofday failed"); + return(EXIT_FAILURE); + } + toc_time = toc_timeval.tv_sec; +#endif /* !HAVE_CLOCK_GETTIME */ +#if 0 + } +#endif /* 0 */ +#else + toc_time = time(NULL); +#endif /* !defined(__OPENSTEP__) */ + } + if (cmd_flags.D == FALSE) { + toc_uid = getuid(); + toc_gid = getgid(); + + numask = 0; + oumask = umask(numask); + toc_mode = S_IFREG | (0666 & ~oumask); + (void)umask(oumask); + } + process(); if(errors == 0) @@ -1321,7 +1421,7 @@ void) struct ofile *ofiles; char *file_name; enum bool flag, ld_trace_archive_printed; - + /* * For libtool processing put all input files in the specified output * file. For ranlib processing all input files should be archives or @@ -1333,6 +1433,8 @@ void) for(i = 0; i < cmd_flags.nfiles; i++){ if(strncmp(cmd_flags.files[i], "-l", 2) == 0 || strncmp(cmd_flags.files[i], "-weak-l", 7) == 0){ + if(cmd_flags.dynamic == TRUE) + continue; file_name = file_name_from_l_flag(cmd_flags.files[i]); if(file_name != NULL) if(ofile_map(file_name, NULL, NULL, ofiles + i, TRUE) == @@ -1357,20 +1459,13 @@ void) if(ofiles[i].file_type == OFILE_FAT){ (void)ofile_first_arch(ofiles + i); - do{ - if(ofiles[i].arch_type == OFILE_ARCHIVE){ - if(cmd_flags.ld_trace_archives == TRUE && - cmd_flags.dynamic == FALSE && - ld_trace_archive_printed == FALSE){ - char resolvedname[MAXPATHLEN]; - if(realpath(ofiles[i].file_name, resolvedname) != - NULL) - ld_trace("[Logging for XBS] Used static " - "archive: %s\n", resolvedname); - else - ld_trace("[Logging for XBS] Used static " - "archive: %s\n", ofiles[i].file_name); - ld_trace_archive_printed = TRUE; + do{ + if(ofiles[i].arch_type == OFILE_ARCHIVE){ + if (cmd_flags.ld_trace_archives == TRUE && + cmd_flags.dynamic == FALSE && + ld_trace_archive_printed == FALSE){ + ld_trace_archive(ofiles[i].file_name); + ld_trace_archive_printed = TRUE; } /* loop through archive */ if((flag = ofile_first_member(ofiles + i)) == TRUE){ @@ -1430,18 +1525,13 @@ void) }while(ofile_next_arch(ofiles + i) == TRUE); } else if(ofiles[i].file_type == OFILE_ARCHIVE){ - if(cmd_flags.ld_trace_archives == TRUE && - cmd_flags.dynamic == FALSE && - ld_trace_archive_printed == FALSE){ - char resolvedname[MAXPATHLEN]; - if(realpath(ofiles[i].file_name, resolvedname) != NULL) - ld_trace("[Logging for XBS] Used static archive: " - "%s\n", resolvedname); - else - ld_trace("[Logging for XBS] Used static archive: " - "%s\n", ofiles[i].file_name); - ld_trace_archive_printed = TRUE; - } + if (cmd_flags.ld_trace_archives == TRUE && + cmd_flags.dynamic == FALSE && + ld_trace_archive_printed == FALSE){ + ld_trace_archive(ofiles[i].file_name); + ld_trace_archive_printed = + TRUE; + } /* loop through archive */ if((flag = ofile_first_member(ofiles + i)) == TRUE){ if(ofiles[i].member_ar_hdr != NULL && @@ -1520,7 +1610,7 @@ void) "library)", cmd_flags.files[i]); } } - + if(cmd_flags.ranlib == TRUE){ /* * In the case where ranlib is being used on an archive that @@ -1561,6 +1651,10 @@ ranlib_fat_error: if(cmd_flags.ranlib == FALSE && errors == 0) create_library(cmd_flags.output, NULL); + /* Finalize the trace log */ + if (cmd_flags.ld_trace_archives) + ld_trace_close(); + /* * Clean-up of ofiles[] and archs could be done here but since this * program is now done it is faster to just exit. @@ -1752,21 +1846,21 @@ struct ofile *ofile) * bytes are set to the character '\n'. */ if(ofile->mh != NULL || ofile->mh64 != NULL) - size = rnd(ofile->object_size, 8); + size = (uint32_t)rnd(ofile->object_size, 8); #ifdef LTO_SUPPORT else if(ofile->lto != NULL){ if(ofile->file_type == OFILE_LLVM_BITCODE) - size = rnd(ofile->file_size, 8); + size = (uint32_t)rnd(ofile->file_size, 8); else if(ofile->file_type == OFILE_FAT || (ofile->file_type == OFILE_ARCHIVE && ofile->member_type == OFILE_FAT)) - size = rnd(ofile->object_size, 8); + size = (uint32_t)rnd(ofile->object_size, 8); else - size = rnd(ofile->member_size, 8); + size = (uint32_t)rnd(ofile->member_size, 8); } #endif /* LTO_SUPPORT */ else - size = rnd(ofile->member_size, 8); + size = (uint32_t)rnd(ofile->member_size, 8); /* select or create an arch type to put this in */ i = 0; @@ -1819,6 +1913,7 @@ struct ofile *ofile) if(cmd_flags.arch_only_flag.cputype != ofile->mh_cputype) return; if(cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM || + cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM64_32 || cmd_flags.arch_only_flag.cputype == CPU_TYPE_X86_64){ if(cmd_flags.arch_only_flag.cpusubtype != ofile->mh_cpusubtype) @@ -1840,6 +1935,8 @@ struct ofile *ofile) for( ; i < narchs; i++){ if(archs[i].arch_flag.cputype == ofile->mh_cputype){ if((archs[i].arch_flag.cputype == CPU_TYPE_ARM || + archs[i].arch_flag.cputype == CPU_TYPE_ARM64 || + archs[i].arch_flag.cputype == CPU_TYPE_ARM64_32 || archs[i].arch_flag.cputype == CPU_TYPE_X86_64) && archs[i].arch_flag.cpusubtype != ofile->mh_cpusubtype) continue; @@ -1868,6 +1965,7 @@ struct ofile *ofile) if(cmd_flags.arch_only_flag.cputype != ofile->lto_cputype) return; if(cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM || + cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM64_32 || cmd_flags.arch_only_flag.cputype == CPU_TYPE_X86_64){ if(cmd_flags.arch_only_flag.cpusubtype != ofile->lto_cpusubtype) @@ -1889,6 +1987,8 @@ struct ofile *ofile) for( ; i < narchs; i++){ if(archs[i].arch_flag.cputype == ofile->lto_cputype){ if((archs[i].arch_flag.cputype == CPU_TYPE_ARM || + archs[i].arch_flag.cputype == CPU_TYPE_ARM64 || + archs[i].arch_flag.cputype == CPU_TYPE_ARM64_32 || archs[i].arch_flag.cputype == CPU_TYPE_X86_64) && archs[i].arch_flag.cpusubtype != ofile->lto_cpusubtype) continue; @@ -1917,6 +2017,7 @@ struct ofile *ofile) ofile->mh64 != NULL){ if(ofile->mh_cputype == CPU_TYPE_ARM || ofile->mh_cputype == CPU_TYPE_ARM64 || + ofile->mh_cputype == CPU_TYPE_ARM64_32 || ofile->mh_cputype == CPU_TYPE_X86_64){ archs[narchs].arch_flag.name = (char *) get_arch_name_from_types( @@ -1935,6 +2036,7 @@ struct ofile *ofile) else if(ofile->lto != NULL){ if(ofile->lto_cputype == CPU_TYPE_ARM || ofile->lto_cputype == CPU_TYPE_ARM64 || + ofile->lto_cputype == CPU_TYPE_ARM64_32 || ofile->lto_cputype == CPU_TYPE_X86_64){ archs[narchs].arch_flag.name = (char *) get_arch_name_from_types( @@ -2019,7 +2121,7 @@ struct ofile *ofile) else p = ofile->file_name; member->input_base_name = p; - member->input_base_name_size = strlen(p); + member->input_base_name_size = (uint32_t)strlen(p); member->member_name = member->input_base_name; /* * If we can use long names then force using them to allow 64-bit @@ -2035,9 +2137,9 @@ struct ofile *ofile) if(cmd_flags.use_long_names == TRUE){ member->output_long_name = TRUE; member->member_name_size = member->input_base_name_size; - ar_name_size = rnd(member->input_base_name_size, 8) + - (rnd(sizeof(struct ar_hdr), 8) - - sizeof(struct ar_hdr)); + ar_name_size = (uint32_t)(rnd(member->input_base_name_size, 8) + + (rnd(sizeof(struct ar_hdr), 8) - + sizeof(struct ar_hdr))); sprintf(ar_name_buf, "%s%-*lu", AR_EFMT1, (int)(sizeof(member->ar_hdr.ar_name) - (sizeof(AR_EFMT1) - 1)), @@ -2062,8 +2164,18 @@ struct ofile *ofile) p[sizeof(member->ar_hdr.ar_name)] = c; member->member_name_size = size_ar_name(&member->ar_hdr); } - if(zero_ar_date == TRUE) - stat_buf.st_mtime = 0; + /* + * adjust the time, mode, uid, and gid for the incoming archive + * member. + */ + if(cmd_flags.D == TRUE || zero_ar_date == TRUE) + stat_buf.st_mtime = toc_time; + if (cmd_flags.D == TRUE) { + stat_buf.st_mode = toc_mode; + stat_buf.st_uid = toc_uid; + stat_buf.st_gid = toc_gid; + } + /* * Create the rest of the archive header after the name. */ @@ -2123,9 +2235,9 @@ struct ofile *ofile) break; } member->member_name_size = ar_name_size; - ar_name_size = rnd(ar_name_size, 8) + - (rnd(sizeof(struct ar_hdr), 8) - - sizeof(struct ar_hdr)); + ar_name_size = (uint32_t)(rnd(ar_name_size, 8) + + (rnd(sizeof(struct ar_hdr), 8) - + sizeof(struct ar_hdr))); sprintf(ar_name_buf, "%s%-*lu", AR_EFMT1, (int)(sizeof(member->ar_hdr.ar_name) - (sizeof(AR_EFMT1) - 1)), @@ -2140,9 +2252,9 @@ struct ofile *ofile) * struct ar_hdr rounded to 8 bytes. */ member->member_name_size = size_ar_name(&member->ar_hdr); - ar_name_size = rnd(ofile->member_name_size, 8) + - (rnd(sizeof(struct ar_hdr), 8) - - sizeof(struct ar_hdr)); + ar_name_size = (uint32_t)(rnd(ofile->member_name_size, 8) + + (rnd(sizeof(struct ar_hdr), 8) - + sizeof(struct ar_hdr))); member->output_long_name = TRUE; sprintf(ar_name_buf, "%s%-*lu", AR_EFMT1, (int)(sizeof(member->ar_hdr.ar_name) - @@ -2198,7 +2310,7 @@ struct ofile *ofile) #ifdef LTO_SUPPORT else if(ofile->file_type == OFILE_LLVM_BITCODE){ member->object_addr = ofile->file_addr; - member->object_size = ofile->file_size; + member->object_size = (uint32_t)ofile->file_size; member->lto_contents = TRUE; save_lto_member_toc_info(member, ofile->lto); lto_free(ofile->lto); @@ -2255,6 +2367,8 @@ void) free(archs[i].tocs); if(archs[i].toc_ranlibs != NULL) free(archs[i].toc_ranlibs); + if(archs[i].toc_ranlibs64 != NULL) + free(archs[i].toc_ranlibs64); if(archs[i].toc_strings != NULL) free(archs[i].toc_strings); if(archs[i].members != NULL) @@ -2285,20 +2399,36 @@ struct ofile *ofile) uint32_t i, j, k, pad; uint64_t library_size, offset, *time_offsets; enum byte_sex target_byte_sex; - char *library, *p, *flush_start; kern_return_t r; struct arch *arch; struct fat_header *fat_header; struct fat_arch *fat_arch; + struct fat_arch_64 *fat_arch64; int fd; + /* cctools-port: commented. */ +/* #ifndef __OPENSTEP__ - struct utimbuf timep; + struct timeval timep[2]; #else time_t timep[2]; #endif +*/ + struct timespec times[2]; /* cctools-port */ struct stat stat_buf; struct ar_hdr toc_ar_hdr; enum bool some_tocs, same_toc, different_offsets; + uint32_t toc_mtime; + enum bool write_in_place; + const char* suffix = ".XXXXXX"; + char* tempfile; + size_t templen; + const char* libtool_force_fail; + const char* ranlib_force_fail; + int time_result; + + libtool_force_fail = getenv("LIBTOOL_FORCE_FAIL"); + ranlib_force_fail = getenv("RANLIB_FORCE_FAIL"); + different_offsets = FALSE; if(narchs == 0){ if(cmd_flags.ranlib == TRUE){ @@ -2336,8 +2466,11 @@ struct ofile *ofile) * architecture. */ if(narchs > 1){ - library_size = sizeof(struct fat_header) + - sizeof(struct fat_arch) * narchs; + library_size = sizeof(struct fat_header); + if(cmd_flags.fat64 == TRUE) + library_size += sizeof(struct fat_arch_64) * narchs; + else + library_size += sizeof(struct fat_arch) * narchs; /* * The ar(1) program uses the -q flag to ranlib(1) to add a table * of contents only of the output is not a fat file. This is done @@ -2396,24 +2529,36 @@ struct ofile *ofile) * the defined global symbols have not changed when rebuilding and it * will just be the offset to archive members that will have changed. */ + write_in_place = FALSE; if(cmd_flags.ranlib == TRUE && narchs == 1 && ofile != NULL && ofile->toc_addr != NULL && ofile->toc_bad == FALSE && + archs[0].using_64toc != ofile->toc_is_32bit && archs[0].toc_nranlibs == ofile->toc_nranlibs && archs[0].toc_strsize == ofile->toc_strsize){ + write_in_place = TRUE; + /* * If the table of contents in the input does have a long name and * the one we built does not (or vice a versa) then don't update it * in place. */ - if(strcmp(ofile->toc_ar_hdr->ar_name, AR_EFMT1) == 0){ - if(archs[0].toc_long_name != TRUE) - goto fail_to_update_toc_in_place; + if(strncmp(ofile->toc_ar_hdr->ar_name, AR_EFMT1, + sizeof(AR_EFMT1) - 1) == 0){ + /* + * Also if it has a long name and the sizes of the long name + * are not the same or the names are not the same don't update + * it in place. + */ + if(archs[0].toc_long_name != TRUE || + ofile->toc_name_size != archs[0].toc_name_size || + strcmp(ofile->toc_name, archs[0].toc_name) != 0) + write_in_place = FALSE; } else{ if(archs[0].toc_long_name == TRUE) - goto fail_to_update_toc_in_place; + write_in_place = FALSE; } /* @@ -2422,7 +2567,6 @@ struct ofile *ofile) * so object files are on their natural alignment. So check to * see if the offsets are not the same and if the alignment is OK. */ - different_offsets = FALSE; for(i = 0; i < archs[0].nmembers; i++){ if(archs[0].members[i].input_member_offset != archs[0].members[i].offset){ @@ -2432,10 +2576,18 @@ struct ofile *ofile) * though we would produce 8 byte alignments. */ if(archs[0].members[i].input_member_offset % 4 != 0){ - goto fail_to_update_toc_in_place; + write_in_place = FALSE; + break; } } } + } + + if (write_in_place == TRUE) { + char *library, *p; + + /* write in place, not into a temporary file. */ + tempfile = NULL; /* * The time_offsets array records the offsets to the table of @@ -2456,13 +2608,27 @@ struct ofile *ofile) */ if(different_offsets == TRUE){ same_toc = FALSE; - for(i = 0; i < archs[0].toc_nranlibs; i++){ - for(j = 0; j < archs[0].nmembers; j++){ - if(archs[0].members[j].offset == - archs[0].toc_ranlibs[i].ran_off){ - archs[0].toc_ranlibs[i].ran_off = - archs[0].members[j].input_member_offset; - break; + if(archs[0].using_64toc == FALSE){ + for(i = 0; i < archs[0].toc_nranlibs; i++){ + for(j = 0; j < archs[0].nmembers; j++){ + if(archs[0].members[j].offset == + archs[0].toc_ranlibs[i].ran_off){ + archs[0].toc_ranlibs[i].ran_off = (uint32_t) + archs[0].members[j].input_member_offset; + break; + } + } + } + } + else{ + for(i = 0; i < archs[0].toc_nranlibs; i++){ + for(j = 0; j < archs[0].nmembers; j++){ + if(archs[0].members[j].offset == + archs[0].toc_ranlibs64[i].ran_off){ + archs[0].toc_ranlibs64[i].ran_off = + archs[0].members[j].input_member_offset; + break; + } } } } @@ -2475,12 +2641,23 @@ struct ofile *ofile) */ same_toc = TRUE; for(i = 0; i < archs[0].toc_nranlibs; i++){ - if(archs[0].toc_ranlibs[i].ran_un.ran_strx != - ofile->toc_ranlibs[i].ran_un.ran_strx || - archs[0].toc_ranlibs[i].ran_off != - ofile->toc_ranlibs[i].ran_off){ - same_toc = FALSE; - break; + if(archs[0].using_64toc == FALSE){ + if(archs[0].toc_ranlibs[i].ran_un.ran_strx != + ofile->toc_ranlibs[i].ran_un.ran_strx || + archs[0].toc_ranlibs[i].ran_off != + ofile->toc_ranlibs[i].ran_off){ + same_toc = FALSE; + break; + } + } + else{ + if(archs[0].toc_ranlibs64[i].ran_un.ran_strx != + ofile->toc_ranlibs64[i].ran_un.ran_strx || + archs[0].toc_ranlibs64[i].ran_off != + ofile->toc_ranlibs64[i].ran_off){ + same_toc = FALSE; + break; + } } } if(same_toc == TRUE){ @@ -2501,7 +2678,6 @@ struct ofile *ofile) mach_fatal(r, "can't vm_allocate() buffer for output file: %s " "of size %llu", output, library_size); - /* put in the archive magic string in the buffer */ p = library; memcpy(p, ARMAG, SARMAG); @@ -2512,258 +2688,332 @@ struct ofile *ofile) if(same_toc == FALSE) p = put_toc_member(p, archs+0, host_byte_sex, target_byte_sex); + /* + * Because we are writing in place, just open the output file + * directly and modify its contents. The output file will be closed + * after the toc timestamps have been refreshed. + */ if((fd = open(output, O_WRONLY, 0)) == -1){ system_error("can't open output file: %s", output); return; } - if(write(fd, library, library_size) != (int)library_size){ + if(write64(fd, library, library_size) != (ssize_t)library_size){ system_error("can't write output file: %s", output); return; } - if(close(fd) == -1){ - system_fatal("can't close output file: %s", output); + + if((r = vm_deallocate(mach_task_self(), (vm_address_t)library, + library_size)) != KERN_SUCCESS){ + my_mach_error(r, "can't vm_deallocate() buffer for output file"); return; } - goto update_toc_ar_dates; - } -fail_to_update_toc_in_place: + } /* write_in_place == TRUE */ + else { /* if (write_in_place != TRUE) */ + char *library, *p, *flush_start; - /* - * This buffer is vm_allocate'ed to make sure all holes are filled with - * zero bytes. - */ - if((r = vm_allocate(mach_task_self(), (vm_address_t *)&library, - library_size, TRUE)) != KERN_SUCCESS) - mach_fatal(r, "can't vm_allocate() buffer for output file: %s of " - "size %llu", output, library_size); + /* create a temporary file name */ + templen = strlen(output) + strlen(suffix) + 1; + tempfile = calloc(templen, sizeof(char)); + if (tempfile == NULL) { + fatal("internal error: calloc() failed"); + } + if (snprintf(tempfile, templen, "%s%s", output, suffix) != + (templen - 1)) { + fatal("internal error: snprintf() failed"); + } - /* - * Create the output file. The unlink() is done to handle the problem - * when the outputfile is not writable but the directory allows the - * file to be removed (since the file may not be there the return code - * of the unlink() is ignored). - */ - (void)unlink(output); - if((fd = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1){ - system_error("can't create output file: %s", output); - return; - } + /* + * This buffer is vm_allocate'ed to make sure all holes are filled + * with zero bytes. The range will be deallocated in pieces via + * output_flush, rather than vm_deallocated at the end. + */ + if((r = vm_allocate(mach_task_self(), (vm_address_t *)&library, + library_size, TRUE)) != KERN_SUCCESS) + mach_fatal(r, + "can't vm_allocate() buffer for output file: %s of " + "size %llu", output, library_size); + + /* + * Create the output file. + */ + if ((fd = mkstemp(tempfile)) == -1) { + system_error("can't create temporary file: %s", tempfile); + return; + } + if (fchmod(fd, toc_mode) == -1) { + system_error("can't update temporary file: %s", tempfile); + return; + } + #ifdef F_NOCACHE - /* tell filesystem to NOT cache the file when reading or writing */ - (void)fcntl(fd, F_NOCACHE, 1); + /* tell filesystem to NOT cache the file when reading or writing */ + (void)fcntl(fd, F_NOCACHE, 1); #endif - /* - * If there is more than one architecture then fill in the fat file - * header and the fat_arch structures in the buffer. - */ - if(narchs > 1){ - fat_header = (struct fat_header *)library; - fat_header->magic = FAT_MAGIC; - fat_header->nfat_arch = narchs; - offset = sizeof(struct fat_header) + - sizeof(struct fat_arch) * narchs; - fat_arch = (struct fat_arch *)(library + sizeof(struct fat_header)); - for(i = 0; i < narchs; i++){ - fat_arch[i].cputype = archs[i].arch_flag.cputype; - fat_arch[i].cpusubtype = archs[i].arch_flag.cpusubtype; - if(offset > UINT32_MAX) - error("file too large to create as a fat file because " - "offset field in struct fat_arch is only 32-bits and " - "offset (%llu) to architecture %s exceeds that", - offset, archs[i].arch_flag.name); - if(fat_arch[i].cputype & CPU_ARCH_ABI64) - fat_arch[i].align = 3; + /* + * If there is more than one architecture then fill in the fat file + * header and the fat_arch or fat_arch64 structures in the buffer. + */ + if(narchs > 1){ + fat_header = (struct fat_header *)library; + if(cmd_flags.fat64 == TRUE) + fat_header->magic = FAT_MAGIC_64; else - fat_arch[i].align = 2; - offset = rnd(offset, 1 << fat_arch[i].align); - fat_arch[i].offset = offset; - if(archs[i].size > UINT32_MAX) - error("file too large to create as a fat file because " - "size field in struct fat_arch is only 32-bits and " - "size (%llu) of architecture %s exceeds that", - archs[i].size, archs[i].arch_flag.name); - fat_arch[i].size = archs[i].size; - offset += archs[i].size; - } - if(errors != 0){ - (void)unlink(output); - return; - } + fat_header->magic = FAT_MAGIC; + fat_header->nfat_arch = narchs; + offset = sizeof(struct fat_header); + if(cmd_flags.fat64 == TRUE){ + offset += sizeof(struct fat_arch_64) * narchs; + fat_arch64 = (struct fat_arch_64 *) + (library + sizeof(struct fat_header)); + fat_arch = NULL; + } + else{ + offset += sizeof(struct fat_arch) * narchs; + fat_arch = (struct fat_arch *) + (library + sizeof(struct fat_header)); + fat_arch64 = NULL; + } + for(i = 0; i < narchs; i++){ + if(cmd_flags.fat64 == TRUE){ + fat_arch64[i].cputype = archs[i].arch_flag.cputype; + fat_arch64[i].cpusubtype = + archs[i].arch_flag.cpusubtype; + } + else{ + fat_arch[i].cputype = archs[i].arch_flag.cputype; + fat_arch[i].cpusubtype = archs[i].arch_flag.cpusubtype; + } + if(cmd_flags.fat64 == FALSE && offset > UINT32_MAX) + error("file too large to create as a fat file because " + "offset field in struct fat_arch is only 32-bits " + "and offset (%llu) to architecture %s exceeds " + "that", offset, archs[i].arch_flag.name); + if(archs[i].arch_flag.cputype & CPU_ARCH_ABI64){ + if(cmd_flags.fat64 == TRUE) + fat_arch64[i].align = 3; + else + fat_arch[i].align = 3; + } + else{ + if(cmd_flags.fat64 == TRUE) + fat_arch64[i].align = 2; + else + fat_arch[i].align = 2; + } + if(cmd_flags.fat64 == TRUE) + offset = rnd(offset, 1 << fat_arch64[i].align); + else + offset = rnd(offset, 1 << fat_arch[i].align); + if(cmd_flags.fat64 == TRUE) + fat_arch64[i].offset = offset; + else + fat_arch[i].offset = (uint32_t)offset; + if(cmd_flags.fat64 == FALSE && archs[i].size > UINT32_MAX) + error("file too large to create as a fat file because " + "size field in struct fat_arch is only 32-bits " + "and size (%llu) of architecture %s exceeds that", + archs[i].size, archs[i].arch_flag.name); + if(cmd_flags.fat64 == TRUE) + fat_arch64[i].size = archs[i].size; + else + fat_arch[i].size = (uint32_t)archs[i].size; + offset += archs[i].size; + } + if(errors != 0){ + (void)unlink(tempfile); + return; + } #ifdef __LITTLE_ENDIAN__ - swap_fat_header(fat_header, BIG_ENDIAN_BYTE_SEX); - swap_fat_arch(fat_arch, narchs, BIG_ENDIAN_BYTE_SEX); -#endif /* __LITTLE_ENDIAN__ */ - offset = sizeof(struct fat_header) + - sizeof(struct fat_arch) * narchs; - } - else - offset = 0; - - /* flush out the fat headers if any */ - output_flush(library, library_size, fd, 0, offset); - - /* - * The time_offsets array records the offsets to the table of conternts - * archive header's ar_date fields. - */ - time_offsets = allocate(narchs * sizeof(uint64_t)); - - /* - * Now put each arch in the buffer. - */ - for(i = 0; i < narchs; i++){ - arch = archs + i; - if(narchs > 1 && (arch->arch_flag.cputype & CPU_ARCH_ABI64)){ - pad = rnd(offset, 1 << 3) - offset; - output_flush(library, library_size, fd, offset, pad); - offset = rnd(offset, 1 << 3); - } - p = library + offset; - flush_start = p; - - /* - * If the input files only contains non-object files then the - * byte sex of the output can't be determined which is needed for - * the two binary long's of the table of contents. But since these - * will be zero (the same in both byte sexes) because there are no - * symbols in the table of contents if there are no object files. - */ - - /* put in the archive magic string */ - memcpy(p, ARMAG, SARMAG); - p += SARMAG; - - /* - * Warn for what really is a bad library that has an empty table of - * contents but this is allowed in the original ranlib. - */ - if(arch->toc_nranlibs == 0 && cmd_flags.q == FALSE){ - if(narchs > 1) - warning("warning for library: %s for architecture: %s the " - "table of contents is empty (no object file members" - " in the library define global symbols)", output, - arch->arch_flag.name); + swap_fat_header(fat_header, BIG_ENDIAN_BYTE_SEX); + if(cmd_flags.fat64 == TRUE) + swap_fat_arch_64(fat_arch64, narchs, BIG_ENDIAN_BYTE_SEX); else - warning("warning for library: %s the table of contents is " - "empty (no object file members in the library " - "define global symbols)", output); + swap_fat_arch(fat_arch, narchs, BIG_ENDIAN_BYTE_SEX); +#endif /* __LITTLE_ENDIAN__ */ + offset = sizeof(struct fat_header); + if(cmd_flags.fat64 == TRUE) + offset += sizeof(struct fat_arch_64) * narchs; + else + offset += sizeof(struct fat_arch) * narchs; } + else + offset = 0; + + /* flush out the fat headers if any */ + output_flush(library, library_size, fd, 0, offset); /* - * Pick the byte sex to write the table of contents in. + * The time_offsets array records the offsets to the table of + * contents archive header's ar_date fields. */ - target_byte_sex = get_target_byte_sex(arch, host_byte_sex); - + time_offsets = allocate(narchs * sizeof(uint64_t)); + /* - * Remember the offset to the archive header's time field for this - * arch's table of contents member. + * Now put each arch in the buffer. */ - time_offsets[i] = - (p - library) + - ((char *)&toc_ar_hdr.ar_date - (char *)&toc_ar_hdr); - - /* - * Put in the table of contents member in the output buffer. - */ - p = put_toc_member(p, arch, host_byte_sex, target_byte_sex); - - output_flush(library, library_size, fd, flush_start - library, - p - flush_start); - - /* - * Put in the archive header and member contents for each member. - */ - for(j = 0; j < arch->nmembers; j++){ + for(i = 0; i < narchs; i++){ + arch = archs + i; + if(narchs > 1 && (arch->arch_flag.cputype & CPU_ARCH_ABI64)){ + pad = (uint32_t)(rnd(offset, 1 << 3) - offset); + output_flush(library, library_size, fd, offset, pad); + offset = rnd(offset, 1 << 3); + } + p = library + offset; flush_start = p; - memcpy(p, (char *)&(arch->members[j].ar_hdr), - sizeof(struct ar_hdr)); - p += sizeof(struct ar_hdr); - + /* - * If we are using extended format #1 for long names write out - * the name. Note the name is padded with '\0' and the - * member_name_size is the unrounded size. + * If the input files only contains non-object files then the + * byte sex of the output can't be determined which is needed + * for the two binary long's of the table of contents. But + * since these will be zero (the same in both byte sexes) + * because there are no symbols in the table of contents if + * there are no object files. */ - if(arch->members[j].output_long_name == TRUE){ - strncpy(p, arch->members[j].member_name, - arch->members[j].member_name_size); - p += rnd(arch->members[j].member_name_size, 8) + - (rnd(sizeof(struct ar_hdr), 8) - - sizeof(struct ar_hdr)); - } - + + /* put in the archive magic string */ + memcpy(p, ARMAG, SARMAG); + p += SARMAG; + /* - * ofile_map swaps the headers to the host_byte_sex if the - * object's byte sex is not the same as the host byte sex so - * if this is the case swap them back before writing them out. + * Warn for what really is a bad library that has an empty table + * of contents but this is allowed in the original ranlib. */ - if(arch->members[j].mh != NULL && - arch->members[j].object_byte_sex != host_byte_sex){ - if(swap_object_headers(arch->members[j].mh, - arch->members[j].load_commands) == FALSE) - fatal("internal error: swap_object_headers() failed"); + if(arch->toc_nranlibs == 0 && cmd_flags.q == FALSE){ + if(narchs > 1) + warning("warning for library: %s for architecture: %s " + "the table of contents is empty (no object " + "file members in the library define global " + "symbols)", output, arch->arch_flag.name); + else + warning("warning for library: %s the table of contents " + "is empty (no object file members in the " + "library define global symbols)", output); } - else if(arch->members[j].mh64 != NULL && - arch->members[j].object_byte_sex != host_byte_sex){ - if(swap_object_headers(arch->members[j].mh64, - arch->members[j].load_commands) == FALSE) - fatal("internal error: swap_object_headers() failed"); - } - memcpy(p, arch->members[j].object_addr, - arch->members[j].object_size); -#ifdef VM_SYNC_DEACTIVATE - vm_msync(mach_task_self(), - (vm_address_t)arch->members[j].object_addr, - (vm_size_t)arch->members[j].object_size, - VM_SYNC_DEACTIVATE); -#endif /* VM_SYNC_DEACTIVATE */ - p += arch->members[j].object_size; - pad = rnd(arch->members[j].object_size, 8) - - arch->members[j].object_size; - /* as with the UNIX ar(1) program pad with '\n' characters */ - for(k = 0; k < pad; k++) - *p++ = '\n'; - + + /* + * Pick the byte sex to write the table of contents in. + */ + target_byte_sex = get_target_byte_sex(arch, host_byte_sex); + + /* + * Remember the offset to the archive header's time field for + * this arch's table of contents member. + */ + time_offsets[i] = + (p - library) + + ((char *)&toc_ar_hdr.ar_date - (char *)&toc_ar_hdr); + + /* + * Put in the table of contents member in the output buffer. + */ + p = put_toc_member(p, arch, host_byte_sex, target_byte_sex); + output_flush(library, library_size, fd, flush_start - library, p - flush_start); + + /* + * Put in the archive header and member contents for each + * member. + */ + for(j = 0; j < arch->nmembers; j++){ + flush_start = p; + memcpy(p, (char *)&(arch->members[j].ar_hdr), + sizeof(struct ar_hdr)); + p += sizeof(struct ar_hdr); + + /* + * If we are using extended format #1 for long names write + * out the name. Note the name is padded with '\0' and the + * member_name_size is the unrounded size. + */ + if(arch->members[j].output_long_name == TRUE){ + strncpy(p, arch->members[j].member_name, + arch->members[j].member_name_size); + p += rnd(arch->members[j].member_name_size, 8) + + (rnd(sizeof(struct ar_hdr), 8) - + sizeof(struct ar_hdr)); + } + + /* + * ofile_map swaps the headers to the host_byte_sex if the + * object's byte sex is not the same as the host byte sex + * so if this is the case swap them back before writing + * them out. + */ + if(arch->members[j].mh != NULL && + arch->members[j].object_byte_sex != host_byte_sex){ + if(swap_object_headers(arch->members[j].mh, + arch->members[j].load_commands) + == FALSE) + fatal("internal error: swap_object_headers() " + "failed"); + } + else if(arch->members[j].mh64 != NULL && + arch->members[j].object_byte_sex != host_byte_sex){ + if(swap_object_headers(arch->members[j].mh64, + arch->members[j].load_commands) + == FALSE) + fatal("internal error: swap_object_headers() " + "failed"); + } + memcpy(p, arch->members[j].object_addr, + arch->members[j].object_size); +#ifdef VM_SYNC_DEACTIVATE + vm_msync(mach_task_self(), + (vm_address_t)arch->members[j].object_addr, + (vm_size_t)arch->members[j].object_size, + VM_SYNC_DEACTIVATE); +#endif /* VM_SYNC_DEACTIVATE */ + p += arch->members[j].object_size; + pad = rnd32(arch->members[j].object_size, 8) - + arch->members[j].object_size; + /* + * as with the UNIX ar(1) program pad with '\n' characters + */ + for(k = 0; k < pad; k++) + *p++ = '\n'; + + output_flush(library, library_size, fd, + flush_start - library, p - flush_start); + } + offset += arch->size; } - offset += arch->size; - } + + /* + * Write the library to the file or flush the remaining buffer to + * the file. + */ + if(cmd_flags.noflush == TRUE){ + if(write64(fd, library, library_size) != (ssize_t)library_size){ + system_error("can't write temporary file: %s", tempfile); + return; + } + if((r = vm_deallocate(mach_task_self(), (vm_address_t)library, + library_size)) != KERN_SUCCESS){ + my_mach_error(r, "can't vm_deallocate() buffer for output " + "file"); + return; + } + } + else{ + final_output_flush(library, fd); + } + } /* if write_in_place != TRUE */ /* - * Write the library to the file or flush the remaining buffer to the - * file. + * Now that the library is created on the file system, stat the file + * to get the time it was last modified from the file system. */ - if(cmd_flags.noflush == TRUE){ - if(write(fd, library, library_size) != (int)library_size){ - system_error("can't write output file: %s", output); - return; - } - } - else{ - final_output_flush(library, fd); - } - if(close(fd) == -1){ - system_fatal("can't close output file: %s", output); + if (fstat(fd, &stat_buf) == -1) { + system_fatal("can't stat output file: %s", + tempfile ? tempfile : output); return; } - -update_toc_ar_dates: - /* - * Now that the library is created on the file system it is written - * to get the time for the file on that file system. - */ - if(stat(output, &stat_buf) == -1){ - system_fatal("can't stat file output file: %s", output); - return; - } - if((fd = open(output, O_WRONLY, 0)) == -1){ - system_error("can't open output file: %s", output); - return; - } - if(zero_ar_date == TRUE) - stat_buf.st_mtime = 0; + if(cmd_flags.D == TRUE || zero_ar_date == TRUE) + toc_mtime = 0; + else + toc_mtime = (uint32_t)stat_buf.st_mtime + 5; /* * With the time from the file system the library is on set the ar_date * using the modification time returned by stat. Then write this into @@ -2773,45 +3023,103 @@ update_toc_ar_dates: (int)sizeof(toc_ar_hdr.ar_name), SYMDEF, (int)sizeof(toc_ar_hdr.ar_date), - (long int)stat_buf.st_mtime + 5); + (long int)toc_mtime); for(i = 0; i < narchs; i++){ if(lseek(fd, time_offsets[i], L_SET) == -1){ - system_error("can't lseek in output file: %s", output); + system_error("can't lseek in output file: %s", + tempfile ? tempfile : output); return; } + /* MDT: write(2) is OK here, size is less than 2^31-1 */ if(write(fd, &toc_ar_hdr.ar_date, sizeof(toc_ar_hdr.ar_date)) != sizeof(toc_ar_hdr.ar_date)){ - system_error("can't write to output file: %s", output); + system_error("can't write to output file: %s", + tempfile ? tempfile : output); return; } } if(close(fd) == -1){ - system_fatal("can't close output file: %s", output); + system_fatal("can't close output file: %s", + tempfile ? tempfile : output); return; } /* * Now set the modtime of the created library back to it's stat time * when we first closed it. */ + + /* + cctools-port: + Original code (949.0.1) + Replaced for portability. + */ + +#if 0 #ifndef __OPENSTEP__ - timep.actime = stat_buf.st_mtime; - timep.modtime = stat_buf.st_mtime; - if(utime(output, &timep) == -1) + if (__builtin_available(macOS 10.12, *)) { + struct timespec times[2]; + memcpy(×[0], &stat_buf.st_atimespec, sizeof(struct timespec)); + memcpy(×[1], &stat_buf.st_mtimespec, sizeof(struct timespec)); + time_result = utimensat(AT_FDCWD, tempfile, times, 0); + } + else { + TIMESPEC_TO_TIMEVAL(&timep[0], &stat_buf.st_atimespec); + TIMESPEC_TO_TIMEVAL(&timep[1], &stat_buf.st_mtimespec); + time_result = utimes(tempfile, timep); + } #else timep[0] = stat_buf.st_mtime; timep[1] = stat_buf.st_mtime; - if(utime(output, timep) == -1) + time_result = utime(tempfile, timep); #endif - { + if (time_result == -1) { system_fatal("can't set the modifiy times in output file: %s", - output); + tempfile ? tempfile : output); return; } - if((r = vm_deallocate(mach_task_self(), (vm_address_t)library, - library_size)) != KERN_SUCCESS){ - my_mach_error(r, "can't vm_deallocate() buffer for output file"); +#endif /* 0 */ + + +#ifdef HAVE_STAT_ST_MTIMESPEC + times[0] = stat_buf.st_atimespec; + times[1] = stat_buf.st_mtimespec; +#elif HAVE_STAT_ST_MTIM + times[0] = stat_buf.st_atim; + times[1] = stat_buf.st_mtim; +#else + times[0].tv_sec = stat_buf.st_atime; + times[0].tv_nsec = 0; + times[1].tv_sec = stat_buf.st_mtime; + times[0].tv_nsec = 0; +#endif + if(utimens(tempfile, times) == -1) + { + system_fatal("can't set the modifiy times in output file: %s", + tempfile ? tempfile : output); return; } + + /* + * Error out before writing the final file, if requested. This is only + * useful for testing. + */ + if (libtool_force_fail != NULL || ranlib_force_fail != NULL) { + system_fatal("%s set, simulating a system-fatal error: %s", + libtool_force_fail != NULL ? "LIBTOOL_FORCE_FAIL" : + "RANLIB_FORCE_FAIL", tempfile ? tempfile : output); + return; + } + + /* + * Move the temporary file into its final location + */ + if (tempfile) { + if (rename(tempfile, output)) { + system_fatal("can't move the output file to its final location: %s", + output); + return; + } + } } /* @@ -2841,14 +3149,20 @@ enum byte_sex host_byte_sex) /* * put_toc_member() put the contents member for arch into the buffer p and * returns the pointer to the buffer after the table of contents. - * The table of contents member is: - * the archive header + * The table of contents member uses either a 32-bit toc or a 64-bit toc. + * Both forms start with: + * the archive header * the archive member name (if using a long name) - * a uint32_t for the number of bytes of the ranlib structs - * the ranlib structs - * a uint32_t for the number of bytes of the strings for the - * ranlibs - * the strings for the ranlib structs + * then for a 32-bit toc the rest is this: + * a uint32_t for the number of bytes of the ranlib structs + * the ranlib structs + * a uint32_t for the number of bytes of the strings for the ranlibs + * the strings for the ranlib structs + * and for a 64-bit toc the rest is this: + * a uint64_t for the number of bytes of the ranlib structs + * the ranlib_64 structs + * a uint64_t for the number of bytes of the strings for the ranlibs + * the strings for the ranlib structs */ static char * @@ -2859,6 +3173,7 @@ enum byte_sex host_byte_sex, enum byte_sex target_byte_sex) { uint32_t l; + uint64_t l64; memcpy(p, (char *)&arch->toc_ar_hdr, sizeof(struct ar_hdr)); p += sizeof(struct ar_hdr); @@ -2870,27 +3185,52 @@ enum byte_sex target_byte_sex) sizeof(struct ar_hdr)); } - l = arch->toc_nranlibs * sizeof(struct ranlib); - if(target_byte_sex != host_byte_sex) - l = SWAP_INT(l); - memcpy(p, (char *)&l, sizeof(uint32_t)); - p += sizeof(uint32_t); + if(arch->using_64toc == FALSE){ + l = (uint32_t)(arch->toc_nranlibs * sizeof(struct ranlib)); + if(target_byte_sex != host_byte_sex) + l = SWAP_INT(l); + memcpy(p, (char *)&l, sizeof(uint32_t)); + p += sizeof(uint32_t); - if(target_byte_sex != host_byte_sex) - swap_ranlib(arch->toc_ranlibs, arch->toc_nranlibs, - target_byte_sex); - memcpy(p, (char *)arch->toc_ranlibs, - arch->toc_nranlibs * sizeof(struct ranlib)); - p += arch->toc_nranlibs * sizeof(struct ranlib); + if(target_byte_sex != host_byte_sex) + swap_ranlib(arch->toc_ranlibs, (uint32_t)arch->toc_nranlibs, + target_byte_sex); + memcpy(p, (char *)arch->toc_ranlibs, + arch->toc_nranlibs * sizeof(struct ranlib)); + p += arch->toc_nranlibs * sizeof(struct ranlib); - l = arch->toc_strsize; - if(target_byte_sex != host_byte_sex) - l = SWAP_INT(l); - memcpy(p, (char *)&l, sizeof(uint32_t)); - p += sizeof(uint32_t); + l = (uint32_t)arch->toc_strsize; + if(target_byte_sex != host_byte_sex) + l = SWAP_INT(l); + memcpy(p, (char *)&l, sizeof(uint32_t)); + p += sizeof(uint32_t); - memcpy(p, (char *)arch->toc_strings, arch->toc_strsize); - p += arch->toc_strsize; + memcpy(p, (char *)arch->toc_strings, arch->toc_strsize); + p += arch->toc_strsize; + } + else{ + l64 = arch->toc_nranlibs * sizeof(struct ranlib_64); + if(target_byte_sex != host_byte_sex) + l64 = SWAP_LONG_LONG(l64); + memcpy(p, (char *)&l64, sizeof(uint64_t)); + p += sizeof(uint64_t); + + if(target_byte_sex != host_byte_sex) + swap_ranlib_64(arch->toc_ranlibs64, arch->toc_nranlibs, + target_byte_sex); + memcpy(p, (char *)arch->toc_ranlibs64, + arch->toc_nranlibs * sizeof(struct ranlib_64)); + p += arch->toc_nranlibs * sizeof(struct ranlib_64); + + l64 = arch->toc_strsize; + if(target_byte_sex != host_byte_sex) + l64 = SWAP_LONG_LONG(l64); + memcpy(p, (char *)&l64, sizeof(uint64_t)); + p += sizeof(uint64_t); + + memcpy(p, (char *)arch->toc_strings, arch->toc_strsize); + p += arch->toc_strsize; + } return(p); } @@ -2917,7 +3257,8 @@ uint64_t size) struct block **p, *block, *before, *after; kern_return_t r; - host_pagesize = 0x2000; + host_pagesize = getpagesize(); + write_offset = 0; if(cmd_flags.noflush == TRUE) return; @@ -3020,11 +3361,11 @@ uint64_t size) else write_offset =before->written_offset + before->written_size; if(after->written_size == 0) - write_size = trnc(after->offset + after->size - - write_offset, host_pagesize); + write_size = trnc64(after->offset + after->size - + write_offset, host_pagesize); else - write_size = trnc(after->written_offset - write_offset, - host_pagesize); + write_size = trnc64(after->written_offset - write_offset, + host_pagesize); if(write_size != 0){ before->written_size += write_size; } @@ -3044,7 +3385,7 @@ uint64_t size) * before the new area. */ write_offset = before->written_offset + before->written_size; - write_size = trnc(offset + size - write_offset, host_pagesize); + write_size = trnc64(offset + size - write_offset,host_pagesize); if(write_size != 0) before->written_size += write_size; before->size += size; @@ -3063,11 +3404,11 @@ uint64_t size) */ write_offset = rnd(offset, host_pagesize); if(after->written_size == 0) - write_size = trnc(after->offset + after->size - write_offset, - host_pagesize); + write_size = trnc64(after->offset + after->size - write_offset, + host_pagesize); else - write_size = trnc(after->written_offset - write_offset, - host_pagesize); + write_size = trnc64(after->written_offset - write_offset, + host_pagesize); if(write_size != 0){ after->written_offset = write_offset; after->written_size += write_size; @@ -3085,8 +3426,8 @@ uint64_t size) * it (if any) starts. A new block is created and the new area is * is placed in it. */ - write_offset = rnd(offset, host_pagesize); - write_size = trnc(offset + size - write_offset, host_pagesize); + write_offset = rnd64(offset, host_pagesize); + write_size = trnc64(offset + size - write_offset, host_pagesize); block = get_block(); block->offset = offset; block->size = size; @@ -3115,8 +3456,8 @@ uint64_t size) write_offset, write_size); #endif /* DEBUG */ lseek(fd, write_offset, L_SET); - if(write(fd, library + write_offset, write_size) != - (int)write_size) + if(write64(fd, library + write_offset, write_size) != + (ssize_t)write_size) system_fatal("can't write to output file"); if((r = vm_deallocate(mach_task_self(), (vm_address_t)(library + write_offset), write_size)) != KERN_SUCCESS) @@ -3144,10 +3485,9 @@ int fd) uint64_t write_offset, write_size; kern_return_t r; -#ifdef DEBUG - /* The compiler "warning: `write_offset' may be used uninitialized in */ - /* this function" can safely be ignored */ write_offset = 0; + +#ifdef DEBUG if((cmd_flags.debug & (1 << 1)) || (cmd_flags.debug & (1 << 0))){ printf("final_output_flush block_list:\n"); print_block_list(); @@ -3179,8 +3519,8 @@ int fd) write_offset, write_size); #endif /* DEBUG */ lseek(fd, write_offset, L_SET); - if(write(fd, library + write_offset, write_size) != - (int)write_size) + if(write64(fd, library + write_offset, write_size) != + (ssize_t)write_size) system_fatal("can't write to output file"); if((r = vm_deallocate(mach_task_self(), (vm_address_t)(library + write_offset), write_size)) != KERN_SUCCESS) @@ -3243,18 +3583,19 @@ struct block *block) } /* - * trnc() truncates the value 'v' to the power of two value 'r'. If v is - * less than zero it returns zero. + * trnc64() truncates the value 'v' to the power of two value 'r'. + * If v is less than zero it returns zero. */ + static -uint32_t -trnc( -uint32_t v, -uint32_t r) +uint64_t +trnc64( +uint64_t v, +uint64_t r) { - if(((int32_t)v) < 0) - return(0); - return(v & ~(r - 1)); + if(((int64_t)v) < 0) + return(0); + return(v & ~(r - 1)); } /* @@ -3363,31 +3704,30 @@ char *output) for(j = 0; j < cmd_flags.nLdirs; j++) add_execute_list(cmd_flags.Ldirs[j]); - // Support using libtool on a systems without the SDK in '/'. This - // works because the shims that are included in 10.9 and forwards - // automatically inject SDKROOT into the environment of the actual - // tools. See . - const char *sdkroot = getenv("SDKROOT"); - - // If the SDKROOT environment variable is set and is an absolute - // path, then see if we can find dylib1.o inside it and use that if - // so. - enum bool use_dashl_dylib1o = TRUE; - if (sdkroot && sdkroot[0] == '/') { - // Construct the path to the object file. - char *sdk_dylib1o_path; - int res = asprintf(&sdk_dylib1o_path, "%s/usr/lib/dylib1.o", - sdkroot); - if (res > 0 && sdk_dylib1o_path) { - struct stat s; - // Add the full path if it exists. - if (stat(sdk_dylib1o_path, &s) == 0) { - add_execute_list(sdk_dylib1o_path); - use_dashl_dylib1o = FALSE; - } - free(sdk_dylib1o_path); - } - } + // Support using libtool on a systems without the SDK in '/'. This + // works because the shims that are included in 10.9 and forwards + // automatically inject SDKROOT into the environment of the actual + // tools. See . + const char *sdkroot = getenv("SDKROOT"); + + // If the SDKROOT environment variable is set and is an absolute + // path, then see if we can find dylib1.o inside it and use that if + // so. + enum bool use_dashl_dylib1o = TRUE; + if (sdkroot && sdkroot[0] == '/') { + // Construct the path to the object file. + char *sdk_dylib1o_path; + int res = asprintf(&sdk_dylib1o_path, "%s/usr/lib/dylib1.o", + sdkroot); + if (res > 0 && sdk_dylib1o_path) { + struct stat s; + // Add the full path if it exists. + if (stat(sdk_dylib1o_path, &s) == 0) { + add_execute_list(sdk_dylib1o_path); + use_dashl_dylib1o = FALSE; + } + } + } filelist = NULL; for(j = 0; j < cmd_flags.nfiles; j++){ @@ -3654,12 +3994,14 @@ char *output) arch->tocs = allocate(sizeof(struct toc) * arch->toc_nranlibs); arch->toc_strsize = rnd(arch->toc_strsize, 8); arch->toc_strings = allocate(arch->toc_strsize); + if(arch->toc_strsize >= 8) + memset(arch->toc_strings + arch->toc_strsize - 7, '\0', 7); /* - * Second pass over the members to fill in the ranlib structs and - * the strings for the table of contents. The ran_name field is + * Second pass over the members to fill in the toc structs and + * the strings for the table of contents. The toc name field is * filled in with a pointer to a string contained in arch->toc_strings - * for easy sorting and conversion to an index. The ran_off field is + * for easy sorting and conversion to an index. The toc index1 field is * filled in with the member index plus one to allow marking with it's * negative value by check_sort_tocs() and easy conversion to the * real offset. @@ -3809,23 +4151,110 @@ char *output) * a uint32_t for the number of bytes of the strings * the strings */ - arch->toc_size = sizeof(struct ar_hdr) + + arch->toc_size = (uint32_t)(sizeof(struct ar_hdr) + sizeof(uint32_t) + arch->toc_nranlibs * sizeof(struct ranlib) + sizeof(uint32_t) + - arch->toc_strsize; + arch->toc_strsize); /* add the size of the name is a long name is used */ if(arch->toc_long_name == TRUE) arch->toc_size += arch->toc_name_size + (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr)); + + /* + * Now with the size of the 32-bit toc known we can now see if it will + * work or if we have offsets to members that are more than 32-bits and + * we need to switch to the 64-bit toc, or switch to that if we are + * forcing a 64-bit toc via the command line option. + */ + if(cmd_flags.toc64 == TRUE) + arch->using_64toc = TRUE; + else{ + arch->using_64toc = FALSE; + for(i = 0; i < arch->nmembers; i++){ + if(arch->members[i].offset + SARMAG + arch->toc_size > + UINT32_MAX){ + arch->using_64toc = TRUE; + break; + } + } + } + if(arch->using_64toc){ + if(cmd_flags.use_long_names == FALSE && + cmd_flags.L_or_T_specified == TRUE) + fatal("archive requires a 64-bit toc that must be aligned so " + "-T can't be specified"); + arch->toc_long_name = TRUE; + if(sorted == FALSE){ + /* + * This assumes that "__.SYMDEF_64\0\0\0\0" is 16 bytes + * and + * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr) + * is 4 bytes. + */ + ar_name = AR_EFMT1 "20"; + arch->toc_name_size = 16; + arch->toc_name = SYMDEF_64 "\0\0\0\0"; + } + else{ + arch->toc_name = SYMDEF_64_SORTED; + arch->toc_name_size = sizeof(SYMDEF_64_SORTED) - 1; + /* + * This assumes that "__.SYMDEF_64 SORTED\0\0\0\0\0" is 24 bytes + * and + * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr) + * is 4 bytes. + */ + ar_name = AR_EFMT1 "28"; + arch->toc_name_size = 24; + arch->toc_name = SYMDEF_64_SORTED "\0\0\0\0\0"; + } + /* + * Free the space for the 32-bit ranlib structs and allocate space + * for the 64-bit ranlib structs. + */ + free(arch->toc_ranlibs); + arch->toc_ranlibs = NULL; + arch->toc_ranlibs64 = allocate(sizeof(struct ranlib_64) * + arch->toc_nranlibs); + /* + * Now the size of the toc member when it is a 64-bit toc can be + * set. It is made up of the sizeof an archive header struct (the + * size of the name which is always a long name to get 8-byte + * alignment then the toc which is (as defined in ranlib.h): + * a uint64_t for the number of bytes of the ranlib_64 structs + * the ranlib_64 structures + * a uint64_t for the number of bytes of the strings + * the strings + */ + arch->toc_size = (uint32_t)(sizeof(struct ar_hdr) + + sizeof(uint64_t) + + arch->toc_nranlibs * sizeof(struct ranlib_64) + + sizeof(uint64_t) + + arch->toc_strsize); + /* add the size of the name as a long name is always used */ + arch->toc_size += arch->toc_name_size + + (rnd(sizeof(struct ar_hdr), 8) - + sizeof(struct ar_hdr)); + } + for(i = 0; i < arch->nmembers; i++) arch->members[i].offset += SARMAG + arch->toc_size; + for(i = 0; i < arch->toc_nranlibs; i++){ - arch->toc_ranlibs[i].ran_un.ran_strx = - arch->tocs[i].name - arch->toc_strings; - arch->toc_ranlibs[i].ran_off = - arch->members[arch->tocs[i].index1 - 1].offset; + if(arch->using_64toc){ + arch->toc_ranlibs64[i].ran_un.ran_strx = + arch->tocs[i].name - arch->toc_strings; + arch->toc_ranlibs64[i].ran_off = + arch->members[arch->tocs[i].index1 - 1].offset; + } + else{ + arch->toc_ranlibs[i].ran_un.ran_strx = + (uint32_t)(arch->tocs[i].name - arch->toc_strings); + arch->toc_ranlibs[i].ran_off = + (uint32_t)(arch->members[arch->tocs[i].index1 - 1].offset); + } } sprintf((char *)(&arch->toc_ar_hdr), "%-*s%-*ld%-*u%-*u%-*o%-*ld", @@ -3834,9 +4263,9 @@ char *output) (int)sizeof(arch->toc_ar_hdr.ar_date), toc_time, (int)sizeof(arch->toc_ar_hdr.ar_uid), - (unsigned short)getuid(), + (unsigned short)toc_uid, (int)sizeof(arch->toc_ar_hdr.ar_gid), - (unsigned short)getgid(), + (unsigned short)toc_gid, (int)sizeof(arch->toc_ar_hdr.ar_mode), (unsigned int)toc_mode, (int)sizeof(arch->toc_ar_hdr.ar_size), @@ -4170,42 +4599,96 @@ const char *format, ...) } /* - * Prints the message to cmd_flags.trace_file_path, or stderr if that - * isn't set. + * Prints a message for the archive file specified by archive to + * cmd_flags.trace_file_path, or stderr if that isn't set. + */ +static void ld_trace_archive(const char* archive) +{ + char resolvedname[MAXPATHLEN]; + const char* path = realpath(archive, resolvedname); + + if (path == NULL) + path = archive; + + if (cmd_flags.ld_trace_dependents) { + if (trace_buffer == NULL) { + ld_trace_append("{\"archives\":["); + } else { + ld_trace_append(","); + } + ld_trace_append("\"%s\"", path); + } + else if (cmd_flags.ld_trace_archives) { + ld_trace_append("[Logging for XBS] Used static archive: " + "%s\n", path); + } +} + +/* + * ld_trace_close completes the trace logging process and writes the contents + * of the trace buffer. + * + * If logging to a JSON object, the object will be closed. + * + * If LD_TRACE_FILE is present in the environment, the trace buffer will be + * written to the path so specified. The file will be created if missing, and + * appended to if present. An exclusive lock with flock(2) semantics will + * be held to prevent problems caused by concurrent writers. + * + * If LD_TRACE_FILE is not present, the contents of the trace buffer will be + * written to stderr. + */ +static void ld_trace_close(void) +{ + int trace_file; + + if (cmd_flags.ld_trace_dependents && trace_buffer) { + ld_trace_append("]}\n"); + } + +#ifndef O_EXLOCK // cctools-port +#define O_EXLOCK 0 +#endif + + if (trace_buffer) { + if (cmd_flags.trace_file_path != NULL) { + trace_file = open(cmd_flags.trace_file_path, + O_WRONLY | O_APPEND | O_CREAT | O_EXLOCK, 0666); + if (trace_file == -1) + error("Could not open or create trace file: %s\n", + cmd_flags.trace_file_path); + } + else { + trace_file = fileno(stderr); + } + + (void)write64(trace_file, trace_buffer, trace_buflen); + /* Failure to write shouldn't fail the build. */ + + close(trace_file); + } +} + +/* + * ld_trace_append appends the message to trace_buffer. */ static void -ld_trace( -const char *format, ...) +ld_trace_append( + const char *format, ...) { - static int trace_file = -1; - char trace_buffer[MAXPATHLEN * 2]; - char *buffer_ptr; - int length; - ssize_t amount_written; - - if(trace_file == -1){ - if(cmd_flags.trace_file_path != NULL){ - trace_file = open(cmd_flags.trace_file_path, O_WRONLY | O_APPEND | O_CREAT, 0666); - if(trace_file == -1) - error("Could not open or create trace file: %s\n", cmd_flags.trace_file_path); - } - else{ - trace_file = fileno(stderr); - } - } va_list ap; + int length; - va_start(ap, format); - length = vsnprintf(trace_buffer, sizeof(trace_buffer), format, ap); - va_end(ap); - buffer_ptr = trace_buffer; - while(length > 0){ - amount_written = write(trace_file, buffer_ptr, length); - if(amount_written == -1) - /* Failure to write shouldn't fail the build. */ - return; - buffer_ptr += amount_written; - length -= amount_written; - } + va_start(ap, format); + length = vsnprintf(NULL, 0, format, ap); + va_end(ap); + + trace_buffer = realloc(trace_buffer, trace_buflen + length + 1); + + va_start(ap, format); + vsnprintf(&trace_buffer[trace_buflen], length + 1, format, ap); + va_end(ap); + + trace_buflen += length; } diff --git a/cctools/misc/lipo.c b/cctools/misc/lipo.c index 8cda74b..cb216b4 100644 --- a/cctools/misc/lipo.c +++ b/cctools/misc/lipo.c @@ -49,6 +49,7 @@ #include #include #ifndef __OPENSTEP__ +#include #include #endif #include @@ -62,6 +63,15 @@ #include "stuff/errors.h" #include "stuff/allocate.h" #include "stuff/lto.h" +#include "stuff/write64.h" +#include "stuff/rnd.h" +#include + +/* cctools-port start */ +#ifndef HAVE_UTIMENS +int utimens(const char *path, const struct timespec times[2]); +#endif +/* cctools-port end */ /* The maximum section alignment allowed to be specified, as a power of two */ #define MAXSECTALIGN 15 /* 2**15 or 0x8000 */ @@ -79,7 +89,9 @@ struct input_file { struct arch_flag arch_flag; struct fat_header *fat_header; struct fat_arch *fat_arches; + struct fat_arch_64 *fat_arches64; enum bool is_thin; + uint32_t raw_nfat_arch; }; static struct input_file *input_files = NULL; static uint32_t ninput_files = 0; @@ -88,7 +100,11 @@ static uint32_t ninput_files = 0; struct thin_file { char *name; char *addr; - struct fat_arch fat_arch; + cpu_type_t cputype; + cpu_subtype_t cpusubtype; + uint64_t offset; + uint64_t size; + uint32_t align; enum bool from_fat; enum bool extract; enum bool remove; @@ -101,7 +117,8 @@ static uint32_t nthin_files = 0; static char *output_file = NULL; static uint32_t output_filemode = 0; #ifndef __OPENSTEP__ -static struct utimbuf output_timep = { 0 }; +static struct timespec output_times[2] = { 0 }; +static struct timeval output_timev[2] = { 0 }; #else static time_t output_timep[2] = { 0 }; #endif @@ -111,6 +128,7 @@ static enum bool archives_in_input = FALSE; static enum bool create_flag = FALSE; static enum bool info_flag = FALSE; static enum bool detailed_info_flag = FALSE; +static enum bool brief_info_flag = FALSE; // -archs static enum bool thin_flag = FALSE; static struct arch_flag thin_arch_flag = { 0 }; @@ -143,18 +161,14 @@ static enum bool arch_blank_flag = FALSE; static struct fat_header fat_header = { 0 }; -static struct fat_arch *arm64_fat_arch = NULL; -static struct fat_arch *get_arm64_fat_arch( - void); - -static struct fat_arch *x86_64h_fat_arch = NULL; -static struct fat_arch *get_x86_64h_fat_arch( - void); - static enum bool verify_flag = FALSE; static struct arch_flag *verify_archs = NULL; static uint32_t nverify_archs = 0; +static enum bool fat64_flag = FALSE; + +static enum bool hideARM64_flag = FALSE; + static void create_fat( void); static void process_input_file( @@ -164,30 +178,34 @@ static void process_replace_file( static void check_archive( char *name, char *addr, - uint32_t size, + uint64_t size, cpu_type_t *cputype, cpu_subtype_t *cpusubtype); static void check_extend_format_1( char *name, struct ar_hdr *ar_hdr, - uint32_t size_left, + uint64_t size_left, uint32_t *member_name_size); +static uint32_t get_mh_filetype( + char* addr, + uint64_t size); static uint32_t get_align( struct mach_header *mhp, struct load_command *load_commands, - uint32_t size, + uint64_t size, char *name, enum bool swapped); static uint32_t get_align_64( struct mach_header_64 *mhp64, struct load_command *load_commands, - uint32_t size, + uint64_t size, char *name, enum bool swapped); static uint32_t guess_align( - uint32_t vmaddr); + uint64_t vmaddr); static void print_arch( - struct fat_arch *fat_arch); + cpu_type_t cputype, + cpu_subtype_t cpusubtype); static void print_cputype( cpu_type_t cputype, cpu_subtype_t cpusubtype); @@ -207,9 +225,6 @@ static struct segalign *new_segalign( static int cmp_qsort( const struct thin_file *thin1, const struct thin_file *thin2); -static uint32_t rnd( - uint32_t v, - uint32_t r); static enum bool ispoweroftwo( uint32_t x); static void check_arch( @@ -240,6 +255,7 @@ char *envp[]) const struct arch_flag *arch_flags; enum bool found; struct arch_flag blank_arch; + int time_result; input = NULL; /* @@ -284,6 +300,9 @@ char *envp[]) new_blank_dylib(&blank_arch); a += 1; } + else if(strcmp(p, "archs") == 0){ + brief_info_flag = TRUE; + } else goto unknown_flag; break; @@ -326,6 +345,13 @@ char *envp[]) else goto unknown_flag; break; + case 'h': + if (strcmp(p, "hideARM64") == 0) { + hideARM64_flag = TRUE; + } + else + goto unknown_flag; + break; case 'i': if(strcmp(p, "info") == 0 || strcmp(p, "i") == 0){ info_flag = TRUE; @@ -401,7 +427,7 @@ char *envp[]) arch_usage(); usage(); } - value = strtoul(argv[a+2], &endp, 16); + value = (uint32_t)strtoul(argv[a+2], &endp, 16); if(*endp != '\0') fatal("argument for -segalign %s not a " "proper hexadecimal number", argv[a+2]); @@ -468,6 +494,12 @@ char *envp[]) else goto unknown_flag; break; + case 'f': + if(strcmp(p, "fat64") == 0) + fat64_flag = TRUE; + else + goto unknown_flag; + break; default: unknown_flag: fatal("unknown flag: %s", argv[a]); @@ -483,13 +515,14 @@ unknown_flag: * Check to see the specified arguments are valid. */ if(info_flag == FALSE && detailed_info_flag == FALSE && + brief_info_flag == FALSE && create_flag == FALSE && thin_flag == FALSE && extract_flag == FALSE && remove_flag == FALSE && replace_flag == FALSE && verify_flag == FALSE){ error("one of -create, -thin , -extract , " "-remove , -replace , " "-verify_arch ... , " - "-info or -detailed_info must be specified"); + "-archs, -info, or -detailed_info must be specified"); usage(); } if((create_flag == TRUE || thin_flag == TRUE || extract_flag == TRUE || @@ -506,18 +539,28 @@ unknown_flag: error("only one input file allowed with -verify_arch"); usage(); } + if(brief_info_flag == TRUE && ninput_files != 1){ + error("only one input file allowed with -archs"); + usage(); + } if(create_flag + thin_flag + extract_flag + remove_flag + replace_flag + - info_flag + detailed_info_flag + verify_flag > 1){ + info_flag + detailed_info_flag + brief_info_flag + verify_flag > 1){ error("only one of -create, -thin , -extract " ", -remove , -replace , " "-verify_arch ..., " - "-info or -detailed_info can be specified"); + "-info, -archs, or -detailed_info can be specified"); usage(); } if(arch_blank_flag == TRUE && create_flag == FALSE){ error("-arch_blank may only be used with -create"); usage(); } + if (hideARM64_flag == TRUE && create_flag == FALSE && + replace_flag == FALSE && remove_flag == FALSE) { + error("-hideARM64 may only be used with -create, -remove, or " + "-replace"); + usage(); + } /* * Determine the types of the input files. @@ -533,17 +576,17 @@ unknown_flag: /* check to make sure no two files have the same architectures */ for(i = 0; i < nthin_files; i++) for(j = i + 1; j < nthin_files; j++) - if(thin_files[i].fat_arch.cputype == - thin_files[j].fat_arch.cputype && - (thin_files[i].fat_arch.cpusubtype & ~CPU_SUBTYPE_MASK)== - (thin_files[j].fat_arch.cpusubtype & ~CPU_SUBTYPE_MASK)){ + if(thin_files[i].cputype == + thin_files[j].cputype && + (thin_files[i].cpusubtype & ~CPU_SUBTYPE_MASK)== + (thin_files[j].cpusubtype & ~CPU_SUBTYPE_MASK)){ arch_flags = get_arch_flags(); for(k = 0; arch_flags[k].name != NULL; k++){ if(arch_flags[k].cputype == - thin_files[j].fat_arch.cputype && + thin_files[j].cputype && (arch_flags[k].cpusubtype & ~CPU_SUBTYPE_MASK) == - (thin_files[j].fat_arch.cpusubtype & + (thin_files[j].cpusubtype & ~CPU_SUBTYPE_MASK)) fatal("%s and %s have the same architectures (%s) " "and can't be in the same fat output file", @@ -553,8 +596,8 @@ unknown_flag: fatal("%s and %s have the same architectures (cputype " "(%d) and cpusubtype (%d)) and can't be in the " "same fat output file", thin_files[i].name, - thin_files[j].name,thin_files[i].fat_arch.cputype, - thin_files[i].fat_arch.cpusubtype & + thin_files[j].name,thin_files[i].cputype, + thin_files[i].cpusubtype & ~CPU_SUBTYPE_MASK); } create_fat(); @@ -568,8 +611,8 @@ unknown_flag: fatal("input file (%s) must be a fat file when the -thin " "option is specified", input_files[0].name); for(i = 0; i < nthin_files; i++){ - if(thin_files[i].fat_arch.cputype == thin_arch_flag.cputype && - (thin_files[i].fat_arch.cpusubtype & ~CPU_SUBTYPE_MASK) == + if(thin_files[i].cputype == thin_arch_flag.cputype && + (thin_files[i].cpusubtype & ~CPU_SUBTYPE_MASK) == (thin_arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK)){ (void)unlink(output_file); if((fd = open(output_file, O_WRONLY | O_CREAT | O_TRUNC, @@ -577,18 +620,28 @@ unknown_flag: system_fatal("can't create output file: %s", output_file); - if(write(fd, thin_files[i].addr,thin_files[i].fat_arch.size) - != (int)(thin_files[i].fat_arch.size)) - system_fatal("can't write thin file to output file: %s", - output_file); + if (write64(fd, thin_files[i].addr, thin_files[i].size) != + thin_files[i].size) + system_fatal("can't write thin file to output " + "file: %s", output_file); if(close(fd) == -1) system_fatal("can't close output file: %s",output_file); - if(utime(output_file, #ifndef __OPENSTEP__ - &output_timep) == -1) -#else - output_timep) == -1) + /* cctools-port: Replaced for portability. */ +#if 0 + if (__builtin_available(macOS 10.12, *)) { + time_result = utimensat(AT_FDCWD, output_file, + output_times, 0); + } + else { + time_result = utimes(output_file, output_timev); + } #endif + time_result = utimens(output_file, output_times); +#else + time_result = utime(output_file, output_timep); +#endif + if (time_result == -1) system_fatal("can't set the modify times for " "output file: %s", output_file); break; @@ -607,6 +660,9 @@ unknown_flag: if(input_files[0].fat_header == NULL) fatal("input file (%s) must be a fat file when the -extract " "option is specified", input_files[0].name); + if(input_files[0].fat_header->magic == FAT_MAGIC_64) + fat64_flag = TRUE; + for(i = 0; i < nextract_arch_flags; i++){ for(j = i + 1; j < nextract_arch_flags; j++){ if(extract_arch_flags[i].cputype == @@ -622,10 +678,10 @@ unknown_flag: found = FALSE; for(j = 0; j < nthin_files; j++){ if(extract_arch_flags[i].cputype == - thin_files[j].fat_arch.cputype && + thin_files[j].cputype && ((extract_arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK)== - (thin_files[j].fat_arch.cpusubtype & + (thin_files[j].cpusubtype & ~CPU_SUBTYPE_MASK) || extract_family_flag == TRUE)){ thin_files[j].extract = TRUE; @@ -657,6 +713,8 @@ unknown_flag: if(input_files[0].fat_header == NULL) fatal("input file (%s) must be a fat file when the -remove " "option is specified", input_files[0].name); + if(input_files[0].fat_header->magic == FAT_MAGIC_64) + fat64_flag = TRUE; for(i = 0; i < nremove_arch_flags; i++){ for(j = i + 1; j < nremove_arch_flags; j++){ if(remove_arch_flags[i].cputype == @@ -671,10 +729,10 @@ unknown_flag: for(i = 0; i < nremove_arch_flags; i++){ for(j = 0; j < nthin_files; j++){ if(remove_arch_flags[i].cputype == - thin_files[j].fat_arch.cputype && + thin_files[j].cputype && (remove_arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) == - (thin_files[j].fat_arch.cpusubtype & + (thin_files[j].cpusubtype & ~CPU_SUBTYPE_MASK)){ thin_files[j].remove = TRUE; break; @@ -707,6 +765,8 @@ unknown_flag: if(input_files[0].fat_header == NULL) fatal("input file (%s) must be a fat file when the -replace " "option is specified", input_files[0].name); + if(input_files[0].fat_header->magic == FAT_MAGIC_64) + fat64_flag = TRUE; for(i = 0; i < nreplaces; i++){ for(j = i + 1; j < nreplaces; j++){ if(replaces[i].arch_flag.cputype == @@ -721,9 +781,9 @@ unknown_flag: process_replace_file(replaces + i); for(j = 0; j < nthin_files; j++){ if(replaces[i].arch_flag.cputype == - thin_files[j].fat_arch.cputype && + thin_files[j].cputype && (replaces[i].arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK) == - (thin_files[j].fat_arch.cpusubtype & ~CPU_SUBTYPE_MASK)){ + (thin_files[j].cpusubtype & ~CPU_SUBTYPE_MASK)){ thin_files[j] = replaces[i].thin_file; break; } @@ -736,14 +796,45 @@ unknown_flag: create_fat(); } + if (brief_info_flag) { + for (i = 0; i < nthin_files; i++) { + const char* s = get_arch_name_if_known( + thin_files[i].cputype, + thin_files[i].cpusubtype); + if (i) { + printf(" "); + } + if (s) { + printf("%s", s); + } + else { + printf("unknown(%u,%u)", thin_files[i].cputype, + thin_files[i].cpusubtype & ~CPU_SUBTYPE_MASK); + } + } + printf("\n"); + } + if(info_flag){ for(i = 0; i < ninput_files; i++){ if(input_files[i].fat_header != NULL){ printf("Architectures in the fat file: %s are: ", input_files[i].name); - for(j = 0; j < input_files[i].fat_header->nfat_arch; j++){ - print_arch(&(input_files[i].fat_arches[j])); - printf(" "); + if(input_files[i].fat_arches != NULL){ + for(j = 0; j < input_files[i].fat_header->nfat_arch; + j++){ + print_arch(input_files[i].fat_arches[j].cputype, + input_files[i].fat_arches[j].cpusubtype); + printf(" "); + } + } + else{ + for(j = 0; j < input_files[i].fat_header->nfat_arch; + j++){ + print_arch(input_files[i].fat_arches64[j].cputype, + input_files[i].fat_arches64[j].cpusubtype); + printf(" "); + } } printf("\n"); } @@ -758,8 +849,8 @@ unknown_flag: continue; printf("Non-fat file: %s is architecture: %s\n", thin_files[i].name, - get_arch_name_from_types(thin_files[i].fat_arch.cputype, - thin_files[i].fat_arch.cpusubtype & ~CPU_SUBTYPE_MASK)); + get_arch_name_from_types(thin_files[i].cputype, + thin_files[i].cpusubtype & ~CPU_SUBTYPE_MASK)); } } @@ -769,22 +860,54 @@ unknown_flag: printf("Fat header in: %s\n", input_files[i].name); printf("fat_magic 0x%x\n", (unsigned int)(input_files[i].fat_header->magic)); - printf("nfat_arch %u\n", - input_files[i].fat_header->nfat_arch); + printf("nfat_arch %u", + input_files[i].raw_nfat_arch); + if (input_files[i].fat_header->nfat_arch - + input_files[i].raw_nfat_arch) { + printf(" (+%u hidden)", + input_files[i].fat_header->nfat_arch - + input_files[i].raw_nfat_arch); + } + printf("\n"); for(j = 0; j < input_files[i].fat_header->nfat_arch; j++){ printf("architecture "); - print_arch(&(input_files[i].fat_arches[j])); - printf("\n"); - print_cputype(input_files[i].fat_arches[j].cputype, + if(input_files[i].fat_arches != NULL){ + print_arch(input_files[i].fat_arches[j].cputype, + input_files[i].fat_arches[j].cpusubtype); + if (j >= input_files[i].raw_nfat_arch) { + printf(" (hidden)"); + } + printf("\n"); + print_cputype(input_files[i].fat_arches[j].cputype, input_files[i].fat_arches[j].cpusubtype & - ~CPU_SUBTYPE_MASK); - printf(" offset %u\n", - input_files[i].fat_arches[j].offset); - printf(" size %u\n", - input_files[i].fat_arches[j].size); - printf(" align 2^%u (%d)\n", - input_files[i].fat_arches[j].align, - 1 << input_files[i].fat_arches[j].align); + ~CPU_SUBTYPE_MASK); + printf(" offset %u\n", + input_files[i].fat_arches[j].offset); + printf(" size %u\n", + input_files[i].fat_arches[j].size); + printf(" align 2^%u (%d)\n", + input_files[i].fat_arches[j].align, + 1 << input_files[i].fat_arches[j].align); + } + else{ + print_arch(input_files[i].fat_arches64[j].cputype, + input_files[i].fat_arches64[j].cpusubtype); + if (j >= input_files[i].raw_nfat_arch) { + printf(" (hidden)"); + } + printf("\n"); + print_cputype( + input_files[i].fat_arches64[j].cputype, + input_files[i].fat_arches64[j].cpusubtype & + ~CPU_SUBTYPE_MASK); + printf(" offset %llu\n", + input_files[i].fat_arches64[j].offset); + printf(" size %llu\n", + input_files[i].fat_arches64[j].size); + printf(" align 2^%u (%d)\n", + input_files[i].fat_arches64[j].align, + 1 << input_files[i].fat_arches64[j].align); + } } } else{ @@ -797,8 +920,8 @@ unknown_flag: continue; printf("Non-fat file: %s is architecture: %s\n", thin_files[i].name, - get_arch_name_from_types(thin_files[i].fat_arch.cputype, - thin_files[i].fat_arch.cpusubtype & ~CPU_SUBTYPE_MASK)); + get_arch_name_from_types(thin_files[i].cputype, + thin_files[i].cpusubtype & ~CPU_SUBTYPE_MASK)); } } @@ -807,9 +930,9 @@ unknown_flag: found = FALSE; for(j = 0; j < nthin_files; j++){ if(verify_archs[i].cputype == - thin_files[j].fat_arch.cputype && + thin_files[j].cputype && (verify_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == - (thin_files[j].fat_arch.cpusubtype & ~CPU_SUBTYPE_MASK)){ + (thin_files[j].cpusubtype & ~CPU_SUBTYPE_MASK)){ found = TRUE; break; } @@ -829,9 +952,12 @@ static void create_fat(void) { - uint32_t i, j, offset; + uint32_t i, j; + uint64_t offset; char *rename_file; int fd; + struct fat_arch fat_arch; + struct fat_arch_64 fat_arch64; /* fold in specified segment alignments */ for(i = 0; i < nsegaligns; i++){ @@ -847,22 +973,22 @@ create_fat(void) for(i = 0; i < nsegaligns; i++){ for(j = 0; j < nthin_files; j++){ if(segaligns[i].arch_flag.cputype == - thin_files[j].fat_arch.cputype && + thin_files[j].cputype && (segaligns[i].arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK) == - (thin_files[j].fat_arch.cpusubtype & ~CPU_SUBTYPE_MASK)){ + (thin_files[j].cpusubtype & ~CPU_SUBTYPE_MASK)){ /* Since this program has to guess at alignments and guesses high when unsure this check shouldn't be used so the the correct alignment can be specified by the the user. - if(thin_files[j].fat_arch.align > segaligns[i].align) + if(thin_files[j].align > segaligns[i].align) fatal("specified segment alignment: %d for " "architecture %s is less than the alignment: %d " "required from the input file", 1 << segaligns[i].align, segaligns[i].arch_flag.name, - 1 << thin_files[j].fat_arch.align); + 1 << thin_files[j].align); */ - thin_files[j].fat_arch.align = segaligns[i].align; + thin_files[j].align = segaligns[i].align; break; } } @@ -875,22 +1001,60 @@ create_fat(void) /* sort the files by alignment to save space in the output file */ qsort(thin_files, nthin_files, sizeof(struct thin_file), (int (*)(const void *, const void *))cmp_qsort); - - /* We will order the ARM64 slice last. */ - arm64_fat_arch = get_arm64_fat_arch(); - - /* We will order the x86_64h slice last too. */ - x86_64h_fat_arch = get_x86_64h_fat_arch(); - + /* Fill in the fat header and the fat_arch's offsets. */ - fat_header.magic = FAT_MAGIC; + if(fat64_flag == TRUE) + fat_header.magic = FAT_MAGIC_64; + else + fat_header.magic = FAT_MAGIC; fat_header.nfat_arch = nthin_files; - offset = sizeof(struct fat_header) + - nthin_files * sizeof(struct fat_arch); + /* begin change for 15002326: write a hidden arm64 arch */ + if (hideARM64_flag) { + enum bool has_arm32 = FALSE; + enum bool has_arm64 = FALSE; + uint32_t num_archs = 0; + uint32_t num_archs_arm64 = 0; + + for(i = 0; i < nthin_files; i++){ + if (MH_EXECUTE != get_mh_filetype(thin_files[i].addr, + thin_files[i].size)) { + fatal("-hideARM64 specified but thin file %s is not of " + "type MH_EXECUTE", thin_files[i].name); + } + if (has_arm64 && thin_files[i].cputype != CPU_TYPE_ARM64) { + fatal("-hideARM64 specified but thin files are not in " + "correct order"); + } + if (thin_files[i].cputype == CPU_TYPE_ARM) { + has_arm32 = TRUE; + } + if (thin_files[i].cputype == CPU_TYPE_ARM64) { + has_arm64 = TRUE; + num_archs_arm64 += 1; + } + num_archs += 1; + } + if (has_arm32 && has_arm64) { + fat_header.nfat_arch = num_archs - num_archs_arm64; + } + } + /* end change for 15002326 */ + offset = sizeof(struct fat_header); + if(fat64_flag == TRUE) + offset += nthin_files * sizeof(struct fat_arch_64); + else + offset += nthin_files * sizeof(struct fat_arch); for(i = 0; i < nthin_files; i++){ - offset = rnd(offset, 1 << thin_files[i].fat_arch.align); - thin_files[i].fat_arch.offset = offset; - offset += thin_files[i].fat_arch.size; + offset = rnd(offset, 1 << thin_files[i].align); + if(fat64_flag == FALSE && offset > UINT32_MAX) + fatal("fat file too large to be created because the offset " + "field in struct fat_arch is only 32-bits and the offset " + "(%llu) for %s for architecture %s exceeds that", + offset, thin_files[i].name, + get_arch_name_from_types(thin_files[i].cputype, + thin_files[i].cpusubtype & ~CPU_SUBTYPE_MASK)); + thin_files[i].offset = offset; + offset += thin_files[i].size; } rename_file = makestr(output_file, ".lipo", NULL); @@ -906,7 +1070,7 @@ create_fat(void) #ifdef __LITTLE_ENDIAN__ swap_fat_header(&fat_header, BIG_ENDIAN_BYTE_SEX); #endif /* __LITTLE_ENDIAN__ */ - if(write(fd, &fat_header, sizeof(struct fat_header)) != + if(write64(fd, &fat_header, sizeof(struct fat_header)) != sizeof(struct fat_header)) system_fatal("can't write fat header to output file: %s", rename_file); @@ -914,70 +1078,48 @@ create_fat(void) swap_fat_header(&fat_header, LITTLE_ENDIAN_BYTE_SEX); #endif /* __LITTLE_ENDIAN__ */ for(i = 0; i < nthin_files; i++){ - /* - * If we are ordering the ARM64 slice last of the fat_arch - * structs, so skip it in this loop. - */ - if(arm64_fat_arch == &(thin_files[i].fat_arch)) - continue; - /* - * If we are ordering the x86_64h slice last too of the fat_arch - * structs, so skip it in this loop. - */ - if(x86_64h_fat_arch == &(thin_files[i].fat_arch)) - continue; + if(fat64_flag == TRUE){ + fat_arch64.cputype = thin_files[i].cputype; + fat_arch64.cpusubtype = thin_files[i].cpusubtype; + fat_arch64.offset = thin_files[i].offset; + fat_arch64.size = thin_files[i].size; + fat_arch64.align = thin_files[i].align; + } + else{ + fat_arch.cputype = thin_files[i].cputype; + fat_arch.cpusubtype = thin_files[i].cpusubtype; + fat_arch.offset = (uint32_t)thin_files[i].offset; + fat_arch.size = (uint32_t)thin_files[i].size; + fat_arch.align = thin_files[i].align; + } + if(fat64_flag == TRUE){ #ifdef __LITTLE_ENDIAN__ - swap_fat_arch(&(thin_files[i].fat_arch), 1,BIG_ENDIAN_BYTE_SEX); + swap_fat_arch_64(&fat_arch64, 1, BIG_ENDIAN_BYTE_SEX); #endif /* __LITTLE_ENDIAN__ */ - if(write(fd, &(thin_files[i].fat_arch), - sizeof(struct fat_arch)) != sizeof(struct fat_arch)) - system_fatal("can't write fat arch to output file: %s", - rename_file); + if(write64(fd, &fat_arch64, sizeof(struct fat_arch_64)) != + sizeof(struct fat_arch_64)) + system_fatal("can't write fat arch to output file: %s", + rename_file); + } + else{ #ifdef __LITTLE_ENDIAN__ - swap_fat_arch(&(thin_files[i].fat_arch), 1, - LITTLE_ENDIAN_BYTE_SEX); + swap_fat_arch(&fat_arch, 1, BIG_ENDIAN_BYTE_SEX); #endif /* __LITTLE_ENDIAN__ */ + if(write64(fd, &fat_arch, sizeof(struct fat_arch)) != + sizeof(struct fat_arch)) + system_fatal("can't write fat arch to output file: %s", + rename_file); + } } } - /* - * We are ordering the ARM64 slice so it gets written last of the - * fat_arch structs, so write it out here as it was skipped above. - */ - if(arm64_fat_arch){ -#ifdef __LITTLE_ENDIAN__ - swap_fat_arch(arm64_fat_arch, 1, BIG_ENDIAN_BYTE_SEX); -#endif /* __LITTLE_ENDIAN__ */ - if(write(fd, arm64_fat_arch, - sizeof(struct fat_arch)) != sizeof(struct fat_arch)) - system_fatal("can't write fat arch to output file: %s", - rename_file); -#ifdef __LITTLE_ENDIAN__ - swap_fat_arch(arm64_fat_arch, 1, LITTLE_ENDIAN_BYTE_SEX); -#endif /* __LITTLE_ENDIAN__ */ - } - /* - * We are ordering the x86_64h slice so it gets written last too of the - * fat_arch structs, so write it out here as it was skipped above. - */ - if(x86_64h_fat_arch){ -#ifdef __LITTLE_ENDIAN__ - swap_fat_arch(x86_64h_fat_arch, 1, BIG_ENDIAN_BYTE_SEX); -#endif /* __LITTLE_ENDIAN__ */ - if(write(fd, x86_64h_fat_arch, - sizeof(struct fat_arch)) != sizeof(struct fat_arch)) - system_fatal("can't write fat arch to output file: %s", - rename_file); -#ifdef __LITTLE_ENDIAN__ - swap_fat_arch(x86_64h_fat_arch, 1, LITTLE_ENDIAN_BYTE_SEX); -#endif /* __LITTLE_ENDIAN__ */ - } + for(i = 0; i < nthin_files; i++){ if(extract_family_flag == FALSE || nthin_files > 1) - if(lseek(fd, thin_files[i].fat_arch.offset, L_SET) == -1) + if(lseek(fd, thin_files[i].offset, L_SET) == -1) system_fatal("can't lseek in output file: %s", rename_file); - if(write(fd, thin_files[i].addr, thin_files[i].fat_arch.size) - != (int)(thin_files[i].fat_arch.size)) - system_fatal("can't write to output file: %s", rename_file); + if(write64(fd, thin_files[i].addr, thin_files[i].size) != + thin_files[i].size) + system_fatal("can't write to output file: %s", rename_file); } if(close(fd) == -1) system_fatal("can't close output file: %s", rename_file); @@ -998,7 +1140,8 @@ struct input_file *input) { int fd; struct stat stat_buf, stat_buf2; - uint32_t size, i, j; + uint32_t i, j; + uint64_t size; char *addr; struct thin_file *thin; struct mach_header *mhp, mh; @@ -1008,6 +1151,7 @@ struct input_file *input) cpu_subtype_t cpusubtype; enum bool swapped; uint64_t big_size; + uint32_t offset, first_offset; /* Open the input file and map it in */ if((fd = open(input->name, O_RDONLY)) == -1) @@ -1017,6 +1161,41 @@ struct input_file *input) size = stat_buf.st_size; /* pick up set uid, set gid and sticky text bits */ output_filemode = stat_buf.st_mode & 07777; +#ifndef __OPENSTEP__ + /* + * Select the first modify time + */ + /* cctools-port: Replaced for portability. */ +#if 0 + if (__builtin_available(macOS 10.12, *)) { + if (output_times[1].tv_sec == 0) { + memcpy(&output_times[0], &stat_buf.st_atimespec, + sizeof(struct timespec)); + memcpy(&output_times[1], &stat_buf.st_mtimespec, + sizeof(struct timespec)); + } + } else { + if (output_timev[1].tv_sec == 0) { + TIMESPEC_TO_TIMEVAL(&output_timev[0], &stat_buf.st_atimespec); + TIMESPEC_TO_TIMEVAL(&output_timev[1], &stat_buf.st_mtimespec); + } + } +#endif + /* cctools-port start */ +#ifdef HAVE_STAT_ST_MTIMESPEC + output_times[0] = stat_buf.st_atimespec; + output_times[1] = stat_buf.st_mtimespec; +#elif HAVE_STAT_ST_MTIM + output_times[0] = stat_buf.st_atim; + output_times[1] = stat_buf.st_mtim; +#else + output_times[0].tv_sec = stat_buf.st_atime; + output_times[0].tv_nsec = 0; + output_times[1].tv_sec = stat_buf.st_mtime; + output_times[0].tv_nsec = 0; +#endif + /* cctools-port end */ +#else /* * Select the eariliest modify time so that if the output file * contains archives with table of contents lipo will not make them @@ -1024,13 +1203,6 @@ struct input_file *input) * contents appear up todate if another file is combined with it that * has a date early enough. */ -#ifndef __OPENSTEP__ - if(output_timep.modtime == 0 || - output_timep.modtime > stat_buf.st_mtime){ - output_timep.actime = stat_buf.st_atime; - output_timep.modtime = stat_buf.st_mtime; - } -#else if(output_timep[1] == 0 || output_timep[1] > stat_buf.st_mtime){ output_timep[0] = stat_buf.st_atime; output_timep[1] = stat_buf.st_mtime; @@ -1062,7 +1234,7 @@ struct input_file *input) /* Try to figure out what kind of file this is */ - /* see if this file is a fat file */ + /* see if this file is a 32-bit fat file */ if(size >= sizeof(struct fat_header) && #ifdef __BIG_ENDIAN__ *((uint32_t *)addr) == FAT_MAGIC) @@ -1087,8 +1259,36 @@ struct input_file *input) if(big_size > size) fatal("truncated or malformed fat file (fat_arch structs would " "extend past the end of the file) %s", input->name); - input->fat_arches = (struct fat_arch *)(addr + - sizeof(struct fat_header)); + input->fat_arches = (struct fat_arch *) + (addr + sizeof(struct fat_header)); + /* + * begin change for 15002326: look for a hidden arm64 arch + * + * the hidden arch(es) must reside between the existing fat_arch + * list and the start of the first file. Also, the hidden arm64 + * arch(es) must be CPU_TYPE_ARM64, natch. + */ + first_offset = 0xFFFFFFFF; + input->raw_nfat_arch = input->fat_header->nfat_arch; + for(i = 0; i < input->fat_header->nfat_arch; i++){ + offset = input->fat_arches[i].offset; +#ifdef __LITTLE_ENDIAN__ + cputype = OSSwapInt32(offset); +#endif + if (offset < first_offset) + first_offset = offset; + } + if (big_size + sizeof(struct fat_arch) <= size && + big_size + sizeof(struct fat_arch) <= first_offset) { + i = input->fat_header->nfat_arch; + cputype = input->fat_arches[i].cputype; +#ifdef __LITTLE_ENDIAN__ + cputype = OSSwapInt32(cputype); +#endif + if (cputype == CPU_TYPE_ARM64) + input->fat_header->nfat_arch += 1; + } + /* end change for 15002326 */ #ifdef __LITTLE_ENDIAN__ swap_fat_arch(input->fat_arches, input->fat_header->nfat_arch, LITTLE_ENDIAN_BYTE_SEX); @@ -1135,13 +1335,104 @@ struct input_file *input) thin = new_thin(); thin->name = input->name; thin->addr = addr + input->fat_arches[i].offset; - thin->fat_arch = input->fat_arches[i]; + thin->cputype = input->fat_arches[i].cputype; + thin->cpusubtype = input->fat_arches[i].cpusubtype; + thin->offset = input->fat_arches[i].offset; + thin->size = input->fat_arches[i].size; + thin->align = input->fat_arches[i].align; thin->from_fat = TRUE; if(input->fat_arches[i].size >= SARMAG && strncmp(thin->addr, ARMAG, SARMAG) == 0) archives_in_input = TRUE; } } + /* see if this file is a 64-bit fat file */ + else if(size >= sizeof(struct fat_header) && +#ifdef __BIG_ENDIAN__ + *((uint32_t *)addr) == FAT_MAGIC_64) +#endif /* __BIG_ENDIAN__ */ +#ifdef __LITTLE_ENDIAN__ + *((uint32_t *)addr) == SWAP_INT(FAT_MAGIC_64)) +#endif /* __LITTLE_ENDIAN__ */ + { + + if(input->arch_flag.name != NULL) + fatal("architecture specifed for fat input file: %s " + "(architectures can't be specifed for fat input files)", + input->name); + + input->fat_header = (struct fat_header *)addr; +#ifdef __LITTLE_ENDIAN__ + swap_fat_header(input->fat_header, LITTLE_ENDIAN_BYTE_SEX); +#endif /* __LITTLE_ENDIAN__ */ + big_size = input->fat_header->nfat_arch; + big_size *= sizeof(struct fat_arch_64); + big_size += sizeof(struct fat_header); + if(big_size > size) + fatal("truncated or malformed fat file (fat_arch_64 structs " + "would extend past the end of the file) %s", input->name); + input->fat_arches64 = (struct fat_arch_64 *) + (addr + sizeof(struct fat_header)); +#ifdef __LITTLE_ENDIAN__ + swap_fat_arch_64(input->fat_arches64, input->fat_header->nfat_arch, + LITTLE_ENDIAN_BYTE_SEX); +#endif /* __LITTLE_ENDIAN__ */ + for(i = 0; i < input->fat_header->nfat_arch; i++){ + if(input->fat_arches64[i].offset + input->fat_arches64[i].size > + size) + fatal("truncated or malformed fat file (offset plus size " + "of cputype (%d) cpusubtype (%d) extends past the " + "end of the file) %s", input->fat_arches64[i].cputype, + input->fat_arches64[i].cpusubtype & ~CPU_SUBTYPE_MASK, + input->name); + if(input->fat_arches64[i].align > MAXSECTALIGN) + fatal("align (2^%u) too large of fat file %s (cputype (%d)" + " cpusubtype (%d)) (maximum 2^%d)", + input->fat_arches64[i].align, input->name, + input->fat_arches64[i].cputype, + input->fat_arches64[i].cpusubtype & ~CPU_SUBTYPE_MASK, + MAXSECTALIGN); + if(input->fat_arches64[i].offset % + (1 << input->fat_arches64[i].align) != 0) + fatal("offset %llu of fat file %s (cputype (%d) cpusubtype " + "(%d)) not aligned on its alignment (2^%u)", + input->fat_arches64[i].offset, input->name, + input->fat_arches64[i].cputype, + input->fat_arches64[i].cpusubtype & ~CPU_SUBTYPE_MASK, + input->fat_arches64[i].align); + } + for(i = 0; i < input->fat_header->nfat_arch; i++){ + for(j = i + 1; j < input->fat_header->nfat_arch; j++){ + if(input->fat_arches64[i].cputype == + input->fat_arches64[j].cputype && + (input->fat_arches64[i].cpusubtype & + ~CPU_SUBTYPE_MASK) == + (input->fat_arches64[j].cpusubtype & + ~CPU_SUBTYPE_MASK)) + fatal("fat file %s contains two of the same architecture " + "(cputype (%d) cpusubtype (%d))", input->name, + input->fat_arches64[i].cputype, + input->fat_arches64[i].cpusubtype & + ~CPU_SUBTYPE_MASK); + } + } + + /* create a thin file struct for each arch in the fat file */ + for(i = 0; i < input->fat_header->nfat_arch; i++){ + thin = new_thin(); + thin->name = input->name; + thin->addr = addr + input->fat_arches64[i].offset; + thin->cputype = input->fat_arches64[i].cputype; + thin->cpusubtype = input->fat_arches64[i].cpusubtype; + thin->offset = input->fat_arches64[i].offset; + thin->size = input->fat_arches64[i].size; + thin->align = input->fat_arches64[i].align; + thin->from_fat = TRUE; + if(input->fat_arches64[i].size >= SARMAG && + strncmp(thin->addr, ARMAG, SARMAG) == 0) + archives_in_input = TRUE; + } + } /* see if this file is Mach-O file for 32-bit architectures */ else if(size >= sizeof(struct mach_header) && (*((uint32_t *)addr) == MH_MAGIC || @@ -1163,12 +1454,15 @@ struct input_file *input) } else swapped = FALSE; - thin->fat_arch.cputype = mhp->cputype; - thin->fat_arch.cpusubtype = mhp->cpusubtype; - thin->fat_arch.offset = 0; - thin->fat_arch.size = size; - thin->fat_arch.align = get_align(mhp, lcp, size, input->name, - swapped); + if(fat64_flag == FALSE && size > UINT32_MAX) + fatal("file too large to be in a fat file because the size " + "field in struct fat_arch is only 32-bits and the size " + "(%llu) of %s exceeds that", size, input->name); + thin->cputype = mhp->cputype; + thin->cpusubtype = mhp->cpusubtype; + thin->offset = 0; + thin->size = size; + thin->align = get_align(mhp, lcp, size, input->name, swapped); /* if the arch type is specified make sure it matches the object */ if(input->arch_flag.name != NULL) @@ -1195,12 +1489,15 @@ struct input_file *input) } else swapped = FALSE; - thin->fat_arch.cputype = mhp64->cputype; - thin->fat_arch.cpusubtype = mhp64->cpusubtype; - thin->fat_arch.offset = 0; - thin->fat_arch.size = size; - thin->fat_arch.align = get_align_64(mhp64, lcp, size, input->name, - swapped); + if(fat64_flag == FALSE && size > UINT32_MAX) + fatal("file too large to be in a fat file because the size " + "field in struct fat_arch is only 32-bits and the size " + "(%llu) of %s exceeds that", size, input->name); + thin->cputype = mhp64->cputype; + thin->cpusubtype = mhp64->cpusubtype; + thin->offset = 0; + thin->size = size; + thin->align = get_align_64(mhp64, lcp, size, input->name, swapped); /* if the arch type is specified make sure it matches the object */ if(input->arch_flag.name != NULL) @@ -1214,22 +1511,27 @@ struct input_file *input) /* create a thin file struct for this archive */ thin = new_thin(); + input->is_thin = TRUE; thin->name = input->name; thin->addr = addr; - thin->fat_arch.cputype = cputype; - thin->fat_arch.cpusubtype = cpusubtype; - thin->fat_arch.offset = 0; - thin->fat_arch.size = size; - if(thin->fat_arch.cputype & CPU_ARCH_ABI64) - thin->fat_arch.align = 3; /* 2^3, alignof(uint64_t) */ + if(fat64_flag == FALSE && size > UINT32_MAX) + fatal("file too large to be in a fat file because the size " + "field in struct fat_arch is only 32-bits and the size " + "(%llu) of %s exceeds that", size, input->name); + thin->cputype = cputype; + thin->cpusubtype = cpusubtype; + thin->offset = 0; + thin->size = size; + if(thin->cputype & CPU_ARCH_ABI64) + thin->align = 3; /* 2^3, alignof(uint64_t) */ else - thin->fat_arch.align = 2; /* 2^2, alignof(uint32_t) */ + thin->align = 2; /* 2^2, alignof(uint32_t) */ /* if the arch type is specified make sure it matches the object */ if(input->arch_flag.name != NULL){ if(cputype == 0){ - thin->fat_arch.cputype = input->arch_flag.cputype; - thin->fat_arch.cpusubtype = input->arch_flag.cpusubtype; + thin->cputype = input->arch_flag.cputype; + thin->cpusubtype = input->arch_flag.cpusubtype; } else check_arch(input, thin); @@ -1248,25 +1550,34 @@ struct input_file *input) thin = new_thin(); thin->name = input->name; thin->addr = addr; - thin->fat_arch.cputype = input->arch_flag.cputype; - thin->fat_arch.cpusubtype = input->arch_flag.cpusubtype; - thin->fat_arch.offset = 0; - thin->fat_arch.size = size; - thin->fat_arch.align = 0; + if(fat64_flag == FALSE && size > UINT32_MAX) + fatal("file too large to be in a fat file because the size " + "field in struct fat_arch is only 32-bits and the " + "size (%llu) of %s exceeds that", size, input->name); + thin->cputype = input->arch_flag.cputype; + thin->cpusubtype = input->arch_flag.cpusubtype; + thin->offset = 0; + thin->size = size; + thin->align = 0; } else{ #ifdef LTO_SUPPORT - if(is_llvm_bitcode_from_memory(addr, size, &input->arch_flag, - NULL) != 0){ + if(is_llvm_bitcode_from_memory(addr, (uint32_t)size, + &input->arch_flag, NULL) != 0){ /* create a thin file struct for it */ thin = new_thin(); thin->name = input->name; thin->addr = addr; - thin->fat_arch.cputype = input->arch_flag.cputype; - thin->fat_arch.cpusubtype = input->arch_flag.cpusubtype; - thin->fat_arch.offset = 0; - thin->fat_arch.size = size; - thin->fat_arch.align = 0; + if(fat64_flag == FALSE && size > UINT32_MAX) + fatal("file too large to be in a fat file because the " + "size field in struct fat_arch is only 32-bits " + "and the size (%llu) of %s exceeds that", size, + input->name); + thin->cputype = input->arch_flag.cputype; + thin->cpusubtype = input->arch_flag.cpusubtype; + thin->offset = 0; + thin->size = size; + thin->align = 0; } else #endif /* LTO_SUPPORT */ @@ -1287,7 +1598,7 @@ struct replace *replace) { int fd; struct stat stat_buf; - uint32_t size; + uint64_t size; char *addr; struct mach_header *mhp, mh; struct mach_header_64 *mhp64, mh64; @@ -1322,7 +1633,15 @@ struct replace *replace) /* see if this file is a fat file */ if(size >= sizeof(struct fat_header) && - *((uint32_t *)addr) == FAT_MAGIC){ +#ifdef __BIG_ENDIAN__ + (*((uint32_t *)addr) == FAT_MAGIC || + *((uint32_t *)addr) == FAT_MAGIC_64)) +#endif /* __BIG_ENDIAN__ */ +#ifdef __LITTLE_ENDIAN__ + (*((uint32_t *)addr) == SWAP_INT(FAT_MAGIC) || + *((uint32_t *)addr) == SWAP_INT(FAT_MAGIC_64))) +#endif /* __LITTLE_ENDIAN__ */ + { fatal("replacement file: %s is a fat file (must be a thin file)", replace->thin_file.name); @@ -1345,11 +1664,16 @@ struct replace *replace) } else swapped = FALSE; - replace->thin_file.fat_arch.cputype = mhp->cputype; - replace->thin_file.fat_arch.cpusubtype = mhp->cpusubtype; - replace->thin_file.fat_arch.offset = 0; - replace->thin_file.fat_arch.size = size; - replace->thin_file.fat_arch.align = + if(fat64_flag == FALSE && size > UINT32_MAX) + fatal("file too large to be in a fat file because the " + "size field in struct fat_arch is only 32-bits " + "and the size (%llu) of %s exceeds that", size, + replace->thin_file.name); + replace->thin_file.cputype = mhp->cputype; + replace->thin_file.cpusubtype = mhp->cpusubtype; + replace->thin_file.offset = 0; + replace->thin_file.size = size; + replace->thin_file.align = get_align(mhp, lcp, size, replace->thin_file.name, swapped); } /* see if this file is Mach-O file for 64-bit architectures */ @@ -1370,11 +1694,16 @@ struct replace *replace) } else swapped = FALSE; - replace->thin_file.fat_arch.cputype = mhp64->cputype; - replace->thin_file.fat_arch.cpusubtype = mhp64->cpusubtype; - replace->thin_file.fat_arch.offset = 0; - replace->thin_file.fat_arch.size = size; - replace->thin_file.fat_arch.align = + if(fat64_flag == FALSE && size > UINT32_MAX) + fatal("file too large to be in a fat file because the " + "size field in struct fat_arch is only 32-bits " + "and the size (%llu) of %s exceeds that", size, + replace->thin_file.name); + replace->thin_file.cputype = mhp64->cputype; + replace->thin_file.cpusubtype = mhp64->cpusubtype; + replace->thin_file.offset = 0; + replace->thin_file.size = size; + replace->thin_file.align = get_align_64(mhp64, lcp, size, replace->thin_file.name, swapped); } /* see if this file is an archive file */ @@ -1383,27 +1712,36 @@ struct replace *replace) check_archive(replace->thin_file.name, addr, size, &cputype, &cpusubtype); + if(fat64_flag == FALSE && size > UINT32_MAX) + fatal("file too large to be in a fat file because the " + "size field in struct fat_arch is only 32-bits " + "and the size (%llu) of %s exceeds that", size, + replace->thin_file.name); /* fill in the thin file struct for this archive */ replace->thin_file.addr = addr; - replace->thin_file.fat_arch.cputype = cputype; - replace->thin_file.fat_arch.cpusubtype = cpusubtype; - replace->thin_file.fat_arch.offset = 0; - replace->thin_file.fat_arch.size = size; - replace->thin_file.fat_arch.align = 2; /* 2^2, sizeof(uint32_t) */ + replace->thin_file.cputype = cputype; + replace->thin_file.cpusubtype = cpusubtype; + replace->thin_file.offset = 0; + replace->thin_file.size = size; + replace->thin_file.align = 2; /* 2^2, sizeof(uint32_t) */ } else{ + if(fat64_flag == FALSE && size > UINT32_MAX) + fatal("file too large to be in a fat file because the " + "size field in struct fat_arch is only 32-bits " + "and the size (%llu) of %s exceeds that", size, + replace->thin_file.name); /* fill in the thin file struct for it */ replace->thin_file.addr = addr; - replace->thin_file.fat_arch.cputype = replace->arch_flag.cputype; - replace->thin_file.fat_arch.cpusubtype = - replace->arch_flag.cpusubtype; - replace->thin_file.fat_arch.offset = 0; - replace->thin_file.fat_arch.size = size; - replace->thin_file.fat_arch.align = 0; + replace->thin_file.cputype = replace->arch_flag.cputype; + replace->thin_file.cpusubtype = replace->arch_flag.cpusubtype; + replace->thin_file.offset = 0; + replace->thin_file.size = size; + replace->thin_file.align = 0; } - if(replace->thin_file.fat_arch.cputype != replace->arch_flag.cputype || - (replace->thin_file.fat_arch.cpusubtype & ~CPU_SUBTYPE_MASK) != + if(replace->thin_file.cputype != replace->arch_flag.cputype || + (replace->thin_file.cpusubtype & ~CPU_SUBTYPE_MASK) != (replace->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK)) fatal("specified architecture: %s for replacement file: %s does " "not match the file's architecture", replace->arch_flag.name, @@ -1420,11 +1758,12 @@ void check_archive( char *name, char *addr, -uint32_t size, +uint64_t size, cpu_type_t *cputype, cpu_subtype_t *cpusubtype) { - uint32_t offset, magic, i, ar_name_size, ar_size; + uint64_t offset; + uint32_t magic, i, ar_name_size, ar_size; struct mach_header mh; struct mach_header_64 mh64; struct ar_hdr *ar_hdr; @@ -1461,7 +1800,13 @@ cpu_subtype_t *cpusubtype) if(size + ar_name_size - offset > sizeof(uint32_t)){ memcpy(&magic, addr + offset + ar_name_size, sizeof(uint32_t)); - if(magic == FAT_MAGIC) +#ifdef __BIG_ENDIAN__ + if(magic == FAT_MAGIC || magic == FAT_MAGIC_64) +#endif /* __BIG_ENDIAN__ */ +#ifdef __LITTLE_ENDIAN__ + if(magic == SWAP_INT(FAT_MAGIC) || + magic == SWAP_INT(FAT_MAGIC_64)) +#endif /* __LITTLE_ENDIAN__ */ fatal("archive member %s(%.*s) is a fat file (not " "allowed in an archive)", name, (int)i, ar_name); if((size - ar_name_size) - offset >= @@ -1484,6 +1829,17 @@ cpu_subtype_t *cpusubtype) ~CPU_SUBTYPE_MASK, *cputype, (*cpusubtype) & ~CPU_SUBTYPE_MASK); } + else { + if (mh.cputype == CPU_TYPE_ARM && + *cpusubtype != mh.cpusubtype) + fatal("archive member %s(%.*s) cputype (%d) and " + "cpusubtype (%d) does not match previous " + "archive members cputype (%d) and cpusubtype" + " (%d) (all members must match)", name, + (int)i, ar_name, mh.cputype, mh.cpusubtype & + ~CPU_SUBTYPE_MASK, *cputype, (*cpusubtype) & + ~CPU_SUBTYPE_MASK); + } } else if((size - ar_name_size) - offset >= sizeof(struct mach_header_64) && @@ -1505,11 +1861,23 @@ cpu_subtype_t *cpusubtype) ~CPU_SUBTYPE_MASK, *cputype, (*cpusubtype) & ~CPU_SUBTYPE_MASK); } + else { + if ((mh64.cputype == CPU_TYPE_X86_64 || + mh64.cputype == CPU_TYPE_ARM64) && + *cpusubtype != mh64.cpusubtype) + fatal("archive member %s(%.*s) cputype (%d) and " + "cpusubtype (%d) does not match previous " + "archive members cputype (%d) and cpusubtype" + " (%d) (all members must match)", name, + (int)i, ar_name, mh64.cputype, mh64.cpusubtype & + ~CPU_SUBTYPE_MASK, *cputype, (*cpusubtype) & + ~CPU_SUBTYPE_MASK); + } } else{ if(strncmp(ar_name, SYMDEF, sizeof(SYMDEF) - 1) != 0){ ar_addr = addr + offset + ar_name_size; - ar_size = strtoul(ar_hdr->ar_size, NULL, 10); + ar_size = (uint32_t)strtoul(ar_hdr->ar_size, NULL, 10); #ifdef LTO_SUPPORT if(is_llvm_bitcode_from_memory(ar_addr, ar_size, &arch_flag, NULL) != 0){ @@ -1532,7 +1900,7 @@ cpu_subtype_t *cpusubtype) } } } - offset += rnd(strtoul(ar_hdr->ar_size, NULL, 10), + offset += rnd64(strtoul(ar_hdr->ar_size, NULL, 10), sizeof(short)); } } @@ -1544,7 +1912,7 @@ void check_extend_format_1( char *name, struct ar_hdr *ar_hdr, -uint32_t size_left, +uint64_t size_left, uint32_t *member_name_size) { char *p, *endp, buf[sizeof(ar_hdr->ar_name)+1]; @@ -1559,7 +1927,7 @@ uint32_t *member_name_size) fatal("archive: %s malformed (ar_name: %.*s for archive extend " "format #1 starts with non-digit)", name, (int)sizeof(ar_hdr->ar_name), ar_hdr->ar_name); - ar_name_size = strtoul(p, &endp, 10); + ar_name_size = (uint32_t)strtoul(p, &endp, 10); if(ar_name_size == UINT_MAX && errno == ERANGE) fatal("archive: %s malformed (size in ar_name: %.*s for archive " "extend format #1 overflows uint32_t)", name, @@ -1578,73 +1946,100 @@ uint32_t *member_name_size) } /* - * get_arm64_fat_arch() will return a pointer to the fat_arch struct for the - * 64-bit arm slice in the thin_files[i] if it is present. Else it returns - * NULL. + * get_default_align() returns the default segment alignment for the specified + * cputype and cpusubtype, as an exponent of a power of 2; e.g., a segment + * alignment of 0x4000 will be described as 14. If the default alignment is not + * known it will return 0. */ static -struct fat_arch * -get_arm64_fat_arch( -void) +uint32_t +get_default_align( +cpu_type_t cputype, +cpu_subtype_t cpusubtype) { - uint32_t i; - struct fat_arch *arm64_fat_arch; - - /* - * Look for a 64-bit arm slice. - */ - arm64_fat_arch = NULL; - for(i = 0; i < nthin_files; i++){ - if(thin_files[i].fat_arch.cputype == CPU_TYPE_ARM64){ - arm64_fat_arch = &(thin_files[i].fat_arch); - return(arm64_fat_arch); - } + const char* arch_name = get_arch_name_from_types(cputype, cpusubtype); + if (arch_name != NULL) { + struct arch_flag arch_flag; + if (get_arch_from_flag((char*)arch_name, &arch_flag)) { + uint32_t pagesize = get_segalign_from_flag(&arch_flag); + return (uint32_t)(log2(pagesize)); } - return(NULL); + } + + return 0; } /* - * get_x86_64h_fat_arch() will return a pointer to the fat_arch struct for the - * x86_64h slice in the thin_files[i] if it is present. Else it returns - * NULL. + * get_mh_filetype() gets the filetype from the mach-o pointed to by addr. + * will return 0 if addr does not point to a struct mach_header or struct + * mach_header_64. */ -static -struct fat_arch * -get_x86_64h_fat_arch( -void) +static uint32_t get_mh_filetype( + char* addr, + uint64_t size) { - uint32_t i; - struct fat_arch *x86_64h_fat_arch; - - /* - * Look for a x86_64h slice. - */ - x86_64h_fat_arch = NULL; - for(i = 0; i < nthin_files; i++){ - if(thin_files[i].fat_arch.cputype == CPU_TYPE_X86_64 && - (thin_files[i].fat_arch.cpusubtype & ~CPU_SUBTYPE_MASK) == - CPU_SUBTYPE_X86_64_H){ - x86_64h_fat_arch = &(thin_files[i].fat_arch); - return(x86_64h_fat_arch); - } - } - return(NULL); + uint32_t filetype; + uint32_t magic; + struct mach_header mh32; + struct mach_header_64 mh64; + + filetype = 0; + + if (size >= sizeof(magic)) { + magic = *(uint32_t*)(addr); + if (magic == MH_MAGIC || magic == MH_CIGAM) { + if (size >= sizeof(mh32)) { + memcpy(&mh32, addr, sizeof(mh32)); + if (magic == MH_CIGAM) + swap_mach_header(&mh32, get_host_byte_sex()); + filetype = mh32.filetype; + } + } + else if (magic == MH_MAGIC_64 || magic == MH_CIGAM_64) { + if (size >= sizeof(mh64)) { + memcpy(&mh64, addr, sizeof(mh64)); + if (magic == MH_CIGAM) + swap_mach_header_64(&mh64, get_host_byte_sex()); + filetype = mh64.filetype; + } + } + } + + return filetype; } /* - * get_align is passed a pointer to a mach header and size of the object. It - * returns the segment alignment the object was created with. It guesses but - * it is conservative. The maximum alignment is that the link editor will allow - * MAXSECTALIGN and the minimum is the conserative alignment for a uint32_t - * which appears in a mach object files (2^2 worst case for all current 32-bit - * machines). + * get_align() returns the segment alignment for this object, as an exponent of + * a power of 2; e.g., a segment alignment of 0x4000 will be described as 14. + * Since the actual segment alignment used by the linker is not recorded in the + * Mach-O file, get_align() will choose an alignment based on the file contents. + * + * If the mach_header points to a well-known cputype, get_align() will return + * the default segment alignment for that cputype. No attempt will be made to + * guess the "-segalign" flag passed into ld(1). + * + * If the cputype isn't recognized, get_align() will issue a warning (this is + * potentially a serious configuration error) and fall back to historical + * methods: + * + * If the Mach-O is an MH_OBJECT (.o) file, get_align() will return the + * largest section alignment within the first-and-only segment. + * + * If the Mach-O is any other file type, get_align() will guess the alignment + * for each segment from vmaddr, and then return the smallest such value. + * Since all well-formed segments are required to be page aligned, the + * resulting alignment will be legal, but there is a risk that unlucky + * binaries will choose an alignment value that is larger than necessary. + * + * In either fall back method, the result of get_align() will be bounded by + * 2 (which is log2(sizeof(uint32_t))) and MAXSECTALIGN. */ static uint32_t get_align( struct mach_header *mhp, struct load_command *load_commands, -uint32_t size, +uint64_t size, char *name, enum bool swapped) { @@ -1653,20 +2048,19 @@ enum bool swapped) struct segment_command *sgp, sg; struct section *sp, s; enum byte_sex host_byte_sex; - + /* - * Special case ppc and i386 architectures and return 12. - * We know that with those architectures that the kernel and mmap only - * need file offsets to be page (4096 byte) aligned. + * Special case well-known architectures. We know that for these + * architectures that the Darwin kernel and mmap require file offsets + * to be page aligned. */ - if(mhp->cputype == CPU_TYPE_POWERPC || - mhp->cputype == CPU_TYPE_I386) - return(12); - /* - * Special case ARM and return 14. As it has 16k pages. - */ - if(mhp->cputype == CPU_TYPE_ARM) - return(14); + align = get_default_align(mhp->cputype, mhp->cpusubtype); + if (align != 0) + return align; + + warning("unknown cputype (%u) cpusubtype (%u), computing the segment " + "alignment from file contents.", mhp->cputype, + mhp->cpusubtype & ~CPU_SUBTYPE_MASK); host_byte_sex = get_host_byte_sex(); @@ -1724,19 +2118,20 @@ enum bool swapped) } /* - * get_align_64 is passed a pointer to a mach_header_64 and size of the object. - * It returns the segment alignment the object was created with. It guesses but - * it is conservative. The maximum alignment is that the link editor will allow - * MAXSECTALIGN and the minimum is the conserative alignment for a long long - * which appears in a mach object files (2^3 worst case for all 64-bit - * machines). + * get_align_64() returns the segment alignment for this object, as an exponent + * of a power of 2; e.g., a segment alignment of 0x4000 will be described as 14. + * The method of determining the segment alignment is the same as get_align() + * above. + * + * In either fall back method, the result of get_align_64() will be bounded by + * 3 (which is log2(sizeof(uint64_t))) and MAXSECTALIGN. */ static uint32_t get_align_64( struct mach_header_64 *mhp64, struct load_command *load_commands, -uint32_t size, +uint64_t size, char *name, enum bool swapped) { @@ -1747,19 +2142,18 @@ enum bool swapped) enum byte_sex host_byte_sex; /* - * Special case ppc64 and x86_64 architectures and return 12. - * We know that with those architectures that the kernel and mmap only - * need file offsets to be page (4096 byte) aligned. + * Special case well-known architectures. We know that for these + * architectures that the Darwin kernel and mmap require file offsets + * to be page aligned. */ - if(mhp64->cputype == CPU_TYPE_POWERPC64 || - mhp64->cputype == CPU_TYPE_X86_64) - return(12); - /* - * Special case ARM64 and return 14. As it has 16k pages. - */ - if(mhp64->cputype == CPU_TYPE_ARM64) - return(14); + align = get_default_align(mhp64->cputype, mhp64->cpusubtype); + if (align != 0) + return align; + warning("unknown cputype (%u) cpusubtype (%u), computing the segment " + "alignment from file contents.", mhp64->cputype, + mhp64->cpusubtype & ~CPU_SUBTYPE_MASK); + host_byte_sex = get_host_byte_sex(); /* set worst case the link editor uses first */ @@ -1823,9 +2217,10 @@ enum bool swapped) static uint32_t guess_align( -uint32_t vmaddr) +uint64_t vmaddr) { - uint32_t align, segalign; + uint32_t align; + uint64_t segalign; if(vmaddr == 0) return(MAXSECTALIGN); @@ -1852,11 +2247,12 @@ uint32_t vmaddr) static void print_arch( -struct fat_arch *fat_arch) +cpu_type_t cputype, +cpu_subtype_t cpusubtype) { - switch(fat_arch->cputype){ + switch(cputype){ case CPU_TYPE_MC680x0: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_MC680x0_ALL: printf("m68k"); break; @@ -1871,7 +2267,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_POWERPC: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_POWERPC_ALL: printf("ppc"); break; @@ -1910,7 +2306,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_POWERPC64: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_POWERPC_ALL: printf("ppc64"); break; @@ -1922,7 +2318,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_VEO: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_VEO_1: printf("veo1"); break; @@ -1940,7 +2336,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_MC88000: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_MC88000_ALL: case CPU_SUBTYPE_MC88110: printf("m88k"); @@ -1950,7 +2346,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_I386: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_I386_ALL: /* case CPU_SUBTYPE_386: same as above */ printf("i386"); @@ -1978,7 +2374,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_X86_64: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_X86_64_ALL: printf("x86_64"); break; @@ -1990,7 +2386,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_I860: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_I860_ALL: case CPU_SUBTYPE_I860_860: printf("i860"); @@ -2000,7 +2396,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_HPPA: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_HPPA_ALL: case CPU_SUBTYPE_HPPA_7100LC: printf("hppa"); @@ -2010,7 +2406,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_SPARC: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_SPARC_ALL: printf("sparc"); break; @@ -2019,7 +2415,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_ARM: - switch(fat_arch->cpusubtype){ + switch(cpusubtype){ case CPU_SUBTYPE_ARM_ALL: printf("arm"); break; @@ -2061,19 +2457,31 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_ARM64: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_ARM64_ALL: printf("arm64"); break; case CPU_SUBTYPE_ARM64_V8: printf("arm64v8"); break; + case CPU_SUBTYPE_ARM64E: + printf("arm64e"); + break; + default: + goto print_arch_unknown; + } + break; + case CPU_TYPE_ARM64_32: + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ + case CPU_SUBTYPE_ARM64_32_V8: + printf("arm64_32"); + break; default: goto print_arch_unknown; } break; case CPU_TYPE_ANY: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_MULTIPLE: printf("any"); break; @@ -2089,8 +2497,8 @@ struct fat_arch *fat_arch) break; print_arch_unknown: default: - printf("(cputype (%d) cpusubtype (%d))", fat_arch->cputype, - fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK); + printf("(cputype (%d) cpusubtype (%d))", cputype, + cpusubtype & ~CPU_SUBTYPE_MASK); break; } } @@ -2375,6 +2783,20 @@ cpu_subtype_t cpusubtype) printf(" cputype CPU_TYPE_ARM64\n" " cpusubtype CPU_SUBTYPE_ARM64_V8\n"); break; + case CPU_SUBTYPE_ARM64E: + printf(" cputype CPU_TYPE_ARM64\n" + " cpusubtype CPU_SUBTYPE_ARM64E\n"); + break; + default: + goto print_arch_unknown; + } + break; + case CPU_TYPE_ARM64_32: + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ + case CPU_SUBTYPE_ARM64_32_V8: + printf(" cputype CPU_TYPE_ARM64_32\n" + " cpusubtype CPU_SUBTYPE_ARM64_32_V8\n"); + break; default: goto print_arch_unknown; } @@ -2521,22 +2943,18 @@ cmp_qsort( const struct thin_file *thin1, const struct thin_file *thin2) { - return(thin1->fat_arch.align - thin2->fat_arch.align); -} + /* if cpu types match, sort by cpu subtype */ + if (thin1->cputype == thin2->cputype) + return thin1->cpusubtype - thin2->cpusubtype; -/* - * rnd() rounds v to a multiple of r. - */ -static -uint32_t -rnd( -uint32_t v, -uint32_t r) -{ - r--; - v += r; - v &= ~(int32_t)r; - return(v); + /* force arm64-family to follow after all other slices */ + if (thin1->cputype == CPU_TYPE_ARM64) + return 1; + if (thin2->cputype == CPU_TYPE_ARM64) + return -1; + + /* sort all other cpu types by alignment */ + return thin1->align - thin2->align; } /* @@ -2570,12 +2988,12 @@ check_arch( struct input_file *input, struct thin_file *thin) { - if(input->arch_flag.cputype != thin->fat_arch.cputype) + if(input->arch_flag.cputype != thin->cputype) fatal("specifed architecture type (%s) for file (%s) does " "not match its cputype (%d) and cpusubtype (%d) " "(should be cputype (%d) and cpusubtype (%d))", input->arch_flag.name, input->name, - thin->fat_arch.cputype, thin->fat_arch.cpusubtype & + thin->cputype, thin->cpusubtype & ~CPU_SUBTYPE_MASK, input->arch_flag.cputype, input->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK); } @@ -2600,14 +3018,14 @@ struct arch_flag *arch) target_page_size = get_segalign_from_flag(arch); file->addr = allocate(target_page_size); memset(file->addr, '\0', target_page_size); - file->fat_arch.cputype = arch->cputype; - file->fat_arch.cpusubtype = arch->cpusubtype; - file->fat_arch.offset = 0; - file->fat_arch.size = target_page_size; + file->cputype = arch->cputype; + file->cpusubtype = arch->cpusubtype; + file->offset = 0; + file->size = target_page_size; onebit = 1; for(align = 1; (target_page_size & onebit) != onebit; align++) onebit = onebit << 1; - file->fat_arch.align = align; + file->align = align; host_byte_sex = get_host_byte_sex(); target_byte_sex = get_byte_sex_from_flag(arch); @@ -2634,17 +3052,30 @@ struct arch_flag *arch) } /* - * Print the current usage line and exit (by calling fatal). + * Print the current usage line and exit. */ static void usage(void) { - fatal("Usage: %s [input_file] ... [-arch input_file] ... " - "[-info] [-detailed_info] [-output output_file] [-create] " - "[-arch_blank ] [-thin ] " - "[-remove ] ... [-extract ] ... " - "[-extract_family ] ... " - "[-verify_arch ...] " - "[-replace ] ...", progname); + fprintf(stderr, +"usage: lipo [ ...]\n" +" command is one of:\n" +" -archs\n" +" -create [-arch_blank ]\n" +" -detailed_info\n" +" -extract [-extract ...]\n" +" -extract_family [-extract_family ...]\n" +" -info\n" +" -remove [-remove ...]\n" +" -replace [-replace ...]\n" +" -thin \n" +" -verify_arch ...\n" +" options are one or more of:\n" +" -arch \n" +" -hideARM64\n" +" -output \n" +" -segalign \n" + ); + exit(EXIT_FAILURE); } diff --git a/cctools/misc/nm.c b/cctools/misc/nm.c index c860ae2..ce69f68 100644 --- a/cctools/misc/nm.c +++ b/cctools/misc/nm.c @@ -85,6 +85,7 @@ #include #include #include +#include /* cctools-port: For bcmp, bzero ... */ #include #include #include @@ -96,6 +97,7 @@ #include "stuff/errors.h" #include "stuff/allocate.h" #include "stuff/guess_short_name.h" +#include "stuff/write64.h" #ifdef LTO_SUPPORT #include "stuff/lto.h" #include @@ -162,7 +164,7 @@ struct process_flags { }; struct symbol { - char *name; + const char *name; char *indr_name; struct nlist_64 nl; }; @@ -501,7 +503,7 @@ struct ofile *ofile, char *arch_name, void *cookie) { - uint32_t ncmds, mh_flags; + uint32_t ncmds, mh_flags, mh_filetype; struct cmd_flags *cmd_flags; struct process_flags process_flags; uint32_t i, j, k; @@ -529,10 +531,6 @@ void *cookie) /* cctools-port start */ memset(&process_flags, '\0', sizeof(process_flags)); -#ifdef LTO_SUPPORT - llvm_bundle_pointer = NULL; - llvm_bundle_size = 0; -#endif /* LTO_SUPPORT */ /* cctools-port end */ cmd_flags = (struct cmd_flags *)cookie; @@ -549,6 +547,11 @@ void *cookie) process_flags.nlibs = 0; process_flags.lib_names = NULL; +#ifdef LTO_SUPPORT + llvm_bundle_pointer = NULL; + llvm_bundle_size = 0; +#endif /* LTO_SUPPORT */ + if(ofile->mh == NULL && ofile->mh64 == NULL){ #ifdef LTO_SUPPORT if(ofile->lto != NULL) @@ -562,10 +565,12 @@ void *cookie) if(ofile->mh != NULL){ ncmds = ofile->mh->ncmds; mh_flags = ofile->mh->flags; + mh_filetype = ofile->mh->filetype; } else{ ncmds = ofile->mh64->ncmds; mh_flags = ofile->mh64->flags; + mh_filetype = ofile->mh64->filetype; } for(i = 0; i < ncmds; i++){ if(st == NULL && lc->cmd == LC_SYMTAB){ @@ -670,6 +675,10 @@ void *cookie) if(strcmp((s64 + j)->sectname, SECT_TEXT) == 0 && strcmp((s64 + j)->segname, SEG_TEXT) == 0) process_flags.text_nsect = k + 1; + else if(mh_filetype == MH_KEXT_BUNDLE && + strcmp((s64 + j)->sectname, SECT_TEXT) == 0 && + strcmp((s64 + j)->segname, "__TEXT_EXEC") == 0) + process_flags.text_nsect = k + 1; else if(strcmp((s64 + j)->sectname, SECT_DATA) == 0 && strcmp((s64 + j)->segname, SEG_DATA) == 0) process_flags.data_nsect = k + 1; @@ -1073,7 +1082,7 @@ struct cmd_flags *cmd_flags) return; xar_fd = mkstemp(xar_filename); - if(write(xar_fd, llvm_bundle_pointer, llvm_bundle_size) != + if(write64(xar_fd, llvm_bundle_pointer, llvm_bundle_size) != llvm_bundle_size){ if(ofile->xar_member_name != NULL) system_error("Can't write (__LLVM,__bundle) section contents " @@ -1768,6 +1777,11 @@ char *arch_name) (symbols[i].nl.n_desc & N_ALT_ENTRY) == N_ALT_ENTRY) printf("[alt entry] "); + if(ofile->mh_filetype == MH_OBJECT && + ((symbols[i].nl.n_type & N_TYPE) != N_UNDF) && + (symbols[i].nl.n_desc & N_COLD_FUNC) == N_COLD_FUNC) + printf("[cold func] "); + if((symbols[i].nl.n_desc & N_ARM_THUMB_DEF) == N_ARM_THUMB_DEF) printf("[Thumb] "); @@ -1818,7 +1832,8 @@ struct value_diff *value_diffs) { uint32_t i; unsigned char c; - char *ta_xfmt, *i_xfmt, *spaces, *dashes, *p; + char *ta_xfmt, *i_xfmt, *spaces, *dashes; + const char *p; if(ofile->mh != NULL || (ofile->lto != NULL && @@ -1872,7 +1887,7 @@ struct value_diff *value_diffs) else{ printf(" (indirect for "); printf(ta_xfmt, symbols[i].nl.n_value); - printf(" %s)\n", symbols[i].indr_name); + printf(" %s)\n", symbols[i].nl.n_value + strings); } } else diff --git a/cctools/misc/pagestuff.c b/cctools/misc/pagestuff.c index c7357dd..2981514 100644 --- a/cctools/misc/pagestuff.c +++ b/cctools/misc/pagestuff.c @@ -81,6 +81,8 @@ enum mach_o_part_type { MP_DATA_IN_CODE, MP_CODE_SIGN_DRS, MP_LINK_OPT_HINT, + MP_DYLD_CHAINED_FIXUPS, + MP_DYLD_EXPORTS_TRIE, MP_DYLD_INFO_REBASE, MP_DYLD_INFO_BIND, MP_DYLD_INFO_WEAK_BIND, @@ -114,6 +116,8 @@ static char *mach_o_part_type_names[] = { "MP_DATA_IN_CODE", "MP_CODE_SIGN_DRS", "MP_LINK_OPT_HINT", + "MP_DYLD_CHAINED_FIXUPS", + "MP_DYLD_EXPORTS_TRIE", "MP_DYLD_INFO_REBASE", "MP_DYLD_INFO_BIND", "MP_DYLD_INFO_WEAK_BIND", @@ -169,7 +173,7 @@ static void print_mach_o_parts( struct mach_o_part *mp); static void print_parts_for_page( - uint32_t page_number); + uint64_t page_number); static void print_arch( struct file_part *fp); static void print_file_part( @@ -208,7 +212,7 @@ int argc, char *argv[]) { int i, start; - uint32_t j, page_number; + uint64_t j, page_number; char *endp; struct arch_flag a; @@ -239,6 +243,8 @@ char *argv[]) arch_flag->name); exit(EXIT_FAILURE); } + if(errors) + exit(EXIT_FAILURE); if(strcmp(argv[start], "-p") == 0){ print_file_parts(); start++; @@ -304,8 +310,13 @@ char *file_name) if(ofile.file_type == OFILE_FAT){ fp = new_file_part(); fp->offset = 0; - fp->size = sizeof(struct fat_header) + - ofile.fat_header->nfat_arch * sizeof(struct fat_arch); + fp->size = sizeof(struct fat_header); + if(ofile.fat_header->magic == FAT_MAGIC_64) + fp->size += ofile.fat_header->nfat_arch * + sizeof(struct fat_arch_64); + else + fp->size += ofile.fat_header->nfat_arch * + sizeof(struct fat_arch); fp->type = FP_FAT_HEADERS; insert_file_part(fp); @@ -321,14 +332,27 @@ char *file_name) arch_flag->cputype == ofile.mh_cputype && (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) == (ofile.mh_cpusubtype & ~CPU_SUBTYPE_MASK)){ - arch_offset = ofile.fat_archs[ofile.narch].offset; - arch_size = ofile.fat_archs[ofile.narch].size; + if(ofile.fat_header->magic == FAT_MAGIC_64){ + arch_offset = + ofile.fat_archs64[ofile.narch].offset; + arch_size = ofile.fat_archs64[ofile.narch].size; + } + else{ + arch_offset = ofile.fat_archs[ofile.narch].offset; + arch_size = ofile.fat_archs[ofile.narch].size; + } arch_found = TRUE; } /* make mach-o parts for this */ fp = new_file_part(); - fp->offset = ofile.fat_archs[ofile.narch].offset; - fp->size = ofile.fat_archs[ofile.narch].size; + if(ofile.fat_header->magic == FAT_MAGIC_64){ + fp->offset = ofile.fat_archs64[ofile.narch].offset; + fp->size = ofile.fat_archs64[ofile.narch].size; + } + else{ + fp->offset = ofile.fat_archs[ofile.narch].offset; + fp->size = ofile.fat_archs[ofile.narch].size; + } fp->type = FP_MACH_O; insert_file_part(fp); create_mach_o_parts(fp); @@ -505,6 +529,7 @@ struct file_part *fp) struct linkedit_data_command *split_info, *code_sig, *func_starts, *data_in_code, *code_sign_drs; struct linkedit_data_command *link_opt_hint; + struct linkedit_data_command *dyld_chained_fixups, *dyld_exports_trie; enum bool dylib_stub; mp = new_mach_o_part(); @@ -546,6 +571,8 @@ struct file_part *fp) data_in_code = NULL; code_sign_drs = NULL; link_opt_hint = NULL; + dyld_chained_fixups = NULL; + dyld_exports_trie = NULL; lc = ofile.load_commands; for(i = 0; i < ncmds; i++){ @@ -580,6 +607,14 @@ struct file_part *fp) lc->cmd == LC_LINKER_OPTIMIZATION_HINT){ link_opt_hint = (struct linkedit_data_command *)lc; } + else if (dyld_chained_fixups == NULL && + lc->cmd == LC_DYLD_CHAINED_FIXUPS) { + dyld_chained_fixups = (struct linkedit_data_command*)lc; + } + else if (dyld_exports_trie == NULL && + lc->cmd == LC_DYLD_EXPORTS_TRIE) { + dyld_exports_trie = (struct linkedit_data_command*)lc; + } else if(lc->cmd == LC_SEGMENT && dylib_stub == FALSE){ sg = (struct segment_command *)lc; s = (struct section *) @@ -1028,6 +1063,20 @@ struct file_part *fp) mp->type = MP_LINK_OPT_HINT; insert_mach_o_part(fp, mp); } + if(dyld_chained_fixups != NULL && dyld_chained_fixups->datasize != 0){ + mp = new_mach_o_part(); + mp->offset = fp->offset + dyld_chained_fixups->dataoff; + mp->size = dyld_chained_fixups->datasize; + mp->type = MP_DYLD_CHAINED_FIXUPS; + insert_mach_o_part(fp, mp); + } + if(dyld_exports_trie != NULL && dyld_exports_trie->datasize != 0){ + mp = new_mach_o_part(); + mp->offset = fp->offset + dyld_exports_trie->dataoff; + mp->size = dyld_exports_trie->datasize; + mp->type = MP_DYLD_EXPORTS_TRIE; + insert_mach_o_part(fp, mp); + } } static @@ -1119,7 +1168,7 @@ print_mach_o_parts( struct mach_o_part *mp) { struct mach_o_part *p, *prev; - uint32_t offset; + uint64_t offset; char *indent; if(arch_flag == NULL) @@ -1154,7 +1203,7 @@ struct mach_o_part *mp) static void print_parts_for_page( -uint32_t page_number) +uint64_t page_number) { uint64_t offset, size, low_addr, high_addr, new_low_addr, new_high_addr; struct file_part *fp; @@ -1170,7 +1219,7 @@ uint32_t page_number) if(arch_flag == NULL){ if(offset > ofile.file_size){ - printf("File has no page %u (file has only %u pages)\n", + printf("File has no page %llu (file has only %u pages)\n", page_number, (uint32_t)((ofile.file_size + vm_page_size -1) / vm_page_size)); @@ -1179,7 +1228,7 @@ uint32_t page_number) } else{ if(offset > arch_size){ - printf("File for architecture %s has no page %u (has only %u " + printf("File for architecture %s has no page %llu (has only %u " "pages)\n", arch_flag->name, page_number, (uint32_t)((arch_size + vm_page_size -1) / @@ -1200,7 +1249,7 @@ uint32_t page_number) continue; switch(fp->type){ case FP_FAT_HEADERS: - printf("File Page %u contains fat file headers\n", + printf("File Page %llu contains fat file headers\n", page_number); printed = TRUE; break; @@ -1214,13 +1263,13 @@ uint32_t page_number) continue; switch(mp->type){ case MP_MACH_HEADERS: - printf("File Page %u contains Mach-O headers", + printf("File Page %llu contains Mach-O headers", page_number); print_arch(fp); printed = TRUE; break; case MP_SECTION: - printf("File Page %u contains contents of " + printf("File Page %llu contains contents of " "section (%.16s,%.16s)", page_number, mp->s->segname, mp->s->sectname); print_arch(fp); @@ -1248,7 +1297,7 @@ uint32_t page_number) sections = TRUE; break; case MP_SECTION_64: - printf("File Page %u contains contents of " + printf("File Page %llu contains contents of " "section (%.16s,%.16s)", page_number, mp->s64->segname, mp->s64->sectname); print_arch(fp); @@ -1277,165 +1326,177 @@ uint32_t page_number) sections64 = TRUE; break; case MP_RELOCS: - printf("File Page %u contains relocation entries for " + printf("File Page %llu contains relocation entries for " "section (%.16s,%.16s)", page_number, mp->s->segname, mp->s->sectname); print_arch(fp); printed = TRUE; break; case MP_RELOCS_64: - printf("File Page %u contains relocation entries for " + printf("File Page %llu contains relocation entries for " "section (%.16s,%.16s)", page_number, mp->s64->segname, mp->s64->sectname); print_arch(fp); printed = TRUE; break; case MP_SPLIT_INFO: - printf("File Page %u contains local of info to split " + printf("File Page %llu contains local of info to split " "segments", page_number); print_arch(fp); printed = TRUE; break; case MP_LOCAL_SYMBOLS: - printf("File Page %u contains symbol table for " + printf("File Page %llu contains symbol table for " "non-global symbols", page_number); print_arch(fp); printed = TRUE; break; case MP_EXTDEF_SYMBOLS: - printf("File Page %u contains symbol table for " + printf("File Page %llu contains symbol table for " "defined global symbols", page_number); print_arch(fp); printed = TRUE; break; case MP_UNDEF_SYMBOLS: - printf("File Page %u contains symbol table for " + printf("File Page %llu contains symbol table for " "undefined symbols", page_number); print_arch(fp); printed = TRUE; break; case MP_TOC: - printf("File Page %u contains table of contents", + printf("File Page %llu contains table of contents", page_number); print_arch(fp); printed = TRUE; break; case MP_MODULE_TABLE: - printf("File Page %u contains module table", + printf("File Page %llu contains module table", page_number); print_arch(fp); printed = TRUE; break; case MP_REFERENCE_TABLE: - printf("File Page %u contains reference table", + printf("File Page %llu contains reference table", page_number); print_arch(fp); printed = TRUE; break; case MP_INDIRECT_SYMBOL_TABLE: - printf("File Page %u contains indirect symbols table", + printf("File Page %llu contains indirect symbols table", page_number); print_arch(fp); printed = TRUE; break; case MP_EXT_RELOCS: - printf("File Page %u contains external relocation " + printf("File Page %llu contains external relocation " "entries", page_number); print_arch(fp); printed = TRUE; break; case MP_LOC_RELOCS: - printf("File Page %u contains local relocation " + printf("File Page %llu contains local relocation " "entries", page_number); print_arch(fp); printed = TRUE; break; case MP_SYMBOL_TABLE: - printf("File Page %u contains symbol table", + printf("File Page %llu contains symbol table", page_number); print_arch(fp); printed = TRUE; break; case MP_HINTS_TABLE: - printf("File Page %u contains hints table", + printf("File Page %llu contains hints table", page_number); print_arch(fp); printed = TRUE; break; case MP_STRING_TABLE: - printf("File Page %u contains string table", + printf("File Page %llu contains string table", page_number); print_arch(fp); printed = TRUE; break; case MP_EXT_STRING_TABLE: - printf("File Page %u contains string table for " + printf("File Page %llu contains string table for " "external symbols", page_number); print_arch(fp); printed = TRUE; break; case MP_LOC_STRING_TABLE: - printf("File Page %u contains string table for " + printf("File Page %llu contains string table for " "local symbols", page_number); print_arch(fp); printed = TRUE; break; case MP_CODE_SIG: - printf("File Page %u contains data of code signature", + printf("File Page %llu contains data of code signature", page_number); print_arch(fp); printed = TRUE; break; case MP_FUNCTION_STARTS: - printf("File Page %u contains data of function starts", + printf("File Page %llu contains data of function starts", page_number); print_arch(fp); printed = TRUE; break; case MP_DATA_IN_CODE: - printf("File Page %u contains info for data in code", + printf("File Page %llu contains info for data in code", page_number); print_arch(fp); printed = TRUE; break; case MP_CODE_SIGN_DRS: - printf("File Page %u contains info for code signing " + printf("File Page %llu contains info for code signing " "DRs copied from linked dylib", page_number); print_arch(fp); printed = TRUE; break; case MP_LINK_OPT_HINT: - printf("File Page %u contains info for linker " + printf("File Page %llu contains info for linker " "optimization hints", page_number); print_arch(fp); printed = TRUE; break; + case MP_DYLD_CHAINED_FIXUPS: + printf("File Page %llu contains dyld info for chained " + "fixups", page_number); + print_arch(fp); + printed = TRUE; + break; + case MP_DYLD_EXPORTS_TRIE: + printf("File Page %llu contains dyld info for exported " + "symbols (TRIE)", page_number); + print_arch(fp); + printed = TRUE; + break; case MP_DYLD_INFO_REBASE: - printf("File Page %u contains dyld info for sliding " + printf("File Page %llu contains dyld info for sliding " "an image", page_number); print_arch(fp); printed = TRUE; break; case MP_DYLD_INFO_BIND: - printf("File Page %u contains dyld info for binding " + printf("File Page %llu contains dyld info for binding " "symbols", page_number); print_arch(fp); printed = TRUE; break; case MP_DYLD_INFO_WEAK_BIND: - printf("File Page %u contains dyld info for weak bound " + printf("File Page %llu contains dyld info for weak bound " "symbols", page_number); print_arch(fp); printed = TRUE; break; case MP_DYLD_INFO_LAZY_BIND: - printf("File Page %u contains dyld info for lazy bound " + printf("File Page %llu contains dyld info for lazy bound " "symbols", page_number); print_arch(fp); printed = TRUE; break; case MP_DYLD_INFO_EXPORT: - printf("File Page %u contains dyld info for symbols " + printf("File Page %llu contains dyld info for symbols " "exported by a dylib", page_number); print_arch(fp); printed = TRUE; @@ -1445,7 +1506,7 @@ uint32_t page_number) } } if(sections == TRUE || sections64 == TRUE){ - printf("Symbols on file page %u virtual address 0x%llx to " + printf("Symbols on file page %llu virtual address 0x%llx to " "0x%llx\n", page_number, low_addr, high_addr); if(sections == TRUE) print_symbols(fp, low_addr, high_addr); @@ -1482,7 +1543,7 @@ uint32_t page_number) else arch_name = get_arch_name_from_types(fp->mh64->cputype, fp->mh64->cpusubtype); - printf("File Page %u contains empty space in the Mach-O " + printf("File Page %llu contains empty space in the Mach-O " "file for %s between:\n", page_number, arch_name); if(mp->prev == NULL) printf(" the start of the Mach-O file"); @@ -1502,7 +1563,7 @@ uint32_t page_number) } break; } - printf("File Page %u contains empty space in the file between:\n", + printf("File Page %llu contains empty space in the file between:\n", page_number); if(fp->prev == NULL) printf(" the start of the file"); @@ -1652,6 +1713,12 @@ struct mach_o_part *mp) case MP_LINK_OPT_HINT: printf("info for linker optimization hints"); break; + case MP_DYLD_CHAINED_FIXUPS: + printf("dyld info for chained fixups"); + break; + case MP_DYLD_EXPORTS_TRIE: + printf("dyld info for exported symbols (TRIE)"); + break; case MP_DYLD_INFO_REBASE: printf("dyld info for sliding an image"); break; diff --git a/cctools/misc/redo_prebinding.c b/cctools/misc/redo_prebinding.c index 97315d0..b01abc2 100644 --- a/cctools/misc/redo_prebinding.c +++ b/cctools/misc/redo_prebinding.c @@ -86,6 +86,7 @@ #import #import #import +#import /* cctools-port: For bcmp, bzero ... */ #import #import #import @@ -106,7 +107,7 @@ #import #import #import -#import +#import /* cctools-port: uncommented */ #import #include @@ -918,7 +919,7 @@ char *envp[]) if(write_to_stdout) output_file = NULL; writeout(archs, narchs, output_file, mode, TRUE, FALSE, FALSE, - NULL); + FALSE, NULL); if(errors){ if(write_to_stdout == FALSE) unlink(output_file); @@ -928,7 +929,7 @@ char *envp[]) else{ output_file = makestr(input_file, ".redo_prebinding", NULL); writeout(archs, narchs, output_file, mode, TRUE, FALSE, FALSE, - NULL); + FALSE, NULL); if(errors){ unlink(output_file); return(2); @@ -1608,8 +1609,8 @@ uint32_t *throttle) gid = stat_buf.st_gid; if(output_file != NULL){ - writeout(archs, narchs, (char *)output_file, mode, TRUE, FALSE, - FALSE, throttle); + writeout(archs, narchs, (char *)output_file, mode, TRUE, FALSE, + FALSE, FALSE, throttle); if(errors){ unlink(output_file); goto error_return; @@ -1617,8 +1618,8 @@ uint32_t *throttle) } else{ output_file = makestr(file_name, ".redo_prebinding", NULL); - writeout(archs, narchs, (char *)output_file, mode, TRUE, FALSE, - FALSE, throttle); + writeout(archs, narchs, (char *)output_file, mode, TRUE, FALSE, + FALSE, FALSE, throttle); if(errors){ unlink(output_file); goto error_return; @@ -1709,6 +1710,11 @@ error_return: * All resulting binaries successfully processed by unprebind() will have * the MH_CANONICAL flag. */ +/* + * Note: unprebind API boundary will not support files larger than 2^32 bytes + * in size. If the output size is too large to fit in outlen unprebind will + * return REDO_PREBINDING_FAILURE. + */ enum redo_prebinding_retval unprebind( const char *file_name, @@ -1729,6 +1735,7 @@ uint32_t *outlen) uid_t uid; gid_t gid; enum bool calculate_input_prebind_cksum, seen_archive; + uint64_t outlen64; reset_statics(); progname = (char *)program_name; @@ -1824,12 +1831,14 @@ uint32_t *outlen) } if(output_file != NULL){ - if(outbuf != NULL) + if(outbuf != NULL){ writeout_to_mem(archs, narchs, (char *)output_file, outbuf, - outlen, TRUE, FALSE, FALSE, &seen_archive); - else + &outlen64, TRUE, FALSE, FALSE, FALSE, + &seen_archive); + *outlen = (uint32_t)outlen64; + }else writeout(archs, narchs, (char *)output_file, mode, TRUE, - FALSE, FALSE, NULL); + FALSE, FALSE, FALSE, NULL); if(errors){ if(outbuf == NULL) unlink(output_file); @@ -1838,12 +1847,20 @@ uint32_t *outlen) } else{ output_file = makestr(file_name, ".redo_prebinding", NULL); - if(outbuf != NULL) + if(outbuf != NULL){ writeout_to_mem(archs, narchs, (char *)output_file, outbuf, - outlen, TRUE, FALSE, FALSE, &seen_archive); - else + &outlen64, TRUE, FALSE, FALSE, FALSE, + &seen_archive); + /* error if outlen is too large */ + if (outlen64 > 0xFFFFFFFF) { + if(outbuf == NULL) + unlink(output_file); + goto error_return; + } + *outlen = (uint32_t)outlen64; + }else writeout(archs, narchs, (char *)output_file, mode, TRUE, - FALSE, FALSE, NULL); + FALSE, FALSE, FALSE, NULL); if(errors){ if(outbuf == NULL) unlink(output_file); @@ -2212,6 +2229,10 @@ char **error_message) (*cksums)[i].cksum = arch->object->cs->cksum; } } + else if(arch->fat_arch64 != NULL){ + (*cksums)[i].cputype = arch->fat_arch64->cputype; + (*cksums)[i].cpusubtype = arch->fat_arch64->cpusubtype; + } else if(arch->fat_arch != NULL){ (*cksums)[i].cputype = arch->fat_arch->cputype; (*cksums)[i].cpusubtype = arch->fat_arch->cpusubtype; @@ -2965,13 +2986,15 @@ void) guess_short_name(arch_lib.dylib_name, &is_framework, &suffix); if(is_framework == TRUE){ - arch_lib.name_size = strlen(arch_lib.umbrella_name); + arch_lib.name_size = + (uint32_t)strlen(arch_lib.umbrella_name); } else{ if(arch_lib.umbrella_name != NULL){ arch_lib.library_name = arch_lib.umbrella_name; arch_lib.umbrella_name = NULL; - arch_lib.name_size = strlen(arch_lib.library_name); + arch_lib.name_size = + (uint32_t)strlen(arch_lib.library_name); } } if(suffix != NULL) @@ -3544,6 +3567,7 @@ uint32_t *image_pointer) char *dylib_name; struct ofile *ofile; struct fat_arch *best_fat_arch; + struct fat_arch_64 *best_fat_arch64; struct load_command *lc; struct dylib_command *dl_id; enum bool already_loaded, is_framework; @@ -3640,12 +3664,23 @@ uint32_t *image_pointer) * the correct architecture. */ if(ofile->file_type == OFILE_FAT){ - best_fat_arch = cpusubtype_findbestarch( - arch_flag.cputype, - arch_flag.cpusubtype, - ofile->fat_archs, - ofile->fat_header->nfat_arch); - if(best_fat_arch == NULL){ + if(ofile->fat_header->magic == FAT_MAGIC_64){ + best_fat_arch64 = cpusubtype_findbestarch_64( + arch_flag.cputype, + arch_flag.cpusubtype, + ofile->fat_archs64, + ofile->fat_header->nfat_arch); + best_fat_arch = NULL; + } + else{ + best_fat_arch = cpusubtype_findbestarch( + arch_flag.cputype, + arch_flag.cpusubtype, + ofile->fat_archs, + ofile->fat_header->nfat_arch); + best_fat_arch64 = NULL; + } + if(best_fat_arch == NULL && best_fat_arch64 == NULL){ /* * If we are allowing missing architectures except one see if * this is not the one that can't be missing. @@ -3664,8 +3699,14 @@ uint32_t *image_pointer) (void)ofile_first_arch(ofile); do{ - if(best_fat_arch != ofile->fat_archs + ofile->narch) - continue; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + if(best_fat_arch64 != ofile->fat_archs64 + ofile->narch) + continue; + } + else{ + if(best_fat_arch != ofile->fat_archs + ofile->narch) + continue; + } if(ofile->arch_type == OFILE_ARCHIVE){ error("file: %s (for architecture %s) is an archive (not " "a Mach-O dynamic shared library)", dylib_name, @@ -3845,13 +3886,15 @@ good: &is_framework, &suffix); if(is_framework == TRUE){ - libs[nlibs].name_size = strlen(libs[nlibs].umbrella_name); + libs[nlibs].name_size = + (uint32_t)strlen(libs[nlibs].umbrella_name); } else{ if(libs[nlibs].umbrella_name != NULL){ libs[nlibs].library_name = libs[nlibs].umbrella_name; libs[nlibs].umbrella_name = NULL; - libs[nlibs].name_size = strlen(libs[nlibs].library_name); + libs[nlibs].name_size = + (uint32_t)strlen(libs[nlibs].library_name); } } if(suffix != NULL) @@ -4581,7 +4624,7 @@ char *symbol_name) (int (*)(const void *,const void *))nlist_bsearch); if(symbol == NULL) continue; - symbol_index = symbol - libs[i].symbols; + symbol_index = (uint32_t)(symbol - libs[i].symbols); } /* * The symbol appears in this library. Now see if it is @@ -4754,9 +4797,9 @@ struct lib *lib) struct lib *ref_lib; uint32_t mh_flags; - module_index = module_state - lib->module_states; + module_index = (uint32_t)(module_state - lib->module_states); dylib_module = lib->mods + module_index; - ilib = lib - libs; + ilib = (uint32_t)(lib - libs); if(lib->ofile->mh != NULL) mh_flags = lib->ofile->mh->flags; @@ -5097,9 +5140,10 @@ struct lib *lib) symbol_name, arch_name); redo_exit(2); } - symbol_index = symbol - symbols; + symbol_index = (uint32_t)(symbol - symbols); } - indr_lib = get_primary_lib(libs - lib, symbols + symbol_index); + indr_lib = get_primary_lib((uint32_t)(libs - lib), + symbols + symbol_index); } return(indr_lib); } @@ -5266,7 +5310,7 @@ struct indr_loop_list *indr_loop) *module_state = &arch_state; *lib = NULL; if(itoc != NULL) - *itoc = toc - arch_tocs; + *itoc = (uint32_t)(toc - arch_tocs); return(TRUE); } } @@ -5346,7 +5390,7 @@ struct indr_loop_list *indr_loop) *module_state = primary_lib->module_states + toc->module_index; *lib = primary_lib; if(itoc != NULL) - *itoc = toc - primary_lib->tocs; + *itoc = (uint32_t)(toc - primary_lib->tocs); return(TRUE); } *symbol = NULL; @@ -5401,6 +5445,10 @@ enum bool missing_arch) enum link_state *module_state; struct lib *lib; + /* silence compiler warnings */ + isub_image = 0; + itoc = 0; + /* the size of the symbol table will not change just the contents */ sym_info_size = arch_nextrel * sizeof(struct relocation_info) + @@ -5453,9 +5501,19 @@ enum bool missing_arch) arch->object->link_opt_hint_cmd->datasize; } + if(arch->object->dyld_chained_fixups != NULL){ + sym_info_size += + arch->object->dyld_chained_fixups->datasize; + } + + if(arch->object->dyld_exports_trie != NULL){ + sym_info_size += + arch->object->dyld_exports_trie->datasize; + } + if(arch->object->code_sig_cmd != NULL){ sym_info_size = - rnd(sym_info_size, 16); + rnd32(sym_info_size, 16); sym_info_size += arch->object->code_sig_cmd->datasize; } @@ -5525,6 +5583,20 @@ enum bool missing_arch) arch->object->output_link_opt_hint_info_data_size = arch->object->link_opt_hint_cmd->datasize; } + if(arch->object->dyld_chained_fixups != NULL){ + arch->object->output_dyld_chained_fixups_data = + arch->object->object_addr + + arch->object->dyld_chained_fixups->dataoff; + arch->object->output_dyld_chained_fixups_data_size = + arch->object->dyld_chained_fixups->datasize; + } + if(arch->object->dyld_exports_trie != NULL){ + arch->object->output_dyld_exports_trie_data = + arch->object->object_addr + + arch->object->dyld_exports_trie->dataoff; + arch->object->output_dyld_exports_trie_data_size = + arch->object->dyld_exports_trie->datasize; + } if(arch->object->code_sig_cmd != NULL){ arch->object->output_code_sig_data = arch->object->object_addr + arch->object->code_sig_cmd->dataoff; @@ -9019,7 +9091,7 @@ uint32_t vmslide) */ size = pbdylib1->cmdsize - (sizeof(struct prebound_dylib_command) + - rnd(strlen(dylib_name) + 1, + rnd32((uint32_t)strlen(dylib_name) + 1, sizeof(uint32_t))); /* * Now see if the size left has enought space to @@ -9043,9 +9115,9 @@ uint32_t vmslide) nmodules = 64; size = sizeof(struct prebound_dylib_command) + - rnd(strlen(dylib_name)+1, - sizeof(uint32_t)) + - rnd(nmodules / 8, sizeof(uint32_t)); + rnd32((uint32_t)strlen(dylib_name)+1, + (uint32_t)sizeof(uint32_t)) + + rnd32(nmodules / 8, sizeof(uint32_t)); libs[i].LC_PREBOUND_DYLIB_size = size; } } @@ -9093,8 +9165,9 @@ uint32_t vmslide) if(nmodules < 64) nmodules = 64; size = sizeof(struct prebound_dylib_command) + - rnd(strlen(libs[i].dylib_name) + 1, sizeof(uint32_t))+ - rnd(nmodules / 8, sizeof(uint32_t)); + rnd32((uint32_t)strlen(libs[i].dylib_name) + 1, + sizeof(uint32_t)) + + rnd32(nmodules / 8, sizeof(uint32_t)); libs[i].LC_PREBOUND_DYLIB_size = size; sizeofcmds += libs[i].LC_PREBOUND_DYLIB_size; ncmds++; @@ -9183,11 +9256,11 @@ uint32_t vmslide) pbdylib2->nmodules = libs[j].nmodtab; pbdylib2->linked_modules.offset = sizeof(struct prebound_dylib_command) + - rnd(strlen(dylib_name) + 1, + rnd32((uint32_t)strlen(dylib_name) + 1, sizeof(uint32_t)); linked_modules = ((char *)pbdylib2) + sizeof(struct prebound_dylib_command) + - rnd(strlen(dylib_name) + 1, + rnd32((uint32_t)strlen(dylib_name) + 1, sizeof(uint32_t)); if(libs[j].ofile->mh != NULL) mh_flags = libs[j].ofile->mh->flags; @@ -9230,11 +9303,11 @@ uint32_t vmslide) pbdylib2->nmodules = libs[i].nmodtab; pbdylib2->linked_modules.offset = sizeof(struct prebound_dylib_command) + - rnd(strlen(libs[i].dylib_name) + 1, + rnd32((uint32_t)strlen(libs[i].dylib_name) + 1, sizeof(uint32_t)); linked_modules = ((char *)pbdylib2) + sizeof(struct prebound_dylib_command) + - rnd(strlen(libs[i].dylib_name) + 1, + rnd32((uint32_t)strlen(libs[i].dylib_name) + 1, sizeof(uint32_t)); if(libs[i].ofile->mh != NULL) mh_flags = libs[i].ofile->mh->flags; @@ -9315,6 +9388,14 @@ uint32_t vmslide) arch->object->link_opt_hint_cmd = (struct linkedit_data_command *)lc1; break; + case LC_DYLD_CHAINED_FIXUPS: + arch->object->dyld_chained_fixups = + (struct linkedit_data_command *)lc1; + break; + case LC_DYLD_EXPORTS_TRIE: + arch->object->dyld_exports_trie = + (struct linkedit_data_command *)lc1; + break; } lc1 = (struct load_command *)((char *)lc1 + lc1->cmdsize); } @@ -9732,7 +9813,7 @@ char * savestr( const char *s) { - uint32_t len; + size_t len; char *r; len = strlen(s) + 1; diff --git a/cctools/misc/seg_hack.c b/cctools/misc/seg_hack.c index d02f237..ef1a807 100644 --- a/cctools/misc/seg_hack.c +++ b/cctools/misc/seg_hack.c @@ -113,7 +113,7 @@ char **envp) if(stat(input, &stat_buf) == -1) system_error("can't stat input file: %s", input); writeout(archs, narchs, output, stat_buf.st_mode & 0777, - TRUE, FALSE, FALSE, NULL); + TRUE, FALSE, FALSE, FALSE, NULL); if(errors) return(EXIT_FAILURE); @@ -196,7 +196,7 @@ uint32_t narchs) archs[i].members[j].offset = offset; size = 0; if(archs[i].members[j].member_long_name == TRUE){ - size = rnd(archs[i].members[j].member_name_size, + size = rnd32(archs[i].members[j].member_name_size, sizeof(long)); archs[i].toc_long_name = TRUE; } diff --git a/cctools/misc/segedit.c b/cctools/misc/segedit.c index 151e5a4..58322b7 100644 --- a/cctools/misc/segedit.c +++ b/cctools/misc/segedit.c @@ -32,6 +32,7 @@ #include #include #include +#include /* cctools-port: For bcmp, bzero ... */ #include #include #include @@ -48,6 +49,8 @@ #include "stuff/errors.h" #include "stuff/rnd.h" #include "stuff/bytesex.h" +#include "stuff/write64.h" +#include "stuff/arch.h" /* These variables are set from the command line arguments */ __private_extern__ @@ -108,7 +111,6 @@ static struct mach_header_64 static uint32_t mh_ncmds; /* number of load commands */ static struct load_command *load_commands; /* pointer to the input file's load commands */ -static uint32_t pagesize = 8192;/* target pagesize */ static enum bool swapped; /* TRUE if the input is to be swapped */ static enum byte_sex host_byte_sex = UNKNOWN_BYTE_SEX; static enum byte_sex target_byte_sex = UNKNOWN_BYTE_SEX; @@ -154,8 +156,8 @@ char *envp[]) for (i = 1; i < argc; i++) { if(argv[i][0] == '-'){ - switch(argv[i][1]){ - case 'e': + if (strncmp("-extract", argv[i], 9) == 0 || + strncmp("-e", argv[i], 3) == 0) { if(i + 4 > argc){ error("missing arguments to %s option", argv[i]); usage(); @@ -168,8 +170,9 @@ char *envp[]) ep->next = extracts; extracts = ep; i += 3; - break; - case 'r': + } + else if (strncmp("-replace", argv[i], 9) == 0 || + strncmp("-r", argv[i], 3) == 0) { if(i + 4 > argc){ error("missing arguments to %s option", argv[i]); usage(); @@ -181,14 +184,15 @@ char *envp[]) rp->next = replaces; replaces = rp; i += 3; - break; - case 'o': + } + else if (strncmp("-output", argv[i], 8) == 0 || + strncmp("-o", argv[i], 3) == 0) { if(output != NULL) fatal("more than one %s option", argv[i]); output = argv[i + 1]; i += 1; - break; - default: + } + else { error("unrecognized option: %s", argv[i]); usage(); } @@ -253,7 +257,7 @@ map_input(void) system_fatal("can't open input file: %s", input); if(fstat(fd, &stat_buf) == -1) system_fatal("Can't stat input file: %s", input); - input_size = stat_buf.st_size; + input_size = (uint32_t)stat_buf.st_size; input_mode = stat_buf.st_mode; input_addr = mmap(0, input_size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0); @@ -266,10 +270,10 @@ map_input(void) "past the end of the file) in: %s", input); magic = *(uint32_t *)input_addr; #ifdef __BIG_ENDIAN__ - if(magic == FAT_MAGIC) + if(magic == FAT_MAGIC || magic == FAT_MAGIC_64) #endif /* __BIG_ENDIAN__ */ #ifdef __LITTLE_ENDIAN__ - if(magic == SWAP_INT(FAT_MAGIC)) + if(magic == SWAP_INT(FAT_MAGIC) || magic == SWAP_INT(FAT_MAGIC_64)) #endif /* __LITTLE_ENDIAN__ */ fatal("file: %s is a fat file (%s only operates on Mach-O files, " "use lipo(1) on it to get a Mach-O file)", input, progname); @@ -412,7 +416,8 @@ extract_sections(void) sizeof(struct segment_command_64)); for(j = 0; j < sgp64->nsects; j++){ extract_section(sp64->segname, sp64->sectname, sp64->flags, - sp64->offset, sp64->size); + (uint32_t)sp64->offset, + (uint32_t)sp64->size); sp64++; } } @@ -462,8 +467,8 @@ uint32_t size) if((fd = open(ep->filename, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) system_fatal("can't create: %s", ep->filename); - if(write(fd, (char *)input_addr + offset, - size) != (int)size) + if(write64(fd, (char *)input_addr + offset, + size) != (ssize_t)size) system_fatal("can't write: %s", ep->filename); if(close(fd) == -1) system_fatal("can't close: %s", ep->filename); @@ -488,6 +493,7 @@ replace_sections(void) struct section_64 *sp64; struct symtab_command *stp; struct symseg_command *ssp; + struct dysymtab_command* dstp; struct replace *rp; struct stat stat_buf; int outfd, sectfd; @@ -495,7 +501,9 @@ replace_sections(void) vm_address_t pad_addr; uint32_t size; kern_return_t r; - + enum bool no_seg_resize; + uint32_t pagesize; + errors = 0; high_reloc_seg = 0; @@ -512,6 +520,9 @@ replace_sections(void) ssp = NULL; linkedit_sgp = NULL; linkedit_sgp64 = NULL; + dstp = NULL; + + no_seg_resize = FALSE; /* * First pass over the load commands and determine if the file is laided @@ -568,16 +579,17 @@ replace_sections(void) if(sgp64->filesize != 0){ if(sgp64->fileoff + sgp64->filesize > high_noreloc_seg) - high_noreloc_seg = sgp64->fileoff + - sgp64->filesize; + high_noreloc_seg = (uint32_t)(sgp64->fileoff + + sgp64->filesize); if(sgp64->fileoff < low_noreloc_seg) - low_noreloc_seg = sgp64->fileoff; + low_noreloc_seg = (uint32_t)sgp64->fileoff; } } else{ if(sgp64->filesize != 0 && sgp64->fileoff + sgp64->filesize > high_reloc_seg) - high_reloc_seg = sgp64->fileoff + sgp64->filesize; + high_reloc_seg = (uint32_t)(sgp64->fileoff + + sgp64->filesize); } } else{ @@ -590,7 +602,8 @@ replace_sections(void) if(sp64->nreloc != 0 && sp64->reloff < low_linkedit) low_linkedit = sp64->reloff; search_for_replace_section(sp64->segname, sp64->sectname, - sgp64->flags, sp64->flags, sp64->offset, sp64->size); + sgp64->flags, sp64->flags, sp64->offset, + (uint32_t)sp64->size); sp64++; } break; @@ -604,8 +617,24 @@ replace_sections(void) low_linkedit = stp->stroff; break; case LC_DYSYMTAB: - fatal("current limitation, can't process files with " - "LC_DYSYMTAB load command as in: %s", input); + if (dstp != NULL) + fatal("more than one dysymtab_command found in: %s", input); + no_seg_resize = TRUE; + dstp = (struct dysymtab_command*)lcp; + if (dstp->tocoff != 0 && dstp->tocoff < low_linkedit) + low_linkedit = dstp->tocoff; + if (dstp->modtaboff != 0 && dstp->modtaboff < low_linkedit) + low_linkedit = dstp->modtaboff; + if (dstp->extrefsymoff != 0 && + dstp->extrefsymoff < low_linkedit) + low_linkedit = dstp->extrefsymoff; + if (dstp->indirectsymoff != 0 && + dstp->indirectsymoff < low_linkedit) + low_linkedit = dstp->indirectsymoff; + if (dstp->extreloff != 0 && dstp->extreloff < low_linkedit) + low_linkedit = dstp->extreloff; + if (dstp->locreloff != 0 && dstp->locreloff < low_linkedit) + low_linkedit = dstp->locreloff; break; case LC_SYMSEG: if(ssp != NULL) @@ -614,6 +643,50 @@ replace_sections(void) if(ssp->size != 0 && ssp->offset < low_linkedit) low_linkedit = ssp->offset; break; + case LC_CODE_SIGNATURE: + case LC_SEGMENT_SPLIT_INFO: + case LC_FUNCTION_STARTS: + case LC_DATA_IN_CODE: + case LC_DYLIB_CODE_SIGN_DRS: + case LC_LINKER_OPTIMIZATION_HINT: + { + struct linkedit_data_command* ldcp = + (struct linkedit_data_command*)lcp; + if (ldcp->dataoff != 0 && ldcp->dataoff < low_linkedit) + low_linkedit = ldcp->dataoff; + } + break; + case LC_DYLD_INFO: + case LC_DYLD_INFO_ONLY: + { + struct dyld_info_command* dicp = + (struct dyld_info_command*)lcp; + no_seg_resize = TRUE; + if (dicp->rebase_off != 0 && + dicp->rebase_off < low_linkedit) + low_linkedit = dicp->rebase_off; + if (dicp->bind_off != 0 && dicp->bind_off < low_linkedit) + low_linkedit = dicp->bind_off; + if (dicp->weak_bind_off != 0 && + dicp->weak_bind_off < low_linkedit) + low_linkedit = dicp->weak_bind_off; + if (dicp->lazy_bind_off != 0 && + dicp->lazy_bind_off < low_linkedit) + low_linkedit = dicp->lazy_bind_off; + if (dicp->export_off != 0 && + dicp->export_off < low_linkedit) + low_linkedit = dicp->export_off; + } + break; + case LC_DYLD_CHAINED_FIXUPS: + case LC_DYLD_EXPORTS_TRIE: + { + struct linkedit_data_command* ldcp = + (struct linkedit_data_command*)lcp; + no_seg_resize = TRUE; + if (ldcp->dataoff != 0 && ldcp->dataoff < low_linkedit) + low_linkedit = ldcp->dataoff; + } case LC_THREAD: case LC_UNIXTHREAD: case LC_LOADFVMLIB: @@ -629,6 +702,29 @@ replace_sections(void) case LC_LOAD_DYLINKER: case LC_ID_DYLINKER: case LC_DYLD_ENVIRONMENT: + case LC_PREBOUND_DYLIB: + case LC_ROUTINES: + case LC_SUB_FRAMEWORK: + case LC_SUB_UMBRELLA: + case LC_SUB_CLIENT: + case LC_SUB_LIBRARY: + case LC_TWOLEVEL_HINTS: + case LC_PREBIND_CKSUM: + case LC_ROUTINES_64: + case LC_UUID: + case LC_RPATH: + case LC_LAZY_LOAD_DYLIB: + case LC_ENCRYPTION_INFO: + case LC_ENCRYPTION_INFO_64: + case LC_VERSION_MIN_MACOSX: + case LC_VERSION_MIN_IPHONEOS: + case LC_VERSION_MIN_TVOS: + case LC_VERSION_MIN_WATCHOS: + case LC_NOTE: + case LC_BUILD_VERSION: + case LC_MAIN: + case LC_SOURCE_VERSION: + case LC_LINKER_OPTION: break; default: error("unknown load command %u (result maybe bad)", i); @@ -650,7 +746,7 @@ replace_sections(void) rp->sectname); errors = 1; } - rp->size = stat_buf.st_size; + rp->size = (uint32_t)stat_buf.st_size; } rp = rp->next; } @@ -669,6 +765,34 @@ replace_sections(void) sects = allocate(nsects * sizeof(struct rep_sect)); bzero(sects, nsects * sizeof(struct rep_sect)); + /* + * Set the pagesize to match that of the input file. Note that we cannot + * assume a single pagesize across all Mach-O files. + */ + pagesize = 0; + if (0 == pagesize) + { + cpu_type_t cputype = (mhp != NULL ? + mhp->cputype : mhp64->cputype); + cpu_subtype_t cpusubtype = (mhp != NULL ? + mhp->cpusubtype : mhp64->cpusubtype); + const char* arch_name = get_arch_name_from_types(cputype, + cpusubtype); + if (arch_name != NULL) { + struct arch_flag arch_flag; + if (get_arch_from_flag((char*)arch_name, &arch_flag)) { + pagesize = get_segalign_from_flag(&arch_flag); + } + else { + /* unreachable? */ + fatal("unknown cputype %u found in %s", cputype, input); + } + } + else { + fatal("unknown cputype %u found in %s", cputype, input); + } + } + /* * First go through the segments and adjust the segment offsets, sizes * and addresses without adjusting the offset to the relocation entries. @@ -676,6 +800,10 @@ replace_sections(void) * address spaces starting at zero and that the offsets in the file for * the contents of the segments also being contiguious and in the same * order as the vmaddresses. + * + * Note that in a modern Mach-O file, segedit can resize individual + * sections, but their overall segment sizes cannot change. There once + * was a time in early NeXTSTEP when that was not true... */ oldvmaddr = 0; newvmaddr = 0; @@ -683,146 +811,266 @@ replace_sections(void) if(segs[0].sgp != NULL) oldoffset = segs[0].sgp->fileoff; else - oldoffset = segs[0].sgp64->fileoff; + oldoffset = (uint32_t)segs[0].sgp64->fileoff; } else oldoffset = 0; newoffset = 0; k = 0; for(i = 0; i < nsegs; i++){ - if(segs[i].sgp != NULL){ + if(segs[i].sgp != NULL){ /* process the 32-bit file */ + /* verify the segment vmaddrs are contiguous */ if(segs[i].sgp->vmaddr != oldvmaddr) fatal("addresses of input file: %s not in an order that " "the specified sections can be replaced by this " "program", input); + /* + * initialize the rep_seg struct's filesize, vmsize, and vmaddr + * fields. update the vmaddr if this file is resizeable (hint: + * it's not). + */ segs[i].filesize = segs[i].sgp->filesize; segs[i].vmsize = segs[i].sgp->vmsize; - segs[i].sgp->vmaddr = newvmaddr; - if(segs[i].sgp->filesize != 0){ + if (no_seg_resize == FALSE) { + segs[i].sgp->vmaddr = (uint32_t)newvmaddr; + } else { + if(segs[i].sgp->vmaddr != newvmaddr) + fatal("input file: %s segment %.16s vmaddr cannot be " + "repositioned", + input, segs[i].sgp->segname); + } + + if(segs[i].sgp->filesize != 0) + { + /* verify the segment fileoffs are contiguous */ if(segs[i].sgp->fileoff != oldoffset) fatal("segment offsets of input file: %s not in an " "order that the specified sections can be " "replaced by this program", input); + /* + * initialize the rep_seg struct's fileoff field, and adjust + * it if this file is resizeable (hint: still no.) + */ segs[i].fileoff = segs[i].sgp->fileoff; if(strcmp(segs[i].sgp->segname, SEG_LINKEDIT) != 0 || - i != nsegs - 1) - segs[i].sgp->fileoff = newoffset; - sp = (struct section *)((char *)(segs[i].sgp) + - sizeof(struct segment_command)); - oldsectsize = 0; - newsectsize = 0; - if(segs[i].sgp->flags & SG_NORELOC){ - for(j = 0; j < segs[i].sgp->nsects; j++){ - sects[k + j].sp = sp; - sects[k + j].offset = sp->offset; - oldsectsize += sp->size; - rp = replaces; - while(rp != NULL){ - if(strncmp(rp->segname, sp->segname, - sizeof(sp->segname)) == 0 && - strncmp(rp->sectname, sp->sectname, - sizeof(sp->sectname)) == 0){ - sects[k + j].rp = rp; - segs[i].modified = 1; - sp->size = rnd(rp->size, 1 << sp->align); - break; - } - rp = rp->next; + i != nsegs - 1) { + if (no_seg_resize == FALSE) { + segs[i].sgp->fileoff = newoffset; + } else { + if (segs[i].sgp->fileoff != newoffset) { + fatal("input file: %s segment %.16s fileoff " + "cannot be repositioned", + input, segs[i].sgp->segname); } - sp->offset = newoffset + newsectsize; - sp->addr = newvmaddr + newsectsize; - newsectsize += sp->size; - sp++; } - if(strcmp(segs[i].sgp->segname, SEG_LINKEDIT) != 0 || - i != nsegs - 1){ - if(segs[i].sgp->filesize != rnd(oldsectsize, - pagesize)) - fatal("contents of input file: %s not in a " - "format that the specified sections can " - "be replaced by this program", input); - segs[i].sgp->filesize = - rnd(newsectsize, pagesize); - segs[i].sgp->vmsize = rnd(newsectsize, pagesize); - segs[i].padsize = - segs[i].sgp->filesize - newsectsize; + } + } + + sp = (struct section *)((char *)(segs[i].sgp) + + sizeof(struct segment_command)); + oldsectsize = 0; + newsectsize = 0; + if(segs[i].sgp->flags & SG_NORELOC){ + /* + * this segment contains sections that can be replaced. + * loop over the sections and record the new offsets + * and sizes for the replaced content. + * + * recall that if no_seg_resize is true the sections + * cannot spill beyond the segment boundary. + */ + for(j = 0; j < segs[i].sgp->nsects; j++){ + sects[k + j].sp = sp; + sects[k + j].offset = sp->offset; + oldsectsize += sp->size; + rp = replaces; + while(rp != NULL){ + if(strncmp(rp->segname, sp->segname, + sizeof(sp->segname)) == 0 && + strncmp(rp->sectname, sp->sectname, + sizeof(sp->sectname)) == 0){ + sects[k + j].rp = rp; + segs[i].modified = 1; + sp->size = rnd32(rp->size, 1 << sp->align); + break; + } + rp = rp->next; } + sp->offset = newoffset + newsectsize; + sp->addr = (uint32_t)(newvmaddr + newsectsize); + newsectsize += sp->size; + sp++; } if(strcmp(segs[i].sgp->segname, SEG_LINKEDIT) != 0 || i != nsegs - 1){ - oldoffset += segs[i].filesize; - newoffset += segs[i].sgp->filesize; + if(segs[i].sgp->filesize != rnd(oldsectsize, + pagesize)) + fatal("contents of input file: %s not in a " + "format that the specified sections can " + "be replaced by this program", input); + segs[i].padsize = + segs[i].sgp->filesize - newsectsize; + if (no_seg_resize == FALSE) { + segs[i].sgp->filesize = + rnd32(newsectsize, pagesize); + segs[i].sgp->vmsize = rnd32(newsectsize, + pagesize); + } else { + if (segs[i].sgp->filesize != + rnd(newsectsize, pagesize)) { + fatal("input file: %s segment %.16s " + "cannot be resized (filesize %u => " + "%llu)", + input, segs[i].sgp->segname, + segs[i].sgp->filesize, + rnd(newsectsize, pagesize)); + } + if (segs[i].sgp->vmsize != + rnd(newsectsize, pagesize)) { + fatal("input file: %s segment %.16s " + "cannot be resized (vmsize %u => " + "%llu)", + input, segs[i].sgp->segname, + segs[i].sgp->vmsize, + rnd(newsectsize, pagesize)); + } + } } } + if(strcmp(segs[i].sgp->segname, SEG_LINKEDIT) != 0 || + i != nsegs - 1){ + oldoffset += segs[i].filesize; + newoffset += segs[i].sgp->filesize; + } + oldvmaddr += segs[i].vmsize; newvmaddr += segs[i].sgp->vmsize; k += segs[i].sgp->nsects; } - else{ + else { /* process the 64-bit file */ + /* verify the segment vmaddrs are contiguous */ if(segs[i].sgp64->vmaddr != oldvmaddr) fatal("addresses of input file: %s not in an order that " "the specified sections can be replaced by this " "program", input); - segs[i].filesize = segs[i].sgp64->filesize; + /* + * initialize the rep_seg struct's filesize, vmsize, and vmaddr + * fields. update the vmaddr if this file is resizeable (hint: + * it's not). + */ + segs[i].filesize = (uint32_t)segs[i].sgp64->filesize; segs[i].vmsize = segs[i].sgp64->vmsize; - segs[i].sgp64->vmaddr = newvmaddr; - if(segs[i].sgp64->filesize != 0){ + if (no_seg_resize == FALSE) { + segs[i].sgp64->vmaddr = newvmaddr; + } else { + if(segs[i].sgp64->vmaddr != newvmaddr) + fatal("input file: %s segment %.16s vmaddr cannot be " + "repositioned", input, segs[i].sgp64->segname); + } + + if(segs[i].sgp64->filesize != 0) + { + /* verify the segment fileoffs are contiguous */ if(segs[i].sgp64->fileoff != oldoffset) fatal("segment offsets of input file: %s not in an " "order that the specified sections can be " "replaced by this program", input); - segs[i].fileoff = segs[i].sgp64->fileoff; + /* + * initialize the rep_seg struct's fileoff field, and adjust + * it if this file is resizeable (hint: still no.) + */ + segs[i].fileoff = (uint32_t)segs[i].sgp64->fileoff; if(strcmp(segs[i].sgp64->segname, SEG_LINKEDIT) != 0 || - i != nsegs - 1) - segs[i].sgp64->fileoff = newoffset; - sp = (struct section *)((char *)(segs[i].sgp) + - sizeof(struct segment_command)); - oldsectsize = 0; - newsectsize = 0; - if(segs[i].sgp64->flags & SG_NORELOC){ - for(j = 0; j < segs[i].sgp64->nsects; j++){ - sects[k + j].sp = sp; - sects[k + j].offset = sp->offset; - oldsectsize += sp->size; - rp = replaces; - while(rp != NULL){ - if(strncmp(rp->segname, sp->segname, - sizeof(sp->segname)) == 0 && - strncmp(rp->sectname, sp->sectname, - sizeof(sp->sectname)) == 0){ - sects[k + j].rp = rp; - segs[i].modified = 1; - sp->size = rnd(rp->size, 1 << sp->align); - break; - } - rp = rp->next; + i != nsegs - 1) { + if (no_seg_resize == FALSE) { + segs[i].sgp64->fileoff = newoffset; + } else { + if (segs[i].sgp64->fileoff != newoffset) { + fatal("input file: %s segment %.16s fileoff " + "cannot be repositioned", + input, segs[i].sgp64->segname); } - sp->offset = newoffset + newsectsize; - sp->addr = newvmaddr + newsectsize; - newsectsize += sp->size; - sp++; } - if(strcmp(segs[i].sgp64->segname, SEG_LINKEDIT) != 0 || - i != nsegs - 1){ - if(segs[i].sgp64->filesize != rnd(oldsectsize, - pagesize)) - fatal("contents of input file: %s not in a " - "format that the specified sections can " - "be replaced by this program", input); + } + } + sp64 = (struct section_64 *)((char *)(segs[i].sgp64) + + sizeof(struct segment_command_64)); + oldsectsize = 0; + newsectsize = 0; + if(segs[i].sgp64->flags & SG_NORELOC){ + /* + * this segment contains sections that can be replaced. + * loop over the sections and record the new offsets + * and sizes for the replaced content. + * + * recall that if no_seg_resize is true the sections + * cannot spill beyond the segment boundary. + */ + for(j = 0; j < segs[i].sgp64->nsects; j++){ + sects[k + j].sp64 = sp64; + sects[k + j].offset = sp64->offset; + oldsectsize += sp64->size; + rp = replaces; + while(rp != NULL){ + if(strncmp(rp->segname, sp64->segname, + sizeof(sp64->segname)) == 0 && + strncmp(rp->sectname, sp64->sectname, + sizeof(sp64->sectname)) == 0){ + sects[k + j].rp = rp; + segs[i].modified = 1; + sp64->size = + rnd(rp->size, 1 << sp64->align); + break; + } + rp = rp->next; + } + sp64->offset = newoffset + newsectsize; + sp64->addr = newvmaddr + newsectsize; + newsectsize += sp64->size; + sp64++; + } + if(strcmp(segs[i].sgp64->segname, SEG_LINKEDIT) != 0 || + i != nsegs - 1){ + if(segs[i].sgp64->filesize != rnd(oldsectsize, + pagesize)) + fatal("contents of input file: %s not in a " + "format that the specified sections can " + "be replaced by this program", input); + segs[i].padsize = (uint32_t) + (segs[i].sgp64->filesize - newsectsize); + if (no_seg_resize == FALSE) { segs[i].sgp64->filesize = rnd(newsectsize, pagesize); segs[i].sgp64->vmsize = rnd(newsectsize, pagesize); - segs[i].padsize = - segs[i].sgp64->filesize - newsectsize; + } else { + if (segs[i].sgp64->filesize != + rnd(newsectsize, pagesize)) { + fatal("input file: %s segment %.16s " + "cannot be resized (filesize %llu => " + "%llu)", + input, segs[i].sgp64->segname, + segs[i].sgp64->filesize, + rnd(newsectsize, pagesize)); + } + if (segs[i].sgp64->vmsize != + rnd(newsectsize, pagesize)) { + fatal("input file: %s segment %.16s " + "cannot be resized (vmsize %llu => " + "%llu)", + input, segs[i].sgp64->segname, + segs[i].sgp64->vmsize, + rnd(newsectsize, pagesize)); + } } } - if(strcmp(segs[i].sgp64->segname, SEG_LINKEDIT) != 0 || - i != nsegs - 1){ - oldoffset += segs[i].filesize; - newoffset += segs[i].sgp64->filesize; - } } + if(strcmp(segs[i].sgp64->segname, SEG_LINKEDIT) != 0 || + i != nsegs - 1){ + oldoffset += segs[i].filesize; + newoffset += segs[i].sgp64->filesize; + } + oldvmaddr += segs[i].vmsize; newvmaddr += segs[i].sgp64->vmsize; k += segs[i].sgp64->nsects; @@ -832,46 +1080,48 @@ replace_sections(void) /* * Now update the offsets to the linkedit information. */ - if(oldoffset != low_linkedit) - fatal("contents of input file: %s not in an order that the " - "specified sections can be replaced by this program", input); - for(i = 0; i < nsegs; i++){ - if(segs[i].sgp != NULL){ - sp = (struct section *)((char *)(segs[i].sgp) + - sizeof(struct segment_command)); - for(j = 0; j < segs[i].sgp->nsects; j++){ - if(sp->nreloc != 0) - sp->reloff += newoffset - oldoffset; - sp++; + if (no_seg_resize == FALSE) { + if(oldoffset != low_linkedit) + fatal("contents of input file: %s not in an order that the " + "specified sections can be replaced by this program", + input); + for(i = 0; i < nsegs; i++){ + if(segs[i].sgp != NULL){ + sp = (struct section *)((char *)(segs[i].sgp) + + sizeof(struct segment_command)); + for(j = 0; j < segs[i].sgp->nsects; j++){ + if(sp->nreloc != 0) + sp->reloff += newoffset - oldoffset; + sp++; + } + } + else{ + sp64 = (struct section_64 *)((char *)(segs[i].sgp64) + + sizeof(struct segment_command_64)); + for(j = 0; j < segs[i].sgp64->nsects; j++){ + if(sp64->nreloc != 0) + sp64->reloff += newoffset - oldoffset; + sp64++; + } } } - else{ - sp64 = (struct section_64 *)((char *)(segs[i].sgp64) + - sizeof(struct segment_command_64)); - for(j = 0; j < segs[i].sgp64->nsects; j++){ - if(sp64->nreloc != 0) - sp64->reloff += newoffset - oldoffset; - sp64++; - } + if(stp != NULL){ + if(stp->nsyms != 0) + stp->symoff += newoffset - oldoffset; + if(stp->strsize != 0) + stp->stroff += newoffset - oldoffset; + } + if(ssp != NULL){ + if(ssp->size != 0) + ssp->offset += newoffset - oldoffset; + } + if(linkedit_sgp != NULL){ + linkedit_sgp->fileoff += newoffset - oldoffset; + } + if(linkedit_sgp64 != NULL){ + linkedit_sgp64->fileoff += newoffset - oldoffset; } } - if(stp != NULL){ - if(stp->nsyms != 0) - stp->symoff += newoffset - oldoffset; - if(stp->strsize != 0) - stp->stroff += newoffset - oldoffset; - } - if(ssp != NULL){ - if(ssp->size != 0) - ssp->offset += newoffset - oldoffset; - } - if(linkedit_sgp != NULL){ - linkedit_sgp->fileoff += newoffset - oldoffset; - } - if(linkedit_sgp64 != NULL){ - linkedit_sgp64->fileoff += newoffset - oldoffset; - } - /* * Now write the new file by writing the header and modified load * commands, then the segments with any new sections and finally @@ -905,8 +1155,8 @@ replace_sections(void) system_error("Can't map file: %s",rp->filename); for(l = rp->size + 1; l < sp->size; l++) *((char *)sect_addr + l) = '\0'; - if(write(outfd, (char *)sect_addr,sp->size) != - sp->size) + if(write64(outfd, (char *)sect_addr,sp->size) != + sp->size) system_fatal("can't write new section contents " "for section (%s,%s) to output file: %s", rp->segname, rp->sectname, output); @@ -927,9 +1177,9 @@ replace_sections(void) "(section (%.16s,%.16s) extends past the " "end of the file)",input, sp->segname, sp->sectname); - if(write(outfd,(char *)input_addr + - sects[k + j].offset, - sp->size) != sp->size) + if(write64(outfd,(char *)input_addr + + sects[k + j].offset, + sp->size) != sp->size) system_fatal("can't write section contents for " "section (%s,%s) to output file: %s", rp->segname, rp->sectname, output); @@ -937,7 +1187,7 @@ replace_sections(void) sp++; } /* write the segment padding */ - if(write(outfd, (char *)pad_addr, segs[i].padsize) != + if(write64(outfd, (char *)pad_addr, segs[i].padsize) != segs[i].padsize) system_fatal("can't write segment padding for segment " "%s to output file: %s", segs[i].sgp->segname, @@ -960,8 +1210,8 @@ replace_sections(void) system_error("Can't map file: %s",rp->filename); for(l = rp->size + 1; l < sp64->size; l++) *((char *)sect_addr + l) = '\0'; - if(write(outfd, (char *)sect_addr,sp64->size) != - sp64->size) + if(write64(outfd, (char *)sect_addr,sp64->size) != + sp64->size) system_fatal("can't write new section contents " "for section (%s,%s) to output file: %s", rp->segname, rp->sectname, output); @@ -982,9 +1232,9 @@ replace_sections(void) "(section (%.16s,%.16s) extends past the " "end of the file)",input, sp64->segname, sp64->sectname); - if(write(outfd,(char *)input_addr + - sects[k + j].offset, - sp64->size) != sp64->size) + if(write64(outfd,(char *)input_addr + + sects[k + j].offset, + sp64->size) != sp64->size) system_fatal("can't write section contents for " "section (%s,%s) to output file: %s", rp->segname, rp->sectname, output); @@ -992,7 +1242,7 @@ replace_sections(void) sp64++; } /* write the segment padding */ - if(write(outfd, (char *)pad_addr, segs[i].padsize) != + if(write64(outfd, (char *)pad_addr, segs[i].padsize) != segs[i].padsize) system_fatal("can't write segment padding for segment " "%s to output file: %s", segs[i].sgp64->segname, @@ -1008,8 +1258,9 @@ replace_sections(void) fatal("truncated or malformed object file: %s " "(segment: %s extends past the end of " "the file)", input, segs[i].sgp->segname); - if(write(outfd, (char *)input_addr + segs[i].fileoff, - segs[i].sgp->filesize) != segs[i].sgp->filesize) + if(write64(outfd, (char *)input_addr + segs[i].fileoff, + segs[i].sgp->filesize) != + segs[i].sgp->filesize) system_fatal("can't write segment contents for " "segment: %s to output file: %s", segs[i].sgp->segname, output); @@ -1023,8 +1274,9 @@ replace_sections(void) fatal("truncated or malformed object file: %s " "(segment: %s extends past the end of " "the file)", input, segs[i].sgp64->segname); - if(write(outfd, (char *)input_addr + segs[i].fileoff, - segs[i].sgp64->filesize) != segs[i].sgp64->filesize) + if(write64(outfd, (char *)input_addr + segs[i].fileoff, + segs[i].sgp64->filesize) != + segs[i].sgp64->filesize) system_fatal("can't write segment contents for " "segment: %s to output file: %s", segs[i].sgp64->segname, output); @@ -1038,7 +1290,7 @@ replace_sections(void) } /* write the linkedit info */ size = input_size - low_linkedit; - if(write(outfd, (char *)input_addr + low_linkedit, size) != size) + if(write64(outfd, (char *)input_addr + low_linkedit, size) != size) system_fatal("can't write link edit information to output file: %s", output); lseek(outfd, 0, L_SET); @@ -1084,7 +1336,7 @@ replace_sections(void) else swap_mach_header_64(mhp64, host_byte_sex); } - if(write(outfd, input_addr, size) != size) + if(write64(outfd, input_addr, size) != size) system_fatal("can't write headers to output file: %s", output); if(close(outfd) == -1) @@ -1166,8 +1418,20 @@ static void usage(void) { - fprintf(stderr, "Usage: %s [-extract " - "] ...\n\t[[-replace " - "] ... -output ]\n", progname); - exit(1); + /* Just print the basename for the usage. */ + const char* basename = strrchr(progname, '/'); + if (basename) { + basename += 1; + } else { + basename = progname; + } + fprintf(stderr, + "usage: %s input_file [-extract seg_name sect_name data_file] " + "...\n", + basename); + fprintf(stderr, + " %s input_file [-replace seg_name sect_name data_file] " + "... -output output_file\n", + basename); + exit(1); } diff --git a/cctools/misc/size.c b/cctools/misc/size.c index d4f0f0b..fdd251e 100644 --- a/cctools/misc/size.c +++ b/cctools/misc/size.c @@ -94,12 +94,13 @@ int argc, char **argv, char **envp) { - int i; + int i,j; enum bool args_left; struct flags flag; struct arch_flag *arch_flags; uint32_t narch_flags; enum bool all_archs; + char **files; progname = argv[0]; arch_flags = NULL; @@ -111,27 +112,14 @@ char **envp) flag.l = FALSE; flag.x = FALSE; + files = allocate(sizeof(char *) * argc); for(i = 1; i < argc; i++){ if(argv[i][0] == '-'){ - if(argv[i][1] == '\0'){ - flag.nfiles += argc - i - 1; - break; - } - if(strcmp(argv[i], "-m") == 0){ - flag.m = TRUE; + if(argv[i][1] == '\0' || + 0 == strcmp("--", argv[i])){ continue; } - if(strcmp(argv[i], "-l") == 0){ - flag.l = TRUE; - flag.m = TRUE; - continue; - } - if(strcmp(argv[i], "-x") == 0){ - flag.x = TRUE; - flag.m = TRUE; - continue; - } - if(strcmp(argv[i], "-arch") == 0){ + else if(strcmp(argv[i], "-arch") == 0){ if(i + 1 == argc){ error("missing argument(s) to %s option", argv[i]); usage(); @@ -154,37 +142,43 @@ char **envp) i++; continue; } + else { + for(j = 1; argv[i][j] != '\0'; j++){ + switch(argv[i][j]){ + case 'l': + flag.l = TRUE; + break; + case 'm': + flag.m = TRUE; + break; + case 'x': + flag.x = TRUE; + break; + default: + error("invalid argument -%c", argv[i][j]); + usage(); + } + } + continue; + } } - flag.nfiles++; + files[flag.nfiles++] = argv[i]; } if(flag.m == FALSE) printf("__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n"); args_left = TRUE; - for (i = 1; i < argc; i++) { - if(args_left == TRUE && argv[i][0] == '-'){ - if(argv[i][1] == '\0'){ - args_left = FALSE; - continue; - } - if(strcmp(argv[i], "-m") == 0) - continue; - if(strcmp(argv[i], "-l") == 0) - continue; - if(strcmp(argv[i], "-x") == 0) - continue; - if(strcmp(argv[i], "-arch") == 0){ - i++; - continue; - } - } - ofile_process(argv[i], arch_flags, narch_flags, all_archs, FALSE, + for (i = 0; i < flag.nfiles; i++) { + ofile_process(files[i], arch_flags, narch_flags, all_archs, FALSE, TRUE, TRUE, size, &flag); } if(flag.nfiles == 0) ofile_process("a.out", arch_flags, narch_flags, all_archs, FALSE, TRUE, TRUE, size, &flag); + + free(files); + if(errors == 0) return(EXIT_SUCCESS); else diff --git a/cctools/misc/strings.c b/cctools/misc/strings.c index 2d01a83..d7f9057 100644 --- a/cctools/misc/strings.c +++ b/cctools/misc/strings.c @@ -74,6 +74,7 @@ #include #include #include +#include #include #include #include "stuff/bool.h" @@ -99,8 +100,8 @@ static void ofile_processor( void *cookie); static void ofile_find( char *addr, - uint32_t size, - uint32_t offset, + uint64_t size, + uint64_t offset, struct flags *flags); static void find( uint32_t cnt, @@ -174,7 +175,8 @@ char **envp) error("missing argument to %s option", argv[i]); usage(); } - flags.minimum_length = strtoul(argv[i+1], &endp, 10); + flags.minimum_length = + (uint32_t)strtoul(argv[i+1], &endp, 10); if(*endp != '\0'){ error("invalid decimal number in option: %s %s", argv[i], argv[i+1]); @@ -228,7 +230,8 @@ char **envp) error("unknown flag: %s", argv[i]); usage(); } - flags.minimum_length = strtoul(argv[i]+j,&endp,10); + flags.minimum_length = + (uint32_t)strtoul(argv[i] + j, &endp, 10); if(*endp != '\0'){ error("invalid decimal number in flag: %s", argv[i]); @@ -319,7 +322,8 @@ char *arch_name, void *cookie) { char *addr; - uint32_t offset, size, i, j; + uint64_t offset, size; + uint32_t i, j; uint32_t ncmds; struct flags *flags; struct load_command *lc; @@ -334,11 +338,24 @@ void *cookie) * If the ofile is not an object file then process it without reguard * to sections. */ - if(ofile->object_addr == NULL){ + if(ofile->object_addr == NULL +#ifdef LTO_SUPPORT + || ofile->member_type == OFILE_LLVM_BITCODE +#endif /* LTO_SUPPORT */ + ){ if(ofile->file_type == OFILE_FAT && ofile->arch_flag.cputype != 0){ - addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset; - size = ofile->fat_archs[ofile->narch].size; - offset = ofile->fat_archs[ofile->narch].offset; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + addr = ofile->file_addr + + ofile->fat_archs64[ofile->narch].offset; + size = ofile->fat_archs64[ofile->narch].size; + offset = ofile->fat_archs64[ofile->narch].offset; + } + else{ + addr = ofile->file_addr + + ofile->fat_archs[ofile->narch].offset; + size = ofile->fat_archs[ofile->narch].size; + offset = ofile->fat_archs[ofile->narch].offset; + } } else{ addr = ofile->file_addr; @@ -456,11 +473,11 @@ static void ofile_find( char *addr, -uint32_t size, -uint32_t offset, +uint64_t size, +uint64_t offset, struct flags *flags) { - uint32_t i, string_length; + uint64_t i, string_length; char c, *string; string = addr; @@ -499,24 +516,29 @@ struct flags *flags) { static char buf[BUFSIZ]; register char *cp; - register int c, cc; + register int c, cc, i; - cp = buf, cc = 0; - for (; cnt != 0; cnt--) { + /* Unix Conformance 2019 */ + setlocale(LC_ALL, ""); + + cp = buf; + cc = 0; + for (i = 0; i < cnt; ++i) { c = getc(stdin); - if (c == '\n' || dirt(c) || cnt == 0) { + if (c == '\n' || !isprint(c) || (i + 1) == cnt) { if (cp > buf && cp[-1] == '\n') --cp; *cp++ = 0; if (cp > &buf[flags->minimum_length]) { if (flags->print_offsets == TRUE){ printf(flags->offset_format, - ftell(stdin) - cc - 1); + i - cc); printf(" "); } printf("%s\n", buf); } - cp = buf, cc = 0; + cp = buf; + cc = 0; } else { if (cp < &buf[sizeof buf - 2]) *cp++ = c; diff --git a/cctools/misc/strip.c b/cctools/misc/strip.c index 3b22b18..42ee2e3 100644 --- a/cctools/misc/strip.c +++ b/cctools/misc/strip.c @@ -28,6 +28,7 @@ #include #include #include +#include /* cctools-port: For bcmp, bzero ... */ #include #include #include @@ -46,6 +47,7 @@ #include "stuff/symbol_list.h" #include "stuff/unix_standard_mode.h" #include "stuff/execute.h" +#include "stuff/write64.h" #ifdef TRIE_SUPPORT #include #endif /* TRIE_SUPPORT */ @@ -69,11 +71,20 @@ static uint32_t nflag; /* save N_SECT global symbols */ static uint32_t Sflag; /* -S strip only debugger symbols N_STAB */ static uint32_t xflag; /* -x strip non-globals */ static uint32_t Xflag; /* -X strip local symbols with 'L' names */ +static uint32_t Tflag; /* -T strip Swift symbols: symbols that start with + '_$S' or '_$s' */ +static uint32_t Nflag; /* -N strip all nlist symbols and strings */ static uint32_t cflag; /* -c strip section contents from dynamic libraries files to create stub libraries */ static uint32_t no_uuid;/* -no_uuid strip LC_UUID load commands */ +static uint32_t no_split_info; /* -no_split_info strip LC_SEGMENT_SPLIT_INFO + load command and its payload */ +static uint32_t no_code_signature_warning; + /* -no_code_signature_warning then don't warn when the code + signature would be invalid */ static uint32_t vflag; /* -v for verbose debugging ld -r executions */ static uint32_t lflag; /* -l do ld -r executions even if it has bugs */ +static enum bool toc64flag = FALSE; /* -toc64 for a 64-bit toc in archives */ static uint32_t strip_all = 1; /* * This is set on an object by object basis if the strip_all flag is still set @@ -81,6 +92,13 @@ static uint32_t strip_all = 1; * This has the same effect as -r and -u. */ static enum bool default_dyld_executable = FALSE; + +/* + * When the -N flag is used it may not be possible to strip all nlists because + * the file is not used by dyld, an MH_KEXT_BUNDLE filetype or has external + * relocations in the LC_DYSYMTAB. + */ +static enum bool strip_all_nlists = FALSE; #endif /* NMEDIT */ /* @@ -169,6 +187,11 @@ struct undef_map64 { struct nlist_64 symbol64; }; static char *qsort_strings = NULL; + +struct strx_map { + uint32_t old_strx; + uint32_t new_strx; +}; #endif /* !defined(NMEDIT) */ @@ -227,6 +250,7 @@ static void check_indirect_symtab( uint32_t nsyms, char *strings, int32_t *missing_reloc_symbols, + uint32_t swift_version, enum byte_sex host_byte_sex); #ifndef NMEDIT @@ -240,7 +264,9 @@ static enum bool strip_symtab( struct dylib_module_64 *mods64, uint32_t nmodtab, struct dylib_reference *refs, - uint32_t nextrefsyms); + uint32_t nextrefsyms, + uint32_t *p_swift_version, + enum bool *nlist_outofsync_with_dyldinfo); #ifdef TRIE_SUPPORT static int prune( @@ -257,6 +283,11 @@ static void strip_LC_UUID_commands( struct member *member, struct object *object); +static void strip_LC_SEGMENT_SPLIT_INFO_command( + struct arch *arch, + struct member *member, + struct object *object); + #ifndef NMEDIT static void strip_LC_CODE_SIGNATURE_commands( struct arch *arch, @@ -274,6 +305,14 @@ static enum bool symbol_pointer_used( uint32_t *indirectsyms, uint32_t nindirectsyms); +static int cmp_qsort_strx_map( + const struct strx_map* a, + const struct strx_map* b); + +static int cmp_bsearch_strx_map( + const uint32_t* old_strx, + const struct strx_map *strx_map); + static int cmp_qsort_undef_map( const struct undef_map *sym1, const struct undef_map *sym2); @@ -413,6 +452,15 @@ char *envp[]) else if(strcmp(argv[i], "-no_uuid") == 0){ no_uuid = 1; } + else if(strcmp(argv[i], "-no_split_info") == 0){ + no_split_info = 1; + } + else if(strcmp(argv[i], "-no_code_signature_warning") == 0){ + no_code_signature_warning = 1; + } + else if(strcmp(argv[i], "-toc64") == 0){ + toc64flag = TRUE; + } #endif /* !defined(NMEDIT) */ else if(strcmp(argv[i], "-arch") == 0){ if(i + 1 == argc){ @@ -463,6 +511,13 @@ char *envp[]) Xflag = 1; strip_all = 0; break; + case 'T': + Tflag = 1; + strip_all = 0; + break; + case 'N': + Nflag = 1; + break; case 'x': xflag = 1; strip_all = 0; @@ -511,6 +566,13 @@ char *envp[]) else files_specified++; } + /* + * This allows testing of stripping all nlists and string tables. + */ +#ifndef NMEDIT + if(getenv("STRIP_NLISTS") != NULL) + Nflag = 1; +#endif /* !defined(NMEDIT) */ if(args_left == 0) files_specified += argc - (i + 1); @@ -657,7 +719,13 @@ enum bool all_archs) system_error("can't stat input file: %s", input_file); if(output_file != NULL){ writeout(archs, narchs, output_file, stat_buf.st_mode & 0777, - TRUE, FALSE, FALSE, NULL); + TRUE, FALSE, +#ifdef NMEDIT + FALSE, +#else + toc64flag, +#endif + FALSE, NULL); } else{ unix_standard_mode = get_unix_standard_mode(); @@ -709,7 +777,13 @@ enum bool all_archs) } #endif /* NMEDIT */ writeout(archs, narchs, output_file, stat_buf.st_mode & 0777, - TRUE, FALSE, FALSE, NULL); + TRUE, FALSE, +#ifdef NMEDIT + FALSE, +#else + toc64flag, +#endif + FALSE, NULL); if(rename_file != NULL){ if(rename(output_file, rename_file) == -1) system_error("can't move temporary file: %s to file: %s", @@ -764,6 +838,10 @@ enum bool all_archs) const struct arch_flag *family_arch_flag; struct ar_hdr h; char size_buf[sizeof(h.ar_size) + 1]; + char date_buf[sizeof(h.ar_date) + 1]; + enum bool zero_ar_date; + + zero_ar_date = getenv("ZERO_AR_DATE") ? TRUE : FALSE; /* * Using the specified arch_flags process specified objects for those @@ -793,6 +871,10 @@ enum bool all_archs) cputype = archs[i].object->mh_cputype; cpusubtype = archs[i].object->mh_cpusubtype; } + else if(archs[i].fat_arch64 != NULL){ + cputype = archs[i].fat_arch64->cputype; + cpusubtype = archs[i].fat_arch64->cpusubtype; + } else if(archs[i].fat_arch != NULL){ cputype = archs[i].fat_arch->cputype; cpusubtype = archs[i].fat_arch->cpusubtype; @@ -885,8 +967,8 @@ enum bool all_archs) archs[i].members[j].offset = offset; size = 0; if(archs[i].members[j].member_long_name == TRUE){ - size = rnd(archs[i].members[j].member_name_size, 8) + - (rnd(sizeof(struct ar_hdr), 8) - + size = rnd32(archs[i].members[j].member_name_size, 8) + + (rnd32(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr)); archs[i].toc_long_name = TRUE; } @@ -912,6 +994,21 @@ enum bool all_archs) offset += sizeof(struct ar_hdr) + size; } archs[i].library_size = offset; + /* + * Reset the library date, if needed + */ + if (zero_ar_date == TRUE) { + sprintf(date_buf, "%-*ld", (int)sizeof(h.ar_date), + (unsigned long)0); + /* + * This has to be done by hand because sprintf puts a + * null at the end of the buffer. + */ + for(j = 0; j < archs[i].nmembers; j++){ + memcpy(archs[i].members[j].ar_hdr->ar_date, date_buf, + (int)sizeof(archs[i].members[j].ar_hdr->ar_date)); + } + } } else if(archs[i].type == OFILE_Mach_O){ strip_object(archs + i, NULL, archs[i].object); @@ -969,8 +1066,18 @@ struct object *object) uint32_t k; #endif uint32_t ncmds; + uint32_t swift_version; + enum bool nlist_outofsync_with_dyldinfo; + uint32_t mh_flags; + + if(object->mh != NULL) + mh_flags = object->mh->flags; + else + mh_flags = object->mh64->flags; host_byte_sex = get_host_byte_sex(); + swift_version = 0; + nlist_outofsync_with_dyldinfo = FALSE; /* Don't do anything to stub dylibs which have no load commands. */ if(object->mh_filetype == MH_DYLIB_STUB){ @@ -1229,11 +1336,19 @@ struct object *object) default_dyld_executable = TRUE; else default_dyld_executable = FALSE; + if(Nflag && + (mh_flags & MH_DYLDLINK) == MH_DYLDLINK && + object->mh_filetype != MH_KEXT_BUNDLE && + object->dyst != NULL && object->dyst->nextrel == 0) + strip_all_nlists = TRUE; + else + strip_all_nlists = FALSE; + #endif /* !defined(NMEDIT) */ #ifndef NMEDIT if(sfile != NULL || Rfile != NULL || dfile != NULL || Aflag || uflag || - Sflag || xflag || Xflag || nflag || rflag || + Sflag || xflag || Xflag || Tflag || nflag || rflag || default_dyld_executable || object->mh_filetype == MH_DYLIB || object->mh_filetype == MH_DYLINKER) #endif /* !defined(NMEDIT) */ @@ -1245,7 +1360,8 @@ struct object *object) return; #else /* !defined(NMEDIT) */ if(strip_symtab(arch, member, object, tocs, ntoc, mods, mods64, - nmodtab, refs, nextrefsyms) == FALSE) + nmodtab, refs, nextrefsyms, &swift_version, + &nlist_outofsync_with_dyldinfo) == FALSE) return; if(no_uuid == TRUE) strip_LC_UUID_commands(arch, member, object); @@ -1347,6 +1463,34 @@ struct object *object) #endif /* !(NMEDIT) */ } + if(object->dyld_chained_fixups != NULL) { +#ifndef NMEDIT + if(!cflag) +#endif /* !(NMEDIT) */ + { + object->output_sym_info_size += + object->dyld_chained_fixups->datasize; + object->output_dyld_chained_fixups_data = + object->object_addr + + object->dyld_chained_fixups->dataoff; + object->output_dyld_chained_fixups_data_size = + object->dyld_chained_fixups->datasize; + } + object->input_sym_info_size += + object->dyld_chained_fixups->datasize; + } + + if(object->dyld_exports_trie != NULL) { + object->input_sym_info_size += + object->dyld_exports_trie->datasize; + object->output_sym_info_size += + object->dyld_exports_trie->datasize; + object->output_dyld_exports_trie_data = + object->object_addr + object->dyld_exports_trie->dataoff; + object->output_dyld_exports_trie_data_size = + object->dyld_exports_trie->datasize; + } + if(object->dyst != NULL){ #ifndef NMEDIT /* @@ -1369,8 +1513,10 @@ struct object *object) /* * When stripping out the section contents to create a * dynamic library stub we also remove the split info data. + * And we also remove the split info data if the -no_split_info + * option is specified */ - if(!cflag) + if(!cflag && !no_split_info) #endif /* !(NMEDIT) */ { object->output_split_info_data = object->object_addr + @@ -1382,6 +1528,10 @@ struct object *object) } object->input_sym_info_size += object->split_info_cmd->datasize; } +#ifndef NMEDIT + if(no_split_info == TRUE) + strip_LC_SEGMENT_SPLIT_INFO_command(arch, member, object); +#endif /* !(NMEDIT) */ if(object->func_starts_info_cmd != NULL){ #ifndef NMEDIT @@ -1558,7 +1708,7 @@ struct object *object) object->code_sig_cmd->datasize; } object->input_sym_info_size = - rnd(object->input_sym_info_size, 16); + rnd32(object->input_sym_info_size, 16); object->input_sym_info_size += object->code_sig_cmd->datasize; #ifndef NMEDIT @@ -1569,7 +1719,7 @@ struct object *object) #endif /* !(NMEDIT) */ { object->output_sym_info_size = - rnd(object->output_sym_info_size, 16); + rnd32(object->output_sym_info_size, 16); object->output_sym_info_size += object->code_sig_cmd->datasize; } @@ -1672,6 +1822,25 @@ struct object *object) } } + if(object->dyld_chained_fixups != NULL){ +#ifndef NMEDIT + if(cflag){ + object->dyld_chained_fixups->dataoff = 0; + object->dyld_chained_fixups->datasize = 0; + } + else +#endif /* !(NMEDIT) */ + { + object->dyld_chained_fixups->dataoff = offset; + offset += object->dyld_chained_fixups->datasize; + } + } + + if(object->dyld_exports_trie != NULL){ + object->dyld_exports_trie->dataoff = offset; + offset += object->dyld_exports_trie->datasize; + } + if(object->dyst->nlocrel != 0){ object->output_loc_relocs = (struct relocation_info *) (object->object_addr + object->dyst->locreloff); @@ -1702,8 +1871,10 @@ struct object *object) * When stripping out the section contents to create a * dynamic library stub the split info data gets * stripped. + * And we it also gets stripped if the -no_split_info + * option is specified */ - if(cflag){ + if(cflag || no_split_info){ object->split_info_cmd->dataoff = 0; object->split_info_cmd->datasize = 0; } @@ -1771,7 +1942,11 @@ struct object *object) offset += object->st->nsyms * sizeof(struct nlist_64); } else - object->st->symoff = 0; + /* + * This should be set to zero when nsyms is zero, but dyld + * will think it is malformed. See rdar://34465083 + */ + object->st->symoff = offset; if(object->hints_cmd != NULL){ if(object->hints_cmd->nhints != 0){ @@ -1894,10 +2069,15 @@ struct object *object) offset += object->st->strsize; } else - object->st->stroff = 0; + /* + * This should be set to zero when strsize is zero, but some + * tools will think it is malformed, like machocheck. See + * rdar://34729011 + */ + object->st->stroff = offset; if(object->code_sig_cmd != NULL){ - offset = rnd(offset, 16); + offset = rnd32(offset, 16); object->code_sig_cmd->dataoff = offset; offset += object->code_sig_cmd->datasize; } @@ -2032,6 +2212,8 @@ struct object *object) } if(no_uuid == TRUE) strip_LC_UUID_commands(arch, member, object); + if(no_split_info == TRUE) + strip_LC_SEGMENT_SPLIT_INFO_command(arch, member, object); } #endif /* !defined(NMEDIT) */ @@ -2161,8 +2343,9 @@ struct object *object) } if(saves[relocs[i].r_symbolnum] == 0){ if(missing_reloc_symbols == 0){ - error_arch(arch, member, "symbols referenced by " - "relocation entries that can't be stripped in: "); + error_arch(arch, member, "error: symbols " + "referenced by relocation entries that can't be " + "stripped in: "); missing_reloc_symbols = 1; } if(object->mh != NULL){ @@ -2237,7 +2420,7 @@ struct object *object) check_indirect_symtab(arch, member, object, nitems, s->reserved1, section_type, contents, symbols, symbols64, nsyms, strings, &missing_reloc_symbols, - host_byte_sex); + swift_version, host_byte_sex); s++; } } @@ -2258,12 +2441,12 @@ struct object *object) s64++; continue; } - nitems = s64->size / stride; + nitems = (uint32_t)(s64->size / stride); contents = object->object_addr + s64->offset; check_indirect_symtab(arch, member, object, nitems, s64->reserved1, section_type, contents, symbols, symbols64, nsyms, strings, &missing_reloc_symbols, - host_byte_sex); + swift_version, host_byte_sex); s64++; } } @@ -2279,9 +2462,20 @@ struct object *object) * Issue a warning if object file has a code signature that the * operation will invalidate it. */ - if(object->code_sig_cmd != NULL) + if(object->code_sig_cmd != NULL +#ifndef NMEDIT + && !no_code_signature_warning +#endif /* !(NMEDIT) */ + ) warning_arch(arch, member, "changes being made to the file will " "invalidate the code signature in: "); + + if(nlist_outofsync_with_dyldinfo == TRUE){ + if(object->mh != NULL) + object->mh->flags |= MH_NLIST_OUTOFSYNC_WITH_DYLDINFO; + else + object->mh64->flags |= MH_NLIST_OUTOFSYNC_WITH_DYLDINFO; + } } /* @@ -2300,7 +2494,7 @@ struct object *object) if(object->mh != NULL) offset = object->seg_linkedit->fileoff; else - offset = object->seg_linkedit64->fileoff; + offset = (uint32_t)object->seg_linkedit64->fileoff; } else{ offset = UINT_MAX; @@ -2401,7 +2595,7 @@ enum byte_sex host_byte_sex) #ifndef NMEDIT if(saves[relocs[k].r_symbolnum] == 0){ if(*missing_reloc_symbols == 0){ - error_arch(arch, member, "symbols referenced by " + error_arch(arch, member, "error: symbols referenced by " "relocation entries that can't be stripped in: "); *missing_reloc_symbols = 1; } @@ -2530,6 +2724,7 @@ struct nlist_64 *symbols64, uint32_t nsyms, char *strings, int32_t *missing_reloc_symbols, +uint32_t swift_version, enum byte_sex host_byte_sex) { uint32_t k, index; @@ -2537,6 +2732,15 @@ enum byte_sex host_byte_sex) uint32_t n_strx, value; uint64_t value64; enum bool made_local; + uint32_t mh_flags, mh_filetype; + + if(object->mh != NULL) { + mh_flags = object->mh->flags; + mh_filetype = object->mh->filetype; + } else { + mh_flags = object->mh64->flags; + mh_filetype = object->mh64->filetype; + } for(k = 0; k < nitems; k++){ made_local = FALSE; @@ -2546,7 +2750,8 @@ enum byte_sex host_byte_sex) index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) continue; if(index > nsyms) - fatal_arch(arch, member,"indirect symbol table entry %d (past " "the end of the symbol table) in: ", reserved1 + k); + fatal_arch(arch, member,"indirect symbol table entry %d (past " + "the end of the symbol table) in: ", reserved1 + k); #ifdef NMEDIT if(pflag == 0 && nmedits[index] == TRUE && saves[index] != -1) #else @@ -2603,9 +2808,19 @@ enum byte_sex host_byte_sex) saves[index] - 1; } #else /* !defined(NMEDIT) */ + else if(strip_all_nlists || + (Tflag && swift_version != 0 && + (mh_flags & MH_DYLDLINK) == MH_DYLDLINK && + n_strx != 0 && + (strncmp(strings + n_strx, "_$S", 3) == 0 || + strncmp(strings + n_strx, "_$s", 3) == 0))){ + object->output_indirect_symtab[reserved1 + k] = + INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS; + made_local = TRUE; + } else{ if(*missing_reloc_symbols == 0){ - error_arch(arch, member, "symbols referenced by " + error_arch(arch, member, "error: symbols referenced by " "indirect symbol table entries that can't be " "stripped in: "); *missing_reloc_symbols = 1; @@ -2638,7 +2853,8 @@ void setup_debug_filenames( char *dfile) { - int fd, i, strings_size; + int fd, i; + off_t strings_size; struct stat stat_buf; char *strings, *p; @@ -2684,6 +2900,26 @@ char *dfile) #endif /* DEBUG */ } +/* + * Hack needed to dig out the swift_version from (flags >> 8) & 0xff to see if + * non-zero to apply the -T hack for trying to removing only swift symbols that + * start with "_$S" and not other symbols starting with "_$S". + */ +struct objc_image_info { + uint32_t version; + uint32_t flags; +}; + +static +void +swap_objc_image_info( +struct objc_image_info *o, +enum byte_sex target_byte_sex) +{ + o->version = SWAP_INT(o->version); + o->flags = SWAP_INT(o->flags); +} + /* * Strip the symbol table to the level specified by the command line arguments. * The new symbol table is built and new_symbols is left pointing to it. The @@ -2703,20 +2939,23 @@ struct dylib_module *mods, struct dylib_module_64 *mods64, uint32_t nmodtab, struct dylib_reference *refs, -uint32_t nextrefsyms) +uint32_t nextrefsyms, +uint32_t *p_swift_version, +enum bool *nlist_outofsync_with_dyldinfo) { uint32_t i, j, k, n, inew_syms, save_debug, missing_syms; uint32_t missing_symbols; char *p, *q, **pp, *basename; struct symbol_list *sp; - uint32_t new_ext_strsize, len, *changes, inew_undefsyms; + uint32_t new_ext_strsize, *changes, inew_undefsyms; + long len; unsigned char nsects; struct load_command *lc; struct segment_command *sg; struct segment_command_64 *sg64; struct section *s, **sections; struct section_64 *s64, **sections64; - uint32_t ncmds, mh_flags, s_flags, n_strx; + uint32_t ncmds, mh_flags, mh_filetype, s_flags, n_strx; struct nlist *sym; struct undef_map *undef_map; struct undef_map64 *undef_map64; @@ -2726,7 +2965,14 @@ uint32_t nextrefsyms) uint32_t module_name, iextdefsym, nextdefsym, ilocalsym, nlocalsym; uint32_t irefsym, nrefsym; enum bool has_dwarf, hack_5614542; + uint32_t swift_version; + char *p_objc_image_info; + struct objc_image_info o; + struct strx_map* strx_map; + uint32_t strx_count; + uint32_t strx_uniqcount; + *nlist_outofsync_with_dyldinfo = FALSE; save_debug = 0; if(saves != NULL) free(saves); @@ -2748,7 +2994,10 @@ uint32_t nextrefsyms) new_nextdefsym = 0; new_nundefsym = 0; new_ext_strsize = 0; - + strx_map = NULL; + strx_count = 0; + strx_uniqcount = 0; + /* * If this an object file that has DWARF debugging sections to strip * then we have to run ld -r on it. We also have to do this for @@ -2823,6 +3072,12 @@ uint32_t nextrefsyms) */ saves = (int32_t *)allocate(nsyms * sizeof(int32_t)); bzero(saves, nsyms * sizeof(int32_t)); + + /* + * Allocate space for the strx_map. This table will be used unique + * local symbol strings, reclaiming space from the file. + */ + strx_map = calloc(nsyms, sizeof(*strx_map)); /* * Gather an array of section struct pointers so we can later determine @@ -2875,10 +3130,70 @@ uint32_t nextrefsyms) lc = (struct load_command *)((char *)lc + lc->cmdsize); } + if(object->mh != NULL) { + mh_flags = object->mh->flags; + mh_filetype = object->mh->filetype; + } else { + mh_flags = object->mh64->flags; + mh_filetype = object->mh64->filetype; + } + + /* + * Get the swift version if any if we are using the -T flag and this is + * an linked image for dyld. This is a hack to try to lessen the + * chance of stripping a symbol that starts with "_$S" that is not a + * swift symbol. + */ + swift_version = 0; + if(Tflag && (mh_flags & MH_DYLDLINK) == MH_DYLDLINK){ + p_objc_image_info = NULL; + for(i = 0; i < nsects; i++){ + if(object->mh != NULL){ + if((strcmp(sections[i]->segname, "__DATA") == 0 || + strcmp(sections[i]->segname, "__DATA_CONST") == 0 || + strcmp(sections[i]->segname, "__DATA_DIRTY") == 0) && + strncmp(sections[i]->sectname, "__objc_imageinfo", 16) + == 0 && + sections[i]->size >= sizeof(struct objc_image_info)) { + p_objc_image_info = object->object_addr + + sections[i]->offset; + break; + } + } + else{ + if((strcmp(sections64[i]->segname, "__DATA") == 0 || + strcmp(sections64[i]->segname, "__DATA_CONST") == 0 || + strcmp(sections64[i]->segname, "__DATA_DIRTY") == 0) && + strncmp(sections64[i]->sectname, "__objc_imageinfo", 16) + == 0 && + sections64[i]->size >= sizeof(struct objc_image_info)) { + p_objc_image_info = object->object_addr + + sections64[i]->offset; + break; + } + } + } + if(p_objc_image_info != NULL){ + memcpy(&o, p_objc_image_info, sizeof(struct objc_image_info)); + if(object->object_byte_sex != get_host_byte_sex()) + swap_objc_image_info(&o, get_host_byte_sex()); + swift_version = (o.flags >> 8) & 0xff; + } + } + *p_swift_version = swift_version; + + /* + * Build the list of symbols to save. Also compute the space required + * by the external and unknown symbol strings, + * + * In order to unique local symbol strings in a reasonable amount of + * time-complexity, we will build a list of strx string indexes to + * retain in the final file. This list will be processed and measured + * outside of this nsyms loop. + */ for(i = 0; i < nsyms; i++){ s_flags = 0; if(object->mh != NULL){ - mh_flags = object->mh->flags; n_strx = symbols[i].n_un.n_strx; n_type = symbols[i].n_type; n_sect = symbols[i].n_sect; @@ -2894,7 +3209,6 @@ uint32_t nextrefsyms) n_value = symbols[i].n_value; } else{ - mh_flags = object->mh64->flags; n_strx = symbols64[i].n_un.n_strx; n_type = symbols64[i].n_type; n_sect = symbols64[i].n_sect; @@ -2925,6 +3239,29 @@ uint32_t nextrefsyms) } } } + /* + * If we use the -N flag to set strip all symbols in binaries used + * with the dynamic linker set *nlist_outofsync_with_dyldinfo to + * true. + */ + if(strip_all_nlists) { + *nlist_outofsync_with_dyldinfo = TRUE; + continue; + } + /* + * If the -T flag is specified then if this is a final linked + * binary never save symbols that start with "_$S" if the + * swift version is non-zero. + */ + if(Tflag && swift_version != 0 && + (mh_flags & MH_DYLDLINK) == MH_DYLDLINK && + n_strx != 0 && + (strncmp(strings + n_strx, "_$S", 3) == 0 || + strncmp(strings + n_strx, "_$s", 3) == 0)){ + /* don't save this symbol */ + *nlist_outofsync_with_dyldinfo = TRUE; + continue; + } if((n_type & N_EXT) == 0){ /* local symbol */ /* * For x86_64, i386 .o or ARM files we have run ld -r on them @@ -2933,10 +3270,11 @@ uint32_t nextrefsyms) if((object->mh_cputype == CPU_TYPE_X86_64 || object->mh_cputype == CPU_TYPE_I386 || object->mh_cputype == CPU_TYPE_ARM64 || + object->mh_cputype == CPU_TYPE_ARM64_32 || object->mh_cputype == CPU_TYPE_ARM) && object->mh_filetype == MH_OBJECT){ if(n_strx != 0) - new_strsize += strlen(strings + n_strx) + 1; + strx_map[strx_count++].old_strx = n_strx; new_nlocalsym++; new_nsyms++; saves[i] = new_nsyms; @@ -2977,8 +3315,8 @@ uint32_t nextrefsyms) */ if(save_debug){ if(n_strx != 0) - new_strsize += strlen(strings + - n_strx) + 1; + strx_map[strx_count++].old_strx = + n_strx; new_nlocalsym++; new_nsyms++; saves[i] = new_nsyms; @@ -2992,7 +3330,7 @@ uint32_t nextrefsyms) } if(saves[i] == 0 && (!Sflag || save_debug)){ if(n_strx != 0) - new_strsize += strlen(strings + n_strx) + 1; + strx_map[strx_count++].old_strx = n_strx; new_nlocalsym++; new_nsyms++; saves[i] = new_nsyms; @@ -3013,7 +3351,7 @@ uint32_t nextrefsyms) (n_type & N_TYPE) != N_SECT || (s_flags & S_ATTR_STRIP_STATIC_SYMS) != S_ATTR_STRIP_STATIC_SYMS){ - new_strsize += strlen(strings + n_strx) + 1; + strx_map[strx_count++].old_strx = n_strx; new_nlocalsym++; new_nsyms++; saves[i] = new_nsyms; @@ -3030,7 +3368,8 @@ uint32_t nextrefsyms) private_extern_reference_by_module( i, refs ,nextrefsyms) == TRUE){ if(n_strx != 0) - new_strsize += strlen(strings + n_strx) + 1; + //new_strsize += strlen(strings + n_strx) + 1; + strx_map[strx_count++].old_strx = n_strx; new_nlocalsym++; new_nsyms++; saves[i] = new_nsyms; @@ -3042,10 +3381,8 @@ uint32_t nextrefsyms) if(saves[i] == 0 && symbol_pointer_used(i, indirectsyms, nindirectsyms) == TRUE){ - if(n_strx != 0){ - len = strlen(strings + n_strx) + 1; - new_strsize += len; - } + if(n_strx != 0) + strx_map[strx_count++].old_strx = n_strx; new_nlocalsym++; new_nsyms++; saves[i] = new_nsyms; @@ -3073,7 +3410,7 @@ uint32_t nextrefsyms) sp->seen = TRUE; } if(n_strx != 0) - new_strsize += strlen(strings + n_strx) + 1; + strx_map[strx_count++].old_strx = n_strx; new_nlocalsym++; new_nsyms++; saves[i] = new_nsyms; @@ -3083,7 +3420,7 @@ uint32_t nextrefsyms) private_extern_reference_by_module( i, refs ,nextrefsyms) == TRUE){ if(n_strx != 0) - new_strsize += strlen(strings + n_strx) + 1; + strx_map[strx_count++].old_strx = n_strx; new_nlocalsym++; new_nsyms++; saves[i] = new_nsyms; @@ -3095,10 +3432,8 @@ uint32_t nextrefsyms) if(saves[i] == 0 && symbol_pointer_used(i, indirectsyms, nindirectsyms) == TRUE){ - if(n_strx != 0){ - len = strlen(strings + n_strx) + 1; - new_strsize += len; - } + if(n_strx != 0) + strx_map[strx_count++].old_strx = n_strx; new_nlocalsym++; new_nsyms++; saves[i] = new_nsyms; @@ -3160,7 +3495,6 @@ uint32_t nextrefsyms) ".objc_class_name_", sizeof(".objc_class_name_") - 1) == 0))){ len = strlen(strings + n_strx) + 1; - new_strsize += len; new_ext_strsize += len; new_nextdefsym++; new_nsyms++; @@ -3172,7 +3506,6 @@ uint32_t nextrefsyms) (n_type & N_TYPE) == N_PBUD)){ if(n_strx != 0){ len = strlen(strings + n_strx) + 1; - new_strsize += len; new_ext_strsize += len; } new_nundefsym++; @@ -3183,7 +3516,6 @@ uint32_t nextrefsyms) (n_type & N_TYPE) == N_SECT){ if(n_strx != 0){ len = strlen(strings + n_strx) + 1; - new_strsize += len; new_ext_strsize += len; } new_nextdefsym++; @@ -3210,7 +3542,6 @@ uint32_t nextrefsyms) sp->sym = &(symbols64[i]); sp->seen = TRUE; len = strlen(strings + n_strx) + 1; - new_strsize += len; new_ext_strsize += len; if((n_type & N_TYPE) == N_UNDF || (n_type & N_TYPE) == N_PBUD) @@ -3236,7 +3567,6 @@ uint32_t nextrefsyms) symbol_pointer_used(i, indirectsyms, nindirectsyms) == TRUE){ if(n_strx != 0){ len = strlen(strings + n_strx) + 1; - new_strsize += len; new_ext_strsize += len; } new_nextdefsym++; @@ -3248,7 +3578,6 @@ uint32_t nextrefsyms) (n_desc & N_WEAK_DEF) != 0){ if(n_strx != 0){ len = strlen(strings + n_strx) + 1; - new_strsize += len; new_ext_strsize += len; } new_nextdefsym++; @@ -3259,11 +3588,9 @@ uint32_t nextrefsyms) ((rflag || default_dyld_executable) && n_desc & REFERENCED_DYNAMICALLY))){ len = strlen(strings + n_strx) + 1; - new_strsize += len; new_ext_strsize += len; if((n_type & N_TYPE) == N_INDR){ len = strlen(strings + n_value) + 1; - new_strsize += len; new_ext_strsize += len; } if((n_type & N_TYPE) == N_UNDF || @@ -3286,11 +3613,9 @@ uint32_t nextrefsyms) object->mh->cputype == CPU_TYPE_I386 && object->mh->filetype == MH_OBJECT))){ len = strlen(strings + n_strx) + 1; - new_strsize += len; new_ext_strsize += len; if((n_type & N_TYPE) == N_INDR){ len = strlen(strings + n_value) + 1; - new_strsize += len; new_ext_strsize += len; } if((n_type & N_TYPE) == N_UNDF || @@ -3318,7 +3643,6 @@ uint32_t nextrefsyms) return(FALSE); } len = strlen(strings + module_name) + 1; - new_strsize += len; new_ext_strsize += len; } @@ -3359,7 +3683,6 @@ uint32_t nextrefsyms) else n_strx = symbols64[refs[i].isym].n_un.n_strx; len = strlen(strings + n_strx) + 1; - new_strsize += len; new_ext_strsize += len; new_nundefsym++; new_nsyms++; @@ -3425,6 +3748,41 @@ uint32_t nextrefsyms) } } + /* + * preserve uniqued local symbol strings by sorting and uniqing the + * n_strx values in strx_map. If the linker or some previous tool has + * uniqued the strings, each n_strx represents a uniqued string. + * + * Note that strip currently will not unique local symbol strings + * itself. It simply preserves the uniqueness when deserializing and + * reserializing the strings table. + */ + qsort(strx_map, strx_count, sizeof(*strx_map), + (int (*)(const void *, const void *))cmp_qsort_strx_map); + for (j = 0; j < strx_count; ++j) { + if (strx_map[strx_uniqcount].old_strx != strx_map[j].old_strx) { + strx_uniqcount += 1; + if (strx_uniqcount < j) { + strx_map[strx_uniqcount].old_strx = strx_map[j].old_strx; + } + } + } + if (strx_count > 0) { + strx_uniqcount += 1; + } + + /* + * compute the size of the local symbol strings by measuring each + * remaining string. new_strsize represents the total size of the + * strings table, so it will include the new_ext_strsize value. From + * this point forward, new_ext_strsize represents the beginning of the + * local symbol strings in the strings table. + */ + for (i = 0; i < strx_uniqcount; ++i) { + new_strsize += strlen(strings + strx_map[i].old_strx) + 1; + } + new_strsize += new_ext_strsize; + /* * If there is a chance that we could end up with an indirect symbol * with an index of zero we need to avoid that due to a work around @@ -3446,7 +3804,8 @@ uint32_t nextrefsyms) * table entry and a few bytes in the string table for the complexity it * would add and what it would save. */ - if(new_nlocalsym == 0 && nindirectsyms != 0){ + if(!strip_all_nlists && + (new_nlocalsym == 0 && nindirectsyms != 0)){ len = strlen("radr://5614542") + 1; new_strsize += len; new_nlocalsym++; @@ -3456,7 +3815,7 @@ uint32_t nextrefsyms) else{ hack_5614542 = FALSE; } - + if(object->mh != NULL){ new_symbols = (struct nlist *) allocate(new_nsyms * sizeof(struct nlist)); @@ -3468,9 +3827,9 @@ uint32_t nextrefsyms) allocate(new_nsyms * sizeof(struct nlist_64)); } if(object->mh != NULL) - new_strsize = rnd(new_strsize, sizeof(int32_t)); + new_strsize = rnd32(new_strsize, sizeof(int32_t)); else - new_strsize = rnd(new_strsize, sizeof(int64_t)); + new_strsize = rnd32(new_strsize, sizeof(int64_t)); new_strings = (char *)allocate(new_strsize); if(object->mh != NULL){ new_strings[new_strsize - 3] = '\0'; @@ -3487,6 +3846,11 @@ uint32_t nextrefsyms) new_strings[new_strsize - 1] = '\0'; } + /* + * Zero out the new_strings table, and calculate working pointers: + * p is the location where the next external string will go + * q is the location where the next local string will go + */ memset(new_strings, '\0', sizeof(int32_t)); p = new_strings + sizeof(int32_t); q = p + new_ext_strsize; @@ -3542,15 +3906,23 @@ uint32_t nextrefsyms) } strcpy(q, "radr://5614542"); if(object->mh != NULL) - new_symbols[inew_syms].n_un.n_strx = - q - new_strings; + new_symbols[inew_syms].n_un.n_strx = (uint32_t) + (q - new_strings); else - new_symbols64[inew_syms].n_un.n_strx = - q - new_strings; + new_symbols64[inew_syms].n_un.n_strx = (uint32_t) + (q - new_strings); q += strlen(q) + 1; inew_syms++; } + /* + * write the local symbol names into the strings table, keeping track + * of the new strx so we can preserve string uniqueness. Begin by + * finding the strx_map entry for each symbol's n_strx. If the strx_map + * entry does not yet have a strx value, copy the string into the + * strings table and compute the new strx value; if the strx_map does + * have a new strx value, simply reuse it and move on... + */ for(i = 0; i < nsyms; i++){ if(saves[i]){ if(object->mh != NULL){ @@ -3567,14 +3939,29 @@ uint32_t nextrefsyms) else new_symbols64[inew_syms] = symbols64[i]; if(n_strx != 0){ - strcpy(q, strings + n_strx); - if(object->mh != NULL) - new_symbols[inew_syms].n_un.n_strx = - q - new_strings; - else - new_symbols64[inew_syms].n_un.n_strx = - q - new_strings; - q += strlen(q) + 1; + struct strx_map* map = + bsearch(&n_strx, strx_map, strx_uniqcount, + sizeof(*strx_map), + (int(*)(const void*, const void*)) + cmp_bsearch_strx_map); + if (map != NULL) { + if (map->new_strx == 0) { + strcpy(q, strings + n_strx); + map->new_strx = (uint32_t)(q - new_strings); + q += strlen(q) + 1; + } + if(object->mh != NULL) + new_symbols[inew_syms].n_un.n_strx = + map->new_strx; + else + new_symbols64[inew_syms].n_un.n_strx = + map->new_strx; + } + else { + error_arch(arch, member, "n_strx %d is not in the " + "local symbol table index: ", n_strx); + return(FALSE); + } } inew_syms++; saves[i] = inew_syms; @@ -3607,10 +3994,10 @@ uint32_t nextrefsyms) strcpy(p, strings + n_strx); if(object->mh != NULL) new_symbols[inew_syms].n_un.n_strx = - p - new_strings; + (uint32_t)(p - new_strings); else new_symbols64[inew_syms].n_un.n_strx = - p - new_strings; + (uint32_t)(p - new_strings); p += strlen(p) + 1; } if((n_type & N_TYPE) == N_INDR){ @@ -3618,10 +4005,10 @@ uint32_t nextrefsyms) strcpy(p, strings + n_value); if(object->mh != NULL) new_symbols[inew_syms].n_value = - p - new_strings; + (uint32_t)(p - new_strings); else new_symbols64[inew_syms].n_value = - p - new_strings; + (uint32_t)(p - new_strings); p += strlen(p) + 1; } } @@ -3665,10 +4052,10 @@ uint32_t nextrefsyms) strcpy(p, strings + n_strx); if(object->mh != NULL) undef_map[inew_undefsyms].symbol.n_un.n_strx = - p - new_strings; + (uint32_t)(p - new_strings); else undef_map64[inew_undefsyms].symbol64.n_un.n_strx = - p - new_strings; + (uint32_t)(p - new_strings); p += strlen(p) + 1; } if(object->mh != NULL) @@ -3689,10 +4076,10 @@ uint32_t nextrefsyms) strcpy(p, strings + n_strx); if(object->mh != NULL) undef_map[inew_undefsyms].symbol.n_un.n_strx = - p - new_strings; + (uint32_t)(p - new_strings); else undef_map64[inew_undefsyms].symbol64.n_un.n_strx = - p - new_strings; + (uint32_t)(p - new_strings); p += strlen(p) + 1; } if(object->mh != NULL){ @@ -3743,7 +4130,7 @@ uint32_t nextrefsyms) for(i = 0; i < nmodtab; i++){ if(object->mh != NULL){ strcpy(p, strings + mods[i].module_name); - mods[i].module_name = p - new_strings; + mods[i].module_name = (uint32_t)(p - new_strings); iextdefsym = mods[i].iextdefsym; nextdefsym = mods[i].nextdefsym; ilocalsym = mods[i].ilocalsym; @@ -3753,7 +4140,7 @@ uint32_t nextrefsyms) } else{ strcpy(p, strings + mods64[i].module_name); - mods64[i].module_name = p - new_strings; + mods64[i].module_name = (uint32_t)(p - new_strings); iextdefsym = mods64[i].iextdefsym; nextdefsym = mods64[i].nextdefsym; ilocalsym = mods64[i].ilocalsym; @@ -3935,9 +4322,10 @@ uint32_t nextrefsyms) * Update the export trie if it has one but only call the the * prune_trie() routine when we are removing global symbols as is * done with default stripping of a dyld executable or with the -s - * or -R options. + * or -R options. If we are stripping nlist with the -N flag we must + * leave the export trie as is. */ - if(object->dyld_info != NULL && + if(!strip_all_nlists && object->dyld_info != NULL && object->dyld_info->export_size != 0 && (default_dyld_executable || sfile != NULL || Rfile != NULL)){ const char *error_string; @@ -3965,6 +4353,8 @@ uint32_t nextrefsyms) free(sections); if(sections64 != NULL) free(sections64); + if (strx_map != NULL) + free(strx_map); if(errors == 0) return(TRUE); @@ -4026,9 +4416,12 @@ struct object *object) struct ofile *ld_r_ofile; struct arch *ld_r_archs; uint32_t ld_r_narchs, save_errors; + char* ld; host_byte_sex = get_host_byte_sex(); + ld = getenv("STRIP_LD"); + /* * Swap the object file back into its bytesex before writing it to the * temporary file if needed. @@ -4060,7 +4453,7 @@ struct object *object) if((fd = open(input_file, O_WRONLY|O_CREAT, 0600)) < 0) system_fatal("can't open temporary file: %s", input_file); - if(write(fd, object->object_addr, object->object_size) != + if(write64(fd, object->object_addr, object->object_size) != object->object_size) system_fatal("can't write temporary file: %s", input_file); @@ -4077,7 +4470,10 @@ struct object *object) * Create the ld -r command line and execute it. */ reset_execute_list(); - add_execute_list_with_prefix("ld"); + if (ld) + add_execute_list(ld); + else + add_execute_list_with_prefix("ld"); add_execute_list("-keep_private_externs"); add_execute_list("-r"); if(Sflag) @@ -4214,14 +4610,14 @@ struct object *object) * See if there are any LC_UUID load commands. */ nuuids = 0; - lc1 = arch->object->load_commands; - if(arch->object->mh != NULL){ - ncmds = arch->object->mh->ncmds; - mh_sizeofcmds = arch->object->mh->sizeofcmds; + lc1 = object->load_commands; + if(object->mh != NULL){ + ncmds = object->mh->ncmds; + mh_sizeofcmds = object->mh->sizeofcmds; } else{ - ncmds = arch->object->mh64->ncmds; - mh_sizeofcmds = arch->object->mh64->sizeofcmds; + ncmds = object->mh64->ncmds; + mh_sizeofcmds = object->mh64->sizeofcmds; } for(i = 0; i < ncmds; i++){ if(lc1->cmd == LC_UUID){ @@ -4244,7 +4640,7 @@ struct object *object) * Copy all the load commands except the LC_UUID load commands into the * allocated space for the new load commands. */ - lc1 = arch->object->load_commands; + lc1 = object->load_commands; lc2 = new_load_commands; sizeofcmds = 0; for(i = 0; i < ncmds; i++){ @@ -4260,41 +4656,41 @@ struct object *object) * Finally copy the updated load commands over the existing load * commands. */ - memcpy(arch->object->load_commands, new_load_commands, sizeofcmds); + memcpy(object->load_commands, new_load_commands, sizeofcmds); if(mh_sizeofcmds > sizeofcmds){ - memset((char *)arch->object->load_commands + sizeofcmds, '\0', + memset((char *)object->load_commands + sizeofcmds, '\0', (mh_sizeofcmds - sizeofcmds)); } ncmds -= nuuids; - if(arch->object->mh != NULL) { - arch->object->mh->sizeofcmds = sizeofcmds; - arch->object->mh->ncmds = ncmds; + if(object->mh != NULL) { + object->mh->sizeofcmds = sizeofcmds; + object->mh->ncmds = ncmds; } else { - arch->object->mh64->sizeofcmds = sizeofcmds; - arch->object->mh64->ncmds = ncmds; + object->mh64->sizeofcmds = sizeofcmds; + object->mh64->ncmds = ncmds; } free(new_load_commands); /* reset the pointers into the load commands */ - lc1 = arch->object->load_commands; + lc1 = object->load_commands; for(i = 0; i < ncmds; i++){ switch(lc1->cmd){ case LC_SYMTAB: - arch->object->st = (struct symtab_command *)lc1; + object->st = (struct symtab_command *)lc1; break; case LC_DYSYMTAB: - arch->object->dyst = (struct dysymtab_command *)lc1; + object->dyst = (struct dysymtab_command *)lc1; break; case LC_TWOLEVEL_HINTS: - arch->object->hints_cmd = (struct twolevel_hints_command *)lc1; + object->hints_cmd = (struct twolevel_hints_command *)lc1; break; case LC_PREBIND_CKSUM: - arch->object->cs = (struct prebind_cksum_command *)lc1; + object->cs = (struct prebind_cksum_command *)lc1; break; case LC_SEGMENT: sg = (struct segment_command *)lc1; if(strcmp(sg->segname, SEG_LINKEDIT) == 0) - arch->object->seg_linkedit = sg; + object->seg_linkedit = sg; break; case LC_SEGMENT_SPLIT_INFO: object->split_info_cmd = (struct linkedit_data_command *)lc1; @@ -4326,6 +4722,128 @@ struct object *object) } } +/* + * strip_LC_SEGMENT_SPLIT_INFO_command() is called when -no_split_info is + * specified to the LC_SEGMENT_SPLIT_INFO load command from the object's load + * commands. + */ +static +void +strip_LC_SEGMENT_SPLIT_INFO_command( +struct arch *arch, +struct member *member, +struct object *object) +{ + uint32_t i, ncmds, mh_sizeofcmds, sizeofcmds; + struct load_command *lc1, *lc2, *new_load_commands; + struct segment_command *sg; + + /* + * See if there is a LC_SEGMENT_SPLIT_INFO load command. + * if no LC_SEGMENT_SPLIT_INFO load command just return. + */ + if(object->split_info_cmd == NULL) + return; + + /* + * Allocate space for the new load commands as zero it out so any holes + * will be zero bytes. + */ + if(object->mh != NULL){ + ncmds = object->mh->ncmds; + mh_sizeofcmds = object->mh->sizeofcmds; + } + else{ + ncmds = object->mh64->ncmds; + mh_sizeofcmds = object->mh64->sizeofcmds; + } + new_load_commands = allocate(mh_sizeofcmds); + memset(new_load_commands, '\0', mh_sizeofcmds); + + /* + * Copy all the load commands except the LC_SEGMENT_SPLIT_INFO load + * command into the allocated space for the new load commands. + */ + lc1 = object->load_commands; + lc2 = new_load_commands; + sizeofcmds = 0; + for(i = 0; i < ncmds; i++){ + if(lc1->cmd != LC_SEGMENT_SPLIT_INFO){ + memcpy(lc2, lc1, lc1->cmdsize); + sizeofcmds += lc2->cmdsize; + lc2 = (struct load_command *)((char *)lc2 + lc2->cmdsize); + } + lc1 = (struct load_command *)((char *)lc1 + lc1->cmdsize); + } + + /* + * Finally copy the updated load commands over the existing load + * commands. + */ + memcpy(object->load_commands, new_load_commands, sizeofcmds); + if(mh_sizeofcmds > sizeofcmds){ + memset((char *)object->load_commands + sizeofcmds, '\0', + (mh_sizeofcmds - sizeofcmds)); + } + ncmds -= 1; + if(object->mh != NULL) { + object->mh->sizeofcmds = sizeofcmds; + object->mh->ncmds = ncmds; + } else { + object->mh64->sizeofcmds = sizeofcmds; + object->mh64->ncmds = ncmds; + } + free(new_load_commands); + + /* reset the pointers into the load commands */ + object->split_info_cmd = NULL; + lc1 = object->load_commands; + for(i = 0; i < ncmds; i++){ + switch(lc1->cmd){ + case LC_SYMTAB: + object->st = (struct symtab_command *)lc1; + break; + case LC_DYSYMTAB: + object->dyst = (struct dysymtab_command *)lc1; + break; + case LC_TWOLEVEL_HINTS: + object->hints_cmd = (struct twolevel_hints_command *)lc1; + break; + case LC_PREBIND_CKSUM: + object->cs = (struct prebind_cksum_command *)lc1; + break; + case LC_SEGMENT: + sg = (struct segment_command *)lc1; + if(strcmp(sg->segname, SEG_LINKEDIT) == 0) + object->seg_linkedit = sg; + break; + case LC_FUNCTION_STARTS: + object->func_starts_info_cmd = + (struct linkedit_data_command *)lc1; + break; + case LC_DATA_IN_CODE: + object->data_in_code_cmd = + (struct linkedit_data_command *)lc1; + break; + case LC_DYLIB_CODE_SIGN_DRS: + object->code_sign_drs_cmd = + (struct linkedit_data_command *)lc1; + break; + case LC_LINKER_OPTIMIZATION_HINT: + object->link_opt_hint_cmd = + (struct linkedit_data_command *)lc1; + break; + case LC_CODE_SIGNATURE: + object->code_sig_cmd = (struct linkedit_data_command *)lc1; + break; + case LC_DYLD_INFO_ONLY: + case LC_DYLD_INFO: + object->dyld_info = (struct dyld_info_command *)lc1; + } + lc1 = (struct load_command *)((char *)lc1 + lc1->cmdsize); + } +} + #ifndef NMEDIT /* * strip_LC_CODE_SIGNATURE_commands() is called when -c is specified to remove @@ -4353,13 +4871,13 @@ struct object *object) * Allocate space for the new load commands and zero it out so any holes * will be zero bytes. */ - if(arch->object->mh != NULL){ - ncmds = arch->object->mh->ncmds; - mh_sizeofcmds = arch->object->mh->sizeofcmds; + if(object->mh != NULL){ + ncmds = object->mh->ncmds; + mh_sizeofcmds = object->mh->sizeofcmds; } else{ - ncmds = arch->object->mh64->ncmds; - mh_sizeofcmds = arch->object->mh64->sizeofcmds; + ncmds = object->mh64->ncmds; + mh_sizeofcmds = object->mh64->sizeofcmds; } new_load_commands = allocate(mh_sizeofcmds); memset(new_load_commands, '\0', mh_sizeofcmds); @@ -4368,7 +4886,7 @@ struct object *object) * Copy all the load commands except the LC_CODE_SIGNATURE load commands * into the allocated space for the new load commands. */ - lc1 = arch->object->load_commands; + lc1 = object->load_commands; lc2 = new_load_commands; sizeofcmds = 0; for(i = 0; i < ncmds; i++){ @@ -4384,42 +4902,42 @@ struct object *object) * Finally copy the updated load commands over the existing load * commands. */ - memcpy(arch->object->load_commands, new_load_commands, sizeofcmds); + memcpy(object->load_commands, new_load_commands, sizeofcmds); if(mh_sizeofcmds > sizeofcmds){ - memset((char *)arch->object->load_commands + sizeofcmds, '\0', + memset((char *)object->load_commands + sizeofcmds, '\0', (mh_sizeofcmds - sizeofcmds)); } ncmds -= 1; - if(arch->object->mh != NULL) { - arch->object->mh->sizeofcmds = sizeofcmds; - arch->object->mh->ncmds = ncmds; + if(object->mh != NULL) { + object->mh->sizeofcmds = sizeofcmds; + object->mh->ncmds = ncmds; } else { - arch->object->mh64->sizeofcmds = sizeofcmds; - arch->object->mh64->ncmds = ncmds; + object->mh64->sizeofcmds = sizeofcmds; + object->mh64->ncmds = ncmds; } free(new_load_commands); /* reset the pointers into the load commands */ object->code_sig_cmd = NULL; - lc1 = arch->object->load_commands; + lc1 = object->load_commands; for(i = 0; i < ncmds; i++){ switch(lc1->cmd){ case LC_SYMTAB: - arch->object->st = (struct symtab_command *)lc1; + object->st = (struct symtab_command *)lc1; break; case LC_DYSYMTAB: - arch->object->dyst = (struct dysymtab_command *)lc1; + object->dyst = (struct dysymtab_command *)lc1; break; case LC_TWOLEVEL_HINTS: - arch->object->hints_cmd = (struct twolevel_hints_command *)lc1; + object->hints_cmd = (struct twolevel_hints_command *)lc1; break; case LC_PREBIND_CKSUM: - arch->object->cs = (struct prebind_cksum_command *)lc1; + object->cs = (struct prebind_cksum_command *)lc1; break; case LC_SEGMENT: sg = (struct segment_command *)lc1; if(strcmp(sg->segname, SEG_LINKEDIT) == 0) - arch->object->seg_linkedit = sg; + object->seg_linkedit = sg; break; case LC_SEGMENT_SPLIT_INFO: object->split_info_cmd = (struct linkedit_data_command *)lc1; @@ -4519,6 +5037,26 @@ uint32_t nindirectsyms) return(FALSE); } +/* + * Functions for comparing strx_map entries. + */ +static +int +cmp_qsort_strx_map( +const struct strx_map* a, +const struct strx_map* b) +{ + return a->old_strx - b->old_strx; +} + +static +int +cmp_bsearch_strx_map(const uint32_t* old_strx, + const struct strx_map *strx_map) +{ + return *old_strx - strx_map->old_strx; +} + /* * Function for qsort for comparing undefined map entries. */ @@ -4796,9 +5334,9 @@ uint32_t nextrefsyms) if(n_strx > strsize){ error_arch(arch, member, "bad string index for symbol " "table entry %u in: ", i); - return(FALSE); + return((uint32_t)FALSE); } - len = strlen(strings + n_strx) + 1; + len = (uint32_t)strlen(strings + n_strx) + 1; } if(n_type & N_EXT){ if((n_type & N_TYPE) != N_UNDF && @@ -4807,7 +5345,7 @@ uint32_t nextrefsyms) if(n_sect > nsects){ error_arch(arch, member, "bad n_sect for symbol " "table entry %u in: ", i); - return(FALSE); + return((uint32_t)FALSE); } if(((s_flags & SECTION_TYPE) == S_COALESCED) && pflag == FALSE && @@ -5009,7 +5547,7 @@ change_symbol: "of module table entry %d in: ", i); return(FALSE); } - len = strlen(strings + module_name) + 1; + len = (uint32_t)strlen(strings + module_name) + 1; new_strsize += len; new_ext_strsize += len; } @@ -5224,7 +5762,7 @@ change_symbol: new_symbols64 = (struct nlist_64 *) allocate(new_nsyms * sizeof(struct nlist_64)); } - new_strsize = rnd(new_strsize, sizeof(int32_t)); + new_strsize = rnd32(new_strsize, sizeof(int32_t)); new_strings = (char *)allocate(new_strsize); new_strings[new_strsize - 3] = '\0'; new_strings[new_strsize - 2] = '\0'; @@ -5294,10 +5832,10 @@ change_symbol: strcpy(q, strings + n_strx); if(object->mh != NULL) new_symbols[inew_syms].n_un.n_strx = - q - new_strings; + (uint32_t)(q - new_strings); else new_symbols64[inew_syms].n_un.n_strx = - q - new_strings; + (uint32_t)(q - new_strings); q += strlen(q) + 1; } inew_syms++; @@ -5350,10 +5888,10 @@ change_symbol: strcpy(q, strings + n_strx); if(object->mh != NULL) new_symbols[inew_syms].n_un.n_strx = - q - new_strings; + (uint32_t)(q - new_strings); else new_symbols64[inew_syms].n_un.n_strx = - q - new_strings; + (uint32_t)(q - new_strings); q += strlen(q) + 1; } inew_syms++; @@ -5402,10 +5940,10 @@ change_symbol: strcpy(p, strings + n_strx); if(object->mh != NULL) new_symbols[inew_syms].n_un.n_strx = - p - new_strings; + (uint32_t)(p - new_strings); else new_symbols64[inew_syms].n_un.n_strx = - p - new_strings; + (uint32_t)(p - new_strings); p += strlen(p) + 1; } inew_syms++; @@ -5441,10 +5979,10 @@ change_symbol: strcpy(p, strings + n_strx); if(object->mh != NULL) new_symbols[inew_syms].n_un.n_strx = - p - new_strings; + (uint32_t)(p - new_strings); else new_symbols64[inew_syms].n_un.n_strx = - p - new_strings; + (uint32_t)(p - new_strings); p += strlen(p) + 1; } inew_syms++; @@ -5460,7 +5998,7 @@ change_symbol: for(i = 0; i < nmodtab; i++){ if(object->mh != NULL){ strcpy(p, strings + mods[i].module_name); - new_mods[i].module_name = p - new_strings; + new_mods[i].module_name = (uint32_t)(p - new_strings); p += strlen(p) + 1; new_mods[i].irefsym = mods[i].irefsym; @@ -5476,7 +6014,7 @@ change_symbol: } else{ strcpy(p, strings + mods64[i].module_name); - new_mods64[i].module_name = p - new_strings; + new_mods64[i].module_name = (uint32_t)(p - new_strings); p += strlen(p) + 1; new_mods64[i].irefsym = mods64[i].irefsym; @@ -5571,10 +6109,10 @@ change_symbol: strcpy(q, strings + n_strx); if(object->mh != NULL) new_symbols[inew_syms].n_un.n_strx = - q - new_strings; + (uint32_t)(q - new_strings); else new_symbols64[inew_syms].n_un.n_strx = - q - new_strings; + (uint32_t)(q - new_strings); q += strlen(q) + 1; } inew_syms++; @@ -5615,10 +6153,10 @@ change_symbol: strcpy(q, strings + n_strx); if(object->mh != NULL) new_symbols[inew_syms].n_un.n_strx = - q - new_strings; + (uint32_t)(q - new_strings); else new_symbols64[inew_syms].n_un.n_strx = - q - new_strings; + (uint32_t)(q - new_strings); q += strlen(q) + 1; } inew_syms++; @@ -5660,10 +6198,10 @@ change_symbol: strcpy(p, strings + n_strx); if(object->mh != NULL) new_symbols[inew_syms].n_un.n_strx = - p - new_strings; + (uint32_t)(p - new_strings); else new_symbols64[inew_syms].n_un.n_strx = - p - new_strings; + (uint32_t)(p - new_strings); p += strlen(p) + 1; } inew_syms++; diff --git a/cctools/misc/vtool.c b/cctools/misc/vtool.c new file mode 100644 index 0000000..3db8787 --- /dev/null +++ b/cctools/misc/vtool.c @@ -0,0 +1,2840 @@ +// +// vtool.c +// cctools +// +// Created by Michael Trent on 12/29/18. +// Copyright © 2018 apple. All rights reserved. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stuff/port.h" /* cctools-port: reallocf() */ + +#ifndef PLATFORM_DRIVERKIT +#define PLATFORM_DRIVERKIT 10 +#endif /* PLATFORM_DRIVERKIT */ + +enum command { + kCommandUnset = 0, + kCommandShow, + kCommandSet, + kCommandRemove, + kCommandHelp, +}; + +enum show_command { + kShowAll = 0, + kShowBuild, + kShowSource, + kShowSpace, +}; + +enum set_command { + kSetBuild, + kSetSource, + kAddTool, +}; + +enum remove_command { + kRemoveBuild, + kRemoveSource, + kRemoveTool, +}; + +struct set_item { + enum set_command type; + uint32_t platform; + uint32_t tool; + uint32_t version; + uint32_t sdk_vers; + uint64_t src_vers; + bool versmin; +}; + +struct remove_item { + enum remove_command type; + uint32_t platform; + uint32_t tool; +}; + +struct lcmds { + struct load_command** items; + uint32_t count; +}; + +struct file { + unsigned char* buf; + off_t len; + mode_t mode; + uint32_t nfat_arch; + struct fat_arch* fat_archs; + uint32_t fat_arch_idx; + struct mach_header_64 mh; + size_t mh_size; + unsigned char* lcs; // a pointer into the raw load commands + struct lcmds* lcmds; // a c-array of pointers to swapped load commands + bool swap; +}; + +static struct options { + enum command command; + const char* inPath; + const char* outPath; + const NXArchInfo **archs; + uint32_t narch; + enum show_command show; + bool replace; + struct set_item* setItems; + uint32_t numSetItems; + struct remove_item* removeItems; + uint32_t numRemoveItems; +} gOptions; + +static const char* gProgramName; +static enum NXByteOrder gByteOrder; + +static int process(void); +static int command_remove(struct file* fb); +static int command_set(struct file* fb); +static int command_show(struct file* fb); + +static int file_read(const char* path, struct file* fb); +static int file_select_macho(const char* path, struct file* fb, uint32_t index); +static int file_write(const char* path, struct file* fb); + +static struct lcmds* lcmds_alloc(struct file* fb); +static void lcmds_free(struct lcmds* lcmds); + +static int parse_version_abcde(const char* rostr, uint64_t *version); +static int parse_version_xyz(const char* rostr, uint32_t *version); + +static uint32_t platform_id_for_name(const char* name); +static uint32_t platform_id_for_vmlc(uint32_t vmlc); +static const char* platform_name_for_id(uint32_t platform_id); +static uint32_t platform_vmlc_for_id(uint32_t platform_id); + +static void print_version_xyz(const char* label, uint32_t version); +static void print_version_min_command(struct version_min_command *vd); +static void print_build_version_command(struct build_version_command *bv); +static void print_build_tool_version(uint32_t tool, uint32_t version); +static void print_source_version_command(struct source_version_command *sv); + +static uint32_t tool_id_for_name(const char* name); +static const char* tool_name_for_id(uint32_t tool_id); + +static void usage(const char * __restrict format, ...); + +int main(int argc, const char * argv[]) +{ + bool read_options = true; + + gByteOrder = NXHostByteOrder(); + gProgramName = *argv++; + argc--; + + if (argc == 0) + usage(NULL); + + while (argc > 0) + { + if (read_options && *argv && '-' == **argv) + { + if (0 == strcmp("-arch", *argv)) + { + argv++; argc--; + + if (!*argv) { + usage("missing arch"); + } + + const NXArchInfo *archInfo = NXGetArchInfoFromName(*argv); + if (!archInfo) { + usage("unknown arch: %s", *argv); + } + + gOptions.archs = reallocf(gOptions.archs, + sizeof(*gOptions.archs) * + (gOptions.narch + 1)); + gOptions.archs[gOptions.narch++] = archInfo; + } + else if (0 == strcmp("-h", *argv) || + 0 == strcmp("-help", *argv)) + { + gOptions.command = kCommandHelp; + usage(NULL); + } + else if (0 == strcmp("-o", *argv) || + 0 == strcmp("-output", *argv)) + { + argv++; argc--; + if (gOptions.outPath) { + usage("only one output file must be specified"); + } + if (!*argv) { + usage("one output file must be specified"); + } + gOptions.outPath = *argv; + } + else if (0 == strcmp("-r", *argv) || + 0 == strcmp("-replace", *argv)) + { + gOptions.replace = true; + } + else if (0 == strcmp("-remove-build-tool", *argv) || + 0 == strcmp("-remove-tool", *argv)) + { + const char* option = *argv; + argv++; argc--; + + if (kCommandUnset != gOptions.command && + kCommandRemove != gOptions.command) + { + usage("option %s cannot be used with -show or -set " + "commands", option); + } + + // make a remove-tool item + gOptions.command = kCommandRemove; + gOptions.removeItems = reallocf(gOptions.removeItems, + sizeof(*gOptions.removeItems) * + (gOptions.numRemoveItems + 1)); + struct remove_item* item = + &gOptions.removeItems[gOptions.numRemoveItems++]; + memset(item, 0, sizeof(*item)); + item->type = kRemoveTool; + + // get the platform id by name, or by literal number. + if (!*argv) { + usage("missing %s platform", option); + } + + item->platform = platform_id_for_name(*argv); + if (0 == item->platform) { + item->platform = (uint32_t)strtol(*argv, NULL, 0); + } + if (0 == item->platform) { + usage("unknown platform: %s", *argv); + } + argv++; argc--; + + // get the tool + if (!*argv) { + usage("missing %s tool", option); + } + + item->tool = tool_id_for_name(*argv); + if (0 == item->tool) { + item->tool = (uint32_t)strtol(*argv, NULL, 0); + } + if (0 == item->tool) { + usage("unknown tool: %s", *argv); + } + } + else if (0 == strcmp("-remove-build-version", *argv)) + { + const char* option = *argv; + argv++; argc--; + + if (kCommandUnset != gOptions.command && + kCommandRemove != gOptions.command) + { + usage("option %s cannot be used with -show or -set " + "commands", option); + } + + gOptions.command = kCommandRemove; + gOptions.removeItems = reallocf(gOptions.removeItems, + sizeof(*gOptions.removeItems) * + (gOptions.numRemoveItems + 1)); + struct remove_item* item = + &gOptions.removeItems[gOptions.numRemoveItems++]; + memset(item, 0, sizeof(*item)); + item->type = kRemoveBuild; + + // get the platform id by name, or by literal number. + if (!*argv) { + usage("missing %s platform", option); + } + + item->platform = platform_id_for_name(*argv); + if (0 == item->platform) { + item->platform = (uint32_t)strtol(*argv, NULL, 0); + } + if (0 == item->platform) { + usage("unknown platform: %s", *argv); + } + } + else if (0 == strcmp("-remove-source-version", *argv)) + { + const char* option = *argv; + + if (kCommandUnset != gOptions.command && + kCommandRemove != gOptions.command) + { + usage("option %s cannot be used with -show or -set " + "commands", option); + } + + gOptions.command = kCommandRemove; + gOptions.removeItems = reallocf(gOptions.removeItems, + sizeof(*gOptions.removeItems) * + (gOptions.numRemoveItems + 1)); + struct remove_item* item = + &gOptions.removeItems[gOptions.numRemoveItems++]; + memset(item, 0, sizeof(*item)); + item->type = kRemoveSource; + } + else if (0 == strcmp("-set-tool", *argv) || + 0 == strcmp("-set-build-tool", *argv)) + { + const char* option = *argv; + argv++; argc--; + + if (kCommandUnset != gOptions.command && + kCommandSet != gOptions.command) + { + usage("option %s cannot be used with -show or -remove " + "commands", option); + } + + // make an add-tool item + gOptions.command = kCommandSet; + gOptions.setItems = reallocf(gOptions.setItems, + sizeof(*gOptions.setItems) * + (gOptions.numSetItems + 1)); + struct set_item* item = + &gOptions.setItems[gOptions.numSetItems++]; + memset(item, 0, sizeof(*item)); + item->type = kAddTool; + + // get the platform id by name, or by literal number. + if (!*argv) { + usage("missing %s platform", option); + } + + item->platform = platform_id_for_name(*argv); + if (0 == item->platform) { + item->platform = (uint32_t)strtol(*argv, NULL, 0); + } + if (0 == item->platform) { + usage("unknown platform: %s", *argv); + } + argv++; argc--; + + // get the tool + if (!*argv) { + usage("missing %s tool", option); + } + + item->tool = tool_id_for_name(*argv); + if (0 == item->tool) { + item->tool = (uint32_t)strtol(*argv, NULL, 0); + } + if (0 == item->tool) { + usage("unknown tool: %s", *argv); + } + argv++; argc--; + + // get the version + if (!*argv) { + usage("missing %s version", option); + } + + if (parse_version_xyz(*argv, &item->version)) { + usage("bad version: %s", gProgramName, *argv); + } + } + + else if (0 == strcmp("-set-build", *argv) || + 0 == strcmp("-set-build-version", *argv) || + 0 == strcmp("-set-version-min", *argv)) + { + const char* option = *argv; + argv++; argc--; + + if (kCommandUnset != gOptions.command && + kCommandSet != gOptions.command) + { + usage("option %s cannot be used with -show or -remove " + "commands", option); + } + + gOptions.command = kCommandSet; + gOptions.setItems = reallocf(gOptions.setItems, + sizeof(*gOptions.setItems) * + (gOptions.numSetItems + 1)); + struct set_item* item = + &gOptions.setItems[gOptions.numSetItems++]; + memset(item, 0, sizeof(*item)); + item->type = kSetBuild; + item->versmin = (0 == strcmp("-set-version-min", option)); + + // get the platform id by name, or by literal number. + if (!*argv) { + usage("missing %s platform", option); + } + + item->platform = platform_id_for_name(*argv); + if (0 == item->platform) { + item->platform = (uint32_t)strtol(*argv, NULL, 0); + } + if (0 == item->platform) { + usage("unknown platform: %s", *argv); + } + + if (item->versmin && 0 == platform_vmlc_for_id(item->platform)){ + usage("version min unsupported for platform: %s", *argv); + } + argv++; argc--; + + // get the minos version + if (!*argv) { + usage("missing %s min_version", option); + } + + if (parse_version_xyz(*argv, &item->version)) { + usage("bad min_version: %s", gProgramName, *argv); + } + argv++; argc--; + + // get the sdk version + if (!*argv) { + usage("missing %s sdk_version", option); + } + + if (parse_version_xyz(*argv, &item->sdk_vers)) { + usage("bad sdk_version: %s", gProgramName, *argv); + } + + while (*(argv + 1) && 0 == strcmp("-tool", *(argv + 1))) + { + uint32_t platform = item->platform; + + argv++; argc--; + argv++; argc--; + + if (item->versmin) { + usage("-tool cannot be used with %s", option); + } + + // make an add-tool item + gOptions.setItems = reallocf(gOptions.setItems, + sizeof(*gOptions.setItems) * + (gOptions.numSetItems + 1)); + item = &gOptions.setItems[gOptions.numSetItems++]; + memset(item, 0, sizeof(*item)); + item->type = kAddTool; + item->platform = platform; + + // get the tool + if (!*argv) { + usage("missing %s -tool tool", option); + } + + item->tool = tool_id_for_name(*argv); + if (0 == item->tool) { + item->tool = (uint32_t)strtol(*argv, NULL, 0); + } + if (0 == item->tool) { + usage("unknown tool: %s", *argv); + } + argv++; argc--; + + // get the version + if (!*argv) { + usage("missing %s -tool version", option); + } + + if (parse_version_xyz(*argv, &item->version)) { + usage("bad version: %s", gProgramName, *argv); + } + } // 0 == strcmp("tool", *(argv + 1)) + } // if -set-build-version || -set-version-min + else if (0 == strcmp("-set-source", *argv) || + 0 == strcmp("-set-source-version", *argv)) + { + const char* option = *argv; + argv++; argc--; + + if (kCommandUnset != gOptions.command && + kCommandSet != gOptions.command) + { + usage("option %s cannot be used with -show or -remove " + "commands", *argv); + } + + gOptions.command = kCommandSet; + gOptions.setItems = reallocf(gOptions.setItems, + sizeof(*gOptions.setItems) * + (gOptions.numSetItems + 1)); + struct set_item* item = + &gOptions.setItems[gOptions.numSetItems++]; + memset(item, 0, sizeof(*item)); + item->type = kSetSource; + + // get the source version + if (!*argv) { + usage("missing %s version", option); + } + + if (parse_version_abcde(*argv, &item->src_vers)) { + usage("bad version: %s", gProgramName, *argv); + } + } // -set-source-version + else if (0 == strcmp("-show", *argv) || + 0 == strcmp("-show-all", *argv)) + { + if (gOptions.command) + usage("option %s cannot be used with other commands", + *argv); + gOptions.command = kCommandShow; + gOptions.show = kShowAll; + } + else if (0 == strcmp("-show-build", *argv) || + 0 == strcmp("-show-build-version", *argv)) + { + if (gOptions.command) + usage("option %s cannot be used with other commands", + *argv); + gOptions.command = kCommandShow; + gOptions.show = kShowBuild; + } + else if (0 == strcmp("-show-source", *argv) || + 0 == strcmp("-show-source-version", *argv)) + { + if (gOptions.command) + usage("option %s cannot be used with other commands", + *argv); + gOptions.command = kCommandShow; + gOptions.show = kShowSource; + } + else if (0 == strcmp("-show-space", *argv)) + { + if (gOptions.command) + usage("option %s cannot be used with other commands", + *argv); + gOptions.command = kCommandShow; + gOptions.show = kShowSpace; + } + else if (0 == strcmp("-", *argv)) + { + read_options = false; + } + else + { + usage("unknown option: %s", *argv); + } + } // if ('-' == **argv) + else + { + if (gOptions.inPath) + usage("only one input file must be specified"); + gOptions.inPath = *argv; + } + + argv++; argc--; + } // while (argc > 0) + + if (!gOptions.inPath) + usage("one input file must be specified"); + + if (gOptions.command == kCommandUnset) + usage("a -show, -set, or -remove command must be specified"); + + if ((gOptions.command==kCommandSet || gOptions.command==kCommandRemove) && + !gOptions.outPath) + usage("one output file must be specified"); + + if (gOptions.command==kCommandShow && gOptions.outPath) + usage("-show commands do not write output"); + + // make sure set options are not specified more than once per platform + for (uint32_t iitem = 0; iitem < gOptions.numSetItems; ++iitem) + { + if (kSetBuild != gOptions.setItems[iitem].type) + continue; + for (uint32_t jitem = 0; jitem < iitem; ++jitem) + { + if (kSetBuild != gOptions.setItems[jitem].type) + continue; + if (gOptions.setItems[iitem].platform == + gOptions.setItems[jitem].platform) + { + uint32_t plid = gOptions.setItems[iitem].platform; + const char* plname = platform_name_for_id(plid); + if (plname) + usage("more than one build version specified for " + "platform %s", plname); + else + usage("more than one build version specified for " + "platform #%u", plid); + } + } + } + + bool foundsrc = false; + for (uint32_t iitem = 0; iitem < gOptions.numSetItems; ++iitem) + { + if (kSetSource != gOptions.setItems[iitem].type) + continue; + if (foundsrc) { + usage("more than one source version specified"); + } + foundsrc = true; + } + + for (uint32_t iitem = 0; iitem < gOptions.numSetItems; ++iitem) + { + if (kAddTool != gOptions.setItems[iitem].type) + continue; + for (uint32_t jitem = 0; jitem < iitem; ++jitem) + { + if (kAddTool != gOptions.setItems[jitem].type) + continue; + if (gOptions.setItems[iitem].platform == + gOptions.setItems[jitem].platform && + gOptions.setItems[iitem].tool == + gOptions.setItems[jitem].tool) + { + uint32_t plid = gOptions.setItems[iitem].platform; + const char* plname = platform_name_for_id(plid); + uint32_t tlid = gOptions.setItems[iitem].tool; + const char* tlname = tool_name_for_id(tlid); + if (plname && tlname) + usage("more than one tool version specified for " + "platform %s, tool %s", plname, tlname); + else if (plname) + usage("more than one tool version specified for " + "platform %s, tool #%u", plname, tlid); + if (tlname) + usage("more than one tool version specified for " + "platform #%u, tool %s", plid, tlname); + else + usage("more than one tool version specified for " + "platform #%u, tool #%u", plid, tlid); + } + } + } + + // do work! + int res = process(); + + return res ? EXIT_FAILURE : EXIT_SUCCESS; +} + +/* + * process opens the input file for reading, calls the requested command + * handler, and if necessary, writes the resulting data back to disk. process + * manages all of the details of processing fat files, filtering on + * architectures, and so on. + */ +int process(void) +{ + struct file file; + int res = 0; + + // read the input file + if (0 == res) + res = file_read(gOptions.inPath, &file); + + // verify the specified archs exist in the file + if (0 == res && gOptions.narch) + { + for (uint32_t iopt = 0; iopt < gOptions.narch; ++iopt) + { + const NXArchInfo* a = gOptions.archs[iopt]; + bool found = false; + + for (uint32_t iarch = 0; false == found && iarch < file.nfat_arch; + ++iarch) + { + struct fat_arch* b = &file.fat_archs[iarch]; + if (a->cputype == b->cputype && + (a->cpusubtype & ~CPU_SUBTYPE_MASK) == + (b->cpusubtype & ~CPU_SUBTYPE_MASK)) + found = true; + } + if (false == found) { + fprintf(stderr, "%s error: %s file does not contain " + "architecture: %s\n", gProgramName, gOptions.inPath, + a->name); + res = -1; + } + } + } + + // process architectures in the order they appear in the file + for (uint32_t iarch = 0; 0 == res && iarch < file.nfat_arch; ++iarch) + { + // prepare the mach-o for reading + res = file_select_macho(gOptions.inPath, &file, iarch); + + // filter on architecture if necessary + if (0 == res && gOptions.narch) + { + bool found = false; + for (uint32_t j = 0; false == found && j < gOptions.narch; ++j) + { + if (gOptions.archs[j]->cputype == file.mh.cputype && + (gOptions.archs[j]->cpusubtype & ~CPU_SUBTYPE_MASK) == + (file.mh.cpusubtype & ~CPU_SUBTYPE_MASK)) + { + found = true; + } + } + if (!found) + continue; + } + + // dispatch the requested commands once per Mach-O + if (0 == res) { + if (kCommandShow == gOptions.command) { + res = command_show(&file); + } else if (kCommandSet == gOptions.command) { + res = command_set(&file); + } else if (kCommandRemove == gOptions.command) { + res = command_remove(&file); + } + } + } // for (uint32_t iarch = 0; 0 == res && iarch < file.nfat_arch; ++iarch) + + // write out the final file + if (0 == res && + (gOptions.command == kCommandSet || gOptions.command == kCommandRemove)) + { + res = file_write(gOptions.outPath, &file); + } + + return res; +} + +/* + * command_remove removes the requested version commands in a Mach-O file or + * Mach-O files in a fat file. + */ +int command_remove(struct file* fb) +{ + // see command_set for detailed notes on how the Mach-O data is updated. + // command_remove is a simplified set of those same instructions, although + // the basic framework remains the same: + // + // 1. build a new array of "set instructions" for modifying build versions + // using a "remove build tool" instruction. That is, removing a + // build tool is the same as modifying a build version. + // + // 2. measure the space between the mach_header and the first segment + // section as well as the space required by the new load commands. + // + // 3. verify the new load commands will fit in the existing structure. + // + // 4. copy the unmodified load commands into a new buffer, and write new + // load commands (see step 1) at the end of that same buffer. + // + // 5. write the load commands and an adjusted mach_header back into + // the file buffer. + // + // Like with command_set, command_remove stops short of writing the new + // data to disk; that will be the calling code's job. + + // cache the swapped load command table in a convenient form + struct lcmds* lcmds = fb->lcmds; + + // build a new setItems array for build version commands whose tools are + // being changed. If a tool is being removed from a build version that + // is not present in the file, return an error. + struct set_item* items = NULL; + uint32_t nitem = 0; + for (uint32_t iitem = 0; iitem < gOptions.numRemoveItems; ++iitem) + { + if (kRemoveTool != gOptions.removeItems[iitem].type) + continue; + + uint32_t platform = gOptions.removeItems[iitem].platform; + struct build_version_command* bv = NULL; + bool found = false; + + // look for this tool's corresponding build version in the program + // arguments. if found, the entire build version is going away and + // there's no need to do more. + if (!found) + { + for (uint32_t jitem = 0; !found && + jitem < gOptions.numRemoveItems; ++jitem) + { + if (kRemoveBuild == gOptions.removeItems[jitem].type && + platform == gOptions.removeItems[jitem].platform) { + found = true; + } + } + } + + // look for this tool's corresponding build version in the input + // file's load commands. + if (!found) + { + for (uint32_t icmd = 0; !found && icmd < lcmds->count; ++icmd) + { + struct load_command* lc = lcmds->items[icmd]; + if (lc->cmd == LC_BUILD_VERSION) + { + bv = (struct build_version_command*)lc; + found = (platform == bv->platform); + } + else if (lc->cmd == LC_VERSION_MIN_MACOSX || + lc->cmd == LC_VERSION_MIN_IPHONEOS || + lc->cmd == LC_VERSION_MIN_WATCHOS || + lc->cmd == LC_VERSION_MIN_TVOS) + { + if (platform_id_for_vmlc(lc->cmd) == platform) { + fprintf(stderr, "%s error: %s version min load " + "commands do not support tool versions\n", + gProgramName, gOptions.inPath); + return -1; + } + } + } + } + + // we looked and we looked but we didn't find a build version for + // this tool. return an error. + if (!found) + { + const char* plname = platform_name_for_id(platform); + if (plname) + fprintf(stderr, "%s error: no build verion load command " + "found for platform %s\n", gProgramName, plname); + else + fprintf(stderr, "%s error: no build verion load command " + "found for platform #%u\n", gProgramName, platform); + return -1; + } + + // if this tool is modifying a build version already in the input + // file, and it's not being completely removed, add it to the list. + // Also add this build version's tools to the list if they aren't + // themselves being replaced. + if (bv) + { + items = reallocf(items, sizeof(*items) * (nitem+1)); + struct set_item* item = &items[nitem++]; + memset(item, 0, sizeof(*item)); + item->type = kSetBuild; + item->platform = platform; + item->version = bv->minos; + item->sdk_vers = bv->sdk; + + for (uint32_t itool = 0; itool < bv->ntools; ++itool) + { + struct build_tool_version* bt = + (struct build_tool_version*) + (((unsigned char*)(bv+1)) + + (itool * sizeof(struct build_tool_version))); + found = false; + for (uint32_t jitem = 0; !found && + jitem < gOptions.numRemoveItems; ++jitem) + { + if (platform == gOptions.removeItems[jitem].platform && + bt->tool == gOptions.removeItems[jitem].tool) { + found = true; + } + } + + if (!found) { + items = reallocf(items, sizeof(*items) * (nitem+1)); + item = &items[nitem++]; + memset(item, 0, sizeof(*item)); + item->type = kAddTool; + item->platform = platform; + item->tool = bt->tool; + item->version = bt->version; + } + } + } // if (bv) + } // for (uint32_t iitem = 0; iitem < gOptions.numSetItems; ++iitem) + + // measure the offset to the first section and the size of load commands + // that will be modified. (Theoretically we're only making the load + // commands smaller here; but it doesn't hurt much to be careful.) + off_t sectoffset = fb->fat_archs[fb->fat_arch_idx].size; + uint32_t modvlcsize = 0; + + for (uint32_t icmd = 0; icmd < lcmds->count; ++icmd) + { + struct load_command* lc = lcmds->items[icmd]; + if (lc->cmd == LC_SEGMENT) + { + // walk the sections + struct segment_command* sg = (struct segment_command*)lc; + for (uint32_t isect = 0; isect < sg->nsects; ++isect) + { + struct section* sc = (struct section*) + (((unsigned char*)(sg+1)) + isect * sizeof(*sc)); + if (sc->flags & S_ZEROFILL) + continue; + if (sc->offset < sectoffset) + sectoffset = sc->offset; + } + } + else if (lc->cmd == LC_SEGMENT_64) + { + // walk the sections + struct segment_command_64* sg = (struct segment_command_64*)lc; + for (uint32_t isect = 0; isect < sg->nsects; ++isect) + { + struct section_64* sc = (struct section_64*) + (((unsigned char*)(sg+1)) + isect * sizeof(*sc)); + if (sc->flags & S_ZEROFILL) + continue; + if (sc->offset < sectoffset) + sectoffset = sc->offset; + } + } + else if (lc->cmd == LC_VERSION_MIN_MACOSX || + lc->cmd == LC_VERSION_MIN_IPHONEOS || + lc->cmd == LC_VERSION_MIN_WATCHOS || + lc->cmd == LC_VERSION_MIN_TVOS || + lc->cmd == LC_BUILD_VERSION) + { + // check if we are modifying this load command. if yes, add the + // concrete load command size to our running total. + bool modify = false; + + uint32_t platform; + if (lc->cmd == LC_BUILD_VERSION) { + struct build_version_command* bv = + (struct build_version_command*)lc; + platform = bv->platform; + } + else { + platform = platform_id_for_vmlc(lc->cmd); + } + + for (uint32_t iitem=0; !modify && + iitem < gOptions.numRemoveItems; ++iitem) + { + if (gOptions.removeItems[iitem].type == kRemoveBuild && + gOptions.removeItems[iitem].platform == platform) + modify = true; + } + for (uint32_t iitem=0; !modify && iitem < nitem; ++iitem) + { + if (items[iitem].type == kSetBuild && + items[iitem].platform == platform) + modify = true; + } + + if (modify) + modvlcsize += lc->cmdsize; + } + else if (lc->cmd == LC_SOURCE_VERSION) + { + // check if we are modifying this load command. if yes, add the + // concrete load command size to our running total. + bool modify = false; + + for (uint32_t iitem=0; !modify && + iitem < gOptions.numRemoveItems; ++iitem) + { + if (gOptions.removeItems[iitem].type == kRemoveSource) + modify = true; + } + + if (modify) + modvlcsize += lc->cmdsize; + } + } // for (uint32_t icmd = 0; icmd < lcmds->count; ++icmd) + + // compute the size requirements for our new load commands by + // subtracting away the existing commands and adding in the + // user-requested ones. + uint32_t sizeofnewcmds = fb->mh.sizeofcmds; + sizeofnewcmds -= modvlcsize; + + for (uint32_t iitem=0; iitem < nitem; ++iitem) + { + if (items[iitem].type == kAddTool) + sizeofnewcmds += sizeof(struct build_tool_version); + if (items[iitem].type == kSetBuild && !items[iitem].versmin) + sizeofnewcmds += sizeof(struct build_version_command); + } + + // verify the load commands still fit below the start of section data. + uint32_t totalcmdspace = (uint32_t)(sectoffset - fb->mh_size); + if (totalcmdspace < sizeofnewcmds) + { + if (fb->nfat_arch > 1 || gOptions.narch) { + const NXArchInfo* archInfo = NULL; + archInfo = NXGetArchInfoFromCpuType(fb->mh.cputype, + fb->mh.cpusubtype); + if (archInfo) + fprintf(stderr, "%s error: %s (%s) not enough space to " + "hold load commands\n", gProgramName, + gOptions.inPath, archInfo->name); + else + fprintf(stderr, "%s error: %s (%u, %u) not enough space to " + "hold load commands\n", gProgramName, + gOptions.inPath, fb->mh.cputype, fb->mh.cpusubtype); + } + else { + fprintf(stderr, "%s error: %s not enough space to hold load " + "commands\n", gProgramName, gOptions.inPath); + } + + return -1; + } + + // copy all of the non-version load commands from the input file into a + // new buffer. keep count of the number of commands written. + // + // note that the newcmds array is zero-filled and is exactly the size of + // available space. the entire buffer will be copied back into the file, + // erasing any previous + unsigned char* newcmds = calloc(1, totalcmdspace); + unsigned char* p = fb->lcs; + unsigned char* q = newcmds; + uint32_t ncmds = 0; + + for (uint32_t icmd = 0; icmd < lcmds->count; ++icmd) + { + struct load_command* lc = lcmds->items[icmd]; + bool copy = true; + + if (lc->cmd == LC_VERSION_MIN_MACOSX || + lc->cmd == LC_VERSION_MIN_IPHONEOS || + lc->cmd == LC_VERSION_MIN_WATCHOS || + lc->cmd == LC_VERSION_MIN_TVOS || + lc->cmd == LC_BUILD_VERSION) + { + uint32_t platform; + if (lc->cmd == LC_BUILD_VERSION) { + struct build_version_command* bv = + (struct build_version_command*)lc; + platform = bv->platform; + } + else { + platform = platform_id_for_vmlc(lc->cmd); + } + + for (uint32_t iitem=0; copy && + iitem < gOptions.numRemoveItems; ++iitem) + { + if (gOptions.removeItems[iitem].type == kRemoveBuild && + gOptions.removeItems[iitem].platform == platform) + copy = false; + } + for (uint32_t iitem=0; copy && iitem < nitem; ++iitem) + { + if (items[iitem].type == kSetBuild && + items[iitem].platform == platform) + copy = false; + } + } + else if (lc->cmd == LC_SOURCE_VERSION) + { + // check if we are modifying this load command. if yes, add the + // concrete load command size to our running total. + for (uint32_t iitem=0; copy && + iitem < gOptions.numRemoveItems; ++iitem) + { + if (gOptions.removeItems[iitem].type == kRemoveSource) + copy = false; + } + } + + // copy unswapped load commands from p to q, skipping version cmds. + if (copy) { + memcpy(q, p, lc->cmdsize); + q += lc->cmdsize; + ncmds += 1; + } + + // advance the unswapped load command pointer + p += lc->cmdsize; + } // for (uint32_t icmd = 0; icmd < lcmds->count; ++icmd) + + // write the new version commands to the output buffer + for (uint32_t iitem=0; iitem < nitem; ++iitem) + { + if (items[iitem].type == kSetBuild) { + struct build_version_command* bv = + (struct build_version_command*)q; + + bv->cmd = LC_BUILD_VERSION; + bv->cmdsize = sizeof(*bv); // for now + bv->platform = items[iitem].platform; + bv->minos = items[iitem].version; + bv->sdk = items[iitem].sdk_vers; + bv->ntools = 0; + q += bv->cmdsize; + + struct build_tool_version* tools = + (struct build_tool_version*)q; + + // copy the tools for this platform + for (uint32_t itool=iitem + 1; itool < nitem; ++itool) { + if (items[itool].type != kAddTool) + continue; + if (items[itool].platform != bv->platform) + continue; + struct build_tool_version* bt = + (struct build_tool_version*)q; + bt->tool = items[itool].tool; + bt->version = items[itool].version; + q += sizeof(*bt); + bv->ntools += 1; + bv->cmdsize += sizeof(*bt); + } + + if (fb->swap) { + swap_build_version_command(bv, gByteOrder); + swap_build_tool_version(tools, bv->ntools, gByteOrder); + } + + ncmds += 1; + } + } + + // update the mach_header and load commands in memory + struct mach_header_64 mh; + memcpy(&mh, &fb->mh, sizeof(mh)); + mh.sizeofcmds = sizeofnewcmds; + mh.ncmds = ncmds; + if (fb->swap) + swap_mach_header_64(&mh, gByteOrder); + + q = fb->buf + fb->fat_archs[fb->fat_arch_idx].offset; + memcpy(q, &mh, fb->mh_size); + q += fb->mh_size; + memcpy(q, newcmds, totalcmdspace); + + free(newcmds); + free(items); + + return 0; +} + +/* + * command_set() adds or replaces the requested version commands in a Mach-O + * file or Mach-O files in a fat file. + */ +int command_set(struct file* fb) +{ + // the write operation for a Mach-O takes place in several phases: + // + // 1. create a new list of set instructions with the "set build version" + // instructions sorted towards the front and the "set build tool" + // instructions sorted towards the end. For each "set build tool" + // instruction verify a "set build version" exists for that platform, + // creating a new set instruction from the source file if needed. + // support for adding new build tools makes this tricksy. + // + // 2. loop over the load commands to find the start of section contents, + // and measure the size of the existing version load commands. + // + // 3. compute the space required to hold the new load commands, and make + // sure they fit in the available space. + // + // 4. copy all of the load commands that aren't being changed or replaced + // into a new temporary buffer, then add the inserted and modified load + // commands at the end of said buffer. + // + // 5. replace the load commands and rewrite the mach header for the + // Mach-O stored in the fb buffer, so that later on someone can write + // that buffer back out to disk again. + // + // command_set does not change the file's size in any way. instead, it will + // rewrite the contents of the file in memory, leaving the broader structure + // of the Mach-O completely unchanged. if the new load commands do not fit + // in the existing space between the mach_header and the first segment, + // command_set will return an error. + // + // the input file on disk is not modified in this process, although the + // copy in memory totally is. + + // cache the swapped load command table in a convenient form + struct lcmds* lcmds = fb->lcmds; + + // build a new setItems array, verifying a build version exists for + // every tool. If a build version was not specified on the command line + // look for the build version in the source file. + struct set_item* items = NULL; + uint32_t nitem = 0; + for (uint32_t iitem = 0; iitem < gOptions.numSetItems; ++iitem) + { + if (kAddTool == gOptions.setItems[iitem].type) + continue; + // add this build version or source version to the list + items = reallocf(items, sizeof(*items) * (nitem+1)); + memcpy(&items[nitem++], &gOptions.setItems[iitem], sizeof(*items)); + } + for (uint32_t iitem = 0; iitem < gOptions.numSetItems; ++iitem) + { + if (kAddTool != gOptions.setItems[iitem].type) + continue; + + uint32_t platform = gOptions.setItems[iitem].platform; + struct build_version_command* bv = NULL; + bool found = false; + + // look for this tool's corresponding build version in the program + // arguments. + if (!found) + { + for (uint32_t jitem = 0; !found && jitem < nitem; ++jitem) + { + if (platform == items[jitem].platform && + kAddTool != items[jitem].type) + { + if (items[jitem].versmin) { + fprintf(stderr, "%s error: version min load commands " + "do not support tool versions\n", gProgramName); + return -1; + } + found = true; + } + } + } + + // look for this tool's corresponding build version in the input + // file's load commands. + if (!found) + { + for (uint32_t icmd = 0; !found && icmd < lcmds->count; ++icmd) + { + struct load_command* lc = lcmds->items[icmd]; + if (lc->cmd == LC_BUILD_VERSION) + { + bv = (struct build_version_command*)lc; + found = (platform == bv->platform); + } + else if (lc->cmd == LC_VERSION_MIN_MACOSX || + lc->cmd == LC_VERSION_MIN_IPHONEOS || + lc->cmd == LC_VERSION_MIN_WATCHOS || + lc->cmd == LC_VERSION_MIN_TVOS) + { + if (platform_id_for_vmlc(lc->cmd) == platform) { + fprintf(stderr, "%s error: %s version min load " + "commands do not support tool versions\n", + gProgramName, gOptions.inPath); + return -1; + } + } + } + } + + // we looked and we looked but we didn't find a build version for + // this tool. return an error. + if (!found) + { + const char* plname = platform_name_for_id(platform); + if (plname) + fprintf(stderr, "%s error: no build verion load command found " + "for platform %s\n", gProgramName, plname); + else + fprintf(stderr, "%s error: no build verion load command found " + "for platform #%u\n", gProgramName, platform); + return -1; + } + + // if this tool is modifying a build version already in the input + // file, add it to the list. Also add this build version's tools + // to the list if they aren't otherwise being replaced. + if (bv) + { + // we found a build version load command for this tool, so + // add it to the list. Also, add all the tools for this build + // version except those we have options for. + items = reallocf(items, sizeof(*items) * (nitem+1)); + struct set_item* item = &items[nitem++]; + memset(item, 0, sizeof(*item)); + item->type = kSetBuild; + item->platform = platform; + item->version = bv->minos; + item->sdk_vers = bv->sdk; + + if (!gOptions.replace) { + for (uint32_t itool = 0; itool < bv->ntools; ++itool) + { + struct build_tool_version* bt = + (struct build_tool_version*) + (((unsigned char*)(bv+1)) + + (itool * sizeof(struct build_tool_version))); + found = false; + for (uint32_t jitem = 0; !found && + jitem < gOptions.numSetItems; ++jitem) + { + if (platform == gOptions.setItems[jitem].platform && + bt->tool == gOptions.setItems[jitem].tool) { + found = true; + } + } + + if (!found) { + items = reallocf(items, sizeof(*items) * (nitem+1)); + item = &items[nitem++]; + memset(item, 0, sizeof(*item)); + item->type = kAddTool; + item->platform = platform; + item->tool = bt->tool; + item->version = bt->version; + } + } + } + } // if (bv) + + // finally, add this tool to the list. + items = reallocf(items, sizeof(*items) * (nitem+1)); + memcpy(&items[nitem++], &gOptions.setItems[iitem], sizeof(*items)); + } // for (uint32_t iitem = 0; iitem < gOptions.numSetItems; ++iitem) + + // measure the offset to the first section and the size of load commands + // that will be modified + off_t sectoffset = fb->fat_archs[fb->fat_arch_idx].size; + uint32_t modvlcsize = 0; + + for (uint32_t icmd = 0; icmd < lcmds->count; ++icmd) + { + struct load_command* lc = lcmds->items[icmd]; + if (lc->cmd == LC_SEGMENT) + { + // walk the sections + struct segment_command* sg = (struct segment_command*)lc; + for (uint32_t isect = 0; isect < sg->nsects; ++isect) + { + struct section* sc = (struct section*) + (((unsigned char*)(sg+1)) + isect * sizeof(*sc)); + if (sc->flags & S_ZEROFILL) + continue; + if (sc->offset < sectoffset) + sectoffset = sc->offset; + } + } + else if (lc->cmd == LC_SEGMENT_64) + { + // walk the sections + struct segment_command_64* sg = (struct segment_command_64*)lc; + for (uint32_t isect = 0; isect < sg->nsects; ++isect) + { + struct section_64* sc = (struct section_64*) + (((unsigned char*)(sg+1)) + isect * sizeof(*sc)); + if (sc->flags & S_ZEROFILL) + continue; + if (sc->offset < sectoffset) + sectoffset = sc->offset; + } + } + else if (lc->cmd == LC_VERSION_MIN_MACOSX || + lc->cmd == LC_VERSION_MIN_IPHONEOS || + lc->cmd == LC_VERSION_MIN_WATCHOS || + lc->cmd == LC_VERSION_MIN_TVOS || + lc->cmd == LC_BUILD_VERSION) + { + // check if we are modifying this load command. if yes, add the + // concrete load command size to our running total. + bool modify = gOptions.replace; + + uint32_t platform; + if (lc->cmd == LC_BUILD_VERSION) { + struct build_version_command* bv = + (struct build_version_command*)lc; + platform = bv->platform; + } + else { + platform = platform_id_for_vmlc(lc->cmd); + } + + for (uint32_t iitem=0; !modify && iitem < nitem; ++iitem) + { + if (items[iitem].type == kSetBuild && + items[iitem].platform == platform) + modify = true; + } + + if (modify) + modvlcsize += lc->cmdsize; + } + else if (lc->cmd == LC_SOURCE_VERSION) + { + // check if we are modifying this load command. if yes, add the + // concrete load command size to our running total. + bool modify = false; + + for (uint32_t iitem=0; !modify && iitem < nitem; ++iitem) + { + if (items[iitem].type == kSetSource) + modify = true; + } + + if (modify) + modvlcsize += lc->cmdsize; + } + } // for (uint32_t icmd = 0; icmd < lcmds->count; ++icmd) + + // compute the size requirements for our new load commands by + // subtracting away the existing commands and adding in the + // user-requested ones. + uint32_t sizeofnewcmds = fb->mh.sizeofcmds; + sizeofnewcmds -= modvlcsize; + + for (uint32_t iitem=0; iitem < nitem; ++iitem) + { + if (items[iitem].type == kSetSource) + sizeofnewcmds += sizeof(struct source_version_command); + if (items[iitem].type == kAddTool) + sizeofnewcmds += sizeof(struct build_tool_version); + if (items[iitem].type == kSetBuild && items[iitem].versmin) + sizeofnewcmds += sizeof(struct version_min_command); + if (items[iitem].type == kSetBuild && !items[iitem].versmin) + sizeofnewcmds += sizeof(struct build_version_command); + } + + // verify the load commands still fit below the start of section data. + uint32_t totalcmdspace = (uint32_t)(sectoffset - fb->mh_size); + if (totalcmdspace < sizeofnewcmds) + { + if (fb->nfat_arch > 1 || gOptions.narch) { + const NXArchInfo* archInfo = NULL; + archInfo = NXGetArchInfoFromCpuType(fb->mh.cputype, + fb->mh.cpusubtype); + if (archInfo) + fprintf(stderr, "%s error: %s (%s) not enough space to " + "hold load commands\n", gProgramName, + gOptions.inPath, archInfo->name); + else + fprintf(stderr, "%s error: %s (%u, %u) not enough space to " + "hold load commands\n", gProgramName, + gOptions.inPath, fb->mh.cputype, fb->mh.cpusubtype); + } + else { + fprintf(stderr, "%s error: %s not enough space to hold load " + "commands\n", gProgramName, gOptions.inPath); + } + + return -1; + } + + // copy all of the non-version load commands from the input file into a + // new buffer. keep count of the number of commands written. + // + // note that the newcmds array is zero-filled and is exactly the size of + // available space. the entire buffer will be copied back into the file, + // erasing any previous + unsigned char* newcmds = calloc(1, totalcmdspace); + unsigned char* p = fb->lcs; + unsigned char* q = newcmds; + uint32_t ncmds = 0; + + for (uint32_t icmd = 0; icmd < lcmds->count; ++icmd) + { + struct load_command* lc = lcmds->items[icmd]; + bool copy = true; + + if (lc->cmd == LC_VERSION_MIN_MACOSX || + lc->cmd == LC_VERSION_MIN_IPHONEOS || + lc->cmd == LC_VERSION_MIN_WATCHOS || + lc->cmd == LC_VERSION_MIN_TVOS || + lc->cmd == LC_BUILD_VERSION) + { + copy = !gOptions.replace; + + uint32_t platform; + if (lc->cmd == LC_BUILD_VERSION) { + struct build_version_command* bv = + (struct build_version_command*)lc; + platform = bv->platform; + } + else { + platform = platform_id_for_vmlc(lc->cmd); + } + + for (uint32_t iitem=0; copy && iitem < nitem; ++iitem) + { + if (items[iitem].type == kSetBuild && + items[iitem].platform == platform) + copy = false; + } + } + else if (lc->cmd == LC_SOURCE_VERSION) + { + // check if we are modifying this load command. if yes, add the + // concrete load command size to our running total. + copy = true; + + for (uint32_t iitem=0; copy && iitem < nitem; ++iitem) + { + if (items[iitem].type == kSetSource) + copy = false; + } + } + + // copy unswapped load commands from p to q, skipping version cmds. + if (copy) { + memcpy(q, p, lc->cmdsize); + q += lc->cmdsize; + ncmds += 1; + } + + // advance the unswapped load command pointer + p += lc->cmdsize; + } // for (uint32_t icmd = 0; icmd < lcmds->count; ++icmd) + + // write the new version commands to the output buffer + for (uint32_t iitem=0; iitem < nitem; ++iitem) + { + if (items[iitem].type == kSetBuild) { + if (items[iitem].versmin) { + struct version_min_command* vmc = + (struct version_min_command*)q; + vmc->cmd = platform_vmlc_for_id(items[iitem].platform); + vmc->cmdsize = sizeof(*vmc); + vmc->version = items[iitem].version; + vmc->sdk = items[iitem].sdk_vers; + if (fb->swap) + swap_version_min_command(vmc, gByteOrder); + q += vmc->cmdsize; + } + else { + struct build_version_command* bv = + (struct build_version_command*)q; + + bv->cmd = LC_BUILD_VERSION; + bv->cmdsize = sizeof(*bv); // for now + bv->platform = items[iitem].platform; + bv->minos = items[iitem].version; + bv->sdk = items[iitem].sdk_vers; + bv->ntools = 0; + q += bv->cmdsize; + + struct build_tool_version* tools = + (struct build_tool_version*)q; + + // copy the tools for this platform + for (uint32_t itool=iitem + 1; itool < nitem; ++itool) { + if (items[itool].type != kAddTool) + continue; + if (items[itool].platform != bv->platform) + continue; + struct build_tool_version* bt = + (struct build_tool_version*)q; + bt->tool = items[itool].tool; + bt->version = items[itool].version; + q += sizeof(*bt); + bv->ntools += 1; + bv->cmdsize += sizeof(*bt); + } + + if (fb->swap) { + swap_build_version_command(bv, gByteOrder); + swap_build_tool_version(tools, bv->ntools, gByteOrder); + } + } + + ncmds += 1; + } + if (items[iitem].type == kSetSource) { + struct source_version_command* sv = + (struct source_version_command*)q; + sv->cmd = LC_SOURCE_VERSION; + sv->cmdsize = sizeof(*sv); + sv->version = items[iitem].src_vers; + if (fb->swap) + swap_source_version_command(sv, gByteOrder); + q += sv->cmdsize; + + ncmds += 1; + } + } + + // update the mach_header and load commands in memory + struct mach_header_64 mh; + memcpy(&mh, &fb->mh, sizeof(mh)); + mh.sizeofcmds = sizeofnewcmds; + mh.ncmds = ncmds; + if (fb->swap) + swap_mach_header_64(&mh, gByteOrder); + + q = fb->buf + fb->fat_archs[fb->fat_arch_idx].offset; + memcpy(q, &mh, fb->mh_size); + q += fb->mh_size; + memcpy(q, newcmds, totalcmdspace); + + free(newcmds); + free(items); + + return 0; +} + +/* + * command_show() prints the requested version commands in a Mach-O file. + */ +int command_show(struct file* fb) +{ + // print the file name + const NXArchInfo* archInfo = NULL; + if (fb->nfat_arch > 1 || gOptions.narch) { + archInfo = NXGetArchInfoFromCpuType(fb->mh.cputype, + fb->mh.cpusubtype); + } + printf("%s", gOptions.inPath); + if (archInfo) { + printf(" (architecture %s)", archInfo->name); + } + printf(":\n"); + + // walk the load commands ... + struct lcmds* lcmds = fb->lcmds; + off_t sectoffset = fb->fat_archs[fb->fat_arch_idx].size; + for (uint32_t icmd = 0; icmd < lcmds->count; ++icmd) + { + struct load_command* lc = lcmds->items[icmd]; + + // measure the offset to the first section + if (lc->cmd == LC_SEGMENT) + { + struct segment_command* sg = (struct segment_command*)lc; + for (uint32_t isect = 0; isect < sg->nsects; ++isect) + { + struct section* sc = (struct section*) + (((unsigned char*)(sg+1)) + isect * sizeof(*sc)); + if (sc->flags & S_ZEROFILL) + continue; + if (sc->offset < sectoffset) + sectoffset = sc->offset; + } + } + else if (lc->cmd == LC_SEGMENT_64) + { + struct segment_command_64* sg = (struct segment_command_64*)lc; + for (uint32_t isect = 0; isect < sg->nsects; ++isect) + { + struct section_64* sc = (struct section_64*) + (((unsigned char*)(sg+1)) + isect * sizeof(*sc)); + if (sc->flags & S_ZEROFILL) + continue; + if (sc->offset < sectoffset) + sectoffset = sc->offset; + } + } + + // display all build and source version load commands + else if (lc->cmd == LC_VERSION_MIN_MACOSX || + lc->cmd == LC_VERSION_MIN_IPHONEOS || + lc->cmd == LC_VERSION_MIN_WATCHOS || + lc->cmd == LC_VERSION_MIN_TVOS) + { + if (gOptions.show == kShowAll || gOptions.show == kShowBuild) + { + struct version_min_command* vmc = + (struct version_min_command*)lc; + printf("Load command %u\n", icmd); + print_version_min_command(vmc); + } + } + else if (lc->cmd == LC_BUILD_VERSION) + { + if (gOptions.show == kShowAll || gOptions.show == kShowBuild) + { + struct build_version_command* bv = + (struct build_version_command*)lc; + + printf("Load command %u\n", icmd); + print_build_version_command(bv); + + unsigned char* q = (unsigned char*)(bv+1); + for (uint32_t itool = 0; itool < bv->ntools; ++itool) { + struct build_tool_version* tv = + (struct build_tool_version*)q; + print_build_tool_version(tv->tool, tv->version); + q += sizeof(*tv); + } + } + } + else if (lc->cmd == LC_SOURCE_VERSION) + { + // verify we are printing build versions + if (gOptions.show == kShowAll || + gOptions.show == kShowSource) + { + struct source_version_command* sv = + (struct source_version_command*)lc; + printf("Load command %u\n", icmd); + print_source_version_command(sv); + } + } + } // for (uint32_t icmd = 0; icmd < lcmds->count; ++icmd) + + if (gOptions.show == kShowSpace ) { + printf(" Mach header size: %5d\n", (int)fb->mh_size); + printf(" Load command size: %5d\n", (int)fb->mh.sizeofcmds); + printf(" Available space: %5d\n", + (int)(sectoffset - fb->mh_size - fb->mh.sizeofcmds)); + printf(" Total: %5d\n", (int)sectoffset); + } + + return 0; +} + +/* + * file_read() reads a Mach-O or fat file into memory and walks enough of its + * structure to determine which architectures this file is relevant for. + * + * Upon success, the following struct file fields will be initialized: + * + * buf + * len + * mode + * nfat_arch + * fat_archs + */ +int file_read(const char* path, struct file* fb) +{ + memset(fb, 0, sizeof(*fb)); + + // open the file for reading + int fd = open(path, O_RDONLY); + if (-1 == fd) { + fprintf(stderr, "%s error: %s: can't open file: %s\n", + gProgramName, path, strerror(errno)); + return -1; + } + + // stat the file + struct stat sb; + if (fstat(fd, &sb)) { + fprintf(stderr, "%s error: %s: can't stat file: %s\n", + gProgramName, path, strerror(errno)); + close(fd); + return -1; + } + + fb->len = sb.st_size; + fb->mode = sb.st_mode; + fb->buf = calloc(1, fb->len); + + // read the contents of the file into memory + ssize_t readed = read(fd, fb->buf, fb->len); // that's unpossible! + if (-1 == readed) { + fprintf(stderr, "%s error: %s: can't read file: %s\n", + gProgramName, path, strerror(errno)); + close(fd); + free(fb->buf); + return -1; + } + else if (readed != fb->len) { + fprintf(stderr, "%s error: %s: partial read (0x%zx of 0x%llx)\n", + gProgramName, path, readed, fb->len); + close(fd); + free(fb->buf); + return -1; + } + + // close the file, we're done with it. + if (close(fd)) { + fprintf(stderr, "%s warning: %s: can't close file: %s\n", + gProgramName, path, strerror(errno)); + } + + // read the magic + uint32_t magic; + + if (fb->len < sizeof(magic)) { + fprintf(stderr, "%s error: %s file is not mach-o\n", + gProgramName, path); + free(fb->buf); + return -1; + } + + magic = *(uint32_t*)(fb->buf); + + if (magic == MH_MAGIC || magic == MH_CIGAM || + magic == MH_MAGIC_64 || magic == MH_CIGAM_64) + { + // get the mach_header size, and confirm it fits + if (magic == MH_MAGIC || magic == MH_CIGAM) { + fb->mh_size = sizeof(struct mach_header); + } else { + fb->mh_size = sizeof(struct mach_header_64); + } + if (fb->len < fb->mh_size) { + fprintf(stderr, "%s error: %s file is not mach-o\n", + gProgramName, path); + free(fb->buf); + return -1; + } + + // read the mach_header and swap it if needed. + if (magic == MH_MAGIC || magic == MH_CIGAM) { + memcpy(&fb->mh, fb->buf, fb->mh_size); + fb->mh.reserved = 0; + } + else if (magic == MH_MAGIC_64 || magic == MH_CIGAM_64) { + memcpy(&fb->mh, fb->buf, fb->mh_size); + } + if (magic == MH_CIGAM || magic == MH_CIGAM_64) { + fb->swap = true; + swap_mach_header_64(&fb->mh, NXHostByteOrder()); + } else { + fb->swap = false; + } + + // build a fat_arch table describing this file + // + // note that we don't know the alignment for this file, and while we + // could guess at the alignment from the cputype, as other cctools do, + // we don't acutally need this value, so we'll leave it blank. + fb->nfat_arch = 1; + fb->fat_archs = calloc(1, sizeof(struct fat_arch)); + fb->fat_archs[0].cputype = fb->mh.cputype; + fb->fat_archs[0].cpusubtype = fb->mh.cpusubtype; + fb->fat_archs[0].offset = 0; + fb->fat_archs[0].size = (uint32_t)fb->len; + fb->fat_archs[0].align = 0; + } + else if (magic == FAT_MAGIC || magic == FAT_CIGAM) { + struct fat_header fh; + + // read the fat header + if (fb->len < sizeof(fh)) { + fprintf(stderr, "%s error: %s file is not mach-o\n", + gProgramName, path); + free(fb->buf); + return -1; + } + + memcpy(&fh, fb->buf, sizeof(fh)); + swap_fat_header(&fh, NXHostByteOrder()); + + // read the initial list of fat archs. deal with arm64ageddon binaries + // by just reserving 1 additional spot in the fat_arch array, and + // reading one additional item off of the arch list. + if (fb->len < sizeof(fh) + sizeof(struct fat_arch) * (fh.nfat_arch+1)) { + fprintf(stderr, "%s error: %s file is not mach-o\n", + gProgramName, path); + free(fb->buf); + return -1; + } + + fb->nfat_arch = fh.nfat_arch; + fb->fat_archs = malloc(sizeof(*fb->fat_archs) * (fb->nfat_arch + 1)); + memcpy(fb->fat_archs, ((struct fat_header*)fb->buf) + 1, + sizeof(*fb->fat_archs) * (fb->nfat_arch + 1)); + swap_fat_arch(fb->fat_archs, fb->nfat_arch + 1, NXHostByteOrder()); + + // look for arm64ageddon binaries + bool foundARM32 = false; + bool foundARM64 = false; + for (uint32_t i = 0; i < fb->nfat_arch; ++i) + { + if (CPU_TYPE_ARM == fb->fat_archs[i].cputype) + foundARM32 = true; + if (CPU_TYPE_ARM64 == fb->fat_archs[i].cputype) + foundARM64 = true; + } + if (foundARM32 && !foundARM64 && + CPU_TYPE_ARM64 == fb->fat_archs[fb->nfat_arch].cputype) + { + fb->nfat_arch += 1; + } + + // verify the fat file contains all its subfiles. + for (uint32_t i = 0; i < fb->nfat_arch; ++i) + { + if (fb->len < fb->fat_archs[i].offset + fb->fat_archs[i].size) { + fprintf(stderr, "%s error: %s file #%d for cputype (%u, %u) " + "extends beyond file boundaries (%llu < %u + %u)\n", + gProgramName, path, i, fb->fat_archs[i].cputype, + fb->fat_archs[i].cpusubtype, fb->len, + fb->fat_archs[i].offset, fb->fat_archs[i].size); + free(fb->buf); + free(fb->fat_archs); + return -1; + } + } + + } + else { + fprintf(stderr, "%s error: %s file is not mach-o\n", + gProgramName, path); + free(fb->buf); + return -1; + } + + return 0; +} + +/* + * file_select_macho() prepares the Mach-O file for reading by completing + * initialization of the file struct and verifying the Mach-O header and load + * command array fit in memory. + * + * Upon success, the following struct file fields will be initialized: + * + * fat_arch_idx + * mh + * mh_size + * lcs + * lcmds + * swap + */ +int file_select_macho(const char* path, struct file* fb, uint32_t index) +{ + if (index >= fb->nfat_arch) { + fprintf(stderr, "%s internal error: reading beyond fat_arch array\n", + gProgramName); + return -1; + } + + fb->fat_arch_idx = index; + + // re-verify the magic + uint32_t offset = fb->fat_archs[index].offset; + const unsigned char* buf = fb->buf + offset; + uint32_t magic = *(uint32_t*)(buf); + + if (magic == MH_MAGIC || magic == MH_CIGAM || + magic == MH_MAGIC_64 || magic == MH_CIGAM_64) + { + // get the mach_header size, and confirm it fits + if (magic == MH_MAGIC || magic == MH_CIGAM) { + fb->mh_size = sizeof(struct mach_header); + } else { + fb->mh_size = sizeof(struct mach_header_64); + } + if (fb->len < offset + fb->mh_size) { + fprintf(stderr, "%s error: %s file #%d for cputype (%u, %u) " + "is not mach-o\n", + gProgramName, path, index, fb->fat_archs[index].cputype, + fb->fat_archs[index].cpusubtype); + return -1; + } + + // read the mach_header and swap it if needed. + if (magic == MH_MAGIC || magic == MH_CIGAM) { + memcpy(&fb->mh, buf, fb->mh_size); + fb->mh.reserved = 0; + } + else if (magic == MH_MAGIC_64 || magic == MH_CIGAM_64) { + memcpy(&fb->mh, buf, fb->mh_size); + } + if (magic == MH_CIGAM || magic == MH_CIGAM_64) { + fb->swap = true; + swap_mach_header_64(&fb->mh, NXHostByteOrder()); + } else { + fb->swap = false; + } + + // verify the load commands fit in the file + if (fb->len < offset + fb->mh_size + fb->mh.sizeofcmds) { + fprintf(stderr, "%s error: %s file #%d for cputype (%u, %u) " + "load command extend beyond length of file\n", + gProgramName, path, index, fb->fat_archs[index].cputype, + fb->fat_archs[index].cpusubtype); + return -1; + } + + // as a convenience, compute the location of the load commands + fb->lcs = (unsigned char*)&buf[fb->mh_size]; + + // also cache the load commands in a convenient indexable form. + if (fb->lcmds) + lcmds_free(fb->lcmds); + fb->lcmds = lcmds_alloc(fb); + if (!fb->lcmds) + return -1; + } + else { + fprintf(stderr, "%s error: %s file #%d for cputype (%u, %u) " + "is not mach-o\n", + gProgramName, path, index, fb->fat_archs[index].cputype, + fb->fat_archs[index].cpusubtype); + return -1; + } + + return 0; +} + +/* + * file_write writes the entire file buffer to the specified path. the new file + * is written into a temporary location and then moved into place. permissions + * on the new file match that of the original file used to initialize fb. + */ +int file_write(const char* path, struct file* fb) +{ + int res = 0; + bool warn = true; + + // warn if any Mach-O files source file contain code signatures. + for (uint32_t iarch = 0; 0 == res && warn && iarch < fb->nfat_arch; ++iarch) + { + // prepare the mach-o for reading + res = file_select_macho(path, fb, iarch); + if (res) + continue; + + // walk the load commands looking for LC_CODE_SIGNATURE + struct lcmds* lcmds = fb->lcmds; + for (uint32_t icmd = 0; warn && icmd < lcmds->count; ++icmd) { + struct load_command* lc = lcmds->items[icmd]; + if (lc->cmd == LC_CODE_SIGNATURE) { + fprintf(stderr, "%s warning: code signature will be invalid " + "for %s\n", gProgramName, path); + warn = false; + } + } + } + + // compute a temporary path to hold our output file during assembly. + size_t pathlen = strlen(path); + const char* prefix = ".XXXXXX"; + size_t tmpsize = pathlen + strlen(prefix) + 1; + char* tmppath = calloc(1, tmpsize); + snprintf(tmppath, tmpsize, "%s%s", path, prefix); + + // open the temp file for writing + int fd = -1; + if (0 == res) { + fd = mkstemp(tmppath); + if (-1 == fd) { + fprintf(stderr, "%s error: ", gProgramName); + perror("mkstemp"); + res = -1; + } + } + + // write the file + if (0 == res) { + ssize_t wrote = write(fd, fb->buf, fb->len); + if (wrote == -1) { + fprintf(stderr, "%s error: %s: write: %s\n", gProgramName, tmppath, + strerror(errno)); + res = -1; + } + else if (wrote != fb->len) { + fprintf(stderr, "%s error: %s: partial write (0x%zx of 0x%llx)\n", + gProgramName, tmppath, wrote, fb->len); + res = -1; + } + } + + // close the file and move the temporary file to its final destination + if (0 == res && close(fd)) { + fprintf(stderr, "%s error: %s: can't close file: %s\n", + gProgramName, tmppath, strerror(errno)); + res = -1; + } + + if (0 == res && chmod(tmppath, fb->mode)) { + fprintf(stderr, "%s error: %s: can't change file permissions: %s\n", + gProgramName, tmppath, strerror(errno)); + res = -1; + } + + if (0 == res && rename(tmppath, path)) { + fprintf(stderr, "%s error: %s: can't rename file: %s\n", gProgramName, + tmppath, strerror(errno)); + res = -1; + } + + // try to lean up if something went wrong + if (res) { + unlink(tmppath); + } + + free(tmppath); + + return res; +} + +/* + * lcmds_alloc reads the load commands from the supplied file, swaps them as + * necessary, and stores the modified structures in a new list of load + * commands. In this form, load commands can be looped over multiple times and + * accessed in random order. + * + * BUG: for brevity, only some load command types are fully swapped. All + * cmd and cmdsize fields will be swapped. Other fields will only be swapped + * for segment, build version, and source version load commands. + * + * TODO: Fully support all load commands. + */ +struct lcmds* lcmds_alloc(struct file* fb) +{ + struct lcmds* lcmds = calloc(1, sizeof(*lcmds)); + if (!lcmds) + return NULL; + + lcmds->count = fb->mh.ncmds; + lcmds->items = calloc(lcmds->count, sizeof(*lcmds->items)); + if (!lcmds->items) { + lcmds_free(lcmds); + return NULL; + } + + unsigned char* p = fb->lcs; + for (uint32_t icmd = 0; icmd < fb->mh.ncmds; ++icmd) + { + // does the next abstract load command struct entirely fit in the + // remaining file? + if (fb->mh.sizeofcmds < p - fb->lcs + sizeof(struct load_command)) { + fprintf(stderr, "%s error: load command %d extends beyond " + "range\n", gProgramName, icmd); + lcmds_free(lcmds); + return NULL; + } + + // read the abstract load command + struct load_command lc; + memcpy(&lc, p, sizeof(lc)); + if (fb->swap) { + swap_load_command(&lc, gByteOrder); + } + + // does the next concrete load command struct entirely fit in the + // remaining file? + if (fb->mh.sizeofcmds < p - fb->lcs + lc.cmdsize) { + fprintf(stderr, "%s error: load command %d (0x%X) extends " + "beyond range\n", gProgramName, icmd, lc.cmd); + lcmds_free(lcmds); + return NULL; + } + + lcmds->items[icmd] = calloc(1, lc.cmdsize); + memcpy(lcmds->items[icmd], p, lc.cmdsize); + + if (LC_SEGMENT == lc.cmd) + { + // verify the load command fits in the command buffer + if (lc.cmdsize < sizeof(struct segment_command)) { + fprintf(stderr, + "%s error: %s file for cputype (%u, %u) load " + "command %d (0x%x) has incorrect size (%d)\n", + gProgramName, gOptions.inPath, fb->mh.cputype, + fb->mh.cpusubtype, icmd, lc.cmd, lc.cmdsize); + lcmds_free(lcmds); + return NULL; + } + + // swap the load command + struct segment_command* sg = + (struct segment_command*)lcmds->items[icmd]; + if (fb->swap) { + swap_segment_command(sg, gByteOrder); + } + + // verify the sections also fit in the command buffer + if (lc.cmdsize != sizeof(struct segment_command) + + sizeof(struct section) * sg->nsects) { + fprintf(stderr, + "%s error: %s file for cputype (%u, %u) load " + "command %d (0x%x) has incorrect size (%d)\n", + gProgramName, gOptions.inPath, fb->mh.cputype, + fb->mh.cpusubtype, icmd, lc.cmd, lc.cmdsize); + lcmds_free(lcmds); + return NULL; + } + + // swap the sections + struct section* sc = (struct section*)(sg+1); + if (fb->swap) { + swap_section(sc, sg->nsects, gByteOrder); + } + } + else if (LC_SEGMENT_64 == lc.cmd) + { + // verify the load command fits in the command buffer + if (lc.cmdsize < sizeof(struct segment_command_64)) { + fprintf(stderr, + "%s error: %s file for cputype (%u, %u) load " + "command %d (0x%x) has incorrect size (%d)\n", + gProgramName, gOptions.inPath, fb->mh.cputype, + fb->mh.cpusubtype, icmd, lc.cmd, lc.cmdsize); + lcmds_free(lcmds); + return NULL; + } + + struct segment_command_64* sg = + (struct segment_command_64*)lcmds->items[icmd]; + if (fb->swap) { + swap_segment_command_64(sg, gByteOrder); + } + + // verify the sections also fit in the command buffer + if (lc.cmdsize != sizeof(struct segment_command_64) + + sizeof(struct section_64) * sg->nsects) { + fprintf(stderr, + "%s error: %s file for cputype (%u, %u) load " + "command %d (0x%x) has incorrect size (%d)\n", + gProgramName, gOptions.inPath, fb->mh.cputype, + fb->mh.cpusubtype, icmd, lc.cmd, lc.cmdsize); + lcmds_free(lcmds); + return NULL; + } + + // swap the sections + struct section_64* sc = (struct section_64*)(sg + 1); + if (fb->swap) { + swap_section_64(sc, sg->nsects, gByteOrder); + } + } + else if (LC_VERSION_MIN_TVOS == lc.cmd || + LC_VERSION_MIN_MACOSX == lc.cmd || + LC_VERSION_MIN_WATCHOS == lc.cmd || + LC_VERSION_MIN_IPHONEOS == lc.cmd) + { + // verify the load command fits in the command buffer + if (sizeof(struct version_min_command) != lc.cmdsize) { + fprintf(stderr, + "%s error: %s file for cputype (%u, %u) load " + "command %d (0x%x) has incorrect size (%d)\n", + gProgramName, gOptions.inPath, fb->mh.cputype, + fb->mh.cpusubtype, icmd, lc.cmd, lc.cmdsize); + lcmds_free(lcmds); + return NULL; + } + // swap the load command + struct version_min_command* vm = + (struct version_min_command*)lcmds->items[icmd]; + if (fb->swap) { + swap_version_min_command(vm, gByteOrder); + } + } + else if (LC_BUILD_VERSION == lc.cmd) + { + // verify the load command fits in the command buffer + if (lc.cmdsize < sizeof(struct build_version_command)) { + fprintf(stderr, + "%s error: %s file for cputype (%u, %u) load " + "command %d (0x%x) has incorrect size (%d)\n", + gProgramName, gOptions.inPath, fb->mh.cputype, + fb->mh.cpusubtype, icmd, lc.cmd, lc.cmdsize); + lcmds_free(lcmds); + return NULL; + } + + // swap the load command + struct build_version_command* bv = + (struct build_version_command*)lcmds->items[icmd]; + if (fb->swap) { + swap_build_version_command(bv, gByteOrder); + } + + // verify the build tools also fit in the command buffer + if (lc.cmdsize < sizeof(struct build_version_command) + + sizeof(struct build_tool_version) * bv->ntools) { + fprintf(stderr, + "%s error: %s file for cputype (%u, %u) load " + "command %d (0x%x) has incorrect size (%d)\n", + gProgramName, gOptions.inPath, fb->mh.cputype, + fb->mh.cpusubtype, icmd, lc.cmd, lc.cmdsize); + lcmds_free(lcmds); + return NULL; + } + + // swap the build tools + struct build_tool_version* tv = (struct build_tool_version*)(bv+1); + if (fb->swap) { + swap_build_tool_version(tv, bv->ntools, gByteOrder); + } + } + else if (LC_SOURCE_VERSION == lc.cmd) + { + // verify the load command fits in the command buffer + if (lc.cmdsize != sizeof(struct source_version_command)) { + fprintf(stderr, + "%s error: %s file for cputype (%u, %u) load " + "command %d (0x%x) has incorrect size (%d)\n", + gProgramName, gOptions.inPath, fb->mh.cputype, + fb->mh.cpusubtype, icmd, lc.cmd, lc.cmdsize); + lcmds_free(lcmds); + return NULL; + } + + // swap the load command + struct source_version_command* sv = + (struct source_version_command*)lcmds->items[icmd]; + if (fb->swap) + swap_source_version_command(sv, gByteOrder); + } + else { + // currently lcmds->items[icmd] is unswapped load command data of + // some size. But we were able to successfully read and swap the + // abstract load command. Let's just write the swapped abstract + // load command into lcmds for now, until the day comes we process + // all defined load commands. See BUG: above. + memcpy(lcmds->items[icmd], &lc, sizeof(lc)); + } + + p += lc.cmdsize; + } // for (uint32_t icmd = 0; icmd < fb->mh.ncmds; ++icmd) + return lcmds; +} + +/* + * lcmds_free frees memory consumed by lcmds. + * + * lcmds_free can be called on a partially initialied structure. + */ +void lcmds_free(struct lcmds* lcmds) +{ + for (uint32_t icmd = 0; icmd < lcmds->count; ++icmd) { + if (lcmds->items[icmd]) + free(lcmds->items[icmd]); + } + if (lcmds->items) + free(lcmds->items); + free(lcmds); +} + +/* + * parse_version_abcde parses a version number out of a supplied string, and + * returns it in the supplied version pointer. The version is packed into 64 + * bits as follows: a24.b10.c10.d10.e10. this function will fail if any of the + * individual components are too large to fit in the available space. + */ +int parse_version_abcde(const char* rostr, uint64_t *version) +{ + uint64_t a, b, c, d, e; + char* str = strdup(rostr); + + // get the major version + char* start = str; + char* end = strchr(start, '.'); + if (end) *end = 0; + a = (uint64_t)strtoull(start, NULL, 10); + + // get the minor version + if (end) { + start = end + 1; + end = strchr(start, '.'); + if (end) *end = 0; + b = (uint64_t)strtoull(start, NULL, 10); + } else { + b = 0; + } + + // get the revision version + if (end) { + start = end + 1; + end = strchr(start, '.'); + if (end) *end = 0; + c = (uint64_t)strtoull(start, NULL, 10); + } else { + c = 0; + } + + // get the penultimate version + if (end) { + start = end + 1; + end = strchr(start, '.'); + if (end) *end = 0; + d = (uint64_t)strtoull(start, NULL, 10); + } else { + d = 0; + } + + // get the ultimate version + if (end) { + start = end + 1; + end = strchr(start, '.'); + if (end) *end = 0; + e = (uint64_t)strtoull(start, NULL, 10); + } else { + e = 0; + } + + free(str); + + if (end) { + fprintf(stderr, "%s error: version has more than 5 components: %s\n", + gProgramName, rostr); + return -1; + } + + if (a > 0xFFFFFF) { + fprintf(stderr, "%s error: major version %llu is too large\n", + gProgramName, a); + return -1; + } + + if (b > 0x3FF) { + fprintf(stderr, "%s error: minor version %llu is too large\n", + gProgramName, b); + return -1; + } + + if (c > 0x3FF) { + fprintf(stderr, "%s error: revision version %llu is too large\n", + gProgramName, c); + return -1; + } + + if (d > 0x3FF) { + fprintf(stderr, "%s error: penultimate version %llu is too large\n", + gProgramName, d); + return -1; + } + + if (e > 0x3FF) { + fprintf(stderr, "%s error: ultimate version %llu is too large\n", + gProgramName, e); + return -1; + } + + if (version) { + *version = (a << 40) | (b << 30) | (c << 20) | (d << 10) | e; + } + + return 0; +} + +/* + * parse_version_xyz parses a version number out of a supplied string, and + * returns it in the supplied version pointer. The version is packed into 4 + * bytes as follows: XXXX.YY.ZZ. this function will fail if any of the + * individual components are too large to fit in the available space. + */ +int parse_version_xyz(const char* rostr, uint32_t *version) +{ + uint32_t x, y, z; + char* str = strdup(rostr); + + // get the major version + char* start = str; + char* end = strchr(start, '.'); + if (end) *end = 0; + x = (uint32_t)strtoul(start, NULL, 10); + + // get the minor version + if (end) { + start = end + 1; + end = strchr(start, '.'); + if (end) *end = 0; + y = (uint32_t)strtoul(start, NULL, 10); + } else { + y = 0; + } + + // get the revision version + if (end) { + start = end + 1; + end = strchr(start, '.'); + if (end) *end = 0; + z = (uint32_t)strtoul(start, NULL, 10); + } else { + z = 0; + } + + free(str); + + if (end) { + fprintf(stderr, "%s error: version has more than 3 components: %s\n", + gProgramName, rostr); + return -1; + } + + if (x > 0xFFFF) { + fprintf(stderr, "%s error: major version is too large\n", gProgramName); + return -1; + } + if (y > 0xFF) { + fprintf(stderr, "%s error: minor version is too large\n", gProgramName); + return -1; + } + if (z > 0xFF) { + fprintf(stderr, "%s error: revision version is too large\n", + gProgramName); + return -1; + } + + if (version) { + *version = (x << 16) | (y << 8) | z; + } + + return 0; +} + +struct platform_entry { + uint32_t platformid; + const char* name; + uint32_t vmlc; +}; + +static const struct platform_entry kPlatforms[] = { + { PLATFORM_MACOS, "macos", LC_VERSION_MIN_MACOSX }, + { PLATFORM_IOS, "ios", LC_VERSION_MIN_IPHONEOS }, + { PLATFORM_WATCHOS, "watchos", LC_VERSION_MIN_WATCHOS }, + { PLATFORM_TVOS, "tvos", LC_VERSION_MIN_TVOS }, + { PLATFORM_BRIDGEOS, "bridgeos", 0 }, + { PLATFORM_MACCATALYST, "maccatalyst", 0 }, + { PLATFORM_MACCATALYST, "uikitformac", 0 }, // temporary + { PLATFORM_IOSSIMULATOR, "iossim", 0 }, + { PLATFORM_WATCHOSSIMULATOR, "watchossim", 0 }, + { PLATFORM_DRIVERKIT, "driverkit", 0 }, +}; + +/* + * platform_id_for_name returns a platform enum for a given name. returns 0 + * if not found. + */ +uint32_t platform_id_for_name(const char* name) +{ + int count = sizeof(kPlatforms) / sizeof(*kPlatforms); + for (int i = 0; i < count; ++i) + { + if (name && 0 == strcmp(name, kPlatforms[i].name)) + return kPlatforms[i].platformid; + } + return 0; +} + +/* + * platform_id_for_vmlc returns a platform enum for a version min load command. + * returns 0 if vmlc is not a valid version min load command. + */ +uint32_t platform_id_for_vmlc(uint32_t vmlc) +{ + int count = sizeof(kPlatforms) / sizeof(*kPlatforms); + for (int i = 0; i < count; ++i) + { + if (kPlatforms[i].vmlc == vmlc) + return kPlatforms[i].platformid; + } + return 0; +} + +/* + * platform_name_for_id returns the name for a given platform id. returns NULL + * if not found. + */ +const char* platform_name_for_id(uint32_t platform_id) +{ + int count = sizeof(kPlatforms) / sizeof(*kPlatforms); + for (int i = 0; i < count; ++i) + { + if (platform_id == kPlatforms[i].platformid) + return kPlatforms[i].name; + } + return NULL; +} + +/* + * platform_vmlc_for_id returns a version min load command id for a given + * platform id. returns 0 if the platform is not found or if that platform does + * not have an associated version min load command. + */ +uint32_t platform_vmlc_for_id(uint32_t platform_id) +{ + int count = sizeof(kPlatforms) / sizeof(*kPlatforms); + for (int i = 0; i < count; ++i) + { + if (platform_id == kPlatforms[i].platformid) + return kPlatforms[i].vmlc; + } + return 0; +} + +/* + * Print a formatted version number where components are encoded into a + * uint32_t in nibbles: X.Y.Z => 0xXXXXYYZZ. If a 'label' is supplied, it will + * precede the version number and a newline will follow. + */ +void print_version_xyz(const char* label, uint32_t version) +{ + const char* space = " "; + const char* nl = "\n"; + if (label == NULL) + label = space = nl = ""; + if((version & 0xff) == 0) + printf("%s%s%u.%u%s", + label, + space, + version >> 16, + (version >> 8) & 0xff, + nl); + else + printf("%s%s%u.%u.%u%s", + label, + space, + version >> 16, + (version >> 8) & 0xff, + version & 0xff, + nl); +} + +/* + * print a version_min_command. The version_min_command structure + * specified must be aligned correctly and in the host byte sex. + */ +void print_version_min_command(struct version_min_command *vd) +{ + if(vd->cmd == LC_VERSION_MIN_MACOSX) + printf(" cmd LC_VERSION_MIN_MACOSX\n"); + else if(vd->cmd == LC_VERSION_MIN_IPHONEOS) + printf(" cmd LC_VERSION_MIN_IPHONEOS\n"); + else if(vd->cmd == LC_VERSION_MIN_WATCHOS) + printf(" cmd LC_VERSION_MIN_WATCHOS\n"); + else if(vd->cmd == LC_VERSION_MIN_TVOS) + printf(" cmd LC_VERSION_MIN_TVOS\n"); + else + printf(" cmd %u (?)\n", vd->cmd); + printf(" cmdsize %u", vd->cmdsize); + if(vd->cmdsize != sizeof(struct version_min_command)) + printf(" Incorrect size\n"); + else + printf("\n"); + print_version_xyz(" version", vd->version); + if(vd->sdk == 0) + printf(" sdk n/a\n"); + else + print_version_xyz(" sdk", vd->sdk); +} + +/* + * print a build_version_command. The build_version_command structure + * specified must be aligned correctly and in the host byte sex. + */ +void print_build_version_command(struct build_version_command *bv) +{ + if(bv->cmd == LC_BUILD_VERSION) + printf(" cmd LC_BUILD_VERSION\n"); + else + printf(" cmd %u (?)\n", bv->cmd); + printf(" cmdsize %u", bv->cmdsize); + if(bv->cmdsize != sizeof(struct build_version_command) + + bv->ntools * sizeof(struct build_tool_version)) + printf(" Incorrect size\n"); + else + printf("\n"); + + printf(" platform "); + switch(bv->platform){ + case PLATFORM_MACOS: + printf("MACOS\n"); + break; + case PLATFORM_IOS: + printf("IOS\n"); + break; + case PLATFORM_TVOS: + printf("TVOS\n"); + break; + case PLATFORM_WATCHOS: + printf("WATCHOS\n"); + break; + case PLATFORM_BRIDGEOS: + printf("BRIDGEOS\n"); + break; + case PLATFORM_MACCATALYST: + printf("MACCATALYST\n"); + break; + case PLATFORM_IOSSIMULATOR: + printf("IOSSIMULATOR\n"); + break; + case PLATFORM_TVOSSIMULATOR: + printf("TVOSSIMULATOR\n"); + break; + case PLATFORM_WATCHOSSIMULATOR: + printf("WATCHOSSIMULATOR\n"); + break; + case PLATFORM_DRIVERKIT: + printf("DRIVERKIT\n"); + break; + default: + printf("%u\n", bv->platform); + break; + } + + print_version_xyz(" minos", bv->minos); + if(bv->sdk == 0) + printf(" sdk n/a\n"); + else{ + print_version_xyz(" sdk", bv->sdk); + } + printf(" ntools %u\n", bv->ntools); +} + +void print_build_tool_version(uint32_t tool, uint32_t version) +{ + printf(" tool "); + switch(tool){ + case TOOL_CLANG: + printf("CLANG\n"); + break; + case TOOL_SWIFT: + printf("SWIFT\n"); + break; + case TOOL_LD: + printf("LD\n"); + break; + default: + printf("%u\n", tool); + break; + } + + print_version_xyz(" version", version); +} + +/* + * print a source_version_command. The source_version_command structure + * specified must be aligned correctly and in the host byte sex. + */ +void print_source_version_command(struct source_version_command *sv) +{ + uint64_t a, b, c, d, e; + + printf(" cmd LC_SOURCE_VERSION\n"); + printf(" cmdsize %u", sv->cmdsize); + if(sv->cmdsize != sizeof(struct source_version_command)) + printf(" Incorrect size\n"); + else + printf("\n"); + a = (sv->version >> 40) & 0xffffff; + b = (sv->version >> 30) & 0x3ff; + c = (sv->version >> 20) & 0x3ff; + d = (sv->version >> 10) & 0x3ff; + e = sv->version & 0x3ff; + if(e != 0) + printf(" version %llu.%llu.%llu.%llu.%llu\n", a, b, c, d, e); + else if(d != 0) + printf(" version %llu.%llu.%llu.%llu\n", a, b, c, d); + else if(c != 0) + printf(" version %llu.%llu.%llu\n", a, b, c); + else + printf(" version %llu.%llu\n", a, b); +} + +struct tool_entry { + uint32_t toolid; + const char* name; +}; + +static const struct tool_entry kTools[] = { + { TOOL_CLANG, "clang" }, + { TOOL_SWIFT, "swift" }, + { TOOL_LD, "ld" }, +}; + +/* + * tool_id_for_name returns a tool enum for a given name. returns 0 if + * not found. + */ + +uint32_t tool_id_for_name(const char* name) +{ + int count = sizeof(kTools) / sizeof(*kTools); + for (int i = 0; i < count; ++i) + { + if (name && 0 == strcmp(name, kTools[i].name)) + return kTools[i].toolid; + } + return 0; +} + +/* + * tool_name_for_id returns the name for a given tool id. returns NULL + * if not found. + */ +const char* tool_name_for_id(uint32_t tool_id) +{ + int count = sizeof(kTools) / sizeof(*kTools); + for (int i = 0; i < count; ++i) + { + if (tool_id == kTools[i].toolid) + return kTools[i].name; + } + return NULL; +} + +/* + * usage + */ +void usage(const char * __restrict format, ...) +{ + const char* basename = strrchr(gProgramName, '/'); + if (basename) + basename++; + else + basename = gProgramName; + + va_list args; + va_start(args, format); + + if (format) { + fprintf(stderr, "error: "); + vfprintf(stderr, format, args);; + fprintf(stderr, "\n"); + } + + va_end(args); + + int size = snprintf(NULL, 0, "%s", basename); + char* spaces = calloc(1, size + 1); + memset(spaces, ' ', size); + + fprintf(stderr, +"usage: %s [-arch ] ... \n", basename); + fprintf(stderr, +" %s [-arch ] ... ... [-replace] [-output ] " + "\n", basename); + fprintf(stderr, +" %s [-arch ] ... ... [-output ] \n", + basename); + fprintf(stderr, +" %s -help\n", basename); + fprintf(stderr, " show_command is exactly one of:\n"); + fprintf(stderr, " -show\n"); + fprintf(stderr, " -show-build\n"); + fprintf(stderr, " -show-source\n"); + fprintf(stderr, " -show-space\n"); + fprintf(stderr, " set_command is one or more of:\n"); + fprintf(stderr, " -set-build-version [-tool " + " ] ...\n"); + fprintf(stderr, " -set-build-tool \n"); + fprintf(stderr, " -set-version-min \n"); + fprintf(stderr, " -set-source-version \n"); + fprintf(stderr, " remove_command is one or more of:\n"); + fprintf(stderr, " -remove-build-version \n"); + fprintf(stderr, " -remove-build-tool \n"); + fprintf(stderr, " -remove-source-version\n"); + + if (gOptions.command == kCommandHelp) { +#if 0 + fprintf(stderr, " arch is one of:\n"); + for (const NXArchInfo* archInfo = NXGetAllArchInfos(); + archInfo->name; + ++archInfo) + { + fprintf(stderr, " %s\n", archInfo->name); + } +#endif + int count = sizeof(kPlatforms) / sizeof(*kPlatforms); + fprintf(stderr, " platform is one of:\n"); + for (uint32_t i = 0; i < count; ++i) { + fprintf(stderr, " %s\n", kPlatforms[i].name); + } + + count = sizeof(kTools) / sizeof(*kTools); + fprintf(stderr, " tool is one of:\n"); + for (uint32_t i = 0; i < count; ++i) { + fprintf(stderr, " %s\n", kTools[i].name); + } + + fprintf(stderr, + " platform and tool can also be specified by number\n"); + } + exit(EXIT_FAILURE); +} diff --git a/cctools/missing b/cctools/missing new file mode 100755 index 0000000..8d0eaad --- /dev/null +++ b/cctools/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 1996-2020 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=https://www.perl.org/ +flex_URL=https://github.com/westes/flex +gnu_software_URL=https://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/cctools/otool/Makefile.am b/cctools/otool/Makefile.am index bf37108..d20c085 100644 --- a/cctools/otool/Makefile.am +++ b/cctools/otool/Makefile.am @@ -8,7 +8,7 @@ else otool_LDADD = \ $(top_builddir)/libstuff/libstuff.la \ $(top_builddir)/libobjc2/libobjc.la \ -$(PTHREAD_FLAGS) $(CXXABI_LIB) $(DL_LIB) +$(PTHREAD_FLAGS) $(CXXABI_LIB) $(DL_LIB) $(REALLOCF_LIB) $(GCC_LIB) endif if ISDARWIN diff --git a/cctools/otool/Makefile.in b/cctools/otool/Makefile.in new file mode 100644 index 0000000..564c967 --- /dev/null +++ b/cctools/otool/Makefile.in @@ -0,0 +1,814 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = otool$(EXEEXT) +subdir = otool +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am__dirstamp = $(am__leading_dot)dirstamp +am_otool_OBJECTS = otool-main.$(OBJEXT) \ + $(top_builddir)/libstuff/otool-ofile.$(OBJEXT) \ + otool-ofile_print.$(OBJEXT) otool-m68k_disasm.$(OBJEXT) \ + otool-i860_disasm.$(OBJEXT) otool-m88k_disasm.$(OBJEXT) \ + otool-i386_disasm.$(OBJEXT) otool-ppc_disasm.$(OBJEXT) \ + otool-hppa_disasm.$(OBJEXT) otool-sparc_disasm.$(OBJEXT) \ + otool-arm_disasm.$(OBJEXT) otool-print_objc.$(OBJEXT) \ + otool-print_objc2_32bit.$(OBJEXT) \ + otool-print_objc2_64bit.$(OBJEXT) \ + otool-print_bitcode.$(OBJEXT) otool-coff_print.$(OBJEXT) \ + otool-arm64_disasm.$(OBJEXT) otool-dyld_bind_info.$(OBJEXT) +otool_OBJECTS = $(am_otool_OBJECTS) +am__DEPENDENCIES_1 = +@ISDARWIN_FALSE@otool_DEPENDENCIES = \ +@ISDARWIN_FALSE@ $(top_builddir)/libstuff/libstuff.la \ +@ISDARWIN_FALSE@ $(top_builddir)/libobjc2/libobjc.la \ +@ISDARWIN_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@ISDARWIN_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@ISDARWIN_FALSE@ $(am__DEPENDENCIES_1) +@ISDARWIN_TRUE@otool_DEPENDENCIES = \ +@ISDARWIN_TRUE@ $(top_builddir)/libstuff/libstuff.la \ +@ISDARWIN_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@ISDARWIN_TRUE@ $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +otool_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(otool_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__maybe_remake_depfiles = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(otool_SOURCES) +DIST_SOURCES = $(otool_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASLIBEXECDIR = @ASLIBEXECDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXABI_LIB = @CXXABI_LIB@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DL_LIB = @DL_LIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENDIAN_FLAG = @ENDIAN_FLAG@ +EXECINFO_LIB = @EXECINFO_LIB@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FTS_LIB = @FTS_LIB@ +GCC_LIB = @GCC_LIB@ +GREP = @GREP@ +HOST_AR = @HOST_AR@ +HOST_RANLIB = @HOST_RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_INCLUDE_DIR = @LLVM_INCLUDE_DIR@ +LLVM_LIB_DIR = @LLVM_LIB_DIR@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTO_DEF = @LTO_DEF@ +LTO_LIB = @LTO_LIB@ +LTO_RPATH = @LTO_RPATH@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MATH_LIB = @MATH_LIB@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCWARNINGS = @OBJCWARNINGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PTHREAD_FLAGS = @PTHREAD_FLAGS@ +RANLIB = @RANLIB@ +REALLOCF_LIB = @REALLOCF_LIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAPI_DEF = @TAPI_DEF@ +TAPI_LIB = @TAPI_LIB@ +UUID_LIB = @UUID_LIB@ +VERSION = @VERSION@ +WARNINGS = @WARNINGS@ +XAR_LIB = @XAR_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@ISDARWIN_FALSE@otool_LDADD = \ +@ISDARWIN_FALSE@$(top_builddir)/libstuff/libstuff.la \ +@ISDARWIN_FALSE@$(top_builddir)/libobjc2/libobjc.la \ +@ISDARWIN_FALSE@$(PTHREAD_FLAGS) $(CXXABI_LIB) $(DL_LIB) $(REALLOCF_LIB) $(GCC_LIB) + +@ISDARWIN_TRUE@otool_LDADD = \ +@ISDARWIN_TRUE@$(top_builddir)/libstuff/libstuff.la \ +@ISDARWIN_TRUE@$(PTHREAD_FLAGS) $(CXXABI_LIB) $(DL_LIB) -lobjc + +@ISDARWIN_FALSE@otool_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -I$(top_srcdir)/libstuff -I$(top_srcdir)/libobjc2 $(WARNINGS) $(LTO_DEF) -D_DARWIN_C_SOURCE -D__DARWIN_UNIX03 $(ENDIAN_FLAG) -DOTOOL -DEFI_SUPPORT +@ISDARWIN_TRUE@otool_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/foreign -I$(top_srcdir)/libstuff $(WARNINGS) $(LTO_DEF) -D_DARWIN_C_SOURCE -D__DARWIN_UNIX03 $(ENDIAN_FLAG) -DOTOOL -DEFI_SUPPORT +otool_SOURCES = \ + main.c \ + $(top_srcdir)/libstuff/ofile.c \ + ofile_print.c \ + m68k_disasm.c \ + i860_disasm.c \ + m88k_disasm.c \ + i386_disasm.c \ + ppc_disasm.c \ + hppa_disasm.c \ + sparc_disasm.c \ + arm_disasm.c \ + print_objc.c \ + print_objc2_32bit.c \ + print_objc2_64bit.c \ + print_bitcode.c \ + coff_print.c \ + arm64_disasm.c \ + dyld_bind_info.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps otool/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps otool/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +$(top_builddir)/libstuff/$(am__dirstamp): + @$(MKDIR_P) $(top_builddir)/libstuff + @: > $(top_builddir)/libstuff/$(am__dirstamp) +$(top_builddir)/libstuff/otool-ofile.$(OBJEXT): \ + $(top_builddir)/libstuff/$(am__dirstamp) + +otool$(EXEEXT): $(otool_OBJECTS) $(otool_DEPENDENCIES) $(EXTRA_otool_DEPENDENCIES) + @rm -f otool$(EXEEXT) + $(AM_V_CCLD)$(otool_LINK) $(otool_OBJECTS) $(otool_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f $(top_builddir)/libstuff/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +otool-main.o: main.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c + +otool-main.obj: main.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` + +$(top_builddir)/libstuff/otool-ofile.o: $(top_builddir)/libstuff/ofile.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o $(top_builddir)/libstuff/otool-ofile.o `test -f '$(top_builddir)/libstuff/ofile.c' || echo '$(srcdir)/'`$(top_builddir)/libstuff/ofile.c + +$(top_builddir)/libstuff/otool-ofile.obj: $(top_builddir)/libstuff/ofile.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o $(top_builddir)/libstuff/otool-ofile.obj `if test -f '$(top_builddir)/libstuff/ofile.c'; then $(CYGPATH_W) '$(top_builddir)/libstuff/ofile.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libstuff/ofile.c'; fi` + +otool-ofile_print.o: ofile_print.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-ofile_print.o `test -f 'ofile_print.c' || echo '$(srcdir)/'`ofile_print.c + +otool-ofile_print.obj: ofile_print.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-ofile_print.obj `if test -f 'ofile_print.c'; then $(CYGPATH_W) 'ofile_print.c'; else $(CYGPATH_W) '$(srcdir)/ofile_print.c'; fi` + +otool-m68k_disasm.o: m68k_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-m68k_disasm.o `test -f 'm68k_disasm.c' || echo '$(srcdir)/'`m68k_disasm.c + +otool-m68k_disasm.obj: m68k_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-m68k_disasm.obj `if test -f 'm68k_disasm.c'; then $(CYGPATH_W) 'm68k_disasm.c'; else $(CYGPATH_W) '$(srcdir)/m68k_disasm.c'; fi` + +otool-i860_disasm.o: i860_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-i860_disasm.o `test -f 'i860_disasm.c' || echo '$(srcdir)/'`i860_disasm.c + +otool-i860_disasm.obj: i860_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-i860_disasm.obj `if test -f 'i860_disasm.c'; then $(CYGPATH_W) 'i860_disasm.c'; else $(CYGPATH_W) '$(srcdir)/i860_disasm.c'; fi` + +otool-m88k_disasm.o: m88k_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-m88k_disasm.o `test -f 'm88k_disasm.c' || echo '$(srcdir)/'`m88k_disasm.c + +otool-m88k_disasm.obj: m88k_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-m88k_disasm.obj `if test -f 'm88k_disasm.c'; then $(CYGPATH_W) 'm88k_disasm.c'; else $(CYGPATH_W) '$(srcdir)/m88k_disasm.c'; fi` + +otool-i386_disasm.o: i386_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-i386_disasm.o `test -f 'i386_disasm.c' || echo '$(srcdir)/'`i386_disasm.c + +otool-i386_disasm.obj: i386_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-i386_disasm.obj `if test -f 'i386_disasm.c'; then $(CYGPATH_W) 'i386_disasm.c'; else $(CYGPATH_W) '$(srcdir)/i386_disasm.c'; fi` + +otool-ppc_disasm.o: ppc_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-ppc_disasm.o `test -f 'ppc_disasm.c' || echo '$(srcdir)/'`ppc_disasm.c + +otool-ppc_disasm.obj: ppc_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-ppc_disasm.obj `if test -f 'ppc_disasm.c'; then $(CYGPATH_W) 'ppc_disasm.c'; else $(CYGPATH_W) '$(srcdir)/ppc_disasm.c'; fi` + +otool-hppa_disasm.o: hppa_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-hppa_disasm.o `test -f 'hppa_disasm.c' || echo '$(srcdir)/'`hppa_disasm.c + +otool-hppa_disasm.obj: hppa_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-hppa_disasm.obj `if test -f 'hppa_disasm.c'; then $(CYGPATH_W) 'hppa_disasm.c'; else $(CYGPATH_W) '$(srcdir)/hppa_disasm.c'; fi` + +otool-sparc_disasm.o: sparc_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-sparc_disasm.o `test -f 'sparc_disasm.c' || echo '$(srcdir)/'`sparc_disasm.c + +otool-sparc_disasm.obj: sparc_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-sparc_disasm.obj `if test -f 'sparc_disasm.c'; then $(CYGPATH_W) 'sparc_disasm.c'; else $(CYGPATH_W) '$(srcdir)/sparc_disasm.c'; fi` + +otool-arm_disasm.o: arm_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-arm_disasm.o `test -f 'arm_disasm.c' || echo '$(srcdir)/'`arm_disasm.c + +otool-arm_disasm.obj: arm_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-arm_disasm.obj `if test -f 'arm_disasm.c'; then $(CYGPATH_W) 'arm_disasm.c'; else $(CYGPATH_W) '$(srcdir)/arm_disasm.c'; fi` + +otool-print_objc.o: print_objc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-print_objc.o `test -f 'print_objc.c' || echo '$(srcdir)/'`print_objc.c + +otool-print_objc.obj: print_objc.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-print_objc.obj `if test -f 'print_objc.c'; then $(CYGPATH_W) 'print_objc.c'; else $(CYGPATH_W) '$(srcdir)/print_objc.c'; fi` + +otool-print_objc2_32bit.o: print_objc2_32bit.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-print_objc2_32bit.o `test -f 'print_objc2_32bit.c' || echo '$(srcdir)/'`print_objc2_32bit.c + +otool-print_objc2_32bit.obj: print_objc2_32bit.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-print_objc2_32bit.obj `if test -f 'print_objc2_32bit.c'; then $(CYGPATH_W) 'print_objc2_32bit.c'; else $(CYGPATH_W) '$(srcdir)/print_objc2_32bit.c'; fi` + +otool-print_objc2_64bit.o: print_objc2_64bit.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-print_objc2_64bit.o `test -f 'print_objc2_64bit.c' || echo '$(srcdir)/'`print_objc2_64bit.c + +otool-print_objc2_64bit.obj: print_objc2_64bit.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-print_objc2_64bit.obj `if test -f 'print_objc2_64bit.c'; then $(CYGPATH_W) 'print_objc2_64bit.c'; else $(CYGPATH_W) '$(srcdir)/print_objc2_64bit.c'; fi` + +otool-print_bitcode.o: print_bitcode.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-print_bitcode.o `test -f 'print_bitcode.c' || echo '$(srcdir)/'`print_bitcode.c + +otool-print_bitcode.obj: print_bitcode.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-print_bitcode.obj `if test -f 'print_bitcode.c'; then $(CYGPATH_W) 'print_bitcode.c'; else $(CYGPATH_W) '$(srcdir)/print_bitcode.c'; fi` + +otool-coff_print.o: coff_print.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-coff_print.o `test -f 'coff_print.c' || echo '$(srcdir)/'`coff_print.c + +otool-coff_print.obj: coff_print.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-coff_print.obj `if test -f 'coff_print.c'; then $(CYGPATH_W) 'coff_print.c'; else $(CYGPATH_W) '$(srcdir)/coff_print.c'; fi` + +otool-arm64_disasm.o: arm64_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-arm64_disasm.o `test -f 'arm64_disasm.c' || echo '$(srcdir)/'`arm64_disasm.c + +otool-arm64_disasm.obj: arm64_disasm.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-arm64_disasm.obj `if test -f 'arm64_disasm.c'; then $(CYGPATH_W) 'arm64_disasm.c'; else $(CYGPATH_W) '$(srcdir)/arm64_disasm.c'; fi` + +otool-dyld_bind_info.o: dyld_bind_info.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-dyld_bind_info.o `test -f 'dyld_bind_info.c' || echo '$(srcdir)/'`dyld_bind_info.c + +otool-dyld_bind_info.obj: dyld_bind_info.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(otool_CFLAGS) $(CFLAGS) -c -o otool-dyld_bind_info.obj `if test -f 'dyld_bind_info.c'; then $(CYGPATH_W) 'dyld_bind_info.c'; else $(CYGPATH_W) '$(srcdir)/dyld_bind_info.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(top_builddir)/libstuff/$(am__dirstamp)" || rm -f $(top_builddir)/libstuff/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-binPROGRAMS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cctools/otool/arm64_disasm.c b/cctools/otool/arm64_disasm.c index 8009063..b02fa71 100644 --- a/cctools/otool/arm64_disasm.c +++ b/cctools/otool/arm64_disasm.c @@ -1,5 +1,6 @@ #include #include +#include /* cctools-port: For bcmp, bzero ... */ #include #include #include @@ -15,7 +16,7 @@ #include "arm64_disasm.h" #include "cxa_demangle.h" -struct disassemble_info { +static struct disassemble_info { /* otool(1) specific stuff */ enum bool verbose; /* Relocation information. */ @@ -28,7 +29,8 @@ struct disassemble_info { struct dyld_bind_info *dbi; uint64_t ndbi; /* Symbol table. */ - struct nlist_64 *symbols; + struct nlist *symbols; + struct nlist_64 *symbols64; uint32_t nsymbols; /* Symbols sorted by address. */ struct symbol *sorted_symbols; @@ -43,6 +45,7 @@ struct disassemble_info { enum byte_sex object_byte_sex; uint32_t *indirect_symbols; uint32_t nindirect_symbols; + cpu_type_t cputype; char *sect; uint32_t left; uint32_t addr; @@ -50,11 +53,12 @@ struct disassemble_info { uint64_t adrp_addr; uint32_t adrp_inst; char *object_addr; - uint32_t object_size; + uint64_t object_size; const char *class_name; const char *selector_name; char *method; char *demangled_name; + enum chain_format_t chain_format; } dis_info; /* @@ -81,7 +85,10 @@ struct LLVMOpInfo1 *op_info) if(r_symbolnum >= dis_info->nsymbols) return(0); - n_strx = dis_info->symbols[r_symbolnum].n_un.n_strx; + if(dis_info->cputype == CPU_TYPE_ARM64) + n_strx = dis_info->symbols64[r_symbolnum].n_un.n_strx; + else + n_strx = dis_info->symbols[r_symbolnum].n_un.n_strx; if(n_strx <= 0 || n_strx >= dis_info->strings_size) return(0); op_info->AddSymbol.Present = 1; @@ -162,7 +169,7 @@ void *TagBuf) return(0); /* First look in the section relocations if any. */ - sect_offset = Pc - dis_info->sect_addr; + sect_offset = (uint32_t)(Pc - dis_info->sect_addr); for(i = 0; i < dis_info->nrelocs; i++){ if(dis_info->relocs[i].r_address == sect_offset){ if(dis_info->relocs[i].r_type == ARM64_RELOC_ADDEND){ @@ -230,12 +237,14 @@ enum bool *cfstring) { enum byte_sex host_byte_sex; enum bool swapped; - uint32_t i, j, section_type; - uint64_t sect_offset, object_offset, pointer_value; + uint32_t i, j, section_type, pointer_value; + uint64_t sect_offset, object_offset, pointer_value64; const struct load_command *lc; struct load_command l; struct segment_command_64 sg64; struct section_64 s64; + struct segment_command sg; + struct section s; char *p; uint64_t big_load_end; @@ -279,10 +288,10 @@ enum bool *cfstring) sect_offset = value - s64.addr; object_offset = s64.offset + sect_offset; if(object_offset < object_size){ - memcpy(&pointer_value, object_addr + object_offset, + memcpy(&pointer_value64, object_addr + object_offset, sizeof(uint64_t)); if(swapped) - pointer_value = SWAP_LONG_LONG(pointer_value); + pointer_value64 = SWAP_LONG_LONG(pointer_value64); if(strncmp(s64.sectname, "__objc_selrefs", 16) == 0) *selref = TRUE; @@ -295,16 +304,70 @@ enum bool *cfstring) "__objc_msgrefs", 16) == 0 && value + 8 < s64.addr + s64.size){ *msgref = TRUE; - memcpy(&pointer_value, + memcpy(&pointer_value64, object_addr + object_offset + 8, sizeof(uint64_t)); if(swapped) - pointer_value = - SWAP_LONG_LONG(pointer_value); + pointer_value64 = + SWAP_LONG_LONG(pointer_value64); } else if(strncmp(s64.sectname, "__cfstring", 16) == 0) *cfstring = TRUE; + return(pointer_value64); + } + else + return(0); + } + } + break; + case LC_SEGMENT: + memcpy((char *)&sg, (char *)lc, + sizeof(struct segment_command)); + if(swapped) + swap_segment_command(&sg, host_byte_sex); + p = (char *)lc + sizeof(struct segment_command); + for(j = 0 ; j < sg.nsects ; j++){ + memcpy((char *)&s, p, sizeof(struct section)); + p += sizeof(struct section); + if(swapped) + swap_section(&s, 1, host_byte_sex); + section_type = s.flags & SECTION_TYPE; + if((strncmp(s.sectname, "__objc_selrefs", 16) == 0 || + strncmp(s.sectname, "__objc_classrefs", 16) == 0 || + strncmp(s.sectname, "__objc_superrefs", 16) == 0 || + strncmp(s.sectname, "__objc_msgrefs", 16) == 0 || + strncmp(s.sectname, "__cfstring", 16) == 0) && + value >= s.addr && value < s.addr + s.size){ + sect_offset = value - s.addr; + object_offset = s.offset + sect_offset; + if(object_offset < object_size){ + memcpy(&pointer_value, object_addr + object_offset, + sizeof(uint32_t)); + if(swapped) + pointer_value = SWAP_INT(pointer_value); + if(strncmp(s.sectname, + "__objc_selrefs", 16) == 0) + *selref = TRUE; + else if(strncmp(s.sectname, + "__objc_classrefs", 16) == 0 || + strncmp(s.sectname, + "__objc_superrefs", 16) == 0) + *classref = TRUE; + else if(strncmp(s.sectname, + "__objc_msgrefs", 16) == 0 && + value + 4 < s.addr + s.size){ + *msgref = TRUE; + memcpy(&pointer_value, + object_addr + object_offset + 4, + sizeof(uint32_t)); + if(swapped) + pointer_value = + SWAP_INT(pointer_value); + } + else if(strncmp(s.sectname, + "__cfstring", 16) == 0) + *cfstring = TRUE; return(pointer_value); } else @@ -440,7 +503,9 @@ struct disassemble_info *info) * And the pointer_value in that section is typically zero as it * will be set by dyld as part of the "bind information". */ - name = get_dyld_bind_info_symbolname(value, info->dbi, info->ndbi); + name = get_dyld_bind_info_symbolname(value, info->dbi, info->ndbi, + info->chain_format, + NULL); if(name != NULL){ *reference_type = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; @@ -455,28 +520,36 @@ struct disassemble_info *info) if(classref == TRUE){ *reference_type = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; - name = get_objc2_64bit_class_name(pointer_value, value, - info->load_commands, info->ncmds, info->sizeofcmds, - info->object_byte_sex, info->object_addr, - info->object_size, info->symbols, info->nsymbols, - info->strings, info->strings_size, CPU_TYPE_ARM64); - if(name != NULL) - info->class_name = name; - else - name = "bad class ref"; + if(info->cputype == CPU_TYPE_ARM64){ + name = get_objc2_64bit_class_name(pointer_value, value, + info->load_commands, info->ncmds, info->sizeofcmds, + info->object_byte_sex, info->object_addr, + info->object_size, info->symbols64, info->nsymbols, + info->strings, info->strings_size, CPU_TYPE_ARM64); + if(name != NULL) + info->class_name = name; + else + name = "bad class ref"; + } else { + name = "TODO: arm64_32 get_objc2_64_32bit_class_name()"; + } return(name); } if(cfstring == TRUE){ *reference_type = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref; - name = get_objc2_64bit_cfstring_name(value, - info->load_commands, info->ncmds, info->sizeofcmds, - info->object_byte_sex, info->object_addr, - info->object_size, info->symbols, info->nsymbols, - info->strings, info->strings_size, CPU_TYPE_ARM64); - if(name == NULL) - name = "bad cfstring ref"; + if(info->cputype == CPU_TYPE_ARM64){ + name = get_objc2_64bit_cfstring_name(value, + info->load_commands, info->ncmds, info->sizeofcmds, + info->object_byte_sex, info->object_addr, + info->object_size, info->symbols64, info->nsymbols, + info->strings, info->strings_size, CPU_TYPE_ARM64); + if(name == NULL) + name = "bad cfstring ref"; + } else { + name = "TODO: arm64_32 get_objc2_64_32bit_cfstring_name()"; + } return(name); } @@ -508,7 +581,7 @@ struct disassemble_info *info) name = guess_indirect_symbol(value, ncmds, sizeofcmds, load_commands, object_byte_sex, info->indirect_symbols,info->nindirect_symbols, - NULL, info->symbols, info->nsymbols, info->strings, + info->symbols, info->symbols64, info->nsymbols, info->strings, info->strings_size); if(name != NULL){ *reference_type = @@ -614,7 +687,7 @@ const char **ReferenceName) indirect_symbol_name = guess_indirect_symbol(SymbolValue, info->ncmds, info->sizeofcmds, info->load_commands, info->object_byte_sex, info->indirect_symbols, - info->nindirect_symbols, NULL, info->symbols, + info->nindirect_symbols, info->symbols, info->symbols64, info->nsymbols, info->strings, info->strings_size); if(indirect_symbol_name != NULL){ *ReferenceName = indirect_symbol_name; @@ -649,7 +722,7 @@ const char **ReferenceName) * we see and add immediate instruction. */ else if(*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP){ - info->adrp_inst = SymbolValue; + info->adrp_inst = (uint32_t)SymbolValue; info->adrp_addr = ReferencePC; symbol_name = NULL; *ReferenceName = NULL; @@ -667,7 +740,7 @@ const char **ReferenceName) ReferencePC - 4 == info->adrp_addr && (info->adrp_inst & 0x9f000000) == 0x90000000 && (info->adrp_inst & 0x1f) == ((SymbolValue >> 5) & 0x1f) ){ - uint32_t addxri_inst; + uint64_t addxri_inst; uint64_t adrp_imm, addxri_imm; adrp_imm = ((info->adrp_inst & 0x00ffffe0) >> 3) | @@ -700,7 +773,7 @@ const char **ReferenceName) ReferencePC - 4 == info->adrp_addr && (info->adrp_inst & 0x9f000000) == 0x90000000 && (info->adrp_inst & 0x1f) == ((SymbolValue >> 5) & 0x1f) ){ - uint32_t ldrxui_inst; + uint64_t ldrxui_inst; uint64_t adrp_imm, ldrxui_imm; adrp_imm = ((info->adrp_inst & 0x00ffffe0) >> 3) | @@ -761,6 +834,10 @@ cpu_subtype_t cpusubtype) if(*mcpu_default == '\0') mcpu_default = "cyclone"; break; + case CPU_SUBTYPE_ARM64E: + if(*mcpu_default == '\0') + mcpu_default = "vortex"; + break; } dc = @@ -801,7 +878,9 @@ struct relocation_info *loc_relocs, uint32_t nloc_relocs, struct dyld_bind_info *dbi, uint64_t ndbi, -struct nlist_64 *symbols, +enum chain_format_t chain_format, +struct nlist *symbols, +struct nlist_64 *symbols64, uint32_t nsymbols, struct symbol *sorted_symbols, uint32_t nsorted_symbols, @@ -809,11 +888,12 @@ char *strings, uint32_t strings_size, uint32_t *indirect_symbols, uint32_t nindirect_symbols, +cpu_type_t cputype, struct load_command *load_commands, uint32_t ncmds, uint32_t sizeofcmds, char *object_addr, -uint32_t object_size, +uint64_t object_size, enum bool verbose, LLVMDisasmContextRef dc) { @@ -825,7 +905,7 @@ LLVMDisasmContextRef dc) host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != object_byte_sex; - sect_offset = addr - sect_addr; + sect_offset = (uint32_t)(addr - sect_addr); if(left < sizeof(uint32_t)){ if(left != 0){ @@ -855,6 +935,7 @@ LLVMDisasmContextRef dc) dis_info.dbi = dbi; dis_info.ndbi = ndbi; dis_info.symbols = symbols; + dis_info.symbols64 = symbols64; dis_info.nsymbols = nsymbols; dis_info.sorted_symbols = sorted_symbols; dis_info.nsorted_symbols = nsorted_symbols; @@ -864,16 +945,18 @@ LLVMDisasmContextRef dc) dis_info.object_byte_sex = object_byte_sex; dis_info.indirect_symbols = indirect_symbols; dis_info.nindirect_symbols = nindirect_symbols; + dis_info.cputype = cputype; dis_info.ncmds = ncmds; dis_info.sizeofcmds = sizeofcmds; dis_info.object_addr = object_addr; dis_info.object_size = object_size; dis_info.sect = sect; dis_info.left = left; - dis_info.addr = addr; + dis_info.addr = (uint32_t)addr; dis_info.sect_addr = sect_addr; dis_info.method = NULL; dis_info.demangled_name = NULL; + dis_info.chain_format = chain_format; dst[4095] = '\0'; if(llvm_disasm_instruction(dc, (uint8_t *)sect, 4, addr, dst, 4095) != 0) diff --git a/cctools/otool/arm64_disasm.h b/cctools/otool/arm64_disasm.h index 4665cf9..affe6b5 100644 --- a/cctools/otool/arm64_disasm.h +++ b/cctools/otool/arm64_disasm.h @@ -19,6 +19,8 @@ extern uint32_t arm64_disassemble( uint32_t nloc_relocs, struct dyld_bind_info *dbi, uint64_t ndbi, + enum chain_format_t chain_format, + struct nlist *symbols, struct nlist_64 *symbols64, uint32_t nsymbols, struct symbol *sorted_symbols, @@ -27,11 +29,12 @@ extern uint32_t arm64_disassemble( uint32_t strings_size, uint32_t *indirect_symbols, uint32_t nindirect_symbols, + cpu_type_t cputype, struct load_command *load_commands, uint32_t ncmds, uint32_t sizeofcmds, char *object_addr, - uint32_t object_size, + uint64_t object_size, enum bool verbose, LLVMDisasmContextRef dc); diff --git a/cctools/otool/arm_disasm.c b/cctools/otool/arm_disasm.c index 8a2ea5d..e68d22e 100644 --- a/cctools/otool/arm_disasm.c +++ b/cctools/otool/arm_disasm.c @@ -64,7 +64,7 @@ typedef char bfd_byte; /* HACKS to avoid pulling in all of FSF binutils include/dis-asm.h */ typedef int (*fprintf_ftype) (void *, const char*, ...); -struct disassemble_info { /* HACK'ed up for just what we need here */ +static struct disassemble_info { /* HACK'ed up for just what we need here */ fprintf_ftype fprintf_func; void *stream; @@ -155,7 +155,7 @@ struct disassemble_info { /* HACK'ed up for just what we need here */ LLVMDisasmContextRef arm_dc; LLVMDisasmContextRef thumb_dc; char *object_addr; - uint32_t object_size; + uint64_t object_size; struct inst *inst; struct inst *insts; uint32_t ninsts; @@ -190,8 +190,8 @@ void *TagBuf) { struct disassemble_info *info; struct LLVMOpInfo1 *op_info; - unsigned int value; - int32_t low, high, mid, reloc_found, offset; + uint64_t value, offset; + int32_t low, high, mid, reloc_found; uint32_t sect_offset, i, r_address, r_symbolnum, r_type, r_extern, r_length, r_value, r_scattered, pair_r_type, pair_r_value; uint32_t other_half; @@ -213,7 +213,7 @@ void *TagBuf) info->verbose == FALSE) return(0); - sect_offset = Pc - info->sect_addr; + sect_offset = (uint32_t)(Pc - info->sect_addr); relocs = info->relocs; nrelocs = info->nrelocs; symbols = info->symbols; @@ -457,7 +457,7 @@ const uint32_t sizeofcmds, const struct load_command *load_commands, const enum byte_sex load_commands_byte_sex, const char *object_addr, -const uint32_t object_size) +const uint64_t object_size) { enum byte_sex host_byte_sex; enum bool swapped; @@ -673,7 +673,7 @@ struct disassemble_info *info) sect_addr = info->sect_addr; object_byte_sex = info->object_byte_sex; object_addr = info->object_addr; - object_size = info->object_size; + object_size = (uint32_t)info->object_size; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != object_byte_sex; @@ -849,7 +849,8 @@ const char **ReferenceName) } } else if(*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load){ - *ReferenceName = guess_literal_pointer(SymbolValue, ReferencePC, + *ReferenceName = guess_literal_pointer((uint32_t)SymbolValue, + (uint32_t)ReferencePC, ReferenceType, info); if(*ReferenceName == NULL) *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; @@ -4885,7 +4886,7 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little) unsigned int size = 4; void (*printer) (bfd_vma, struct disassemble_info *, int32_t); char *llvm_arch_name; - LLVMDisasmContextRef dc; + LLVMDisasmContextRef dc = NULL; #ifdef NOTDEF bfd_boolean found = FALSE; @@ -5793,7 +5794,7 @@ enum bool verbose, LLVMDisasmContextRef arm_dc, LLVMDisasmContextRef thumb_dc, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct data_in_code_entry *dices, uint32_t ndices, uint64_t seg_addr, @@ -5874,7 +5875,7 @@ uint32_t ninsts) /* Note: in final linked images, offset is from the base address */ /* Note: in object files, offset is from first section address */ if(nrelocs == 0) /* TODO better test for final linked image */ - offset = addr - seg_addr; + offset = (uint32_t)(addr - seg_addr); else offset = addr - sect_addr; for(i = 0; i < ndices; i++){ diff --git a/cctools/otool/arm_disasm.h b/cctools/otool/arm_disasm.h index 1b4407c..659b033 100644 --- a/cctools/otool/arm_disasm.h +++ b/cctools/otool/arm_disasm.h @@ -62,7 +62,7 @@ extern uint32_t arm_disassemble( LLVMDisasmContextRef arm_dc, LLVMDisasmContextRef thumb_dc, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct data_in_code_entry *dices, uint32_t ndices, uint64_t seg_addr, diff --git a/cctools/otool/coff_print.c b/cctools/otool/coff_print.c index b495cf4..63e7f11 100644 --- a/cctools/otool/coff_print.c +++ b/cctools/otool/coff_print.c @@ -45,7 +45,7 @@ uint32_t sizeofcmds, uint32_t filetype, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, enum bool verbose) { char *sect, *p; diff --git a/cctools/otool/dyld_bind_info.c b/cctools/otool/dyld_bind_info.c index de32b78..23a3274 100644 --- a/cctools/otool/dyld_bind_info.c +++ b/cctools/otool/dyld_bind_info.c @@ -1,43 +1,157 @@ #include +#include +#include #include #include #include +#include +#include /* cctools-port: reallocf() */ #include "dyld_bind_info.h" +#include "fixup-chains.h" + +/* cctools-port start */ +#undef swap16 +#undef swap32 +#undef swap64 +/* cctools-port end */ + +/***************************************************************************** + * + * LC_DYLD_INFO, LC_DYLD_INFO_ONLY + * + */ + +/* The entries of the ordinalTable for ThreadedRebaseBind. */ +struct ThreadedBindData { + const char* symbolName; + int64_t addend; + int libraryOrdinal; + uint8_t flags; + uint8_t type; +}; const char * bindTypeName( uint8_t type) { - switch(type){ - case BIND_TYPE_POINTER: - return("pointer"); - case BIND_TYPE_TEXT_ABSOLUTE32: - return("text abs32"); - case BIND_TYPE_TEXT_PCREL32: - return("text rel32"); - } - return("!!unknown!!"); + switch(type){ + case BIND_TYPE_POINTER: + return("pointer"); + case BIND_TYPE_TEXT_ABSOLUTE32: + return("text abs32"); + case BIND_TYPE_TEXT_PCREL32: + return("text rel32"); + } + return("!!Unknown!!"); } - +/* +static const char * ordinalName( int libraryOrdinal, const char **dylibs, -uint32_t ndylibs) +uint32_t ndylibs, +enum bool *libraryOrdinalSet) { - switch(libraryOrdinal){ - case BIND_SPECIAL_DYLIB_SELF: - return("this-image"); - case BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: - return("main-executable"); - case BIND_SPECIAL_DYLIB_FLAT_LOOKUP: - return("flat-namespace"); - } - if(libraryOrdinal < BIND_SPECIAL_DYLIB_FLAT_LOOKUP) - return("unknown special ordinal"); - if(libraryOrdinal > ndylibs) - return("libraryOrdinal out of range"); - return(dylibs[libraryOrdinal-1]); + *libraryOrdinalSet = TRUE; + switch(libraryOrdinal){ + case BIND_SPECIAL_DYLIB_SELF: + return("this-image"); + case BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: + return("main-executable"); + case BIND_SPECIAL_DYLIB_FLAT_LOOKUP: + return("flat-namespace"); + case BIND_SPECIAL_DYLIB_WEAK_LOOKUP: + return("weak"); + } + if(libraryOrdinal < BIND_SPECIAL_DYLIB_WEAK_LOOKUP){ + *libraryOrdinalSet = FALSE; + return("Unknown special ordinal"); + } + if(libraryOrdinal > ndylibs){ + *libraryOrdinalSet = FALSE; + return("LibraryOrdinal out of range"); + } + return(dylibs[libraryOrdinal-1]); +} +*/ +/* + * validateOrdinal validates a dylibOrdinal value as read from the LC_DYLD_INFO + * opcodes. If dylibOrdinal is valid, validateOrdinal will return TRUE and set + * dylibName to either the name of a dylib or to a human-readable special name. + * If dylibOrdinal is not valid, it will return FALSE and set error to a + * human-readable error string. error may be NULL. + */ +static +enum bool +validateOrdinal( +int dylibOrdinal, +const char **dylibs, +uint32_t ndylibs, +const char** dylibName, +const char** error) +{ + *dylibName = NULL; + if (error) + *error = NULL; + + if (dylibOrdinal < BIND_SPECIAL_DYLIB_WEAK_LOOKUP){ + if (error) + *error = "Unknown special ordinal"; + return FALSE; + } + if (dylibOrdinal > 0 && dylibOrdinal > ndylibs){ + if (error) + *error = "dylibOrdinal out of range"; + return FALSE; + } + + switch(dylibOrdinal){ + case BIND_SPECIAL_DYLIB_SELF: + *dylibName = "this-image"; + break; + case BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: + *dylibName = "main-executable"; + break; + case BIND_SPECIAL_DYLIB_FLAT_LOOKUP: + *dylibName = "flat-namespace"; + break; + case BIND_SPECIAL_DYLIB_WEAK_LOOKUP: + *dylibName = "weak"; + break; + default: + *dylibName = dylibs[dylibOrdinal-1]; + } + + return TRUE; +} + +/* + * validateSegIndex validates a segIndex value as read from the LC_DYLD_INFO + * opcodes. If segIndex is in range of the segs64 or segs arrays, + * validateSegIndex will return TRUE. Otherwise, it will return FALSE and set + * error to a human-readable error string. + */ +static +enum bool +validateSegIndex( +uint8_t segIndex, +struct segment_command **segs, +uint32_t nsegs, +struct segment_command_64 **segs64, +uint32_t nsegs64, +const char** error) +{ + *error = NULL; + if(segs64 != NULL && segIndex >= nsegs64) { + *error = "segment index out of range"; + return FALSE; + } + if(segs != NULL && segIndex >= nsegs) { + *error = "segment index out of range"; + return FALSE; + } + return TRUE; } uint64_t @@ -48,17 +162,17 @@ uint32_t nsegs, struct segment_command_64 **segs64, uint32_t nsegs64) { - if(segs != NULL){ - if(segIndex >= nsegs) - return(0); /* throw "segment index out of range"; */ - return(segs[segIndex]->vmaddr); - } - else if(segs64 != NULL){ - if(segIndex >= nsegs64) - return(0); /* throw "segment index out of range"; */ - return(segs64[segIndex]->vmaddr); - } - return(0); + if(segs != NULL){ + if(segIndex >= nsegs) + return(0); /* throw "segment index out of range"; */ + return(segs[segIndex]->vmaddr); + } + else if(segs64 != NULL){ + if(segIndex >= nsegs64) + return(0); /* throw "segment index out of range"; */ + return(segs64[segIndex]->vmaddr); + } + return(0); } const char * @@ -69,17 +183,17 @@ uint32_t nsegs, struct segment_command_64 **segs64, uint32_t nsegs64) { - if(segs != NULL){ - if(segIndex >= nsegs) - return("??"); /* throw "segment index out of range"; */ - return(segs[segIndex]->segname); - } - else if(segs64 != NULL){ - if(segIndex >= nsegs64) - return("??"); /* throw "segment index out of range"; */ - return(segs64[segIndex]->segname); - } - return("??"); + if(segs != NULL){ + if(segIndex >= nsegs) + return("??"); /* throw "segment index out of range"; */ + return(segs[segIndex]->segname); + } + else if(segs64 != NULL){ + if(segIndex >= nsegs64) + return("??"); /* throw "segment index out of range"; */ + return(segs64[segIndex]->segname); + } + return("??"); } const char * @@ -94,92 +208,308 @@ uint32_t nsegs64) struct section *s; struct section_64 *s64; uint32_t i; + + if(segs != NULL){ + if(segIndex >= nsegs) + return("??"); /* throw "segment index out of range"; */ + + s = (struct section *)((char *)segs[segIndex] + + sizeof(struct segment_command)); + for(i = 0; i < segs[segIndex]->nsects; i++){ + if(s->addr <= address && address < s->addr + s->size) + return(s->sectname); + s++; + } + } + else if(segs64 != NULL){ + if(segIndex >= nsegs64) + return("??"); /* throw "segment index out of range"; */ + + s64 = (struct section_64 *)((char *)segs64[segIndex] + + sizeof(struct segment_command_64)); + for(i = 0; i < segs64[segIndex]->nsects; i++){ + if(s64->addr <= address && address < s64->addr + s64->size) + return(s64->sectname); + s64++; + } + } + return("??"); +} - if(segs != NULL){ - if(segIndex >= nsegs) - return("??"); /* throw "segment index out of range"; */ - - s = (struct section *)((char *)segs[segIndex] + - sizeof(struct segment_command)); - for(i = 0; i < segs[segIndex]->nsects; i++){ - if(s->addr <= address && address < s->addr + s->size) - return(s->sectname); - s++; - } - } - else if(segs64 != NULL){ - if(segIndex >= nsegs64) - return("??"); /* throw "segment index out of range"; */ - - s64 = (struct section_64 *)((char *)segs64[segIndex] + - sizeof(struct segment_command_64)); - for(i = 0; i < segs64[segIndex]->nsects; i++){ - if(s64->addr <= address && address < s64->addr + s64->size) - return(s64->sectname); - s64++; - } - } - return("??"); +const char * +checkSegAndOffset( +int segIndex, +uint64_t segOffset, +struct segment_command **segs, +uint32_t nsegs, +struct segment_command_64 **segs64, +uint32_t nsegs64, +enum bool endInvalid) +{ + uint64_t address; + + if(segIndex == -1) + return("missing preceding BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB"); + if(segs != NULL){ + if(segIndex >= nsegs) + return("bad segIndex (too large)"); + address = segs[segIndex]->vmaddr + segOffset; + if(address > segs[segIndex]->vmaddr + segs[segIndex]->vmsize) + return("bad segOffset, too large"); + if(endInvalid == TRUE && + address == segs[segIndex]->vmaddr + segs[segIndex]->vmsize) + return("bad segOffset, too large"); + } + else if(segs64 != NULL){ + if(segIndex >= nsegs64) + return("bad segIndex (too large)"); + address = segs64[segIndex]->vmaddr + segOffset; + if(address > segs64[segIndex]->vmaddr + segs64[segIndex]->vmsize) + return("bad segOffset, too large"); + if(endInvalid == TRUE && + address == segs64[segIndex]->vmaddr + segs64[segIndex]->vmsize) + return("bad segOffset, too large"); + } + return(NULL); +} + +const char * +checkCountAndSkip( +uint32_t *count, +uint64_t skip, +int segIndex, +uint64_t segOffset, +struct segment_command **segs, +uint32_t nsegs, +struct segment_command_64 **segs64, +uint32_t nsegs64) +{ + uint64_t address, i; + + i = 0; + if(segs != NULL){ + if(segIndex >= nsegs){ + *count = 1; + return("bad segIndex (too large)"); + } + if(*count > 1) + i = (skip + 4) * (*count - 1); + address = segs[segIndex]->vmaddr + segOffset; + if(address >= segs[segIndex]->vmaddr + segs[segIndex]->vmsize){ + *count = 1; + return("bad segOffset, too large"); + } + if(address + i >= segs[segIndex]->vmaddr + segs[segIndex]->vmsize){ + *count = 1; + return("bad count and skip, too large"); + } + } + else if(segs64 != NULL){ + if(segIndex >= nsegs64){ + *count = 1; + return("bad segIndex (too large)"); + } + if(*count > 1) + i = (skip + 8) * (*count - 1); + address = segs64[segIndex]->vmaddr + segOffset; + if(address >= segs64[segIndex]->vmaddr + segs64[segIndex]->vmsize){ + *count = 1; + return("bad segOffset, too large"); + } + if(address + i >= + segs64[segIndex]->vmaddr + segs64[segIndex]->vmsize){ + *count = 1; + return("bad count and skip, too large"); + } + } + return(NULL); } static uint64_t read_uleb128( const uint8_t **pp, -const uint8_t* end) +const uint8_t* end, +const char **error) { const uint8_t *p = *pp; uint64_t result = 0; int bit = 0; - - do{ - if(p == end){ - *pp = p; - return(0); /* throwf("malformed uleb128"); */ - } - - uint64_t slice = *p & 0x7f; - - if(bit >= 64 || slice << bit >> bit != slice){ - *pp = p; - return(0); /* throwf("uleb128 too big"); */ - } - else { - result |= (slice << bit); - bit += 7; - } - }while(*p++ & 0x80); - *pp = p; - return(result); + + *error = NULL; + do{ + if(p >= end){ + *pp = p; + *error = "malformed uleb128, extends past opcode bytes"; + return(0); + } + + uint64_t slice = *p & 0x7f; + + if(bit >= 64 || slice << bit >> bit != slice){ + *pp = p; + *error = "uleb128 too big for uint64"; + return(0); + } + else { + result |= (slice << bit); + bit += 7; + } + }while(*p++ & 0x80); + *pp = p; + return(result); } static int64_t read_sleb128( const uint8_t **pp, -const uint8_t* end) +const uint8_t* end, +const char **error) { const uint8_t *p = *pp; int64_t result = 0; int bit = 0; uint8_t byte; - - do{ - if(p == end){ - *pp = p; - return(0); /* throwf("malformed sleb128"); */ - } - byte = *p++; - result |= (((int64_t)(byte & 0x7f)) << bit); - bit += 7; - }while (byte & 0x80); - // sign extend negative numbers - if((byte & 0x40) != 0) - result |= (-1LL) << bit; - *pp = p; - return(result); + + *error = NULL; + do{ + if(p == end){ + *pp = p; + *error = "malformed sleb128, extends past opcode bytes"; + return(0); + } + byte = *p++; + result |= (((int64_t)(byte & 0x7f)) << bit); + bit += 7; + }while (byte & 0x80); + // sign extend negative numbers + if((byte & 0x40) != 0) + result |= (-1LL) << bit; + *pp = p; + return(result); } +static inline +void +printErrorBind( +int pass, +enum bool verbose, +const char* opName, +unsigned long location, +const char* error, +uint32_t *errorCount) +{ + if (1 == pass && verbose && error) { + printf("bad bind info (for %s opcode at 0x%lx) %s\n", + opName, location, error); + } + errorCount++; +} + +static inline +void +printErrorOrdinal( +int pass, +enum bool verbose, +const char* opName, +unsigned long location, +int32_t ordinal, +uint32_t ndylibs, +const char* error, +uint32_t *errorCount) +{ + if (1 == pass && verbose && error) { + printf("bad bind info (for %s opcode at 0x%lx) bad library ordinal " + "%u (max %u): %s\n", + opName, location, ordinal, ndylibs, error); + } + errorCount +=1; +} + +static inline +void +printErrorOrdAddr( + int pass, + enum bool verbose, + const char* opName, + unsigned long location, + int32_t ordinal, + uint64_t ordAddr, + uint32_t *errorCount) +{ + if (1 == pass && verbose) { + printf("bad bind info (for %s opcode at 0x%lx) bad ordinal: %u in " + "pointer at address 0x%llx\n", + opName, location, ordinal, ordAddr); + } + errorCount +=1; +} + +static inline +void +printErrorBindType( +int pass, +enum bool verbose, +const char* opName, +unsigned long location, +uint8_t bindType, +uint32_t *errorCount) +{ + if (1 == pass && verbose) { + printf("bad bind info (for %s opcode at 0x%lx) " + "bad bind type: %u\n", + opName, location, bindType); + } + errorCount +=1; +} + +static inline +void +printErrorOffset( +int pass, +enum bool verbose, +const char* opName, +unsigned long location, +uint64_t address, +int reason, +uint32_t *errorCount) +{ + if (1 == pass && verbose) { + const char* error = "invalid"; + if (0 == reason) + error = "past end of file"; + else if (1 == reason) + error = "past end of the same page"; + printf("bad bind info (for %s opcode at: 0x%lx) offset to next pointer " + "in the chain after one at address 0x%llx is %s\n", + opName, location, address, error); + } + errorCount +=1; +} + +static inline +void +printErrorOpcode( +int pass, +enum bool verbose, +const char* opName, +unsigned long location, +uint8_t opcode, +uint32_t *errorCount) +{ + if (1 == pass && verbose) { + if (opName) + printf("bad bind info (for %s opcode at 0x%lx) bad sub-opcode " + "value 0x%x\n", + opName, location, opcode); + else + printf("bad bind info (for opcode at 0x%lx) bad opcode " + "value 0x%x\n", + location, opcode); + } + errorCount++; +} /* * get_dyld_bind_info() unpacks the dyld bind info from the data from an * LC_BIND_INFO load command pointed to by start through end into the internal @@ -187,10 +517,27 @@ const uint8_t* end) * of dylib names and their count are passed in in dylibs and ndylibs. The * array of segments (either 32-bit with segs & nsegs or 64-bit segs64 & nsegs64) * are used to determine which sections the pointers are in. + * + * A word about libraryOrdinal. The libraryOrdinal is a combination of array + * ordinals and special magic values: + * + * -3 BIND_SPECIAL_DYLIB_WEAK_LOOKUP + * -2 BIND_SPECIAL_DYLIB_FLAT_LOOKUP + * -1 BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE + * 0 BIND_SPECIAL_DYLIB_SELF + * [1..n] library ordinal + * + * The libraryOrdinal is commonly used to index into a C-array (that is, in + * the range [0, n-1]) of dylibs. Ordinarily, once libraryOrdinal is assigned + * one should call ordinalName to validate the ordinal. ordinalName will either + * set libraryOrdinalSet to TRUE and return a human-readable library or special + * name, or it will set libraryOrdinalSet to FALSE and return a human-readable + * error message. While all this sounds perfectly reasonable, there is a + * potential for mischief here ... */ void get_dyld_bind_info( -const uint8_t *start, /* inputs */ +const uint8_t* start, /* inputs */ const uint8_t* end, const char **dylibs, uint32_t ndylibs, @@ -198,184 +545,1184 @@ struct segment_command **segs, uint32_t nsegs, struct segment_command_64 **segs64, uint32_t nsegs64, +enum bool swapped, +char *object_addr, +uint64_t object_size, struct dyld_bind_info **dbi, /* output */ -uint64_t *ndbi) +uint64_t *ndbi, +enum chain_format_t *chain_format, +enum bool print_errors) { - const uint8_t *p; + const uint8_t *p, *opcode_start; uint8_t type; - uint8_t segIndex; + int segIndex; uint64_t segOffset; const char* symbolName; const char* fromDylib; + enum bool libraryOrdinalSet; int libraryOrdinal; int64_t addend; + int64_t flags; uint32_t count; uint32_t skip; uint64_t segStartAddr; const char* segName; - const char* typeName; const char* weak_import; enum bool done = FALSE; - - const char *sectName; - uint32_t pass; + const char *sectName, *error; +#define MAXERRORCOUNT 20 + uint32_t pass, errorCount; uint64_t n; - uint32_t sizeof_pointer; - if(segs) - sizeof_pointer = 4; - else - sizeof_pointer = 8; + char *pointerLocation; + uint64_t offset, ordinalTableCount, ordinalTableIndex, delta; + struct ThreadedBindData *ordinalTable; + uint16_t ordinal; + uint64_t pointerAddress, pointerPageStart; + const char* opName; + + *chain_format = CHAIN_FORMAT_NONE; + *dbi = NULL; + *ndbi = 0; + if (start == NULL) { + printf("missing dyld bind info.\n"); + return; + } + + ordinalTable = NULL; + ordinalTableCount = 0; + sizeof_pointer = segs ? 4 : 8; + errorCount = 0; n = 0; for(pass = 1; pass <= 2; pass++){ - p = start; - type = 0; - segIndex = 0; - segOffset = 0; - symbolName = NULL; - fromDylib = "??"; - libraryOrdinal = 0; - addend = 0; - segStartAddr = 0; - segName = "??"; - typeName = "??"; - weak_import = ""; - done = FALSE; - if(pass == 2){ - *dbi = (struct dyld_bind_info *) - allocate(n * sizeof(struct dyld_bind_info)); - *ndbi = n; - n = 0; - } - while(!done && (p < end)){ - uint8_t immediate = *p & BIND_IMMEDIATE_MASK; - uint8_t opcode = *p & BIND_OPCODE_MASK; - ++p; - switch(opcode){ - case BIND_OPCODE_DONE: - done = TRUE; - break; - case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: - libraryOrdinal = immediate; - fromDylib = ordinalName(libraryOrdinal, dylibs, ndylibs); - break; - case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: - libraryOrdinal = read_uleb128(&p, end); - fromDylib = ordinalName(libraryOrdinal, dylibs, ndylibs); - break; - case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: - // the special ordinals are negative numbers - if(immediate == 0) - libraryOrdinal = 0; - else { - int8_t signExtended = BIND_OPCODE_MASK | immediate; - libraryOrdinal = signExtended; - } - fromDylib = ordinalName(libraryOrdinal, dylibs, ndylibs); - break; - case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: - symbolName = (char*)p; - while(*p != '\0') - ++p; - ++p; - if((immediate & BIND_SYMBOL_FLAGS_WEAK_IMPORT) != 0) - weak_import = " (weak import)"; - else - weak_import = ""; - break; - case BIND_OPCODE_SET_TYPE_IMM: - type = immediate; - typeName = bindTypeName(type); - break; - case BIND_OPCODE_SET_ADDEND_SLEB: - addend = read_sleb128(&p, end); - break; - case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: - segIndex = immediate; - segStartAddr = segStartAddress(segIndex, segs, nsegs, - segs64, nsegs64); - segName = segmentName(segIndex, segs, nsegs, - segs64, nsegs64); - segOffset = read_uleb128(&p, end); - break; - case BIND_OPCODE_ADD_ADDR_ULEB: - segOffset += read_uleb128(&p, end); - break; - case BIND_OPCODE_DO_BIND: - sectName = sectionName(segIndex, segStartAddr + segOffset, - segs, nsegs, segs64, nsegs64); - if(pass == 2){ - (*dbi)[n].segname = segName; - (*dbi)[n].sectname = sectName; - (*dbi)[n].address = segStartAddr+segOffset; - (*dbi)[n].bind_type = type; - (*dbi)[n].addend = addend; - (*dbi)[n].dylibname = fromDylib; - (*dbi)[n].symbolname = symbolName; - (*dbi)[n].weak_import = *weak_import != '\0'; - } - n++; - segOffset += sizeof_pointer; - break; - case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: - sectName = sectionName(segIndex, segStartAddr + segOffset, - segs, nsegs, segs64, nsegs64); - if(pass == 2){ - (*dbi)[n].segname = segName; - (*dbi)[n].sectname = sectName; - (*dbi)[n].address = segStartAddr+segOffset; - (*dbi)[n].bind_type = type; - (*dbi)[n].addend = addend; - (*dbi)[n].dylibname = fromDylib; - (*dbi)[n].symbolname = symbolName; - (*dbi)[n].weak_import = *weak_import != '\0'; - } - n++; - segOffset += read_uleb128(&p, end) + sizeof_pointer; - break; - case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: - sectName = sectionName(segIndex, segStartAddr + segOffset, - segs, nsegs, segs64, nsegs64); - if(pass == 2){ - (*dbi)[n].segname = segName; - (*dbi)[n].sectname = sectName; - (*dbi)[n].address = segStartAddr+segOffset; - (*dbi)[n].bind_type = type; - (*dbi)[n].addend = addend; - (*dbi)[n].dylibname = fromDylib; - (*dbi)[n].symbolname = symbolName; - (*dbi)[n].weak_import = *weak_import != '\0'; - } - n++; - segOffset += immediate * sizeof_pointer + sizeof_pointer; - break; - case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: - count = read_uleb128(&p, end); - skip = read_uleb128(&p, end); - sectName = sectionName(segIndex, segStartAddr + segOffset, - segs, nsegs, segs64, nsegs64); - for (uint32_t i=0; i < count; ++i) { - if(pass == 2){ - (*dbi)[n].segname = segName; - (*dbi)[n].sectname = sectName; - (*dbi)[n].address = segStartAddr+segOffset; - (*dbi)[n].bind_type = type; - (*dbi)[n].addend = addend; - (*dbi)[n].dylibname = fromDylib; - (*dbi)[n].symbolname = symbolName; - (*dbi)[n].weak_import = *weak_import != '\0'; - } - n++; - segOffset += skip + sizeof_pointer; - } - break; - default: - return; /* throwf("bad bind opcode %d", *p); */ - } - } + p = start; + type = 0; + segIndex = -1; + segOffset = 0; + symbolName = NULL; + fromDylib = NULL; + libraryOrdinalSet = FALSE; + libraryOrdinal = 0; + addend = 0; + segStartAddr = 0; + segName = NULL; + sectName = NULL; + weak_import = ""; + done = FALSE; + ordinalTableIndex = (uint64_t)-1; + flags = 0; + if(errorCount >= MAXERRORCOUNT){ + if(print_errors) + printf("too many bind info errors, giving up.\n"); + *dbi = NULL; + *ndbi = 0; + if(ordinalTable != NULL) + free(ordinalTable); + return; + } + if(pass == 2){ + *dbi = (struct dyld_bind_info *) + allocate(n * sizeof(struct dyld_bind_info)); + memset(*dbi, 0, n * sizeof(struct dyld_bind_info)); + *ndbi = n; + n = 0; + } + while(!done && (p < end) && errorCount < MAXERRORCOUNT){ + error = NULL; + opcode_start = p; + uint8_t immediate = *p & BIND_IMMEDIATE_MASK; + uint8_t opcode = *p & BIND_OPCODE_MASK; + opcode = *p & BIND_OPCODE_MASK; + ++p; + switch(opcode){ + case BIND_OPCODE_DONE: + done = TRUE; + break; + case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: + /* + * consume: immediate + * produce: libraryOrdinal, libraryOrdinalSet, fromDylib + */ + opName = "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM"; + libraryOrdinal = immediate; + libraryOrdinalSet = validateOrdinal(libraryOrdinal, + dylibs, ndylibs, + &fromDylib, &error); + if (FALSE == libraryOrdinalSet) + printErrorOrdinal(pass, print_errors, opName, + opcode_start - start, + libraryOrdinal, ndylibs, + error, &errorCount); + break; + case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: + /* + * consume: p, end + * produce: libraryOrdinal, libraryOrdinalSet, fromDylib, + * error + */ + opName = "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB"; + libraryOrdinal = (int)read_uleb128(&p, end, &error); + if (error) { + libraryOrdinalSet = FALSE; + } + else { + libraryOrdinalSet = validateOrdinal(libraryOrdinal, + dylibs, ndylibs, + &fromDylib, &error); + } + if (FALSE == libraryOrdinalSet) + printErrorOrdinal(pass, print_errors, opName, + opcode_start - start, + libraryOrdinal, ndylibs, + error, &errorCount); + break; + case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: + /* + * consume: immediate + * produce: libraryOrdinal, libraryOrdinalSet, fromDylib + * + * the special ordinals are in the range of [-3, 0] + */ + opName = "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM"; + if (immediate == 0) { + libraryOrdinal = 0; + } + else { + int8_t signExtended = BIND_OPCODE_MASK | immediate; + libraryOrdinal = signExtended; + } + libraryOrdinalSet = validateOrdinal(libraryOrdinal, + dylibs, ndylibs, + &fromDylib, &error); + if (FALSE == libraryOrdinalSet) + printErrorOrdinal(pass, print_errors, opName, + opcode_start - start, + libraryOrdinal, ndylibs, + error, &errorCount); + break; + case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: + /* + * consume: p, end, immediate + * produce: p, symbolName, flags, weak_import + */ + opName = "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM"; + weak_import = ""; + symbolName = (char*)p; + while(*p != '\0' && (p < end)) + ++p; + if(p == end){ + error = "symbol name extends past opcodes"; + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + /* + * Even though the name does not end with a '\0' it will + * not be used as it is past the opcodes so there can't + * be a BIND opcode that follows that will use it. + */ + } + else { + /* string terminator */ + ++p; + } + flags = immediate; + if((flags & BIND_SYMBOL_FLAGS_WEAK_IMPORT) != 0) + weak_import = " (weak import)"; + break; + case BIND_OPCODE_SET_TYPE_IMM: + /* + * consume: immediate + * produce: type + */ + opName = "BIND_OPCODE_SET_TYPE_IMM"; + if (immediate == 0 || immediate > BIND_TYPE_TEXT_PCREL32) { + printErrorBindType(pass, print_errors, opName, + opcode_start - start, + immediate, &errorCount); + type = 0; + } + else { + type = immediate; + } + break; + case BIND_OPCODE_SET_ADDEND_SLEB: + /* + * consume: p, end + * produce: addend, error + */ + opName = "BIND_OPCODE_SET_ADDEND_SLEB"; + addend = read_sleb128(&p, end, &error); + if (error) { + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + addend = 0; + } + break; + case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: + /* + * consume: immediate + * produce: segIndex, segStartAddr, segName, segOffset, + * error + */ + opName = "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB"; + if (validateSegIndex(immediate, segs, nsegs, + segs64, nsegs64, &error)) + { + segOffset = read_uleb128(&p, end, &error); + } + if (!error) { + segIndex = immediate; + segStartAddr = segStartAddress(segIndex, segs, nsegs, + segs64, nsegs64); + segName = segmentName(segIndex, segs, nsegs, + segs64, nsegs64); + error = checkSegAndOffset(segIndex, segOffset, + segs, nsegs, + segs64, nsegs64, TRUE); + } + if (error) { + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + segIndex = -1; + segStartAddr = 0; + segName = NULL; + segOffset = 0; + error = NULL; + } + break; + case BIND_OPCODE_ADD_ADDR_ULEB: + /* + * consume: p, end, segOffset + * produce: segOffset, error + */ + opName = "BIND_OPCODE_ADD_ADDR_ULEB"; + error = NULL; + if (-1 == segIndex) { + error = "segment index is invalid"; + } + if (!error) { + segOffset += read_uleb128(&p, end, &error); + } + if (!error) { + error = checkSegAndOffset(segIndex, segOffset, + segs, nsegs, + segs64, nsegs64, TRUE); + } + if (error) { + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + segIndex = -1; + segName = NULL; + segStartAddr = 0; + segOffset = 0; + error = NULL; + } + break; + case BIND_OPCODE_DO_BIND: + /* + * consume: segIndex, segOffset, symbolName, + * libraryOrdinalSet, ordinalTableIndex, + * ordinalTableCount, ordinalTable, libraryOrdinal, + * addend, flags, type, segName, segStartAddr, + * fromDylib, weak_import + * produce: sectName, segOffset, dbi + */ + opName = "BIND_OPCODE_DO_BIND"; + /* start by doing all of the validations */ + if(CHAIN_FORMAT_NONE == *chain_format) + { + error = checkSegAndOffset(segIndex, segOffset, segs, + nsegs, segs64, nsegs64, TRUE); + if (error) { + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, + &errorCount); + segIndex = -1; + segName = NULL; + segStartAddr = 0; + segOffset = 0; + sectName = NULL; + } + else { + sectName = sectionName(segIndex, + segStartAddr + segOffset, + segs, nsegs, + segs64, nsegs64); + } + } + if (NULL == symbolName) { + error = "missing preceding BIND_OPCODE_SET_SYMBOL_" + "TRAILING_FLAGS_IMM opcode"; + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + } + if (FALSE == libraryOrdinalSet){ + error = "missing preceding BIND_OPCODE_SET_DYLIB_" + "ORDINAL_* opcode"; + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + } + if(CHAIN_FORMAT_ARM64E == *chain_format){ + /* + * At this point ordinalTableIndex should not equal + * ordinalTableCount or we have seen too many + * BIND_OPCODE_DO_BIND opcodes and that does not match + * the ordinalTableCount. + */ + if(ordinalTableIndex >= ordinalTableCount){ + error = "incorrect ordinal table size: number of " + "BIND_OPCODE_DO_BIND opcodes exceed the count in " + "previous BIND_SUBOPCODE_THREADED_SET_BIND_" + "ORDINAL_TABLE_SIZE_ULEB opcode"; + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, + &errorCount); + } + + /* + * The ordinalTable needs to be built regardless of + * success or failure. + */ + const uint64_t oti = ordinalTableIndex++; + ordinalTable[oti].symbolName = symbolName; + ordinalTable[oti].addend = addend; + ordinalTable[oti].libraryOrdinal + = libraryOrdinalSet ? libraryOrdinal : 0; + ordinalTable[oti].flags = flags; + ordinalTable[oti].type = type; + } + else + { + if(pass == 2){ + char* segname = strdup(segName ? segName : "??"); + char* sectname = strdup(sectName ? sectName : "??"); + if (strlen(segname)>16) + segname[16] = 0; + if (strlen(sectname)>16) + sectname[16] = 0; + (*dbi)[n].segname = segname; + (*dbi)[n].sectname = sectname; + (*dbi)[n].address = segStartAddr + segOffset; + (*dbi)[n].bind_type = type; + (*dbi)[n].addend = addend; + (*dbi)[n].dylibname = fromDylib ? fromDylib : "??"; + (*dbi)[n].symbolname = (symbolName ? symbolName : + "Symbol name not set"); + (*dbi)[n].weak_import = *weak_import != '\0'; + (*dbi)[n].pointer_value = 0; + } + n++; + segOffset += sizeof_pointer; + } + break; + case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: + /* + * consume: segIndex, segOffset, symbolName, + * libraryOrdinalSet, ordinalTableIndex, + * ordinalTableCount, ordinalTable, libraryOrdinal, + * addend, flags, type, segName, segStartAddr, + * fromDylib, weak_import + * produce: sectName, segOffset, dbi + */ + opName = "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB"; + error = checkSegAndOffset(segIndex, segOffset, segs, nsegs, + segs64, nsegs64, TRUE); + if (error) { + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + segIndex = -1; + segName = NULL; + segStartAddr = 0; + segOffset = 0; + sectName = NULL; + } + else { + sectName = sectionName(segIndex, segStartAddr+segOffset, + segs, nsegs, segs64, nsegs64); + } + if (NULL == symbolName) { + error = "missing preceding BIND_OPCODE_SET_SYMBOL_" + "TRAILING_FLAGS_IMM opcode"; + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + } + if (FALSE == libraryOrdinalSet){ + error = "missing preceding BIND_OPCODE_SET_DYLIB_" + "ORDINAL_* opcode"; + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + } + if(2 == pass){ + char* segname = strdup(segName ? segName : "??"); + char* sectname = strdup(sectName ? sectName : "??"); + if (strlen(segname)>16) + segname[16] = 0; + if (strlen(sectname)>16) + sectname[16] = 0; + (*dbi)[n].segname = segname; + (*dbi)[n].sectname = sectname; + (*dbi)[n].address = segStartAddr+segOffset; + (*dbi)[n].bind_type = type; + (*dbi)[n].addend = addend; + (*dbi)[n].dylibname = fromDylib ? fromDylib : "??"; + (*dbi)[n].symbolname = (symbolName ? symbolName : + "Symbol name not set"); + (*dbi)[n].weak_import = *weak_import != '\0'; + (*dbi)[n].pointer_value = 0; + } + n++; + segOffset += read_uleb128(&p, end, &error) + sizeof_pointer; + if (error) { + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + segIndex = -1; + segName = NULL; + segStartAddr = 0; + segOffset = 0; + sectName = NULL; + } + /* + * Note, this is not really an error until the next bind + * but make so sense for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB + * to not be followed by another bind operation. + */ + error = checkSegAndOffset(segIndex, segOffset, segs, nsegs, + segs64, nsegs64, FALSE); + if (error) { + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + segIndex = -1; + segName = NULL; + segStartAddr = 0; + segOffset = 0; + sectName = NULL; + } + break; + case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: + /* + * consume: segIndex, segOffset, symbolName, + * libraryOrdinalSet, ordinalTableIndex, + * ordinalTableCount, ordinalTable, libraryOrdinal, + * addend, flags, type, segName, segStartAddr, + * fromDylib, weak_import + * produce: sectName, segOffset, dbi + */ + opName = "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED"; + error = checkSegAndOffset(segIndex, segOffset, segs, nsegs, + segs64, nsegs64, TRUE); + if (error) { + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + segIndex = -1; + segName = NULL; + segStartAddr = 0; + segOffset = 0; + sectName = NULL; + } + else { + sectName = sectionName(segIndex, segStartAddr+segOffset, + segs, nsegs, segs64, nsegs64); + } + if (NULL == symbolName) { + error = "missing preceding BIND_OPCODE_SET_SYMBOL_" + "TRAILING_FLAGS_IMM opcode"; + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + } + if (FALSE == libraryOrdinalSet){ + error = "missing preceding BIND_OPCODE_SET_DYLIB_" + "ORDINAL_* opcode"; + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + } + if(2 == pass){ + char* segname = strdup(segName ? segName : "??"); + char* sectname = strdup(sectName ? sectName : "??"); + if (strlen(segname)>16) + segname[16] = 0; + if (strlen(sectname)>16) + sectname[16] = 0; + (*dbi)[n].segname = segname; + (*dbi)[n].sectname = sectname; + (*dbi)[n].address = segStartAddr+segOffset; + (*dbi)[n].bind_type = type; + (*dbi)[n].addend = addend; + (*dbi)[n].dylibname = fromDylib ? fromDylib : "??"; + (*dbi)[n].symbolname = (symbolName ? symbolName : + "Symbol name not set"); + (*dbi)[n].weak_import = *weak_import != '\0'; + (*dbi)[n].pointer_value = 0; + } + n++; + segOffset += immediate * sizeof_pointer + sizeof_pointer; + /* + * Note, this is not really an error until the next bind + * but make so sense for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB + * to not be followed by another bind operation. + */ + error = checkSegAndOffset(segIndex, segOffset, segs, nsegs, + segs64, nsegs64, FALSE); + if (error) { + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + segIndex = -1; + segName = NULL; + segStartAddr = 0; + segOffset = 0; + sectName = NULL; + } + break; + case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: + /* + * consume: p, end, segIndex, segOffset,symbolName, + * libraryOrdinalSet, fromDylib, + * produce: count, skip, sectName + */ + opName = "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB"; + count = (uint32_t)read_uleb128(&p, end, &error); + if (error) { + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + count = 0; + } + skip = (uint32_t)read_uleb128(&p, end, &error); + if (error) { + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + skip = 0; + } + error = checkSegAndOffset(segIndex, segOffset, segs, nsegs, + segs64, nsegs64, TRUE); + if (error) { + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + segIndex = -1; + segName = NULL; + segStartAddr = 0; + segOffset = 0; + sectName = NULL; + } + else { + sectName = sectionName(segIndex, segStartAddr + segOffset, + segs, nsegs, segs64, nsegs64); + } + if (NULL == symbolName) { + error = "missing preceding BIND_OPCODE_SET_SYMBOL_" + "TRAILING_FLAGS_IMM opcode"; + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + } + if (FALSE == libraryOrdinalSet){ + error = "missing preceding BIND_OPCODE_SET_DYLIB_" + "ORDINAL_* opcode"; + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + } + error = checkCountAndSkip(&count, skip, segIndex, + segOffset, segs, nsegs, + segs64, nsegs64); + if (error) { + printErrorBind(pass, print_errors, opName, + opcode_start-start, error, &errorCount); + segIndex = -1; + segName = NULL; + segStartAddr = 0; + segOffset = 0; + sectName = NULL; + } + for (uint32_t i=0; i < count; ++i) { + if(2 == pass){ + char* segname = strdup(segName ? segName : "??"); + char* sectname = strdup(sectName ? sectName : "??"); + if (strlen(segname)>16) + segname[16] = 0; + if (strlen(sectname)>16) + sectname[16] = 0; + (*dbi)[n].segname = segname; + (*dbi)[n].sectname = sectname; + (*dbi)[n].address = segStartAddr+segOffset; + (*dbi)[n].bind_type = type; + (*dbi)[n].addend = addend; + (*dbi)[n].dylibname = fromDylib ? fromDylib : "??"; + (*dbi)[n].symbolname = (symbolName ? symbolName : + "Symbol name not set"); + (*dbi)[n].weak_import = *weak_import != '\0'; + (*dbi)[n].pointer_value = 0; + } + n++; + if (-1 != segIndex) + segOffset += skip + sizeof_pointer; + } + break; + case BIND_OPCODE_THREADED: + /* Note the immediate is a sub opcode */ + /* + * [MDT: Giving up on 80 column formatting here... ] + */ + switch(immediate){ + case BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB: + /* + * consume: p, end + * produce: ordinalTableCount, ordinalTableIndex, + * ordinalTable, chain_format + */ + opName = "BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB"; + ordinalTableCount = read_uleb128(&p, end, &error); + if (error) { + printErrorBind(pass, print_errors, opName, opcode_start - start, error, &errorCount); + ordinalTableCount = 0; + ordinalTableIndex = (uint64_t)-1; + } + else { + ordinalTableIndex = 0; + } + ordinalTable = reallocate(ordinalTable, sizeof(struct ThreadedBindData) * ordinalTableCount); + *chain_format = CHAIN_FORMAT_ARM64E; + break; + case BIND_SUBOPCODE_THREADED_APPLY: + /* + * consume: ordinalTableIndex, ordinalTableCount, + * ordinalTable, segIndex, segOffset, + * segAddr, + * produce: sectName, offset, pointerAddress, + * pointerPageStart, pointerLocation, + * delta, ordinal, + */ + opName = "BIND_SUBOPCODE_THREADED_APPLY"; + /* + * At this point ordinalTableIndex should equal + * ordinalTableCount or we have a mismatch between + * BIND_OPCODE_DO_BIND and ordinalTableCount. + */ + if(ordinalTableIndex != ordinalTableCount){ + error = ("incorrect ordinal table size: count of previous " + "BIND_OPCODE_DO_BIND opcodes don't match count in previous " + "BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB opcodes"); + printErrorBind(pass, print_errors, opName, opcode_start - start, error, &errorCount); + } + /* + * We check for segOffset + 8 as we need to read a + * 64-bit pointer. + */ + error = checkSegAndOffset(segIndex, segOffset, segs, nsegs, segs64, nsegs64, FALSE); + if (error) { + printErrorBind(pass, print_errors, opName, opcode_start-start, error, &errorCount); + segIndex = -1; + segName = NULL; + segStartAddr = 0; + segOffset = 0; + sectName = NULL; + } + else { + sectName = sectionName(segIndex, segStartAddr + segOffset, segs, nsegs, segs64, nsegs64); + } + /* + * Check segStartAddr + segOffset is 8-byte aligned. + */ + if(((segStartAddr + segOffset) & 0x3) != 0){ + error = "bad segOffset, not 8-byte aligned"; + printErrorBind(pass, print_errors, opName, opcode_start - start, error, &errorCount); + } + /* + * This is a start a new thread of Rebase/Bind + * pointer chain from the previously set segIndex + * and segOffset. Record these locations even if + * misaligned. Do not record these locations if + * segIndex is invalid. + */ + if (-1 != segIndex) { + offset = segs64[segIndex]->fileoff + segOffset; + pointerAddress = segs64[segIndex]->vmaddr + segOffset; + pointerPageStart = pointerAddress & ~0x3fff; + delta = 0; + do{ + uint64_t value; + enum bool isRebase; + pointerLocation = object_addr + offset; + value = *(uint64_t *)pointerLocation; + if(swapped) + value = SWAP_LONG_LONG(value); + isRebase = (value & (1ULL << 62)) == 0; + if(isRebase){ + /* not doing anything with Rebase, + only bind so no code here. */ + ; + } else { + /* the ordinal is bits are [0..15] */ + ordinal = value & 0xFFFF; + if(ordinal >= ordinalTableCount){ + printErrorOrdAddr(pass, print_errors, opName, opcode_start - start, + ordinal, pointerAddress, &errorCount); + break; + } + libraryOrdinal = ordinalTable[ordinal].libraryOrdinal; + if (!validateOrdinal(libraryOrdinal, dylibs, ndylibs, &fromDylib, &error)) { + printErrorOrdinal(pass, print_errors, opName, opcode_start - start, libraryOrdinal, ndylibs, error, &errorCount); + break; + } + flags = ordinalTable[ordinal].flags; + if((flags & BIND_SYMBOL_FLAGS_WEAK_IMPORT) != 0) + weak_import = " (weak import)"; + else + weak_import = ""; + if(pass == 2){ + char* segname = strdup(segName ? segName : "??"); + char* sectname = strdup(sectName ? sectName : "??"); + if (strlen(segname)>16) + segname[16] = 0; + if (strlen(sectname)>16) + sectname[16] = 0; + (*dbi)[n].segname = segname; + (*dbi)[n].sectname = sectname; + (*dbi)[n].address = segStartAddr+segOffset; + (*dbi)[n].bind_type = ordinalTable[ordinal].type; + (*dbi)[n].addend = ordinalTable[ordinal].addend; + (*dbi)[n].dylibname = fromDylib; + (*dbi)[n].symbolname = ordinalTable[ordinal].symbolName; + (*dbi)[n].weak_import = *weak_import != '\0'; + (*dbi)[n].pointer_value = value; + } + n++; + } + + /* + * Now on to the next pointer in the chain if there + * is one. + */ + /* The delta is bits [51..61] */ + /* And bit 62 is to tell us if we are a rebase (0) + or bind (1) */ + value &= ~(1ULL << 62); + delta = (value & 0x3FF8000000000000) >> 51; + /* + * If the delta is zero there is no next pointer so + * don't check the offset to the next pointer. + */ + if(delta == 0) + break; + segOffset += delta * 8; /* sizeof(pint_t); */ + /* + * Want to check that the segOffset plus 8 is not + * past the end of this file and on the same page + * in this segment so we can get the next pointer + * in this thread. + */ + offset = segs64[segIndex]->fileoff + segOffset; + pointerAddress = segs64[segIndex]->vmaddr + + segOffset; + if(offset + 8 > object_size){ + printErrorOffset(pass, print_errors, opName, opcode_start - start, + pointerAddress, 0, &errorCount); + break; + } + if(pointerPageStart != (pointerAddress & ~0x3fff)){ + printErrorOffset(pass, print_errors, opName, opcode_start - start, + pointerAddress, 1, &errorCount); + break; + } + } while(delta != 0); + } + break; + default: + printErrorOpcode(pass, print_errors, opName, + opcode_start - start, immediate, + &errorCount); + done = TRUE; + break; + } + break; + default: + printErrorOpcode(pass, print_errors, NULL, + opcode_start - start, opcode, &errorCount); + done = TRUE; + break; + } + } + } + if(ordinalTable != NULL) + free(ordinalTable); +} + +/* + * print_dyld_rebase_opcodes() prints the raw contents of the DYLD_INFO rebase + * data. Its purpose is to "disassemble" the contents of the opcode stream, + * not to interpret the data. It is resilient to errors in the data, making it + * useful for debugging malformed binaries. + * + * opcodes are printed in a concise table of data: + * + * index, file offset, raw byte, symbolic opcode and opcode-specific data + * + * this format differs from dyldinfo(1) slightly, in that the offset is + * relative to the start of mach_header, rather than to the start of the + * opcode stream. Meaning, this output can be compared directly with commands + * such as hexdump(1). + */ +extern +void +print_dyld_rebase_opcodes( +const uint8_t* object_addr, +uint64_t object_size, +uint32_t offset, +uint32_t size) +{ + if (offset > object_size) { + printf("rebase offset %u beyond the size of file %llu\n", + offset, object_size); + return; + } + if (offset + size > object_size) { + printf("rebase offset + size %u beyond the size of file %llu\n", + offset + size, object_size); + size = (uint32_t)(offset - object_size); } + const uint8_t* p = object_addr + offset; + const uint8_t* end = object_addr + offset + size; + enum bool done = FALSE; + uint32_t idx = 0; + + printf("rebase opcodes:\n"); + printf(" %4s %-10s %4s %s\n", "idx", "offset", "byte", "opcode"); + + while (!done) + { + uint32_t poffset = (uint32_t)(p - object_addr); + idx++; + + if (poffset >= object_size) { + printf("rebase opcode #%u offset %u beyond the size of file %llu\n", + idx, poffset, object_size); + break; + } + if (p >= end) { + printf("%s opcode #%u offset %u beyond the size of opcodes %u\n", + "rebase", idx, poffset, size); + break; + } + + uint8_t byte = *p; + uint8_t immediate = byte & REBASE_IMMEDIATE_MASK; + uint8_t opcode = byte & REBASE_OPCODE_MASK; + ++p; + + const char* name = NULL; + const char* error = NULL; + uint64_t uleb = 0; + + switch (opcode) { + /* + * codes with IMM + */ + case REBASE_OPCODE_SET_TYPE_IMM: + if (!name) + name = "REBASE_OPCODE_SET_TYPE_IMM"; + /* FALLTHROUGH */ + case REBASE_OPCODE_ADD_ADDR_IMM_SCALED: + if (!name) + name = "REBASE_OPCODE_ADD_ADDR_IMM_SCALED"; + /* FALLTHROUGH */ + case REBASE_OPCODE_DO_REBASE_IMM_TIMES: + if (!name) + name = "REBASE_OPCODE_DO_REBASE_IMM_TIMES"; + printf(" %4u 0x%08x 0x%02x %s(%d)\n", + idx, poffset, byte, name, immediate); + break; + /* + * codes with ULEB + */ + case REBASE_OPCODE_ADD_ADDR_ULEB: + if (!name) + name = "REBASE_OPCODE_ADD_ADDR_ULEB"; + /* FALLTHROUGH */ + case REBASE_OPCODE_DO_REBASE_ULEB_TIMES: + if (!name) + name = "REBASE_OPCODE_DO_REBASE_ULEB_TIMES"; + /* FALLTHROUGH */ + case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: + if (!name) + name = "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB"; + uleb = read_uleb128(&p, end, &error); + if (error) + printf(" %4u 0x%08x 0x%02x %s(error: %s)\n", + idx, poffset, byte, name, error); + else + printf(" %4u 0x%08x 0x%02x %s(0x%llx)\n", + idx, poffset, byte, name, uleb); + break; + /* + * codes with IMM and ULEB + */ + case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: + name = "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB"; + uleb = read_uleb128(&p, end, &error); + if (error) + printf(" %4u 0x%08x 0x%02x %s(%d, error: %s)\n", + idx, poffset, byte, name, immediate, error); + else + printf(" %4u 0x%08x 0x%02x %s(%d, 0x%llx)\n", + idx, poffset, byte, name, immediate, uleb); + break; + /* + * codes with ULEB and ULEB + */ + case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: + name = "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB"; + printf(" %4u 0x%08x 0x%02x %s(", idx, poffset, byte, name); + uleb = read_uleb128(&p, end, &error); + if (error) + printf("error: %s, ", error); + else + printf("0x%llx, ", uleb); + uleb = read_uleb128(&p, end, &error); + if (error) + printf("error: %s)\n", error); + else + printf("0x%llx)\n", uleb); + break; + /* + * codes with no arguments + */ + case REBASE_OPCODE_DONE: + name = "REBASE_OPCODE_DONE"; + done = TRUE; + /* FALLTHROUGH */ + default: + if (!name) + name = "UNKNOWN OPCODE"; + printf(" %4u 0x%08x 0x%02x %s\n", idx, poffset, byte, name); + } + } +} + +/* + * print_dyld_bind_opcodes() prints the raw contents of DYLD_INFO bind data. + * Its purpose is to "disassemble" the contents of the opcode stream, not to + * interpret the data. It is resilient to errors in the data, making it useful + * for debugging malformed binaries. + * + * opcodes are printed in a concise table of data: + * + * index, file offset, raw byte, symbolic opcode and opcode-specific data + * + * this format differs from dyldinfo(1) slightly, in that the offset is + * relative to the start of mach_header, rather than to the start of the + * opcode stream. Meaning, this output can be compared directly with commands + * such as hexdump(1). + */ +extern +void +print_dyld_bind_opcodes( +const uint8_t* object_addr, +uint64_t object_size, +const char* type, +uint32_t offset, +uint32_t size) +{ + if (offset > object_size) { + printf("%s offset %u beyond the size of file %llu\n", + type, offset, object_size); + return; + } + if (offset + size > object_size) { + printf("%s offset + size %u beyond the size of file %llu\n", + type, offset + size, object_size); + size = (uint32_t)(offset - object_size); + } + + const uint8_t* p = object_addr + offset; + const uint8_t* end = object_addr + offset + size; + enum bool done = FALSE; + uint32_t idx = 0; + + printf("%s opcodes:\n", type); + printf(" %4s %-10s %4s %s\n", "idx", "offset", "byte", "opcode"); + + while (!done) + { + uint32_t poffset = (uint32_t)(p - object_addr); + idx++; + + if (poffset >= object_size) { + printf("%s opcode #%u offset %u beyond the size of file %llu\n", + type, idx, poffset, object_size); + break; + } + if (p >= end) { + printf("%s opcode #%u offset %u beyond the size of opcodes %u\n", + type, idx, poffset, size); + break; + } + + uint8_t byte = *p; + uint8_t immediate = byte & REBASE_IMMEDIATE_MASK; + uint8_t opcode = byte & REBASE_OPCODE_MASK; + ++p; + + const char* name = NULL; + const char* error = NULL; + const char* symbol = NULL; + uint64_t uleb = 0; + int64_t sleb = 0; + + switch (opcode) { + /* + * codes with IMM + */ + case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: + if (!name) + name = "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM"; + /* FALLTHROUGH */ + case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: + if (!name) + name = "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM"; + /* FALLTHROUGH */ + case BIND_OPCODE_SET_TYPE_IMM: + if (!name) + name = "BIND_OPCODE_SET_TYPE_IMM"; + /* FALLTHROUGH */ + case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: + if (!name) + name = "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED"; + printf(" %4u 0x%08x 0x%02x %s(%d)\n", + idx, poffset, byte, name, immediate); + break; + /* + * codes with IMM and symbol name + */ + case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: + name = "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM"; + printf(" %4u 0x%08x 0x%02x %s(%d, ", + idx, poffset, byte, name, immediate); + symbol = (const char*)p; + while(p < end && *p != '\0') + ++p; + if (p < end && *p == '\0') { + if (p == (uint8_t*)symbol) + printf("(empty string))\n"); + else + printf("%s)\n", symbol); + ++p; + } + else { + size_t len = strlen(symbol); + char* str = malloc(len + 1); + if (str) { + memcpy(str, symbol, len); + str[len] = '\0'; + printf("%s (unterminated string)", str); + free(str); + } + printf(")\n"); + } + break; + /* + * codes with SLEB + */ + case BIND_OPCODE_SET_ADDEND_SLEB: + name = "BIND_OPCODE_SET_ADDEND_SLEB"; + sleb = read_sleb128(&p, end, &error); + if (error) + printf(" %4u 0x%08x 0x%02x %s(error: %s)\n", + idx, poffset, byte, name, error); + else + printf(" %4u 0x%08x 0x%02x %s(%lld)\n", + idx, poffset, byte, name, sleb); + break; + /* + * codes with ULEB + */ + case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: + if (!name) + name = "REBASE_OPCODE_ADD_ADDR_ULEB"; + /* FALLTHROUGH */ + case BIND_OPCODE_ADD_ADDR_ULEB: + if (!name) + name = "BIND_OPCODE_ADD_ADDR_ULEB"; + /* FALLTHROUGH */ + case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: + if (!name) + name = "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB"; + uleb = read_uleb128(&p, end, &error); + if (error) + printf(" %4u 0x%08x 0x%02x %s(error: %s)\n", + idx, poffset, byte, name, error); + else + printf(" %4u 0x%08x 0x%02x %s(0x%llx)\n", + idx, poffset, byte, name, uleb); + break; + /* + * codes with IMM and ULEB + */ + case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: + name = "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB"; + uleb = read_uleb128(&p, end, &error); + if (error) + printf(" %4u 0x%08x 0x%02x %s(%d, error: %s)\n", + idx, poffset, byte, name, immediate, error); + else + printf(" %4u 0x%08x 0x%02x %s(%d, 0x%llx)\n", + idx, poffset, byte, name, immediate, uleb); + break; + /* + * codes with ULEB and ULEB + */ + case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: + name = "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB"; + printf(" %4u 0x%08x 0x%02x %s(", idx, poffset, byte, name); + uleb = read_uleb128(&p, end, &error); + if (error) + printf("error: %s, ", error); + else + printf("0x%llx, ", uleb); + uleb = read_uleb128(&p, end, &error); + if (error) + printf("error: %s)\n", error); + else + printf("0x%llx)\n", uleb); + break; + /* + * codes with IMM opcodes + */ + case BIND_OPCODE_THREADED: + switch (immediate) { + case BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB: + name = ("BIND_OPCODE_THREADED " + "BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_" + "TABLE_SIZE_ULEB"); + uleb = read_uleb128(&p, end, &error); + if (error) + printf(" %4u 0x%08x 0x%02x %s(error: %s)\n", + idx, poffset, byte, name, error); + else + printf(" %4u 0x%08x 0x%02x %s(0x%llx)\n", + idx, poffset, byte, name, uleb); + break; + case BIND_SUBOPCODE_THREADED_APPLY: + name = ("BIND_OPCODE_THREADED " + "BIND_SUBOPCODE_THREADED_APPLY"); + printf(" %4u 0x%08x 0x%02x %s\n", + idx, poffset, byte, name); + break; + } + break; + /* + * codes with no arguments + */ + case BIND_OPCODE_DONE: + name = "BIND_OPCODE_DONE"; + done = TRUE; + /* FALLTHROUGH */ + case BIND_OPCODE_DO_BIND: + if (!name) + name = "BIND_OPCODE_DO_BIND"; + /* FALLTHROUGH */ + default: + if (!name) + name = "UNKNOWN OPCODE"; + printf(" %4u 0x%08x 0x%02x %s\n", idx, poffset, byte, name); + } + } } /* @@ -388,39 +1735,884 @@ struct dyld_bind_info *dbi, uint64_t ndbi) { uint64_t n; + uint64_t value; + uint16_t diversity; + enum bool hasAddressDiversity; + uint8_t key; + enum bool isAuthenticated; + static const char *keyNames[] = { "IA", "IB", "DA", "DB" }; + const char* bind_name; + const char* symbolName; + const char* dylibName; + char valuestr[20]; + + if (0 == ndbi) + return; + + enum bool is32 = (DYLD_CHAINED_PTR_32 == dbi[0].pointer_format || + DYLD_CHAINED_PTR_32_CACHE == dbi[0].pointer_format || + DYLD_CHAINED_PTR_32_FIRMWARE == dbi[0].pointer_format); + + size_t maxsegname = strlen("segment"); + size_t maxsectname = strlen("section"); + size_t maxdylibname = strlen("dylib"); + size_t maxaddr = 0; + size_t maxvalue = is32 ? 10 : 18; + + for (n = 0; n < ndbi; n++) { + const char* name = dbi[n].segname ? dbi[n].segname : ""; + size_t len = strlen(name); + if (len > maxsegname) + maxsegname = len; + name = dbi[n].sectname ? dbi[n].sectname : ""; + len = strlen(name); + if (len > maxsectname) + maxsectname = len; + name = dbi[n].dylibname ? dbi[n].dylibname : ""; + len = strlen(name); + if (len > maxdylibname) + maxdylibname = len; + len = snprintf(NULL, 0, "%llX", dbi[n].address); + if (len > maxaddr) + maxaddr = len; + } - printf("bind information:\n"); - printf("segment section address type addend dylib" - " symbol\n"); - for(n = 0; n < ndbi; n++){ - printf("%-7s %-16.16s 0x%08llX %10s %5lld %-16s %s%s\n", - dbi[n].segname, - dbi[n].sectname, - dbi[n].address, - bindTypeName(dbi[n].bind_type), - dbi[n].addend, - dbi[n].dylibname, - dbi[n].symbolname, - dbi[n].weak_import ? " (weak import)" : ""); - } + printf("bind information:\n"); + printf("%*s %*s %*s %*s %-10s %-8s %*s %s\n", + -(int)maxsegname, "segment", + -(int)maxsectname, "section", + -(int)(maxaddr+2), "address", + -(int)maxvalue, "value", + "type", + "addend", + -(int)maxdylibname, "dylib", + "symbol"); + for(n = 0; n < ndbi; n++){ + bind_name = (dbi[n].bind_name ? dbi[n].bind_name : + bindTypeName(dbi[n].bind_type)); + dylibName = dbi[n].dylibname ? dbi[n].dylibname : ""; + symbolName = dbi[n].symbolname ? dbi[n].symbolname : ""; + if (dbi[n].pointer_value) { + if (is32) { + snprintf(valuestr, sizeof(valuestr), "0x%08llX", + dbi[n].pointer_value); + } else { + snprintf(valuestr, sizeof(valuestr), "0x%016llX", + dbi[n].pointer_value); + } + } + else { + snprintf(valuestr, sizeof(valuestr), ""); + } + + printf("%*s %*s 0x%*llX %*s %-10s 0x%-6llX %*s %s%s", + -(int)maxsegname, dbi[n].segname, + -(int)maxsectname, dbi[n].sectname, + -(int)maxaddr, dbi[n].address, + -(int)maxvalue, valuestr, + bind_name, + dbi[n].addend, + -(int)maxdylibname, dylibName, + symbolName, + dbi[n].weak_import ? " (weak import)" : ""); + + value = dbi[n].pointer_value; + diversity = (uint16_t)(value >> 32); + hasAddressDiversity = (value & (1ULL << 48)) != 0; + key = (value >> 49) & 0x3; + isAuthenticated = (value & (1ULL << 63)) != 0; + if(isAuthenticated){ + printf(" (JOP: diversity %d, address %s, %s)", diversity, + hasAddressDiversity ? "true" : "false", keyNames[key]); + } + printf("\n"); + } } /* - * get_dyld_bind_info_symbolname() is passed an address and the internal expanded - * dyld bind information. If the address is found its binding symbol name is - * returned. If not NULL. + * get_dyld_bind_info_symbolname() is passed an address and the internal + * expanded dyld bind information. If the address is found its binding symbol + * name is returned. If not NULL. */ const char * get_dyld_bind_info_symbolname( uint64_t address, struct dyld_bind_info *dbi, -uint64_t ndbi) +uint64_t ndbi, +enum chain_format_t chain_format, +int64_t *addend) { uint64_t n; - - for(n = 0; n < ndbi; n++){ - if(dbi[n].address == address) - return(dbi[n].symbolname); - } - return(NULL); + + for(n = 0; n < ndbi; n++){ + if(dbi[n].address == address){ + if(chain_format && addend != NULL) + *addend = dbi[n].addend; + return(dbi[n].symbolname); + } + } + return(NULL); +} + +/***************************************************************************** + * + * Chained Fixups + * + */ + +/* + * swap16, swap32, and swap64 are little inline functions for abstracting away + * endian swapping. + */ +static inline uint16_t swap16(uint16_t x, enum bool swapped) +{ + return swapped == TRUE ? OSSwapInt16(x): x; +} +static inline uint32_t swap32(uint32_t x, enum bool swapped) +{ + return swapped == TRUE ? OSSwapInt32(x): x; +} + +static inline uint64_t swap64(uint64_t x, enum bool swapped) +{ + return swapped == TRUE ? OSSwapInt64(x): x; +} + +/* + * get_base_addr computes the base vmaddress from a list of segments. by + * convention, this is the vmaddr of the __TEXT segment. It will return + * (uint64_t)-1 on error; + */ +static uint64_t +get_base_addr(struct segment_command **segs, + uint32_t nsegs, + struct segment_command_64 **segs64, + uint32_t nsegs64) +{ + for (uint32_t i = 0; i < nsegs64; ++i) { + if (0 == strcmp("__TEXT", segs64[i]->segname)) + return segs64[i]->vmaddr; + } + for (uint32_t i = 0; i < nsegs; ++i) { + if (0 == strcmp("__TEXT", segs[i]->segname)) + return segs[i]->vmaddr; + } + + return ((uint64_t)-1); +} + +/* + * segmentIndexFromAddr returns the index of a segment that contains the + * specified input address. The address is a vmaddr, not a fileoff. Canonical + * Mach-O files will include either 32-bit or 64-bit segments. If for some + * reason both 32- and 64-bit segments are passed in here, 64-bit segments will + * be consulted first; but really, you'll have other issues ... + * + * Earlier Mach-O structures encoded segment indicies directly. dyld3's + * chained fixups format saves space by ommitting this information, knowing + * that with a quick O(N) algorithm one can simply compute this information + * from a vmaddr. + */ +static uint32_t +segmentIndexFromAddr(uint64_t addr, + struct segment_command **segs, + uint32_t nsegs, + struct segment_command_64 **segs64, + uint32_t nsegs64) +{ + for (uint32_t i = 0; i < nsegs64; ++i) { + if (segs64[i]->vmaddr <= addr && + segs64[i]->vmaddr + segs64[i]->vmsize > addr) + return i; + } + for (uint32_t i = 0; i < nsegs; ++i) { + if (segs[i]->vmaddr <= addr && + segs[i]->vmaddr + segs[i]->vmsize > addr) + return i; + } + + return ((uint32_t)-1); +} + +/* + * fixup_target comes from dyld3. it represents a fixup target, which is most + * likely a symbol. this structure captures values from a variety of different + * fixup formats. + */ +struct fixup_target +{ + uint64_t value; + const char* dylib; + const char* symbolName; + uint64_t addend; + enum bool weakImport; +}; + +/* + * signExtendedAddend64 comes from dyld3. It computes the sign extended + * addend from a 64-bit pointer. + */ +static uint64_t signExtendedAddend64(uint64_t addend27) +{ + uint64_t top8Bits = addend27 & 0x00007F80000ULL; + uint64_t bottom19Bits = addend27 & 0x0000007FFFFULL; + uint64_t newValue = (top8Bits << 13) | + (((uint64_t)(bottom19Bits << 37) >> 37) & + 0x00FFFFFFFFFFFFFF); + return newValue; +} + +/* + * signExtendedAddend64e comes from dyld3. It computes the sign extended + * addend from a 64-bit arm64e pointer (no auth). + */ +static uint64_t signExtendedAddend64e(uint64_t addend19) +{ + if ( addend19 & 0x40000 ) + return addend19 | 0xFFFFFFFFFFFC0000ULL; + else + return addend19; +} + +/* + * libOrdinalFromUInt8() returns a signed libOrdinal (aka dylibOrdinal) from + * a uint8_t as found in the chained import data. + */ +static int libOrdinalFromUInt8(uint8_t value) +{ + if (((uint8_t)-1) == value) + return -1; + else if (((uint8_t)-2) == value) + return -2; + else if (((uint8_t)-3) == value) + return -3; + return value; +} + +/* + * libOrdinalFromUInt16() returns a signed libOrdinal (aka dylibOrdinal) from + * a uint16_t as found in the chained import data. + */ +static int libOrdinalFromUInt16(uint16_t value) +{ + if (((uint16_t)-1) == value) + return -1; + else if (((uint16_t)-2) == value) + return -2; + else if (((uint16_t)-3) == value) + return -3; + return value; +} + +/* + * get_fixup_targets builds a list of targets from a dyld_chained_fixups_header + * and a list of dylibs ordered by ordinal. targets and ntarget may be + * uninitialized prior to call. + * + * This function will print errors as they are encountered, some of which + * will halt processing early and some of which will not. + */ +static void get_fixup_targets(/* inputs */ + uint32_t datasize, + struct dyld_chained_fixups_header* header, + enum bool swapped, + const char **dylibs, + uint32_t ndylibs, + /* outputs */ + struct fixup_target **targets, + uint32_t *ntarget + ) +{ + /* build the list of fixup targets, one per symbol */ + uint32_t imports_count = swap32(header->imports_count, swapped); + uint32_t imports_format = swap32(header->imports_format, swapped); + uint32_t symbols_offset = swap32(header->symbols_offset, swapped); + uint32_t max_symbols_offset = datasize - symbols_offset; + const char* symbolsPool = (char*)header + symbols_offset; + const char* dylibName; + + *ntarget = imports_count; + *targets = reallocf(*targets, sizeof(struct fixup_target) * imports_count); + memset(*targets, 0, sizeof(struct fixup_target) * imports_count); + + if (imports_format < 1 || imports_format > 3) { + printf("unknown chained-fixups import format: %d\n", imports_format); + return; + } + + for (uint32_t i=0; i < imports_count; ++i) { + int lib_ordinal = 0; + + if (imports_format == DYLD_CHAINED_IMPORT) { + /* get a swapped dyld_chained_import struct */ + uint32_t values[1]; + memcpy(values, ((uint8_t*)header + header->imports_offset + + i * sizeof(struct dyld_chained_import)), + sizeof(values)); + values[0] = swap32(values[0], swapped); + struct dyld_chained_import imports; + memcpy(&imports, &values, sizeof(imports)); + + /* look for overflow */ + if (imports.name_offset > max_symbols_offset) { + printf("chained-fixups import #%u symbol offset extends " + "past end: %u (max %u)\n", i, imports.name_offset, + max_symbols_offset); + imports.name_offset = 0; + } + + /* record the information */ + (*targets)[i].symbolName = &symbolsPool[imports.name_offset]; + (*targets)[i].weakImport = imports.weak_import; + lib_ordinal = libOrdinalFromUInt8(imports.lib_ordinal); + } + else if (imports_format == DYLD_CHAINED_IMPORT_ADDEND) { + /* get a swapped dyld_chained_import_addend struct */ + uint32_t values[2]; + memcpy(values, ((uint8_t*)header + header->imports_offset + + i * sizeof(struct dyld_chained_import_addend)), + sizeof(values)); + values[0] = swap32(values[0], swapped); + values[1] = swap32(values[1], swapped); + struct dyld_chained_import_addend imports; + memcpy(&imports, &values, sizeof(imports)); + + /* look for overflow */ + if (imports.name_offset > max_symbols_offset) { + printf("chained-fixups import #%u symbol offset extends " + "past end: %u (max %u)\n", i, imports.name_offset, + max_symbols_offset); + imports.name_offset = 0; + } + + /* record the information */ + (*targets)[i].symbolName = &symbolsPool[imports.name_offset]; + (*targets)[i].weakImport = imports.weak_import; + (*targets)[i].addend = imports.addend; + lib_ordinal = libOrdinalFromUInt8(imports.lib_ordinal); + } + else if (imports_format == DYLD_CHAINED_IMPORT_ADDEND64) { + /* get a swapped dyld_chained_import_addend64 struct */ + uint64_t values[2]; + memcpy(values, ((uint8_t*)header + header->imports_offset + + i * sizeof(struct dyld_chained_import_addend64)), + sizeof(values)); + values[0] = swap64(values[0], swapped); + values[1] = swap64(values[1], swapped); + struct dyld_chained_import_addend64 imports; + memcpy(&imports, &values, sizeof(imports)); + + /* look for overflow */ + if (imports.name_offset > max_symbols_offset) { + printf("chained-fixups import #%u symbol offset extends " + "past end: %u (max %u)\n", i, imports.name_offset, + max_symbols_offset); + imports.name_offset = 0; + } + + /* record the information */ + (*targets)[i].symbolName = &symbolsPool[imports.name_offset]; + (*targets)[i].weakImport = imports.weak_import; + (*targets)[i].addend = imports.addend; + lib_ordinal = libOrdinalFromUInt16(imports.lib_ordinal); + } + + if (!validateOrdinal(lib_ordinal, dylibs, ndylibs, &dylibName, NULL)) { + if (lib_ordinal < 0) + printf("chained-fixups import #%u bad special library ordinal: " + "%d\n", i, lib_ordinal); + else + printf("chained-fixups import #%u bad library ordinal: %d " + "(max %u)\n", i, lib_ordinal, ndylibs); + continue; + } + + (*targets)[i].dylib = dylibName; + } +} + +/* + * walk_chain walks a chain of binds and rebases, starting at the pointer + * location indicated by the dyld_chained_starts_in_segment struct, the + * pageIndex, and the offsetInPage values. The chain will be followed until + * it ends. + * + * For each pointer found in the chain, walk_chain will build a dyld_bind_info + * structure using information found in the segment lists and the list of fixup + * targets (e.g., symbols). The dyld_bind_info is not quiiiiiite what we want + * for this: it does not properly support BIND types vs REBASE types. But the + * format used by the original arm64e format and the new chained binds format + * are so semantically equivalent, it does a reasonable job. + * + * The output values dbi and ndbi must be initialized to NULL / 0 before + * first calling walk_chain; values modified by walk_chain may be passed + * back into walk_chain safely. + */ +static void walk_chain(/* inputs */ + char *object_addr, + uint64_t object_size, + struct segment_command **segs, + uint32_t nsegs, + struct segment_command_64 **segs64, + uint32_t nsegs64, + struct fixup_target *targets, + uint32_t ntarget, + enum bool swapped, + struct dyld_chained_starts_in_segment* segInfo, + uint16_t pageIndex, + uint16_t offsetInPage, + /* output */ + struct dyld_bind_info **dbi, + uint64_t *ndbi) +{ + uint64_t segment_offset = swap64(segInfo->segment_offset, swapped); + uint16_t page_size = swap16(segInfo->page_size, swapped); + uint16_t pointer_format = swap16(segInfo->pointer_format, swapped); + uint64_t vmaddr = segment_offset + pageIndex * page_size; + uint64_t baseaddr = get_base_addr(segs, nsegs, segs64, nsegs64); + uint8_t* pageContentStart = (uint8_t*)(object_addr + vmaddr); + void* chain = (pageContentStart+offsetInPage); + uint64_t chain_addr = baseaddr + vmaddr + offsetInPage; + enum bool done = FALSE; + + /* loop over all of the fixups in the chain */ + while (!done) { + uint64_t dbii = *ndbi; + *ndbi += 1; + *dbi = reallocf(*dbi, sizeof(**dbi) * (*ndbi)); + memset(&(*dbi)[dbii], 0, sizeof(**dbi)); + + uint64_t addend = 0; + uint32_t segIndex = segmentIndexFromAddr(chain_addr, segs, nsegs, + segs64, nsegs64); + const char* symbolName = NULL; + const char* dylibName = NULL; + const char* bindName = NULL; + enum bool weakImport = FALSE; + + switch (pointer_format) { + case DYLD_CHAINED_PTR_ARM64E: + { + uint64_t chain_value = swap64(*(uint64_t*)chain, swapped); + uint64_t address = chain_addr; + uint64_t pointer_value = chain_value; + + struct dyld_chained_ptr_arm64e_auth_rebase auth_rebase; + memcpy(&auth_rebase, &chain_value, sizeof(auth_rebase)); + + if (auth_rebase.auth) { + struct dyld_chained_ptr_arm64e_auth_bind auth_bind; + memcpy(&auth_bind, &chain_value, sizeof(auth_bind)); + if (auth_bind.bind) { + struct fixup_target* target = + &targets[auth_bind.ordinal]; + if (target->addend) { + addend = target->addend; + } + symbolName = target->symbolName; + dylibName = target->dylib; + weakImport = target->weakImport; + bindName = "bind aptr"; + } + else { + uint64_t targetOffset = auth_rebase.target; + address = targetOffset + baseaddr; + bindName = "rebase aptr"; + pointer_value = targetOffset + baseaddr; + } + } + else { + struct dyld_chained_ptr_arm64e_bind bind; + memcpy(&bind, &chain_value, sizeof(bind)); + if (bind.bind) { + struct fixup_target* target = &targets[bind.ordinal]; + addend = target->addend + + signExtendedAddend64e(bind.addend); + symbolName = target->symbolName; + dylibName = target->dylib; + weakImport = target->weakImport; + bindName = "bind ptr"; + pointer_value = 0; + } + else { + struct dyld_chained_ptr_arm64e_rebase rebase; + memcpy(&rebase, &chain_value, sizeof(rebase)); + bindName = "rebase ptr"; + pointer_value = ((uint64_t)(rebase.high8) << 56) | + rebase.target; + } + } + + const char* csegname = segmentName(segIndex, segs, nsegs, + segs64, nsegs64); + const char* csectname = sectionName(segIndex, chain_addr, segs, + nsegs, segs64, nsegs64); + char* segname = strdup(csegname); + char* sectname = strdup(csectname); + if (strlen(segname)>16) + segname[16] = 0; + if (strlen(sectname)>16) + sectname[16] = 0; + + (*dbi)[dbii].segname = segname; + (*dbi)[dbii].sectname = sectname; + (*dbi)[dbii].address = address; + (*dbi)[dbii].bind_name = bindName; + (*dbi)[dbii].addend = addend; + (*dbi)[dbii].dylibname = dylibName; + (*dbi)[dbii].symbolname = symbolName; + (*dbi)[dbii].weak_import = weakImport; + (*dbi)[dbii].pointer_value = pointer_value; + + if (auth_rebase.next == 0) { + done = TRUE; + } + else { + chain += auth_rebase.next * 8; + chain_addr += auth_rebase.next * 8; + } + } + break; + case DYLD_CHAINED_PTR_64: + { + uint64_t chain_value = swap64(*(uint64_t*)chain, swapped); + uint64_t pointer_value = chain_value; + + struct dyld_chained_ptr_64_bind bind; + memcpy(&bind, &chain_value, sizeof(bind)); + + if (bind.bind) { + struct fixup_target* target = &targets[bind.ordinal]; + addend = target->addend + + signExtendedAddend64(bind.addend); + symbolName = target->symbolName; + dylibName = target->dylib; + weakImport = target->weakImport; + bindName = "bind ptr"; + pointer_value = 0; + } + else { + struct dyld_chained_ptr_64_rebase rebase; + memcpy(&rebase, &chain_value, sizeof(rebase)); + bindName = "rebase ptr"; + pointer_value = ((uint64_t)(rebase.high8) << 56) | + rebase.target; + } + + const char* csegname = segmentName(segIndex, segs, nsegs, + segs64, nsegs64); + const char* csectname = sectionName(segIndex, chain_addr, segs, + nsegs, segs64, nsegs64); + char* segname = strdup(csegname); + char* sectname = strdup(csectname); + if (strlen(segname)>16) + segname[16] = 0; + if (strlen(sectname)>16) + sectname[16] = 0; + + (*dbi)[dbii].segname = segname; + (*dbi)[dbii].sectname = sectname; + (*dbi)[dbii].address = chain_addr; + (*dbi)[dbii].bind_name = bindName; + (*dbi)[dbii].addend = addend; + (*dbi)[dbii].dylibname = dylibName; + (*dbi)[dbii].symbolname = symbolName; + (*dbi)[dbii].weak_import = weakImport; + (*dbi)[dbii].pointer_value = pointer_value; + + if (bind.next == 0) { + done = TRUE; + } + else { + chain += bind.next * 4; + chain_addr += bind.next * 4; + } + } + break; + case DYLD_CHAINED_PTR_32: + { + uint32_t chain_value = swap32(*(uint32_t*)chain, swapped); + uint32_t pointer_value = chain_value; + + struct dyld_chained_ptr_32_bind bind; + memcpy(&bind, &chain_value, sizeof(bind)); + + if (bind.bind) { + struct fixup_target* target = &targets[bind.ordinal]; + addend = target->addend + bind.addend; + symbolName = target->symbolName; + dylibName = target->dylib; + weakImport = target->weakImport; + bindName = "bind ptr"; + pointer_value = 0; + } + else { + struct dyld_chained_ptr_32_rebase rebase; + memcpy(&rebase, &chain_value, sizeof(rebase)); + bindName = "rebase ptr"; + pointer_value = rebase.target; + } + + const char* csegname = segmentName(segIndex, segs, nsegs, + segs64, nsegs64); + const char* csectname = sectionName(segIndex, chain_addr, segs, + nsegs, segs64, nsegs64); + char* segname = strdup(csegname); + char* sectname = strdup(csectname); + if (strlen(segname)>16) + segname[16] = 0; + if (strlen(sectname)>16) + sectname[16] = 0; + + (*dbi)[dbii].segname = segname; + (*dbi)[dbii].sectname = sectname; + (*dbi)[dbii].address = chain_addr; + (*dbi)[dbii].bind_name = bindName; + (*dbi)[dbii].addend = addend; + (*dbi)[dbii].dylibname = dylibName; + (*dbi)[dbii].symbolname = symbolName; + (*dbi)[dbii].weak_import = weakImport; + (*dbi)[dbii].pointer_value = pointer_value; + (*dbi)[dbii].pointer_format = pointer_format; + + if (bind.next == 0) { + done = TRUE; + } + else { + struct dyld_chained_ptr_32_rebase rebase; + memcpy(&rebase, &chain_value, sizeof(rebase)); + chain += rebase.next * 4; + chain_addr += rebase.next * 4; + + /* Skip over non-pointers */ + chain_value = swap32(*(uint32_t*)chain, swapped); + memcpy(&rebase, &chain_value, sizeof(rebase)); + while ((rebase.bind == 0) && + (rebase.target > segInfo->max_valid_pointer)) + { + chain += rebase.next * 4; + chain_addr += rebase.next * 4; + chain_value = swap32(*(uint32_t*)chain, swapped); + memcpy(&rebase, &chain_value, sizeof(rebase)); + } + } + } + break; + case DYLD_CHAINED_PTR_32_CACHE: + case DYLD_CHAINED_PTR_32_FIRMWARE: + /* otool does not support printing these formats */ + done = TRUE; + break; + } + } +} + +/* + * get_dyld_chained_fixups() unpacks the dyld bind info from the data pointed + * to by an LC_DYLD_CHAINED_FIXUPS load command. Information is returned in + * the older dyld_bind_info so that existing logic can be reused. + */ +void +get_dyld_chained_fixups(/* input */ + const uint8_t* start, + const uint8_t* end, + const char **dylibs, + uint32_t ndylibs, + struct segment_command **segs, + uint32_t nsegs, + struct segment_command_64 **segs64, + uint32_t nsegs64, + enum bool swapped, + char *object_addr, + uint64_t object_size, + /* output */ + struct dyld_bind_info **dbi, + uint64_t *ndbi, + enum chain_format_t *chain_format, + enum bool print_errors) +{ + uint64_t end_offset = end - start; + struct fixup_target* targets = NULL; + uint32_t ntarget = 0; + + struct dyld_chained_fixups_header* header; + struct dyld_chained_starts_in_image* imageStarts; + + *chain_format = CHAIN_FORMAT_NONE; + + /* get the chained fixups header */ + if (sizeof(struct dyld_chained_fixups_header) + start > end) { + printf("bad chained fixups: header size %lu extends past end %llu\n", + sizeof(struct dyld_chained_fixups_header), end_offset); + return; + } + header = (struct dyld_chained_fixups_header*)start; + + /* get the fixup targets */ + get_fixup_targets((uint32_t)(end - start), header, swapped, dylibs, ndylibs, + &targets, &ntarget); + + /* get the chained starts */ + uint32_t starts_offset = swap32(header->starts_offset, swapped); + if (starts_offset < sizeof(struct dyld_chained_fixups_header)) { + printf("bad chained fixups: image starts offset %u overlaps with " + "fixups header size %lu\n", starts_offset, + sizeof(struct dyld_chained_fixups_header)); + return; + } + if (starts_offset + + sizeof(struct dyld_chained_starts_in_image) > end_offset) { + printf("bad chained fixups: image starts end %lu extends past " + "end %llu\n", starts_offset + + sizeof(struct dyld_chained_starts_in_image), end_offset); + return; + } + imageStarts = (struct dyld_chained_starts_in_image*)(start + starts_offset); + + /* walk the image starts */ + uint32_t nseg = swap32(imageStarts->seg_count, swapped); + for (uint32_t iseg = 0; iseg < nseg; ++iseg) + { + struct dyld_chained_starts_in_segment* segInfo; + + uint32_t seg_info_offset = swap32(imageStarts->seg_info_offset[iseg], + swapped); + + /* seg_info_offsets are allowed to be 0 */ + if (0 == seg_info_offset) + continue; + + /* + * dyld does not strictly check that the dyld_chained_starts_in_segment + * struct fits in the Mach-O. As long as page_count is addressable + * and has a 0 value, the rest of the struct can be any random data. + */ + if (starts_offset + seg_info_offset > end_offset) { + printf("bad chained fixups: seg_info %i offset %u starts past " + "end %llu\n", iseg, starts_offset + seg_info_offset, + end_offset); + continue; + } + if (starts_offset + seg_info_offset + + sizeof(struct dyld_chained_starts_in_segment) > end_offset) { + printf("bad chained fixups: seg_info %i end %lu extends past " + "end %llu\n", iseg, starts_offset + seg_info_offset + + sizeof(struct dyld_chained_starts_in_segment), end_offset); + } + + segInfo = ((struct dyld_chained_starts_in_segment*) + (start + starts_offset + seg_info_offset)); + + uint16_t page_count = swap16(segInfo->page_count, swapped); + for (uint16_t pageIndex = 0; pageIndex < page_count; ++pageIndex) + { + /* set the chain format. If already set, verify it. */ + uint16_t pointer_format = swap16(segInfo->pointer_format, swapped); + if (CHAIN_FORMAT_NONE == *chain_format) { + *chain_format = (enum chain_format_t)pointer_format; + } + else if (pointer_format != *chain_format) { + printf("bad chained fixups: seg_info %i pointer format %d " + "does not match previous pointer format %d\n", iseg, + pointer_format, *chain_format); + } + + /* walk the chains */ + uint16_t offsetInPage = swap16(segInfo->page_start[pageIndex], + swapped); + if ( offsetInPage == DYLD_CHAINED_PTR_START_NONE ) + continue; + if ( offsetInPage & DYLD_CHAINED_PTR_START_MULTI ) { + uint32_t overflowIndex = + offsetInPage & ~DYLD_CHAINED_PTR_START_MULTI; + enum bool chainEnd = FALSE; + while (!chainEnd) { + uint16_t page_start = + swap16(segInfo->page_start[overflowIndex], swapped); + chainEnd = (page_start & DYLD_CHAINED_PTR_START_LAST); + offsetInPage = (page_start & ~DYLD_CHAINED_PTR_START_LAST); + walk_chain(object_addr, object_size, segs, nsegs, + segs64, nsegs64, targets, ntarget, swapped, + segInfo, pageIndex, offsetInPage, dbi, ndbi); + ++overflowIndex; + } + } + else { + walk_chain(object_addr, object_size, segs, nsegs, + segs64, nsegs64, targets, ntarget, swapped, + segInfo, pageIndex, offsetInPage, dbi, ndbi); + } + } + } + + free(targets); +} + +uint64_t get_chained_rebase_value( + uint64_t chain_value, + enum chain_format_t chain_format, + enum bool *has_auth) +{ + if (has_auth) + *has_auth = FALSE; + + switch (chain_format) { + case CHAIN_FORMAT_NONE: + break; + case CHAIN_FORMAT_ARM64E: + { + struct dyld_chained_ptr_arm64e_auth_rebase* auth_rebase = + (struct dyld_chained_ptr_arm64e_auth_rebase*)&chain_value; + + if (auth_rebase->auth) { + if (!auth_rebase->bind) { + if (has_auth) + *has_auth = TRUE; + return auth_rebase->target; + } + } + else { + struct dyld_chained_ptr_arm64e_rebase* rebase = + (struct dyld_chained_ptr_arm64e_rebase*)&chain_value; + if (!rebase->bind) { + return rebase->target; + } + } + } + break; + case CHAIN_FORMAT_PTR_64: + { + struct dyld_chained_ptr_64_rebase* rebase = + (struct dyld_chained_ptr_64_rebase*)&chain_value; + if (!rebase->bind) { + return rebase->target; + } + } + break; + case CHAIN_FORMAT_PTR_32: + { + struct dyld_chained_ptr_32_rebase* rebase = + (struct dyld_chained_ptr_32_rebase*)&chain_value; + if (!rebase->bind) { + return rebase->target; + } + } + break; + case CHAIN_FORMAT_PTR_32_CACHE: + { + struct dyld_chained_ptr_32_cache_rebase* rebase = + (struct dyld_chained_ptr_32_cache_rebase*)&chain_value; + return rebase->target; + } + break; + case CHAIN_FORMAT_PTR_32_FIRMWARE: + { + struct dyld_chained_ptr_32_firmware_rebase* rebase = + (struct dyld_chained_ptr_32_firmware_rebase*)&chain_value; + return rebase->target; + } + break; + } + + return chain_value; } diff --git a/cctools/otool/dyld_bind_info.h b/cctools/otool/dyld_bind_info.h index 6a60947..6390205 100644 --- a/cctools/otool/dyld_bind_info.h +++ b/cctools/otool/dyld_bind_info.h @@ -1,15 +1,44 @@ /* - * The internal structure for the broken out bind info. + * enum chain_format_t matches the dyld pointer format uint32_t values used + * by LC_DYLD_CHAINED_FIXUPS. Note that the CHAIN_FORMAT_ARM64E format is also + * used by LC_DYLD_INFO for arm64e. + */ +enum chain_format_t { + CHAIN_FORMAT_NONE = 0, + CHAIN_FORMAT_ARM64E = 1, + CHAIN_FORMAT_PTR_64 = 2, + CHAIN_FORMAT_PTR_32 = 3, + CHAIN_FORMAT_PTR_32_CACHE = 4, + CHAIN_FORMAT_PTR_32_FIRMWARE = 5, +}; + +/* + * dyld_bind_info is the internal structure for the broken out bind info. + * + * When printing arm64e data from DYLD_INFO: + * bind_type will be set to the bind type. rebase_type will be ignored. + * bind_name will be NULL. + * pointer_format will be set to 0 (default to the 64-bit behavior, even + * though not strictly a legal value) + * + * When printing info from DYLD_CHAINED_FIXUPS: + * bind_type will be 0. + * bind_name will be set to a human-readable value. + * pointer_format will be set to one of the following chained_fixup pointer + * format values: 0 (not set, default to 64-bit), 3 (32-bit) */ struct dyld_bind_info { const char *segname; const char *sectname; uint64_t address; int bind_type; + const char *bind_name; uint64_t addend; const char *dylibname; const char *symbolname; enum bool weak_import; + uint64_t pointer_value; + uint32_t pointer_format;/* dyld_chained_starts_in_segment.pointer_format */ }; extern void get_dyld_bind_info( @@ -21,14 +50,56 @@ extern void get_dyld_bind_info( uint32_t nsegs, struct segment_command_64 **segs64, uint32_t nsegs64, + enum bool swapped, + char *object_addr, + uint64_t object_size, struct dyld_bind_info **dbi, /* outputs */ - uint64_t *ndbi); + uint64_t *ndbi, + enum chain_format_t *chain_format, + enum bool print_errors); extern void print_dyld_bind_info( struct dyld_bind_info *dbi, uint64_t ndbi); +extern void print_dyld_rebase_opcodes( + const uint8_t* object_addr, + uint64_t object_size, + uint32_t offset, + uint32_t size); + +extern void print_dyld_bind_opcodes( + const uint8_t* object_addr, + uint64_t object_size, + const char* type, + uint32_t offset, + uint32_t size); + extern const char * get_dyld_bind_info_symbolname( uint64_t address, struct dyld_bind_info *dbi, - uint64_t ndbi); + uint64_t ndbi, + enum chain_format_t chain_format, + int64_t *addend); + +extern void get_dyld_chained_fixups( + const uint8_t *start, /* inputs */ + const uint8_t *end, + const char **dylibs, + uint32_t ndylibs, + struct segment_command **segs, + uint32_t nsegs, + struct segment_command_64 **segs64, + uint32_t nsegs64, + enum bool swapped, + char *object_addr, + uint64_t object_size, + struct dyld_bind_info **dbi, /* outputs */ + uint64_t *ndbi, + enum chain_format_t *chain_format, + enum bool print_errors); + +extern uint64_t get_chained_rebase_value( + uint64_t chain_value, + enum chain_format_t chain_format, + enum bool *has_auth); diff --git a/cctools/otool/fixup-chains.h b/cctools/otool/fixup-chains.h new file mode 100644 index 0000000..907a0e7 --- /dev/null +++ b/cctools/otool/fixup-chains.h @@ -0,0 +1,238 @@ +/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- + * + * Copyright (c) 2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef __MACH_O_FIXUP_CHAINS__ +#define __MACH_O_FIXUP_CHAINS__ + + +#include + + +//#define LC_DYLD_EXPORTS_TRIE 0x80000033 // used with linkedit_data_command +//#define LC_DYLD_CHAINED_FIXUPS 0x80000034 // used with linkedit_data_command, payload is dyld_chained_fixups_header + + +// header of the LC_DYLD_CHAINED_FIXUPS payload +struct dyld_chained_fixups_header +{ + uint32_t fixups_version; // 0 + uint32_t starts_offset; // offset of dyld_chained_starts_in_image in chain_data + uint32_t imports_offset; // offset of imports table in chain_data + uint32_t symbols_offset; // offset of symbol strings in chain_data + uint32_t imports_count; // number of imported symbol names + uint32_t imports_format; // DYLD_CHAINED_IMPORT* + uint32_t symbols_format; // 0 => uncompressed, 1 => zlib compressed +}; + +// This struct is embedded in LC_DYLD_CHAINED_FIXUPS payload +struct dyld_chained_starts_in_image +{ + uint32_t seg_count; + uint32_t seg_info_offset[1]; // each entry is offset into this struct for that segment + // followed by pool of dyld_chain_starts_in_segment data +}; + +// This struct is embedded in dyld_chain_starts_in_image +// and passed down to the kernel for page-in linking +struct dyld_chained_starts_in_segment +{ + uint32_t size; // size of this (amount kernel needs to copy) + uint16_t page_size; // 0x1000 or 0x4000 + uint16_t pointer_format; // DYLD_CHAINED_PTR_* + uint64_t segment_offset; // offset in memory to start of segment + uint32_t max_valid_pointer; // for 32-bit OS, any value beyond this is not a pointer + uint16_t page_count; // how many pages are in array + uint16_t page_start[1]; // each entry is offset in each page of first element in chain + // or DYLD_CHAINED_PTR_START_NONE if no fixups on page + // uint16_t chain_starts[1]; // some 32-bit formats may require multiple starts per page. + // for those, if high bit is set in page_starts[], then it + // is index into chain_starts[] which is a list of starts + // the last of which has the high bit set +}; + +enum { + DYLD_CHAINED_PTR_START_NONE = 0xFFFF, // used in page_start[] to denote a page with no fixups + DYLD_CHAINED_PTR_START_MULTI = 0x8000, // used in page_start[] to denote a page which has multiple starts + DYLD_CHAINED_PTR_START_LAST = 0x8000, // used in chain_starts[] to denote last start in list for page +}; + +// This struct is embedded in __TEXT,__chain_starts section in firmware +struct dyld_chained_starts_offsets +{ + uint32_t pointer_format; // DYLD_CHAINED_PTR_32_FIRMWARE + uint32_t starts_count; // number of starts in array + uint32_t chain_starts[1]; // array chain start offsets +}; + + +// values for dyld_chained_starts_in_segment.pointer_format +enum { + DYLD_CHAINED_PTR_ARM64E = 1, + DYLD_CHAINED_PTR_64 = 2, + DYLD_CHAINED_PTR_32 = 3, + DYLD_CHAINED_PTR_32_CACHE = 4, + DYLD_CHAINED_PTR_32_FIRMWARE = 5, +}; + + +// DYLD_CHAINED_PTR_ARM64E +struct dyld_chained_ptr_arm64e_rebase +{ + uint64_t target : 43, // vmaddr + high8 : 8, + next : 11, // 8-byte stide + bind : 1, // == 0 + auth : 1; // == 0 +}; + +// DYLD_CHAINED_PTR_ARM64E +struct dyld_chained_ptr_arm64e_bind +{ + uint64_t ordinal : 16, + zero : 16, + addend : 19, + next : 11, // 8-byte stide + bind : 1, // == 1 + auth : 1; // == 0 +}; + +// DYLD_CHAINED_PTR_ARM64E +struct dyld_chained_ptr_arm64e_auth_rebase +{ + uint64_t target : 32, // runtimeOffset + diversity : 16, + addrDiv : 1, + key : 2, + next : 11, // 8-byte stide + bind : 1, // == 0 + auth : 1; // == 1 +}; + +// DYLD_CHAINED_PTR_ARM64E +struct dyld_chained_ptr_arm64e_auth_bind +{ + uint64_t ordinal : 16, + zero : 16, + diversity : 16, + addrDiv : 1, + key : 2, + next : 11, // 8-byte stide + bind : 1, // == 1 + auth : 1; // == 1 +}; + +// DYLD_CHAINED_PTR_64 +struct dyld_chained_ptr_64_rebase +{ + uint64_t target : 36, // vmaddr, 64GB max image size + high8 : 8, // top 8 bits set to this after slide added + reserved : 7, // all zeros + next : 12, // 4-byte stride + bind : 1; // == 0 +}; + +// DYLD_CHAINED_PTR_64 +struct dyld_chained_ptr_64_bind +{ + uint64_t ordinal : 24, + addend : 8, // 0 thru 255 + reserved : 19, // all zeros + next : 12, // 4-byte stride + bind : 1; // == 1 +}; + +// DYLD_CHAINED_PTR_32 +// Note: for DYLD_CHAINED_PTR_32 some non-pointer values are co-opted into the chain +// as out of range rebases. If an entry in the chain is > max_valid_pointer, then it +// is not a pointer. To restore the value, subtract off the bias, which is +// (64MB+max_valid_pointer)/2. +struct dyld_chained_ptr_32_rebase +{ + uint32_t target : 26, // vmaddr, 64MB max image size + next : 5, // 4-byte stride + bind : 1; // == 0 +}; + +// DYLD_CHAINED_PTR_32 +struct dyld_chained_ptr_32_bind +{ + uint32_t ordinal : 20, + addend : 6, // 0 thru 63 + next : 5, // 4-byte stride + bind : 1; // == 1 +}; + +// DYLD_CHAINED_PTR_32_CACHE +struct dyld_chained_ptr_32_cache_rebase +{ + uint32_t target : 30, // 1GB max dyld cache TEXT and DATA + next : 2; // 4-byte stride +}; + + +// DYLD_CHAINED_PTR_32_FIRMWARE +struct dyld_chained_ptr_32_firmware_rebase +{ + uint32_t target : 26, // 64MB max firmware TEXT and DATA + next : 6; // 4-byte stride +}; + + + +// values for dyld_chained_fixups_header.imports_format +enum { + DYLD_CHAINED_IMPORT = 1, + DYLD_CHAINED_IMPORT_ADDEND = 2, + DYLD_CHAINED_IMPORT_ADDEND64 = 3, +}; + +// DYLD_CHAINED_IMPORT +struct dyld_chained_import +{ + uint32_t lib_ordinal : 8, + weak_import : 1, + name_offset : 23; +}; + +// DYLD_CHAINED_IMPORT_ADDEND +struct dyld_chained_import_addend +{ + uint32_t lib_ordinal : 8, + weak_import : 1, + name_offset : 23; + int32_t addend; +}; + +// DYLD_CHAINED_IMPORT_ADDEND64 +struct dyld_chained_import_addend64 +{ + uint64_t lib_ordinal : 16, + weak_import : 1, + reserved : 15, + name_offset : 32; + uint64_t addend; +}; + +#endif // __MACH_O_FIXUP_CHAINS__ + diff --git a/cctools/otool/i386_disasm.c b/cctools/otool/i386_disasm.c index 0b60eb8..ec97c10 100644 --- a/cctools/otool/i386_disasm.c +++ b/cctools/otool/i386_disasm.c @@ -57,6 +57,7 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include /* cctools-port: For bcmp, bzero ... */ #include #include #include @@ -134,10 +135,10 @@ static void get_operand( const enum bool mmx, const unsigned int rex, const char *sect, - uint32_t sect_addr, + uint64_t sect_addr, uint32_t *length, uint32_t *left, - const uint32_t addr, + const uint64_t addr, const struct relocation_info *sorted_relocs, const uint32_t nsorted_relocs, const struct relocation_info *ext_relocs, @@ -157,11 +158,11 @@ static void immediate( uint64_t *value, uint32_t value_size, const char *sect, - uint32_t sect_addr, + uint64_t sect_addr, uint32_t *length, uint32_t *left, const cpu_type_t cputype, - const uint32_t addr, + const uint64_t addr, const struct relocation_info *sorted_relocs, const uint32_t nsorted_relocs, const struct relocation_info *ext_relocs, @@ -204,8 +205,8 @@ static void get_symbol( const char **symsub, uint64_t *offset, const cpu_type_t cputype, - const uint32_t sect_offset, - const uint32_t seg_offset, + const uint64_t sect_offset, + const uint64_t seg_offset, const uint64_t value, const struct relocation_info *relocs, const uint32_t nrelocs, @@ -1617,7 +1618,7 @@ static unsigned int xmm_rm(int r_m, int rex) /* * This is passed to the llvm disassembler. */ -struct disassemble_info { +static struct disassemble_info { enum bool verbose; /* Relocation information. */ struct relocation_info *sorted_relocs; @@ -1647,13 +1648,13 @@ struct disassemble_info { uint32_t nindirect_symbols; char *sect; uint32_t left; - uint32_t addr; - uint32_t sect_addr; + uint64_t addr; + uint64_t sect_addr; cpu_type_t cputype; LLVMDisasmContextRef i386_dc; LLVMDisasmContextRef x86_64_dc; char *object_addr; - uint32_t object_size; + uint64_t object_size; struct inst *inst; struct inst *insts; uint32_t ninsts; @@ -1699,7 +1700,7 @@ enum bool llvm_mc, LLVMDisasmContextRef i386_dc, LLVMDisasmContextRef x86_64_dc, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct inst *inst, struct inst *insts, uint32_t ninsts) @@ -1778,8 +1779,8 @@ uint32_t ninsts) dc = i386_dc; else dc = x86_64_dc; - length = llvm_disasm_instruction(dc, (uint8_t *)sect, left, - addr, dst, 8191); + length = (uint32_t)llvm_disasm_instruction(dc, (uint8_t *)sect, + left, addr, dst, 8191); if(length != 0){ if(inst == NULL || inst->print){ /* print the opcode bytes */ @@ -3903,11 +3904,11 @@ const enum bool mmx, const unsigned int rex, const char *sect, -uint32_t sect_addr, +uint64_t sect_addr, uint32_t *length, uint32_t *left, -const uint32_t addr, +const uint64_t addr, const struct relocation_info *sorted_relocs, const uint32_t nsorted_relocs, const struct relocation_info *ext_relocs, @@ -3927,7 +3928,7 @@ const enum bool verbose) uint32_t ss; /* scale-factor from scale-index-byte */ uint32_t index; /* index register number from scale-index-byte*/ uint32_t base; /* base register number from scale-index-byte */ - uint32_t sect_offset, seg_offset; + uint64_t sect_offset, seg_offset; uint64_t offset; *symadd = NULL; @@ -3959,10 +3960,10 @@ const enum bool verbose) if(*value_size != 0){ seg_offset = addr + *length; sect_offset = addr + *length - sect_addr; - *value = get_value(*value_size, sect, length, left); + *value = (uint32_t)get_value(*value_size, sect, length, left); GET_SYMBOL(symadd, symsub, &offset, sect_offset, seg_offset,*value); if(*symadd != NULL){ - *value = offset; + *value = (uint32_t)offset; } else{ *symadd = GUESS_SYMBOL(*value); @@ -4090,12 +4091,12 @@ uint64_t *value, uint32_t value_size, const char *sect, -uint32_t sect_addr, +uint64_t sect_addr, uint32_t *length, uint32_t *left, const cpu_type_t cputype, -const uint32_t addr, +const uint64_t addr, const struct relocation_info *sorted_relocs, const uint32_t nsorted_relocs, const struct relocation_info *ext_relocs, @@ -4110,7 +4111,7 @@ const struct symbol *sorted_symbols, const uint32_t nsorted_symbols, const enum bool verbose) { - uint32_t sect_offset, seg_offset; + uint64_t sect_offset, seg_offset; uint64_t offset; seg_offset = addr + *length; @@ -4160,7 +4161,7 @@ const struct symbol *sorted_symbols, const uint32_t nsorted_symbols, const enum bool verbose) { - uint32_t sect_offset, seg_offset; + uint64_t sect_offset, seg_offset; uint64_t offset; uint64_t guess_addr; @@ -4222,8 +4223,8 @@ const char **symsub, uint64_t *offset, const cpu_type_t cputype, -const uint32_t sect_offset, -const uint32_t seg_offset, +const uint64_t sect_offset, +const uint64_t seg_offset, const uint64_t value, const struct relocation_info *relocs, const uint32_t nrelocs, @@ -4502,9 +4503,9 @@ void *TagBuf) { struct disassemble_info *info; struct LLVMOpInfo1 *op_info; - unsigned int value; - int32_t reloc_found, offset; - uint32_t sect_offset, i, r_address, r_symbolnum, r_type, r_extern, r_length, + uint64_t value; + uint64_t reloc_found, offset; + uint64_t sect_offset, i, r_address, r_symbolnum, r_type, r_extern, r_length, r_value, r_scattered, pair_r_type, pair_r_value, seg_offset; uint32_t other_half; const char *strings, *name, *add, *sub; @@ -4708,9 +4709,9 @@ void *TagBuf) { struct disassemble_info *info; struct LLVMOpInfo1 *op_info; - unsigned int value; + uint64_t value; int32_t reloc_found; - uint32_t sect_offset, seg_offset, i; + uint64_t sect_offset, seg_offset, i; const char *strings, *name; struct relocation_info *relocs; uint32_t nrelocs, strings_size, n_strx; @@ -5020,7 +5021,8 @@ const uint64_t pc, /* pc of the referencing instruction */ uint64_t *reference_type, /* type returned, symbol name or string literal */ struct disassemble_info *info) { - uint32_t reloc_found, sect_offset, i, nrelocs, ncmds, sizeofcmds; + uint32_t reloc_found, i, nrelocs, ncmds, sizeofcmds; + uint64_t sect_offset; struct relocation_info *relocs; struct nlist_64 *symbols; struct load_command *load_commands; @@ -5078,7 +5080,8 @@ struct disassemble_info *info) * And the pointer_value in that section is typically zero as it * will be set by dyld as part of the "bind information". */ - name = get_dyld_bind_info_symbolname(value, info->dbi, info->ndbi); + name = get_dyld_bind_info_symbolname(value, info->dbi, info->ndbi, + CHAIN_FORMAT_NONE, NULL); if(name != NULL){ *reference_type = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; diff --git a/cctools/otool/i386_disasm.h b/cctools/otool/i386_disasm.h index 83d1be6..4850364 100644 --- a/cctools/otool/i386_disasm.h +++ b/cctools/otool/i386_disasm.h @@ -68,7 +68,7 @@ extern uint32_t i386_disassemble( LLVMDisasmContextRef i386_dc, LLVMDisasmContextRef x86_64_dc, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct inst *inst, struct inst *insts, uint32_t ninsts); diff --git a/cctools/otool/m68k_disasm.c b/cctools/otool/m68k_disasm.c index 6c75bde..da084cf 100644 --- a/cctools/otool/m68k_disasm.c +++ b/cctools/otool/m68k_disasm.c @@ -2239,6 +2239,7 @@ enum bool swapped) length = 0; bd_addr = 0; od_addr = 0; + od = bd = 0; switch(mode){ case 0: printf("%s", dregs[reg]); diff --git a/cctools/otool/main.c b/cctools/otool/main.c index bc7e760..0ed7e2c 100644 --- a/cctools/otool/main.c +++ b/cctools/otool/main.c @@ -104,6 +104,7 @@ enum bool Qflag = FALSE; /* use otool's disassembler */ enum bool qflag = FALSE; /* use 'C' Public llvm-mc disassembler */ enum bool jflag = FALSE; /* print opcode bytes */ enum bool Pflag = FALSE; /* print (__TEXT,__info_plist) section as strings */ +enum bool xflag = FALSE; /* print every __text section */ char *pflag = NULL; /* procedure name to start disassembling from */ char *segname = NULL; /* name of the section to print the contents of */ char *sectname = NULL; @@ -112,6 +113,7 @@ char *mcpu = ""; /* the arg of the -mcpu=arg flag */ /* Print function offsets when disassembling when TRUE. */ enum bool function_offsets = FALSE; enum bool print_bind_info = FALSE; /* print dyld bind information */ +enum bool print_dyld_opcodes = FALSE; /* print raw dyld bind/reebase opcodes */ /* this is set when any of the flags that process object files is set */ enum bool object_processing = FALSE; @@ -133,7 +135,7 @@ static void get_symbol_table_info( cpu_type_t cputype, enum byte_sex load_commands_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct nlist **symbols, struct nlist_64 **symbols64, uint32_t *nsymbols, @@ -146,7 +148,7 @@ static void get_toc_info( uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct dylib_table_of_contents **tocs, uint32_t *ntocs); @@ -157,7 +159,7 @@ static void get_module_table_info( cpu_type_t cputype, enum byte_sex load_commands_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct dylib_module **mods, struct dylib_module_64 **mods64, uint32_t *nmods); @@ -168,7 +170,7 @@ static void get_ref_info( uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct dylib_reference **refs, uint32_t *nrefs); @@ -178,7 +180,7 @@ static void get_indirect_symbol_table_info( uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, uint32_t **indirect_symbols, uint32_t *nindirect_symbols); @@ -195,7 +197,7 @@ static void get_hints_table_info( uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct twolevel_hint **hints, uint32_t *nhints); @@ -212,7 +214,7 @@ static void get_link_opt_hints( uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, char **loh, uint32_t *nloh); @@ -229,7 +231,7 @@ static void get_data_in_code_info( uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct data_in_code_entry **dices, uint32_t *ndices); @@ -254,7 +256,7 @@ static void get_linked_reloc_info( uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct relocation_info **ext_relocs, uint32_t *next_relocs, struct relocation_info **loc_relocs, @@ -266,15 +268,24 @@ static void setup_dyld_bind_info( uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct dyld_bind_info **dbi, /* output */ - uint64_t *ndbi); + uint64_t *ndbi, + enum chain_format_t *chain_format); + +static void print_dyld_info_opcodes( + struct load_command *load_commands, + uint32_t ncmds, + uint32_t sizeofcmds, + enum byte_sex load_commands_byte_sex, + char *object_addr, + uint64_t object_size); static void print_text_by_symbols( cpu_type_t cputype, enum byte_sex object_byte_sex, char *sect, - uint32_t size, + uint64_t size, uint64_t addr, uint32_t sect_flags, struct symbol *sorted_symbols, @@ -292,6 +303,7 @@ static void print_text_by_symbols( uint32_t nloc_relocs, struct dyld_bind_info *dbi, uint64_t ndbi, + enum chain_format_t chain_format, uint32_t *indirect_symbols, uint32_t nindirect_symbols, struct load_command *load_commands, @@ -301,7 +313,7 @@ static void print_text_by_symbols( enum bool verbose, cpu_subtype_t cpusubtype, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct data_in_code_entry *dices, uint32_t ndices, uint64_t seg_addr); @@ -310,7 +322,7 @@ static void print_text( cpu_type_t cputype, enum byte_sex object_byte_sex, char *sect, - uint32_t size, + uint64_t size, uint64_t addr, uint32_t sect_flags, struct symbol *sorted_symbols, @@ -328,6 +340,7 @@ static void print_text( uint32_t nloc_relocs, struct dyld_bind_info *dbi, uint64_t ndbi, + enum chain_format_t chain_format, uint32_t *indirect_symbols, uint32_t nindirect_symbols, struct load_command *load_commands, @@ -337,7 +350,7 @@ static void print_text( enum bool verbose, cpu_subtype_t cpusubtype, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct data_in_code_entry *dices, uint32_t ndices, uint64_t seg_addr); @@ -351,7 +364,7 @@ static void print_argstrings( cpu_subtype_t cpusubtype, enum byte_sex load_commands_byte_sex, char *object_addr, - uint32_t object_size); + uint64_t object_size); #else /* defined(LLVM_OTOOL) */ @@ -463,11 +476,17 @@ char **envp) function_offsets = TRUE; continue; } - if(strcmp(argv[i], "-bind_info") == 0){ + if(strcmp(argv[i], "-bind_info") == 0 || + strcmp(argv[i], "-dyld_info") == 0){ print_bind_info = TRUE; object_processing = TRUE; continue; } + if(strcmp(argv[i], "-dyld_opcodes") == 0){ + print_dyld_opcodes = TRUE; + object_processing = TRUE; + continue; + } if(strncmp(argv[i], "-mcpu=", sizeof("-mcpu=")-1) == 0){ mcpu = argv[i] + sizeof("-mcpu=")-1; if(*mcpu == '\0'){ @@ -638,6 +657,10 @@ char **envp) Pflag = TRUE; object_processing = TRUE; break; + case 'x': + xflag = TRUE; + object_processing = TRUE; + break; default: error("unknown char `%c' in flag %s\n", argv[i][j],argv[i]); usage(); @@ -650,9 +673,10 @@ char **envp) */ if(!fflag && !aflag && !hflag && !lflag && !Lflag && !tflag && !dflag && !oflag && !Oflag && !rflag && !Tflag && !Mflag && !Rflag && !Iflag && - !Cflag && !print_bind_info && !version && !Pflag && - !Hflag && !Gflag && !Sflag && !cflag && !iflag && !Dflag &&!segname){ - error("one of -fahlLtdoOrTMRIHCGScisP or --version must be " + !Cflag && !print_bind_info && !print_dyld_opcodes && !version && + !Pflag && !xflag && !Hflag && !Gflag && !Sflag && !cflag && !iflag && + !Dflag &&!segname){ + error("one of -fahlLtdoOrTMRIHCGScisPx or --version must be " "specified"); usage(); } @@ -728,6 +752,7 @@ void) fprintf(stderr, "\t-L print shared libraries used\n"); fprintf(stderr, "\t-D print shared library id name\n"); fprintf(stderr, "\t-t print the text section (disassemble with -v)\n"); + fprintf(stderr, "\t-x print all text sections (disassemble with -v)\n"); fprintf(stderr, "\t-p start dissassemble from routine " "name\n"); fprintf(stderr, "\t-s print contents of " @@ -735,15 +760,35 @@ void) fprintf(stderr, "\t-d print the data section\n"); fprintf(stderr, "\t-o print the Objective-C segment\n"); fprintf(stderr, "\t-r print the relocation entries\n"); - fprintf(stderr, "\t-S print the table of contents of a library\n"); + fprintf(stderr, "\t-S print the table of contents of a library"); +#ifdef LLVM_OTOOL + fprintf(stderr, " (obsolete)"); +#endif /* LLVM_OTOOL */ + fprintf(stderr, "\n"); fprintf(stderr, "\t-T print the table of contents of a dynamic " - "shared library\n"); + "shared library"); +#ifdef LLVM_OTOOL + fprintf(stderr, " (obsolete)"); +#endif /* LLVM_OTOOL */ + fprintf(stderr, "\n"); fprintf(stderr, "\t-M print the module table of a dynamic shared " - "library\n"); + "library"); +#ifdef LLVM_OTOOL + fprintf(stderr, " (obsolete)"); +#endif /* LLVM_OTOOL */ + fprintf(stderr, "\n"); fprintf(stderr, "\t-R print the reference table of a dynamic shared " - "library\n"); + "library"); +#ifdef LLVM_OTOOL + fprintf(stderr, " (obsolete)"); +#endif /* LLVM_OTOOL */ + fprintf(stderr, "\n"); fprintf(stderr, "\t-I print the indirect symbol table\n"); - fprintf(stderr, "\t-H print the two-level hints table\n"); + fprintf(stderr, "\t-H print the two-level hints table"); +#ifdef LLVM_OTOOL + fprintf(stderr, " (obsolete)"); +#endif /* LLVM_OTOOL */ + fprintf(stderr, "\n"); fprintf(stderr, "\t-G print the data in code table\n"); fprintf(stderr, "\t-v print verbosely (symbolically) when possible\n"); fprintf(stderr, "\t-V print disassembled operands symbolically\n"); @@ -794,7 +839,15 @@ enum bool version) add_execute_list("-private-header"); if(lflag) add_execute_list("-private-headers"); - if(tflag){ + if(xflag){ + if(vflag) + add_execute_list("-disassemble-all"); + else{ + add_execute_list("-section"); + add_execute_list(",__text"); + } + } + else if(tflag){ if(vflag) add_execute_list("-disassemble"); else{ @@ -802,7 +855,7 @@ enum bool version) add_execute_list("__TEXT,__text"); } } - if(tflag || segname != NULL){ + if(tflag || xflag || segname != NULL){ add_execute_list("-full-leading-addr"); add_execute_list("-print-imm-hex"); } @@ -845,12 +898,14 @@ enum bool version) if(!vflag) add_execute_list("-non-verbose"); - if(!Vflag && (tflag || segname != NULL)) + if(!Vflag && (tflag || xflag || segname != NULL)) add_execute_list("-no-symbolic-operands"); - if((!jflag && (tflag || segname != NULL)) || no_show_raw_insn) + if((!jflag && (tflag || xflag || segname != NULL)) || no_show_raw_insn) add_execute_list("-no-show-raw-insn"); - if(Xflag) + if(Xflag){ add_execute_list("-no-leading-addr"); + add_execute_list("-no-leading-headers"); + } if(all_archs){ add_execute_list("-arch"); @@ -887,7 +942,8 @@ enum bool version) add_execute_list(files[i]); if(execute_list(show_objdump_command) == 0) - fatal("internal objdump command failed"); + /* Internal objdump command failed. */ + exit(EXIT_FAILURE); } #else /* !defined(LLVM_OTOOL) */ @@ -908,7 +964,8 @@ void *cookie) /* cookie is not used */ cpu_subtype_t mh_cpusubtype; uint32_t mh_magic, mh_filetype, mh_ncmds, mh_sizeofcmds, sizeof_mach_header; struct load_command *load_commands; - uint32_t nsymbols, nsorted_symbols, strings_size, len; + uint32_t nsymbols, nsorted_symbols, strings_size; + size_t len; struct nlist *symbols, *allocated_symbols; struct nlist_64 *symbols64, *allocated_symbols64; struct symbol *sorted_symbols; @@ -936,7 +993,10 @@ void *cookie) /* cookie is not used */ uint32_t nloh; struct dyld_bind_info *dbi; uint64_t ndbi; + enum chain_format_t chain_format; uint64_t big_size; + char** segnames; + uint32_t nsegname; sorted_symbols = NULL; nsorted_symbols = 0; @@ -953,6 +1013,14 @@ void *cookie) /* cookie is not used */ nmods = 0; mods64 = NULL; mods = NULL; + strings_size = 0; + sect_relocs = 0; + sect_nrelocs = 0; + sect = NULL; + sect_size = 0; + sect_addr = 0; + seg_addr = 0; + chain_format = CHAIN_FORMAT_NONE; /* * These may or may not be allocated. If allocated they will not be * NULL and then free'ed before returning. @@ -968,7 +1036,9 @@ void *cookie) /* cookie is not used */ allocated_hints = NULL; allocated_dices = NULL; dbi = NULL; + segnames = NULL; ndbi = 0; + nsegname = 0; /* * The fat headers are printed in ofile_map() in ofile.c #ifdef'ed @@ -979,7 +1049,7 @@ void *cookie) /* cookie is not used */ * Archive headers. */ if(aflag && ofile->member_ar_hdr != NULL){ - uint32_t member_offset; + uint64_t member_offset; member_offset = ofile->member_offset - sizeof(struct ar_hdr); if(strncmp(ofile->member_ar_hdr->ar_name, AR_EFMT1, @@ -999,8 +1069,16 @@ void *cookie) /* cookie is not used */ if(Sflag == FALSE) return; if(ofile->file_type == OFILE_FAT){ - addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset; - size = ofile->fat_archs[ofile->narch].size; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + addr = ofile->file_addr + + ofile->fat_archs64[ofile->narch].offset; + size = ofile->fat_archs64[ofile->narch].size; + } + else{ + addr = ofile->file_addr + + ofile->fat_archs[ofile->narch].offset; + size = ofile->fat_archs[ofile->narch].size; + } } else{ addr = ofile->file_addr; @@ -1080,9 +1158,16 @@ void *cookie) /* cookie is not used */ size = ofile->member_size; } else{ - addr = ofile->file_addr + - ofile->fat_archs[ofile->narch].offset; - size = ofile->fat_archs[ofile->narch].size; + if(ofile->fat_header->magic == FAT_MAGIC_64){ + addr = ofile->file_addr + + ofile->fat_archs64[ofile->narch].offset; + size = ofile->fat_archs64[ofile->narch].size; + } + else{ + addr = ofile->file_addr + + ofile->fat_archs[ofile->narch].offset; + size = ofile->fat_archs[ofile->narch].size; + } } if(addr + size > ofile->file_addr + ofile->file_size) size = (ofile->file_addr + ofile->file_size) - addr; @@ -1240,8 +1325,13 @@ void *cookie) /* cookie is not used */ * appear to be in an infinite loop printing the zero's we created * with the memset(). */ - if(size > sizeof_mach_header) - mh_sizeofcmds = size - sizeof_mach_header; + if(size > sizeof_mach_header) { + uint64_t mh_sizeofcmds64 = size - sizeof_mach_header; + if (mh_sizeofcmds64 > 0xFFFFFFFF) + printf("load commands do not fit in 2^32 bytes, " + "truncating\n"); + mh_sizeofcmds = (uint32_t)mh_sizeofcmds64; + } else mh_sizeofcmds = sizeof(struct load_command); load_commands = allocate(mh_sizeofcmds); @@ -1277,7 +1367,7 @@ void *cookie) /* cookie is not used */ * the section contents of one of these sections in a MH_DYLIB_STUB * we assume it has been stripped and set the section size to zero. */ - if(mh_filetype == MH_DYLIB_STUB && + if((mh_filetype == MH_DYLIB_STUB || mh_filetype == MH_DSYM) && ((sect_flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS || (sect_flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS || (sect_flags & SECTION_TYPE) == S_LAZY_DYLIB_SYMBOL_POINTERS || @@ -1288,8 +1378,8 @@ void *cookie) /* cookie is not used */ get_symbol_table_info(ofile->load_commands, mh_ncmds, mh_sizeofcmds, mh_cputype, ofile->object_byte_sex, addr, size, &symbols, &symbols64, &nsymbols, &strings, &strings_size); - if(vflag && (rflag || Tflag || Mflag || Rflag || Iflag || Hflag || tflag - || iflag || oflag || + if((vflag && (rflag || Tflag || Mflag || Rflag || Iflag || Hflag || + tflag || iflag || oflag || xflag || (sect_flags & SECTION_TYPE) == S_LITERAL_POINTERS || (sect_flags & SECTION_TYPE) == S_MOD_INIT_FUNC_POINTERS || (sect_flags & SECTION_TYPE) == S_MOD_TERM_FUNC_POINTERS || @@ -1297,7 +1387,8 @@ void *cookie) /* cookie is not used */ S_ATTR_PURE_INSTRUCTIONS || (sect_flags & S_ATTR_SOME_INSTRUCTIONS) == S_ATTR_SOME_INSTRUCTIONS || - segname != NULL)){ + segname != NULL)) || + (oflag && (mh_cputype & CPU_ARCH_ABI64) != 0)){ get_symbol_table_info(ofile->load_commands, mh_ncmds, mh_sizeofcmds, mh_cputype, ofile->object_byte_sex, addr, size, &symbols, &symbols64, &nsymbols, &strings, &strings_size); @@ -1330,7 +1421,7 @@ void *cookie) /* cookie is not used */ /* * If the operation needs a sorted symbol table create it. */ - if(tflag || iflag || oflag || + if(tflag || iflag || oflag || xflag || (((sect_flags & SECTION_TYPE) == S_MOD_INIT_FUNC_POINTERS || (sect_flags & SECTION_TYPE) == S_MOD_TERM_FUNC_POINTERS) && Vflag) || @@ -1383,6 +1474,15 @@ void *cookie) /* cookie is not used */ } } + /* + * if xflag, build a list of segment names in this ofile. + */ + if(xflag) { + get_seg_names(ofile->load_commands, mh_ncmds, mh_sizeofcmds, + ofile->object_byte_sex, SECT_TEXT, &segnames, + &nsegname); + } + if(Mflag || Tflag || Rflag){ get_module_table_info(ofile->load_commands, mh_ncmds, mh_sizeofcmds, mh_cputype, ofile->object_byte_sex, addr, size, &mods, &mods64, @@ -1457,7 +1557,7 @@ void *cookie) /* cookie is not used */ nsymbols, strings, strings_size, vflag); } - if(Iflag || (tflag && vflag)){ + if(Iflag || (tflag && vflag) || (xflag && vflag)){ get_indirect_symbol_table_info(ofile->load_commands, mh_ncmds, mh_sizeofcmds, ofile->object_byte_sex, addr, size, &indirect_symbols, &nindirect_symbols); @@ -1495,7 +1595,8 @@ void *cookie) /* cookie is not used */ ofile->object_byte_sex, addr, size, &loh, &nloh); print_link_opt_hints(loh, nloh); } - if(Gflag || (tflag && vflag)){ + if((Gflag || (tflag && vflag) || (xflag && vflag)) && + (mh_filetype != MH_DYLIB_STUB && mh_filetype != MH_DSYM)){ get_data_in_code_info(ofile->load_commands, mh_ncmds, mh_sizeofcmds, ofile->object_byte_sex, addr, size, &dices, &ndices); if((intptr_t)dices % sizeof(uint32_t) || @@ -1521,113 +1622,135 @@ void *cookie) /* cookie is not used */ print_reloc(ofile->load_commands, mh_ncmds, mh_sizeofcmds, mh_cputype, ofile->object_byte_sex, addr, size, symbols, symbols64, nsymbols, strings, strings_size, vflag); + if(print_dyld_opcodes){ + print_dyld_info_opcodes(ofile->load_commands, mh_ncmds, + mh_sizeofcmds, ofile->object_byte_sex, + ofile->object_addr, ofile->object_size); + } if(print_bind_info){ setup_dyld_bind_info(ofile->load_commands, mh_ncmds, mh_sizeofcmds, ofile->object_byte_sex, ofile->object_addr, ofile->object_size, - &dbi, &ndbi); + &dbi, &ndbi, &chain_format); print_dyld_bind_info(dbi, ndbi); } - if(tflag || + if(tflag || xflag || (sect_flags & S_ATTR_PURE_INSTRUCTIONS) == S_ATTR_PURE_INSTRUCTIONS || (sect_flags & S_ATTR_SOME_INSTRUCTIONS) == S_ATTR_SOME_INSTRUCTIONS){ - if(tflag) - (void)get_sect_info(SEG_TEXT, SECT_TEXT, ofile->load_commands, - mh_ncmds, mh_sizeofcmds, mh_filetype, - ofile->object_byte_sex, - addr, size, §, §_size, §_addr, - §_relocs, §_nrelocs, §_flags, &seg_addr); - - /* create aligned relocations entries as needed */ - relocs = NULL; - nrelocs = 0; - ext_relocs = NULL; - next_relocs = 0; - loc_relocs = NULL; - nloc_relocs = 0; - if(Vflag){ - if(mh_filetype == MH_KEXT_BUNDLE){ - get_linked_reloc_info(ofile->load_commands, mh_ncmds, + /* loop over every segment looking for text */ + for(i = 0; !xflag || i < nsegname; i++){ + if(tflag) + (void)get_sect_info(SEG_TEXT, SECT_TEXT, + ofile->load_commands, mh_ncmds, mh_sizeofcmds, + mh_filetype, ofile->object_byte_sex, addr, size, §, + §_size, §_addr, §_relocs, §_nrelocs, + §_flags, &seg_addr); + else if(xflag) + (void)get_sect_info(segnames[i], SECT_TEXT, + ofile->load_commands, mh_ncmds, mh_sizeofcmds, + mh_filetype, ofile->object_byte_sex, addr, size, §, + §_size, §_addr, §_relocs, §_nrelocs, + §_flags, &seg_addr); + + /* create aligned relocations entries as needed */ + relocs = NULL; + nrelocs = 0; + ext_relocs = NULL; + next_relocs = 0; + loc_relocs = NULL; + nloc_relocs = 0; + if(Vflag){ + if(mh_filetype == MH_KEXT_BUNDLE){ + get_linked_reloc_info(ofile->load_commands, mh_ncmds, mh_sizeofcmds, ofile->object_byte_sex, ofile->object_addr, ofile->object_size, &ext_relocs, &next_relocs, &loc_relocs, &nloc_relocs); - /* create aligned relocations entries as needed */ - if((intptr_t)ext_relocs % sizeof(int32_t) != 0 || + /* create aligned relocations entries as needed */ + if((intptr_t)ext_relocs % sizeof(int32_t) != 0 || + ofile->object_byte_sex != get_host_byte_sex()){ + relocs = allocate(next_relocs * + sizeof(struct relocation_info)); + memcpy(relocs, ext_relocs, next_relocs * + sizeof(struct relocation_info)); + ext_relocs = relocs; + } + if((intptr_t)loc_relocs % sizeof(int32_t) != 0 || + ofile->object_byte_sex != get_host_byte_sex()){ + relocs = allocate(nloc_relocs * + sizeof(struct relocation_info)); + memcpy(relocs, loc_relocs, nloc_relocs * + sizeof(struct relocation_info)); + loc_relocs = relocs; + } + if(ofile->object_byte_sex != get_host_byte_sex()){ + swap_relocation_info(ext_relocs, next_relocs, + get_host_byte_sex()); + swap_relocation_info(loc_relocs, nloc_relocs, + get_host_byte_sex()); + } + relocs = NULL; + } + if((intptr_t)sect_relocs % sizeof(int32_t) != 0 || ofile->object_byte_sex != get_host_byte_sex()){ - relocs = allocate(next_relocs * + nrelocs = sect_nrelocs; + relocs = allocate(nrelocs * sizeof(struct relocation_info)); - memcpy(relocs, ext_relocs, next_relocs * + memcpy(relocs, sect_relocs, nrelocs * sizeof(struct relocation_info)); - ext_relocs = relocs; } - if((intptr_t)loc_relocs % sizeof(int32_t) != 0 || - ofile->object_byte_sex != get_host_byte_sex()){ - relocs = allocate(nloc_relocs * - sizeof(struct relocation_info)); - memcpy(relocs, loc_relocs, nloc_relocs * - sizeof(struct relocation_info)); - loc_relocs = relocs; + else{ + nrelocs = sect_nrelocs; + relocs = sect_relocs; } - if(ofile->object_byte_sex != get_host_byte_sex()){ - swap_relocation_info(ext_relocs, next_relocs, - get_host_byte_sex()); - swap_relocation_info(loc_relocs, nloc_relocs, + if(ofile->object_byte_sex != get_host_byte_sex()) + swap_relocation_info(relocs, nrelocs, get_host_byte_sex()); + setup_dyld_bind_info(ofile->load_commands, mh_ncmds, + mh_sizeofcmds, ofile->object_byte_sex, + ofile->object_addr, ofile->object_size, + &dbi, &ndbi, &chain_format); + } + if(Xflag == FALSE){ + if(tflag) + printf("(%s,%s) section\n", SEG_TEXT, SECT_TEXT); + else if(xflag){ + if (mh_filetype == MH_OBJECT) + printf("(%s,%s) section\n", SEG_TEXT, SECT_TEXT); + else + printf("(%s,%s) section\n", segnames[i], SECT_TEXT); } - relocs = NULL; + else + printf("Contents of (%.16s,%.16s) section\n", segname, + sectname); } - if((intptr_t)sect_relocs % sizeof(int32_t) != 0 || - ofile->object_byte_sex != get_host_byte_sex()){ - nrelocs = sect_nrelocs; - relocs = allocate(nrelocs * - sizeof(struct relocation_info)); - memcpy(relocs, sect_relocs, nrelocs * - sizeof(struct relocation_info)); - } - else{ - nrelocs = sect_nrelocs; - relocs = sect_relocs; - } - if(ofile->object_byte_sex != get_host_byte_sex()) - swap_relocation_info(relocs, nrelocs, - get_host_byte_sex()); - setup_dyld_bind_info(ofile->load_commands, mh_ncmds, - mh_sizeofcmds, ofile->object_byte_sex, - ofile->object_addr, ofile->object_size, - &dbi, &ndbi); - } - if(Xflag == FALSE){ - if(tflag) - printf("(%s,%s) section\n", SEG_TEXT, SECT_TEXT); + if(Uflag) + print_text_by_symbols(mh_cputype, ofile->object_byte_sex, + sect, sect_size, sect_addr, sect_flags, sorted_symbols, + nsorted_symbols, symbols, symbols64, nsymbols, strings, + strings_size, relocs, nrelocs, ext_relocs, next_relocs, + loc_relocs, nloc_relocs, dbi, ndbi, chain_format, + indirect_symbols, nindirect_symbols, + ofile->load_commands, mh_ncmds, mh_sizeofcmds, vflag, + Vflag, mh_cpusubtype, ofile->object_addr, + ofile->object_size, dices, ndices, seg_addr); else - printf("Contents of (%.16s,%.16s) section\n", segname, - sectname); + print_text(mh_cputype, ofile->object_byte_sex, sect, + sect_size, sect_addr, sect_flags, sorted_symbols, + nsorted_symbols, symbols, symbols64, nsymbols, strings, + strings_size, relocs, nrelocs, ext_relocs, next_relocs, + loc_relocs, nloc_relocs, dbi, ndbi, chain_format, + indirect_symbols, nindirect_symbols, + ofile->load_commands, mh_ncmds, mh_sizeofcmds, vflag, + Vflag, mh_cpusubtype, ofile->object_addr, + ofile->object_size, dices, ndices, seg_addr); + + if(relocs != NULL && relocs != sect_relocs) + free(relocs); + if (!xflag) + break; } - if(Uflag) - print_text_by_symbols(mh_cputype, ofile->object_byte_sex, sect, - sect_size, sect_addr, sect_flags, sorted_symbols, - nsorted_symbols, symbols, symbols64, nsymbols, strings, - strings_size, relocs, nrelocs, ext_relocs, next_relocs, - loc_relocs, nloc_relocs, dbi, ndbi, indirect_symbols, - nindirect_symbols, ofile->load_commands, mh_ncmds, - mh_sizeofcmds, vflag, Vflag, mh_cpusubtype, - ofile->object_addr, ofile->object_size, dices, ndices, - seg_addr); - else - print_text(mh_cputype, ofile->object_byte_sex, sect, sect_size, - sect_addr, sect_flags, sorted_symbols, - nsorted_symbols, symbols, symbols64, nsymbols, strings, - strings_size, relocs, nrelocs, ext_relocs, next_relocs, - loc_relocs, nloc_relocs, dbi, ndbi, indirect_symbols, - nindirect_symbols, ofile->load_commands, mh_ncmds, - mh_sizeofcmds, vflag, Vflag, mh_cpusubtype, - ofile->object_addr, ofile->object_size, dices, ndices, - seg_addr); - - if(relocs != NULL && relocs != sect_relocs) - free(relocs); } if(iflag){ @@ -1650,9 +1773,9 @@ void *cookie) /* cookie is not used */ printf("Shared library initialization (%s,%s) section\n", SEG_TEXT, SECT_FVMLIB_INIT0); print_shlib_init(ofile->object_byte_sex, sect, sect_size, - sect_addr, sorted_symbols, nsorted_symbols, symbols, - symbols64, nsymbols, strings, strings_size, relocs, - nrelocs, vflag); + sect_addr, sorted_symbols, nsorted_symbols, symbols, + symbols64, nsymbols, strings, strings_size, relocs, + nrelocs, vflag); free(relocs); } } @@ -1665,8 +1788,9 @@ void *cookie) /* cookie is not used */ if(Xflag == FALSE) printf("(%s,%s) section\n", SEG_DATA, SECT_DATA); - print_sect(mh_cputype, ofile->object_byte_sex, sect, sect_size, - sect_addr); + if(sect != NULL) + print_sect(mh_cputype, ofile->object_byte_sex, sect, + sect_size, sect_addr); } } @@ -1788,10 +1912,10 @@ void *cookie) /* cookie is not used */ get_host_byte_sex()); qsort(relocs, nrelocs, sizeof(struct relocation_info), (int (*)(const void *, const void *))rel_compare); - print_literal_pointer_section(mh_cputype, + print_literal_pointer_section(mh_cputype, mh_cpusubtype, ofile->load_commands, mh_ncmds, mh_sizeofcmds, - ofile->object_byte_sex, addr, size, sect, - sect_size, sect_addr, symbols, symbols64, + mh_filetype, ofile->object_byte_sex, addr, size, + sect, sect_size, sect_addr, symbols, symbols64, nsymbols, strings, strings_size, relocs, nrelocs, Xflag == TRUE ? FALSE : TRUE); free(relocs); @@ -1800,9 +1924,22 @@ void *cookie) /* cookie is not used */ case S_MOD_INIT_FUNC_POINTERS: case S_MOD_TERM_FUNC_POINTERS: + /* create aligned, sorted relocations entries */ + nrelocs = sect_nrelocs; + relocs = allocate(nrelocs * + sizeof(struct relocation_info)); + memcpy(relocs, sect_relocs, nrelocs * + sizeof(struct relocation_info)); + if(ofile->object_byte_sex != get_host_byte_sex()) + swap_relocation_info(relocs, nrelocs, + get_host_byte_sex()); + qsort(relocs, nrelocs, sizeof(struct relocation_info), + (int (*)(const void *, const void *))rel_compare); print_init_term_pointer_section(mh_cputype, sect, sect_size, sect_addr, ofile->object_byte_sex, - sorted_symbols, nsorted_symbols, Vflag); + sorted_symbols, nsorted_symbols, symbols, symbols64, + nsymbols, strings, strings_size, relocs, nrelocs, + Vflag); break; default: @@ -1864,15 +2001,17 @@ void *cookie) /* cookie is not used */ setup_dyld_bind_info(ofile->load_commands, mh_ncmds, mh_sizeofcmds, ofile->object_byte_sex, ofile->object_addr, ofile->object_size, - &dbi, &ndbi); - print_objc2_64bit(mh_cputype, ofile->load_commands, mh_ncmds, - mh_sizeofcmds, ofile->object_byte_sex, - ofile->object_addr, ofile->object_size, symbols64, - nsymbols, strings, strings_size, sorted_symbols, - nsorted_symbols, ext_relocs, next_relocs, - loc_relocs, nloc_relocs, dbi, ndbi, vflag, Vflag); + &dbi, &ndbi, &chain_format); + print_objc2_64bit(mh_cputype, mh_cpusubtype, + ofile->load_commands, mh_ncmds, mh_sizeofcmds, + ofile->object_byte_sex, ofile->object_addr, + ofile->object_size, symbols64, nsymbols, strings, + strings_size, sorted_symbols, nsorted_symbols, + ext_relocs, next_relocs, loc_relocs, nloc_relocs, + dbi, ndbi, chain_format, vflag, Vflag); } - else if(mh_cputype == CPU_TYPE_ARM){ + else if(mh_cputype == CPU_TYPE_ARM || + mh_cputype & CPU_ARCH_ABI64_32){ get_linked_reloc_info(ofile->load_commands, mh_ncmds, mh_sizeofcmds, ofile->object_byte_sex, ofile->object_addr, ofile->object_size, &ext_relocs, @@ -1902,12 +2041,17 @@ void *cookie) /* cookie is not used */ swap_relocation_info(loc_relocs, nloc_relocs, get_host_byte_sex()); } + setup_dyld_bind_info(ofile->load_commands, mh_ncmds, + mh_sizeofcmds, ofile->object_byte_sex, + ofile->object_addr, ofile->object_size, + &dbi, &ndbi, &chain_format); print_objc2_32bit(mh_cputype, ofile->load_commands, mh_ncmds, mh_sizeofcmds, ofile->object_byte_sex, ofile->object_addr, ofile->object_size, symbols, nsymbols, strings, strings_size, sorted_symbols, nsorted_symbols, ext_relocs, next_relocs, - loc_relocs, nloc_relocs, vflag); + loc_relocs, nloc_relocs, dbi, ndbi, chain_format, + vflag); } else{ /* @@ -1950,12 +2094,17 @@ void *cookie) /* cookie is not used */ swap_relocation_info(loc_relocs, nloc_relocs, get_host_byte_sex()); } + setup_dyld_bind_info(ofile->load_commands, mh_ncmds, + mh_sizeofcmds, ofile->object_byte_sex, + ofile->object_addr, ofile->object_size, + &dbi, &ndbi, &chain_format); print_objc2_32bit(mh_cputype, ofile->load_commands, mh_ncmds, mh_sizeofcmds, ofile->object_byte_sex, ofile->object_addr, ofile->object_size, symbols, nsymbols, strings, strings_size, sorted_symbols, nsorted_symbols, ext_relocs, next_relocs, - loc_relocs, nloc_relocs, vflag); + loc_relocs, nloc_relocs, dbi, ndbi, chain_format, + vflag); } } } @@ -1980,6 +2129,12 @@ void *cookie) /* cookie is not used */ free(allocated_refs); if(dbi != NULL) free(dbi); + if(segnames != NULL) { + for (uint32_t i = 0; i < nsegname; ++i) { + free(segnames[i]); + } + free(segnames); + } } /* @@ -2000,7 +2155,7 @@ uint32_t sizeofcmds, cpu_type_t cputype, enum byte_sex load_commands_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct nlist **symbols, /* output */ struct nlist_64 **symbols64, uint32_t *nsymbols, @@ -2037,7 +2192,7 @@ uint32_t *strings_size) (char *)load_commands + sizeofcmds) printf("load command %u extends past end of load " "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_SYMTAB: @@ -2080,8 +2235,8 @@ uint32_t *strings_size) bigsize += st.symoff; if(bigsize > object_size){ printf("symbol table extends past end of file\n"); - *nsymbols = (object_size - st.symoff) / - sizeof(struct nlist_64); + *nsymbols = (uint32_t)((object_size - st.symoff) / + sizeof(struct nlist_64)); } else *nsymbols = st.nsyms; @@ -2093,8 +2248,8 @@ uint32_t *strings_size) bigsize += st.symoff; if(bigsize > object_size){ printf("symbol table extends past end of file\n"); - *nsymbols = (object_size - st.symoff) / - sizeof(struct nlist); + *nsymbols = (uint32_t)((object_size - st.symoff) / + sizeof(struct nlist)); } else *nsymbols = st.nsyms; @@ -2132,7 +2287,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct dylib_table_of_contents **tocs, /* output */ uint32_t *ntocs) { @@ -2157,8 +2312,8 @@ uint32_t *ntocs) bigsize += dyst.tocoff; if(bigsize > object_size){ printf("table of contents extends past end of file\n"); - *ntocs = (object_size - dyst.tocoff) / - sizeof(struct dylib_table_of_contents); + *ntocs = (uint32_t)((object_size - dyst.tocoff) / + sizeof(struct dylib_table_of_contents)); } else *ntocs = dyst.ntoc; @@ -2182,7 +2337,7 @@ uint32_t sizeofcmds, cpu_type_t cputype, enum byte_sex load_commands_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct dylib_module **mods, /* output */ struct dylib_module_64 **mods64, uint32_t *nmods) @@ -2210,8 +2365,8 @@ uint32_t *nmods) bigsize += dyst.modtaboff; if(bigsize > object_size){ printf("module table extends past end of file\n"); - *nmods = (object_size - dyst.modtaboff) / - sizeof(struct dylib_module_64); + *nmods = (uint32_t)((object_size - dyst.modtaboff) / + sizeof(struct dylib_module_64)); } else *nmods = dyst.nmodtab; @@ -2221,8 +2376,8 @@ uint32_t *nmods) if(dyst.modtaboff + dyst.nmodtab * sizeof(struct dylib_module) > object_size){ printf("module table extends past end of file\n"); - *nmods = (object_size - dyst.modtaboff) / - sizeof(struct dylib_module); + *nmods = (uint32_t)((object_size - dyst.modtaboff) / + sizeof(struct dylib_module)); } else *nmods = dyst.nmodtab; @@ -2246,7 +2401,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct dylib_reference **refs, /* output */ uint32_t *nrefs) { @@ -2270,8 +2425,8 @@ uint32_t *nrefs) bigsize += dyst.extrefsymoff; if(bigsize > object_size){ printf("reference table extends past end of file\n"); - *nrefs = (object_size - dyst.extrefsymoff) / - sizeof(struct dylib_reference); + *nrefs = (uint32_t)((object_size - dyst.extrefsymoff) / + sizeof(struct dylib_reference)); } else *nrefs = dyst.nextrefsyms; @@ -2294,7 +2449,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, uint32_t **indirect_symbols, /* output */ uint32_t *nindirect_symbols) { @@ -2318,8 +2473,9 @@ uint32_t *nindirect_symbols) bigsize += dyst.indirectsymoff; if(bigsize > object_size){ printf("indirect symbol table extends past end of file\n"); - *nindirect_symbols = (object_size - dyst.indirectsymoff) / - sizeof(uint32_t); + *nindirect_symbols = (uint32_t)((object_size - + dyst.indirectsymoff) / + sizeof(uint32_t)); } else *nindirect_symbols = dyst.nindirectsyms; @@ -2361,7 +2517,7 @@ struct dysymtab_command *dyst) (char *)load_commands + sizeofcmds) printf("load command %u extends past end of load " "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_DYSYMTAB: @@ -2412,7 +2568,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct twolevel_hint **hints, /* output */ uint32_t *nhints) { @@ -2437,8 +2593,8 @@ uint32_t *nhints) bigsize += hints_cmd.offset; if(bigsize > object_size){ printf("two-level hints table extends past end of file\n"); - *nhints = (object_size - hints_cmd.offset) / - sizeof(struct twolevel_hint); + *nhints = (uint32_t)((object_size - hints_cmd.offset) / + sizeof(struct twolevel_hint)); } else *nhints = hints_cmd.nhints; @@ -2480,7 +2636,7 @@ struct twolevel_hints_command *hints_cmd) (char *)load_commands + sizeofcmds) printf("load command %u extends past end of load " "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_TWOLEVEL_HINTS: @@ -2530,7 +2686,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, char **loh, uint32_t *nloh) { @@ -2554,7 +2710,7 @@ uint32_t *nloh) bigsize += loh_cmd.datasize; if(bigsize > object_size){ printf("linker optimization hints extends past end of file\n"); - *nloh = object_size - loh_cmd.dataoff; + *nloh = (uint32_t)object_size - loh_cmd.dataoff; } else *nloh = loh_cmd.datasize; @@ -2596,7 +2752,7 @@ struct linkedit_data_command *loh_cmd) (char *)load_commands + sizeofcmds) printf("load command %u extends past end of load " "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_LINKER_OPTIMIZATION_HINT: @@ -2648,7 +2804,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct data_in_code_entry **dices, /* output */ uint32_t *ndices) { @@ -2673,8 +2829,8 @@ uint32_t *ndices) bigsize += dices_cmd.dataoff; if(bigsize > object_size){ printf("data in code table extends past end of file\n"); - *ndices = (object_size - dices_cmd.dataoff) / - sizeof(struct data_in_code_entry); + *ndices = (uint32_t)((object_size - dices_cmd.dataoff) / + sizeof(struct data_in_code_entry)); } else *ndices = dices_cmd.datasize / @@ -2717,7 +2873,7 @@ struct linkedit_data_command *dices_cmd) (char *)load_commands + sizeofcmds) printf("load command %u extends past end of load " "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_DATA_IN_CODE: @@ -2813,7 +2969,7 @@ uint32_t sizeofcmds, uint32_t filetype, enum byte_sex load_commands_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, char **sect_pointer, /* output */ uint64_t *sect_size, uint64_t *sect_addr, @@ -2857,7 +3013,7 @@ uint64_t *seg_addr) (char *)load_commands + sizeofcmds) printf("load command %u extends past end of load " "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_SEGMENT: @@ -2878,7 +3034,7 @@ uint64_t *seg_addr) printf("section structure command extends past " "end of load commands\n"); } - left = sizeofcmds - (p - (char *)load_commands); + left = sizeofcmds - (uint32_t)(p - (char *)load_commands); memset((char *)&s, '\0', sizeof(struct section)); size = left < sizeof(struct section) ? left : sizeof(struct section); @@ -2920,7 +3076,7 @@ uint64_t *seg_addr) printf("section structure command extends past " "end of load commands\n"); } - left = sizeofcmds - (p - (char *)load_commands); + left = sizeofcmds - (uint32_t)(p - (char *)load_commands); memset((char *)&s64, '\0', sizeof(struct section_64)); size = left < sizeof(struct section_64) ? left : sizeof(struct section_64); @@ -2958,6 +3114,8 @@ uint64_t *seg_addr) return(FALSE); if(cmd == LC_SEGMENT){ + if(filetype == MH_DSYM && sg.fileoff == 0 && sg.filesize == 0) + return(TRUE); if((s.flags & SECTION_TYPE) == S_ZEROFILL){ *sect_pointer = NULL; *sect_size = s.size; @@ -2990,8 +3148,8 @@ uint64_t *seg_addr) object_size){ printf("relocation entries for section (%.16s,%.16s) " "extends past end of file\n", s.segname, s.sectname); - *sect_nrelocs = (object_size - s.reloff) / - sizeof(struct relocation_info); + *sect_nrelocs = (uint32_t)((object_size - s.reloff) / + sizeof(struct relocation_info)); } else *sect_nrelocs = s.nreloc; @@ -3000,6 +3158,8 @@ uint64_t *seg_addr) *sect_flags = s.flags; } else{ + if(filetype == MH_DSYM && sg64.fileoff == 0 && sg64.filesize == 0) + return(TRUE); if((s64.flags & SECTION_TYPE) == S_ZEROFILL){ *sect_pointer = NULL; *sect_size = s64.size; @@ -3032,8 +3192,8 @@ uint64_t *seg_addr) printf("relocation entries for section (%.16s,%.16s) " "extends past end of file\n", s64.segname, s64.sectname); - *sect_nrelocs = (object_size - s64.reloff) / - sizeof(struct relocation_info); + *sect_nrelocs = (uint32_t)((object_size - s64.reloff) / + sizeof(struct relocation_info)); } else *sect_nrelocs = s64.nreloc; @@ -3044,6 +3204,149 @@ uint64_t *seg_addr) return(TRUE); } +void +get_seg_names( +struct load_command *load_commands, +uint32_t ncmds, +uint32_t sizeofcmds, +enum byte_sex load_commands_byte_sex, +char* sectname, +char*** out_segnames, +uint32_t* out_nsegname) +{ + enum byte_sex host_byte_sex; + enum bool swapped; + uint32_t i, j, left, size; + struct load_command *lc, l; + uint32_t cmd; + struct segment_command sg; + struct segment_command_64 sg64; + char** segnames = NULL; + uint32_t nsegname = 0; + uint32_t iseg; + struct section s; + struct section_64 s64; + char *p; + enum bool found; + + cmd = 0; + host_byte_sex = get_host_byte_sex(); + swapped = host_byte_sex != load_commands_byte_sex; + + lc = load_commands; + for(i = 0 ; i < ncmds; ++i){ + memcpy((char *)&l, (char *)lc, sizeof(struct load_command)); + if(swapped) + swap_load_command(&l, host_byte_sex); + if(l.cmdsize % sizeof(int32_t) != 0) + printf("load command %u size not a multiple of " + "sizeof(int32_t)\n", i); + if((char *)lc + l.cmdsize > + (char *)load_commands + sizeofcmds) + printf("load command %u extends past end of load " + "commands\n", i); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); + + switch(l.cmd){ + case LC_SEGMENT: + memset((char *)&sg, '\0', sizeof(struct segment_command)); + size = left < sizeof(struct segment_command) ? + left : sizeof(struct segment_command); + memcpy((char *)&sg, (char *)lc, size); + if(swapped) + swap_segment_command(&sg, host_byte_sex); + + p = (char *)lc + sizeof(struct segment_command); + found = FALSE; + for(j = 0; !found && j < sg.nsects ; j++){ + if(p + sizeof(struct section) > + (char *)load_commands + sizeofcmds){ + printf("section structure command extends past " + "end of load commands\n"); + } + left = sizeofcmds - + (uint32_t)(p - (char *)load_commands); + memset((char *)&s, '\0', sizeof(struct section)); + size = left < sizeof(struct section) ? + left : sizeof(struct section); + memcpy((char *)&s, p, size); + if(swapped) + swap_section(&s, 1, host_byte_sex); + + if(0 == strncmp(s.sectname, sectname, + sizeof(s.sectname))){ + segnames = realloc(segnames, + sizeof(*segnames)*(nsegname+1)); + iseg = nsegname++; + segnames[iseg] = calloc(1, sizeof(s64.segname) + 1); + memcpy(segnames[iseg], s64.segname, + sizeof(s64.segname)); + found = TRUE; + } + + if(p + sizeof(struct section) > + (char *)load_commands + sizeofcmds) + return; + p += size; + } + break; + case LC_SEGMENT_64: + memset((char *)&sg64, '\0', sizeof(struct segment_command_64)); + size = left < sizeof(struct segment_command_64) ? + left : sizeof(struct segment_command_64); + memcpy((char *)&sg64, (char *)lc, size); + if(swapped) + swap_segment_command_64(&sg64, host_byte_sex); + + p = (char *)lc + sizeof(struct segment_command_64); + found = FALSE; + for(j = 0; !found && j < sg64.nsects ; j++){ + if(p + sizeof(struct section) > + (char *)load_commands + sizeofcmds){ + printf("section structure command extends past " + "end of load commands\n"); + } + left = sizeofcmds - + (uint32_t)(p - (char *)load_commands); + memset((char *)&s64, '\0', sizeof(struct section_64)); + size = left < sizeof(struct section_64) ? + left : sizeof(struct section_64); + memcpy((char *)&s64, p, size); + if(swapped) + swap_section_64(&s64, 1, host_byte_sex); + + if(0 == strncmp(s64.sectname, sectname, + sizeof(s64.sectname))){ + segnames = realloc(segnames, + sizeof(*segnames)*(nsegname+1)); + iseg = nsegname++; + segnames[iseg] = calloc(1, sizeof(s64.segname) + 1); + memcpy(segnames[iseg], s64.segname, + sizeof(s64.segname)); + found = TRUE; + } + + if(p + sizeof(struct section_64) > + (char *)load_commands + sizeofcmds) + return; + p += size; + } + break; + } + if(l.cmdsize == 0){ + printf("load command %u size zero (can't advance to other " + "load commands)\n", i); + break; + } + lc = (struct load_command *)((char *)lc + l.cmdsize); + if((char *)lc > (char *)load_commands + sizeofcmds) + break; + } + + *out_segnames = segnames; + *out_nsegname = nsegname; +} + static void get_linked_reloc_info( @@ -3052,7 +3355,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct relocation_info **ext_relocs, /* output */ uint32_t *next_relocs, struct relocation_info **loc_relocs, @@ -3081,8 +3384,8 @@ uint32_t *nloc_relocs) bigsize += dyst.extreloff; if(bigsize > object_size){ printf("external relocation entries extend past end of file\n"); - *next_relocs = (object_size - dyst.extreloff) / - sizeof(struct relocation_info); + *next_relocs = (uint32_t)((object_size - dyst.extreloff) / + sizeof(struct relocation_info)); } else *next_relocs = dyst.nextrel; @@ -3098,8 +3401,8 @@ uint32_t *nloc_relocs) bigsize += dyst.locreloff; if(bigsize > object_size){ printf("local relocation entries extend past end of file\n"); - *nloc_relocs = (object_size - dyst.locreloff) / - sizeof(struct relocation_info); + *nloc_relocs = (uint32_t)((object_size - dyst.locreloff) / + sizeof(struct relocation_info)); } else *nloc_relocs = dyst.nlocrel; @@ -3119,16 +3422,18 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct dyld_bind_info **dbi, /* output */ -uint64_t *ndbi) +uint64_t *ndbi, +enum chain_format_t *chain_format) { enum byte_sex host_byte_sex; - enum bool swapped, found_bind; + enum bool swapped, found_bind, found_chained_fixups; uint32_t pass, i, j, left, size, nsegs, nsegs64, ndylibs; uint64_t big_size; struct load_command *lc, l; struct dyld_info_command dyld_info; + struct linkedit_data_command chained_fixups; struct dylib_command dl; struct segment_command sg, **segs; struct segment_command_64 sg64, **segs64; @@ -3147,8 +3452,10 @@ uint64_t *ndbi) return; found_bind = FALSE; + found_chained_fixups = FALSE; *dbi = NULL; *ndbi = 0; + *chain_format = CHAIN_FORMAT_NONE; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != load_commands_byte_sex; @@ -3160,6 +3467,9 @@ uint64_t *ndbi) dylibs = NULL; segs = NULL; segs64 = NULL; + + a = NULL; + /* * Make two passes over the load commands. On the first pass count the * number of load commands for dylibs and segments and look for an @@ -3183,7 +3493,7 @@ uint64_t *ndbi) (char *)load_commands + sizeofcmds) printf("load command %u extends past end of load " "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); switch(l.cmd){ @@ -3210,13 +3520,56 @@ uint64_t *ndbi) return; } if(found_bind == TRUE){ + if (found_chained_fixups == TRUE) { + printf("multiple LC_DYLD_INFO and " + " LC_DYLD_CHAINED_FIXUPS load " + "commands\n"); + return; + } printf("more than one LC_DYLD_INFO load command\n"); return; } found_bind = TRUE; } break; - + case LC_DYLD_CHAINED_FIXUPS: + if (pass == 1) { + memset((char *)&chained_fixups, '\0', + sizeof(struct linkedit_data_command)); + size = left < sizeof(struct linkedit_data_command) ? + left : sizeof(struct linkedit_data_command); + memcpy((char *)&chained_fixups, (char *)lc, size); + if(swapped) + swap_linkedit_data_command(&chained_fixups, + host_byte_sex); + if(chained_fixups.dataoff > object_size){ + printf("dataoff in LC_DYLD_CHAINED_FIXUPS load " + "command %u past end of file\n", i); + return; + } + big_size = chained_fixups.dataoff; + big_size += chained_fixups.datasize; + if(big_size > object_size){ + printf("dataoff plus datasize in " + "LC_DYLD_CHAINED_FIXUPS load command %u " + "past end of file\n", i); + return; + } + if(found_bind == TRUE){ + if (found_chained_fixups == FALSE) { + printf("multiple LC_DYLD_INFO and " + " LC_DYLD_CHAINED_FIXUPS load " + "commands\n"); + return; + } + printf("more than one LC_DYLD_CHAINED_FIXUPS " + "load command\n"); + return; + } + found_bind = TRUE; + found_chained_fixups = TRUE; + } + break; case LC_LOAD_DYLIB: case LC_LOAD_WEAK_DYLIB: case LC_REEXPORT_DYLIB: @@ -3273,7 +3626,7 @@ uint64_t *ndbi) "end of load commands\n"); return; } - left = sizeofcmds - (p - (char *)load_commands); + left = sizeofcmds - (uint32_t)(p - (char *)load_commands); memset((char *)&s, '\0', sizeof(struct section)); size = left < sizeof(struct section) ? left : sizeof(struct section); @@ -3317,7 +3670,7 @@ uint64_t *ndbi) printf("section structure command extends past " "end of load commands\n"); } - left = sizeofcmds - (p - (char *)load_commands); + left = sizeofcmds - (uint32_t)(p - (char *)load_commands); memset((char *)&s64, '\0', sizeof(struct section_64)); size = left < sizeof(struct section_64) ? left : sizeof(struct section_64); @@ -3357,10 +3710,21 @@ uint64_t *ndbi) } } - start = (uint8_t *)(object_addr + dyld_info.bind_off); - end = start + dyld_info.bind_size; - get_dyld_bind_info(start, end, dylibs, ndylibs, segs, nsegs, - segs64, nsegs64, dbi, ndbi); + if (found_chained_fixups) { + start = (uint8_t *)(object_addr + chained_fixups.dataoff); + end = start + chained_fixups.datasize; + get_dyld_chained_fixups(start, end, dylibs, ndylibs, segs, nsegs, + segs64, nsegs64, swapped, object_addr, + object_size, dbi, ndbi, chain_format, + print_bind_info || vflag); + } else { + start = (uint8_t *)(object_addr + dyld_info.bind_off); + end = start + dyld_info.bind_size; + get_dyld_bind_info(start, end, dylibs, ndylibs, segs, nsegs, + segs64, nsegs64, swapped, object_addr, + object_size, dbi, ndbi, chain_format, + print_bind_info || vflag); + } if(dylibs != NULL) free(dylibs); @@ -3376,13 +3740,115 @@ uint64_t *ndbi) } } +/* + * print_dyld_info_opcodes() looks for a LC_DYLD_INFO load command and if it has + * bind info prints its raw contents. + */ +static +void +print_dyld_info_opcodes( +struct load_command *load_commands, /* input */ +uint32_t ncmds, +uint32_t sizeofcmds, +enum byte_sex load_commands_byte_sex, +char *object_addr, +uint64_t object_size) +{ + enum byte_sex host_byte_sex; + enum bool swapped, found_dyld_info; + struct load_command *lc, l; + struct dyld_info_command dyld_info; + uint32_t i, left, size; + const char* lcname; + + host_byte_sex = get_host_byte_sex(); + swapped = host_byte_sex != load_commands_byte_sex; + found_dyld_info = FALSE; + + lc = load_commands; + for(i = 0 ; i < ncmds; i++){ + memcpy((char *)&l, (char *)lc, sizeof(struct load_command)); + if(swapped) + swap_load_command(&l, host_byte_sex); + if(l.cmdsize % sizeof(int32_t) != 0) + printf("load command %u size not a multiple of " + "sizeof(int32_t)\n", i); + if((char *)lc + l.cmdsize > + (char *)load_commands + sizeofcmds) + printf("load command %u extends past end of load " + "commands\n", i); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); + + lcname = NULL; + switch(l.cmd){ + case LC_DYLD_INFO: + lcname = "LC_DYLD_INFO"; + /* FALLTHROUGH */ + case LC_DYLD_INFO_ONLY: + if (!lcname) + lcname = "LC_DYLD_INFO_ONLY"; + + if(found_dyld_info == TRUE){ + printf("more than one LC_DYLD_INFO or LC_DYLD_INFO_ONLY " + "load command\n"); + return; + } + + found_dyld_info = TRUE; + + memset((char *)&dyld_info, '\0', + sizeof(struct dyld_info_command)); + size = (left < sizeof(struct dyld_info_command) ? + left : sizeof(struct dyld_info_command)); + memcpy((char *)&dyld_info, (char *)lc, size); + if(swapped) + swap_dyld_info_command(&dyld_info, host_byte_sex); + break; + default: + ; + } + + if(l.cmdsize == 0){ + printf("load command %u size zero (can't advance to other " + "load commands)\n", i); + break; + } + lc = (struct load_command *)((char *)lc + l.cmdsize); + if((char *)lc > (char *)load_commands + sizeofcmds) + break; + } + + if (!found_dyld_info) { + return; + } + + if (dyld_info.rebase_off) { + print_dyld_rebase_opcodes((uint8_t*)object_addr, object_size, + dyld_info.rebase_off, dyld_info.rebase_size); + } + if (dyld_info.bind_off) { + print_dyld_bind_opcodes((uint8_t*)object_addr, object_size, "bind", + dyld_info.bind_off, dyld_info.bind_size); + } + if (dyld_info.weak_bind_off) { + print_dyld_bind_opcodes((uint8_t*)object_addr, object_size, "weak_bind", + dyld_info.weak_bind_off, + dyld_info.weak_bind_size); + } + if (dyld_info.lazy_bind_off) { + print_dyld_bind_opcodes((uint8_t*)object_addr, object_size, "lazy_bind", + dyld_info.lazy_bind_off, + dyld_info.lazy_bind_size); + } +} + static void print_text_by_symbols( cpu_type_t cputype, enum byte_sex object_byte_sex, char *sect, -uint32_t size, +uint64_t size, uint64_t addr, uint32_t sect_flags, struct symbol *sorted_symbols, @@ -3400,6 +3866,7 @@ struct relocation_info *loc_relocs, uint32_t nloc_relocs, struct dyld_bind_info *dbi, uint64_t ndbi, +enum chain_format_t chain_format, uint32_t *indirect_symbols, uint32_t nindirect_symbols, struct load_command *load_commands, @@ -3409,7 +3876,7 @@ enum bool disassemble, enum bool verbose, cpu_subtype_t cpusubtype, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct data_in_code_entry *dices, uint32_t ndices, uint64_t seg_addr) @@ -3424,17 +3891,18 @@ uint64_t seg_addr) symbol_offset = symbol_addr - addr; if(i+1 < nsorted_symbols && sorted_symbols[i+1].n_value < addr + size) - symbol_size = sorted_symbols[i+1].n_value - symbol_addr; + symbol_size = (uint32_t)(sorted_symbols[i+1].n_value - + symbol_addr); else - symbol_size = (addr + size) - symbol_addr; + symbol_size = (uint32_t)((addr + size) - symbol_addr); print_text(cputype, object_byte_sex, sect + symbol_offset, symbol_size, symbol_addr, sect_flags, sorted_symbols, nsorted_symbols, symbols, symbols64, nsymbols, strings, strings_size, relocs, nrelocs, ext_relocs, next_relocs, - loc_relocs, nloc_relocs, dbi, ndbi, indirect_symbols, - nindirect_symbols, load_commands, ncmds, sizeofcmds, - disassemble, verbose, cpusubtype, object_addr, - object_size, dices, ndices, seg_addr); + loc_relocs, nloc_relocs, dbi, ndbi, chain_format, + indirect_symbols, nindirect_symbols, load_commands, + ncmds, sizeofcmds, disassemble, verbose, cpusubtype, + object_addr, object_size, dices, ndices, seg_addr); } } @@ -3444,7 +3912,7 @@ print_text( cpu_type_t cputype, enum byte_sex object_byte_sex, char *sect, -uint32_t size, +uint64_t size, uint64_t addr, uint32_t sect_flags, struct symbol *sorted_symbols, @@ -3462,6 +3930,7 @@ struct relocation_info *loc_relocs, uint32_t nloc_relocs, struct dyld_bind_info *dbi, uint64_t ndbi, +enum chain_format_t chain_format, uint32_t *indirect_symbols, uint32_t nindirect_symbols, struct load_command *load_commands, @@ -3471,7 +3940,7 @@ enum bool disassemble, enum bool verbose, cpu_subtype_t cpusubtype, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct data_in_code_entry *dices, uint32_t ndices, uint64_t seg_addr) @@ -3521,7 +3990,7 @@ uint64_t seg_addr) printf("-p symbol: %s not in text section\n", pflag); return; } - offset = sorted_symbols[i].n_value - addr; + offset = (uint32_t)(sorted_symbols[i].n_value - addr); sect += offset; cur_addr = sorted_symbols[i].n_value; sect_start = sect; @@ -3556,8 +4025,12 @@ uint64_t seg_addr) } llvm_disasm_set_options(arm_dc, LLVMDisassembler_Option_PrintImmHex); + llvm_disasm_set_options(arm_dc, + LLVMDisassembler_Option_PrintLatency); llvm_disasm_set_options(thumb_dc, LLVMDisassembler_Option_PrintImmHex); + llvm_disasm_set_options(thumb_dc, + LLVMDisassembler_Option_PrintLatency); if(eflag){ llvm_disasm_set_options(arm_dc, LLVMDisassembler_Option_UseMarkup); @@ -3575,6 +4048,8 @@ uint64_t seg_addr) LLVMDisassembler_Option_PrintImmHex); llvm_disasm_set_options(i386_dc, LLVMDisassembler_Option_SetInstrComments); + llvm_disasm_set_options(i386_dc, + LLVMDisassembler_Option_PrintLatency); if(eflag) llvm_disasm_set_options(i386_dc, LLVMDisassembler_Option_UseMarkup); @@ -3589,11 +4064,13 @@ uint64_t seg_addr) LLVMDisassembler_Option_PrintImmHex); llvm_disasm_set_options(x86_64_dc, LLVMDisassembler_Option_SetInstrComments); + llvm_disasm_set_options(x86_64_dc, + LLVMDisassembler_Option_PrintLatency); if(eflag) llvm_disasm_set_options(x86_64_dc, LLVMDisassembler_Option_UseMarkup); } - if(cputype == CPU_TYPE_ARM64){ + if(cputype == CPU_TYPE_ARM64 || cputype == CPU_TYPE_ARM64_32){ arm64_dc = create_arm64_llvm_disassembler(cpusubtype); if(arm64_dc == NULL){ printf("can't create arm64 llvm disassembler\n"); @@ -3601,6 +4078,8 @@ uint64_t seg_addr) } llvm_disasm_set_options(arm64_dc, LLVMDisassembler_Option_PrintImmHex); + llvm_disasm_set_options(arm64_dc, + LLVMDisassembler_Option_PrintLatency); } if(gflag){ ninsts = 100; @@ -3634,19 +4113,21 @@ uint64_t seg_addr) printf("%08x", (uint32_t)cur_addr); if((qflag == FALSE || (cputype == CPU_TYPE_POWERPC)) && - cputype != CPU_TYPE_ARM64) + (cputype != CPU_TYPE_ARM64 && + cputype != CPU_TYPE_ARM64_32)) printf("\t"); } } if(cputype == CPU_TYPE_POWERPC64) - j = ppc_disassemble(sect, size - i, cur_addr, addr, + j = ppc_disassemble(sect, (uint32_t)size - i, + (uint32_t)cur_addr, (uint32_t)addr, object_byte_sex, relocs, nrelocs, symbols, symbols64, nsymbols, sorted_symbols, nsorted_symbols, strings, strings_size, indirect_symbols, nindirect_symbols, load_commands, ncmds, sizeofcmds, verbose); else if(cputype == CPU_TYPE_X86_64) - j = i386_disassemble(sect, size - i, cur_addr, addr, + j = i386_disassemble(sect, (uint32_t)size - i, cur_addr, addr, object_byte_sex, relocs, nrelocs, ext_relocs, next_relocs, loc_relocs, nloc_relocs, dbi, ndbi, NULL, symbols64, nsymbols, sorted_symbols, @@ -3656,19 +4137,21 @@ uint64_t seg_addr) llvm_mc, i386_dc, x86_64_dc , object_addr, object_size, &(insts[n]), NULL, 0); else if(cputype == CPU_TYPE_MC680x0) - j = m68k_disassemble(sect, size - i, cur_addr, addr, + j = m68k_disassemble(sect, (uint32_t)size - i, + (uint32_t)cur_addr, (uint32_t)addr, object_byte_sex, relocs, nrelocs, symbols, nsymbols, sorted_symbols, nsorted_symbols, strings, strings_size, indirect_symbols, nindirect_symbols, load_commands, ncmds, sizeofcmds, verbose); else if(cputype == CPU_TYPE_I860) - j = i860_disassemble(sect, size - i, cur_addr, addr, + j = i860_disassemble(sect, (uint32_t)size - i, + (uint32_t)cur_addr, (uint32_t)addr, object_byte_sex, relocs, nrelocs, symbols, nsymbols, sorted_symbols, nsorted_symbols, strings, strings_size, verbose); else if(cputype == CPU_TYPE_I386) - j = i386_disassemble(sect, size - i, cur_addr, addr, + j = i386_disassemble(sect, (uint32_t)size - i,cur_addr,addr, object_byte_sex, relocs, nrelocs, ext_relocs, next_relocs, loc_relocs, nloc_relocs, dbi, ndbi, symbols, NULL, nsymbols, sorted_symbols, @@ -3678,32 +4161,37 @@ uint64_t seg_addr) llvm_mc, i386_dc, x86_64_dc, object_addr, object_size, &(insts[n]), NULL, 0); else if(cputype == CPU_TYPE_MC88000) - j = m88k_disassemble(sect, size - i, cur_addr, addr, + j = m88k_disassemble(sect, (uint32_t)size - i, + (uint32_t)cur_addr, (uint32_t)addr, object_byte_sex, relocs, nrelocs, symbols, nsymbols, sorted_symbols, nsorted_symbols, strings, strings_size, verbose); else if(cputype == CPU_TYPE_POWERPC || cputype == CPU_TYPE_VEO) - j = ppc_disassemble(sect, size - i, cur_addr, addr, + j = ppc_disassemble(sect, (uint32_t)size - i, + (uint32_t)cur_addr, (uint32_t)addr, object_byte_sex, relocs, nrelocs, symbols, symbols64, nsymbols, sorted_symbols, nsorted_symbols, strings, strings_size, indirect_symbols, nindirect_symbols, load_commands, ncmds, sizeofcmds, verbose); else if(cputype == CPU_TYPE_HPPA) - j = hppa_disassemble(sect, size - i, cur_addr, addr, + j = hppa_disassemble(sect, (uint32_t)size - i, + (uint32_t)cur_addr, (uint32_t)addr, object_byte_sex, relocs, nrelocs, symbols, nsymbols, sorted_symbols, nsorted_symbols, strings, strings_size, verbose); else if(cputype == CPU_TYPE_SPARC) - j = sparc_disassemble(sect, size - i, cur_addr, addr, + j = sparc_disassemble(sect, (uint32_t)size - i, + (uint32_t)cur_addr, (uint32_t)addr, object_byte_sex, relocs, nrelocs, symbols, nsymbols, sorted_symbols, nsorted_symbols, strings, strings_size, indirect_symbols, nindirect_symbols, load_commands, ncmds, sizeofcmds, verbose); else if(cputype == CPU_TYPE_ARM) - j = arm_disassemble(sect, size - i, cur_addr, addr, + j = arm_disassemble(sect, (uint32_t)size - i, + (uint32_t)cur_addr, (uint32_t)addr, object_byte_sex, relocs, nrelocs, symbols, nsymbols, sorted_symbols, nsorted_symbols, strings, strings_size, indirect_symbols, @@ -3711,15 +4199,16 @@ uint64_t seg_addr) sizeofcmds, cpusubtype, verbose, arm_dc, thumb_dc, object_addr, object_size, dices, ndices, seg_addr, &(insts[n]), NULL, 0); - else if(cputype == CPU_TYPE_ARM64) - j = arm64_disassemble(sect, size - i, cur_addr, addr, + else if(cputype == CPU_TYPE_ARM64 || cputype == CPU_TYPE_ARM64_32) + j = arm64_disassemble(sect, (uint32_t)size - i, + (uint32_t)cur_addr, (uint32_t)addr, object_byte_sex, relocs, nrelocs, ext_relocs, next_relocs, loc_relocs, nloc_relocs, dbi, ndbi, - symbols64, nsymbols, sorted_symbols, - nsorted_symbols, strings, strings_size, - indirect_symbols, nindirect_symbols, - load_commands, ncmds, sizeofcmds, object_addr, - object_size, verbose, arm64_dc); + chain_format, symbols, symbols64, nsymbols, + sorted_symbols, nsorted_symbols, strings, + strings_size, indirect_symbols, nindirect_symbols, + cputype, load_commands, ncmds, sizeofcmds, + object_addr, object_size, verbose, arm64_dc); else{ printf("Can't disassemble unknown cputype %d\n", cputype); @@ -3765,10 +4254,11 @@ uint64_t seg_addr) printf("%s:", insts[i].tmp_label); insts[i].print = TRUE; cur_addr = insts[i].address; - offset = cur_addr - addr; + offset = (uint32_t)(cur_addr - addr); sect = sect_start + offset; if(cputype == CPU_TYPE_X86_64 || cputype == CPU_TYPE_I386) - j = i386_disassemble(sect, size - offset, cur_addr, + j = i386_disassemble(sect, (uint32_t)size - offset, + cur_addr, addr, object_byte_sex, relocs, nrelocs, ext_relocs, next_relocs, loc_relocs, nloc_relocs, dbi, ndbi, symbols, NULL, @@ -3779,7 +4269,8 @@ uint64_t seg_addr) x86_64_dc, object_addr, object_size, &(insts[i]), insts, n); else if(cputype == CPU_TYPE_ARM) - j = arm_disassemble(sect, size - offset, cur_addr, addr, + j = arm_disassemble(sect, (uint32_t)size - offset, + (uint32_t)cur_addr, (uint32_t)addr, object_byte_sex, relocs, nrelocs, symbols, nsymbols, sorted_symbols, nsorted_symbols, strings, strings_size, indirect_symbols, @@ -3868,7 +4359,7 @@ cpu_type_t cputype, cpu_subtype_t cpusubtype, enum byte_sex load_commands_byte_sex, char *object_addr, -uint32_t object_size) +uint64_t object_size) { enum byte_sex host_byte_sex; enum bool swapped; @@ -3915,7 +4406,7 @@ uint32_t object_size) (char *)load_commands + sizeofcmds) printf("load command %u extends past end of load " "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_SEGMENT: diff --git a/cctools/otool/ofile_print.c b/cctools/otool/ofile_print.c index e6ac4cc..6179139 100644 --- a/cctools/otool/ofile_print.c +++ b/cctools/otool/ofile_print.c @@ -240,10 +240,14 @@ #define MAXSECTALIGN 15 /* 2**15 or 0x8000 */ static void print_arch( - struct fat_arch *fat_arch); + cpu_type_t cputype, + cpu_subtype_t cpusubtype); static void print_cputype( cpu_type_t cputype, cpu_subtype_t cpusubtype); +static void print_version_xyz( + const char* label, + uint32_t version); #if i386_THREAD_STATE == 1 #ifdef i386_EXCEPTION_STATE_COUNT @@ -275,7 +279,7 @@ static void print_relocs( enum bool swapped, cpu_type_t cputype, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct nlist *symbols, struct nlist_64 *symbols64, uint32_t nsymbols, @@ -306,92 +310,130 @@ static int rel_bsearch( struct relocation_info *rel); /* - * Print the fat header and the fat_archs. The caller is responsible for making - * sure the structures are properly aligned and that the fat_archs is of the - * size fat_header->nfat_arch * sizeof(struct fat_arch). + * Print the fat header and the fat_archs or fat_archs64. The caller is + * responsible for making sure the structures are properly aligned and that the + * fat_archs or fat_archs64 is of the size fat_header->nfat_arch * + * sizeof(struct fat_arch) or sizeof(struct fat_arch_64). */ void print_fat_headers( struct fat_header *fat_header, struct fat_arch *fat_archs, -uint64_t size, +struct fat_arch_64 *fat_archs64, +uint64_t filesize, enum bool verbose) { - uint32_t i, j; + uint32_t i, j, sizeof_fat_arch; uint64_t big_size; + cpu_type_t cputype; + cpu_subtype_t cpusubtype; + uint64_t offset; + uint64_t size; + uint32_t align; if(verbose){ - if(fat_header->magic == FAT_MAGIC) + if(fat_header->magic == FAT_MAGIC_64) + printf("fat_magic FAT_MAGIC_64\n"); + else if(fat_header->magic == FAT_MAGIC) printf("fat_magic FAT_MAGIC\n"); else printf("fat_magic 0x%x\n", (unsigned int)(fat_header->magic)); } else printf("fat_magic 0x%x\n", (unsigned int)(fat_header->magic)); + if(fat_header->magic == FAT_MAGIC_64) + sizeof_fat_arch = sizeof(struct fat_arch_64); + else + sizeof_fat_arch = sizeof(struct fat_arch); + + printf("nfat_arch %u", fat_header->nfat_arch); big_size = fat_header->nfat_arch; - big_size *= sizeof(struct fat_arch); + big_size *= sizeof_fat_arch; big_size += sizeof(struct fat_header); if(fat_header->nfat_arch == 0) printf(" (malformed, contains zero architecture types)\n"); - else if(big_size > size) + else if(big_size > filesize) printf(" (malformed, architectures past end of file)\n"); else printf("\n"); for(i = 0; i < fat_header->nfat_arch; i++){ big_size = i; - big_size *= sizeof(struct fat_arch); + big_size *= sizeof_fat_arch; big_size += sizeof(struct fat_header); - if(big_size > size) + if(big_size > filesize) break; printf("architecture "); for(j = 0; i != 0 && j <= i - 1; j++){ - if(fat_archs[i].cputype != 0 && fat_archs[i].cpusubtype != 0 && - fat_archs[i].cputype == fat_archs[j].cputype && - (fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == - (fat_archs[j].cpusubtype & ~CPU_SUBTYPE_MASK)){ - printf("(illegal duplicate architecture) "); - break; + if(fat_header->magic == FAT_MAGIC_64){ + if(fat_archs64[i].cputype != 0 && + fat_archs64[i].cpusubtype != 0 && + fat_archs64[i].cputype == fat_archs64[j].cputype && + (fat_archs64[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + (fat_archs64[j].cpusubtype & ~CPU_SUBTYPE_MASK)){ + printf("(illegal duplicate architecture) "); + break; + } + } + else{ + if(fat_archs[i].cputype != 0 && + fat_archs[i].cpusubtype != 0 && + fat_archs[i].cputype == fat_archs[j].cputype && + (fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == + (fat_archs[j].cpusubtype & ~CPU_SUBTYPE_MASK)){ + printf("(illegal duplicate architecture) "); + break; + } } } + if(fat_header->magic == FAT_MAGIC_64){ + cputype = fat_archs64[i].cputype; + cpusubtype = fat_archs64[i].cpusubtype; + offset = fat_archs64[i].offset; + size = fat_archs64[i].size; + align = fat_archs64[i].align; + } + else{ + cputype = fat_archs[i].cputype; + cpusubtype = fat_archs[i].cpusubtype; + offset = fat_archs[i].offset; + size = fat_archs[i].size; + align = fat_archs[i].align; + } if(verbose){ - print_arch(fat_archs + i); - print_cputype(fat_archs[i].cputype, - fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); + print_arch(cputype, cpusubtype); + print_cputype(cputype, cpusubtype & ~CPU_SUBTYPE_MASK); } else{ printf("%u\n", i); - printf(" cputype %d\n", fat_archs[i].cputype); - printf(" cpusubtype %d\n", fat_archs[i].cpusubtype & - ~CPU_SUBTYPE_MASK); + printf(" cputype %d\n", cputype); + printf(" cpusubtype %d\n", cpusubtype & ~CPU_SUBTYPE_MASK); } - if(verbose && (fat_archs[i].cpusubtype & CPU_SUBTYPE_MASK) == + if(verbose && (cpusubtype & CPU_SUBTYPE_MASK) == CPU_SUBTYPE_LIB64) printf(" capabilities CPU_SUBTYPE_LIB64\n"); else printf(" capabilities 0x%x\n", (unsigned int) - ((fat_archs[i].cpusubtype & CPU_SUBTYPE_MASK) >>24)); - printf(" offset %u", fat_archs[i].offset); - if(fat_archs[i].offset > size) + ((cpusubtype & CPU_SUBTYPE_MASK) >>24)); + printf(" offset %llu", offset); + if(offset > filesize) printf(" (past end of file)"); - if(fat_archs[i].offset % (1 << fat_archs[i].align) != 0) - printf(" (not aligned on it's alignment (2^%u))\n", - fat_archs[i].align); + if(offset % (1 << align) != 0) + printf(" (not aligned on it's alignment (2^%u))\n", align); else printf("\n"); - printf(" size %u", fat_archs[i].size); - big_size = fat_archs[i].offset; - big_size += fat_archs[i].size; - if(big_size > size) + printf(" size %llu", size); + big_size = offset; + big_size += size; + if(big_size > filesize) printf(" (past end of file)\n"); else printf("\n"); - printf(" align 2^%u (%d)", fat_archs[i].align, - 1 << fat_archs[i].align); - if(fat_archs[i].align > MAXSECTALIGN) + printf(" align 2^%u (%d)", align, 1 << align); + if(align > MAXSECTALIGN) printf("( too large, maximum 2^%d)\n", MAXSECTALIGN); else printf("\n"); @@ -405,11 +447,12 @@ enum bool verbose) static void print_arch( -struct fat_arch *fat_arch) +cpu_type_t cputype, +cpu_subtype_t cpusubtype) { - switch(fat_arch->cputype){ + switch(cputype){ case CPU_TYPE_MC680x0: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_MC680x0_ALL: printf("m68k\n"); break; @@ -424,7 +467,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_MC88000: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_MC88000_ALL: case CPU_SUBTYPE_MC88110: printf("m88k\n"); @@ -434,7 +477,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_I386: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_I386_ALL: /* case CPU_SUBTYPE_386: same as above */ printf("i386\n"); @@ -459,15 +502,15 @@ struct fat_arch *fat_arch) break; default: printf("intel x86 family %d model %d\n", - CPU_SUBTYPE_INTEL_FAMILY(fat_arch->cpusubtype & + CPU_SUBTYPE_INTEL_FAMILY(cpusubtype & ~CPU_SUBTYPE_MASK), - CPU_SUBTYPE_INTEL_MODEL(fat_arch->cpusubtype & + CPU_SUBTYPE_INTEL_MODEL(cpusubtype & ~CPU_SUBTYPE_MASK)); break; } break; case CPU_TYPE_X86_64: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_X86_64_ALL: printf("x86_64\n"); break; @@ -479,7 +522,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_I860: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_I860_ALL: case CPU_SUBTYPE_I860_860: printf("i860\n"); @@ -489,7 +532,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_POWERPC: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_POWERPC_ALL: printf("ppc\n"); break; @@ -534,7 +577,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_POWERPC64: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_POWERPC_ALL: printf("ppc64\n"); break; @@ -546,7 +589,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_VEO: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_VEO_1: printf("veo1\n"); break; @@ -564,7 +607,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_HPPA: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_HPPA_ALL: case CPU_SUBTYPE_HPPA_7100LC: printf("hppa\n"); @@ -574,7 +617,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_SPARC: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_SPARC_ALL: printf("sparc\n"); break; @@ -583,7 +626,7 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_ARM: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_ARM_ALL: printf("arm\n"); break; @@ -626,18 +669,29 @@ struct fat_arch *fat_arch) } break; case CPU_TYPE_ARM64: - switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_ARM64_ALL: printf("arm64\n"); break; case CPU_SUBTYPE_ARM64_V8: printf("arm64v8\n"); + case CPU_SUBTYPE_ARM64E: + printf("arm64e\n"); + default: + goto print_arch_unknown; + } + break; + case CPU_TYPE_ARM64_32: + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ + case CPU_SUBTYPE_ARM64_32_V8: + printf("arm64_32\n"); + break; default: goto print_arch_unknown; } break; case CPU_TYPE_ANY: - switch((int)(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK)){ + switch((int)(cpusubtype & ~CPU_SUBTYPE_MASK)){ case CPU_SUBTYPE_MULTIPLE: printf("any\n"); break; @@ -653,8 +707,8 @@ struct fat_arch *fat_arch) break; print_arch_unknown: default: - printf("cputype (%d) cpusubtype (%d)\n", fat_arch->cputype, - fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK); + printf("cputype (%d) cpusubtype (%d)\n", cputype, + cpusubtype & ~CPU_SUBTYPE_MASK); break; } } @@ -947,6 +1001,20 @@ cpu_subtype_t cpusubtype) printf(" cputype CPU_TYPE_ARM64\n" " cpusubtype CPU_SUBTYPE_ARM64_V8\n"); break; + case CPU_SUBTYPE_ARM64E: + printf(" cputype CPU_TYPE_ARM64\n" + " cpusubtype CPU_SUBTYPE_ARM64E\n"); + break; + default: + goto print_arch_unknown; + } + break; + case CPU_TYPE_ARM64_32: + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ + case CPU_SUBTYPE_ARM64_32_V8: + printf(" cputype CPU_TYPE_ARM64_32\n" + " cpusubtype CPU_SUBTYPE_ARM64_32_V8\n"); + break; default: goto print_arch_unknown; } @@ -978,6 +1046,34 @@ print_arch_unknown: } } +/* + * Print a formatted version number where components are encoded into a + * uint32_t in nibbles: X.Y.Z => 0xXXXXYYZZ. If a 'label' is supplied, it will + * precede the version number and a newline will follow. + */ +void print_version_xyz(const char* label, uint32_t version) +{ + const char* space = " "; + const char* nl = "\n"; + if (label == NULL) + label = space = nl = ""; + if((version & 0xff) == 0) + printf("%s%s%u.%u%s", + label, + space, + version >> 16, + (version >> 8) & 0xff, + nl); + else + printf("%s%s%u.%u.%u%s", + label, + space, + version >> 16, + (version >> 8) & 0xff, + version & 0xff, + nl); +} + /* * Print the archive header. The format is constant width character fields * blank padded. So the trailing blanks are stripped and full field widths @@ -988,7 +1084,7 @@ print_ar_hdr( struct ar_hdr *ar_hdr, char *member_name, uint32_t member_name_size, -uint32_t member_offset, +uint64_t member_offset, enum bool verbose, enum bool print_offset) { @@ -1029,10 +1125,10 @@ enum bool print_offset) size_buf[sizeof(ar_hdr->ar_size)] = '\0'; if(print_offset == TRUE) - printf("%u\t", member_offset); + printf("%llu\t", member_offset); if(verbose == TRUE){ - mode = strtoul(mode_buf, &endp, 8); + mode = (uint32_t)strtoul(mode_buf, &endp, 8); if(*endp != '\0') printf("(mode: \"%s\" contains non-octal chars) ", mode_buf); print_mode_verbose(mode); @@ -1049,7 +1145,7 @@ enum bool print_offset) * and the new line is not wanted a '\0' is placed there. */ if(verbose){ - date = strtoul(date_buf, &endp, 10); + date = (uint32_t)strtoul(date_buf, &endp, 10); if(*endp != '\0') printf("(date: \"%s\" contains non-decimal chars) ", date_buf); p = ctime(&date); @@ -1159,7 +1255,8 @@ uint32_t mode) * object files could be of differing byte sex in an erroneous library). There * is no problem of a library containing no objects with respect to the byte * sex of the table of contents since the table of contents would be made up - * of two binary uint32_t zeros which are the same in either byte sex. + * of two binary uint32_t or two binary uint64_t zeros which are the same in + * either byte sex. */ void print_library_toc( @@ -1175,30 +1272,57 @@ uint64_t library_size, char *arch_name, enum bool verbose) { + enum bool using_64toc; enum byte_sex host_byte_sex; - uint32_t ran_size, nranlibs, str_size, i, member_name_size; - uint64_t toc_offset; + uint32_t ran_size, str_size, i, member_name_size; + uint64_t ran_size64, nranlibs, str_size64, sizeof_rans, string_size; + uint64_t toc_offset, ran_off, ran_strx; struct ranlib *ranlibs; + struct ranlib_64 *ranlibs64; char *strings, *member_name; struct ar_hdr *ar_hdr; int n; char buf[20]; uint64_t big_size; - str_size = 0; /* cctools-port */ + /* cctools-port start */ + str_size = 0; + string_size = 0; + /* cctools-port end */ host_byte_sex = get_host_byte_sex(); toc_offset = 0; strings = NULL; + ran_size = 0; + ran_size64 = 0; + string_size = 0; - if(toc_offset + sizeof(uint32_t) > toc_size){ - error_with_arch(arch_name, "truncated table of contents in: " - "%s(%.*s) (size of ranlib structs extends past the end of the " - "table of contents member)", library_name, (int)toc_name_size, - toc_name); - return; + if(strncmp(toc_name, SYMDEF_64, sizeof(SYMDEF_64)-1) == 0 || + strncmp(toc_name, SYMDEF_64_SORTED, sizeof(SYMDEF_64_SORTED)-1) == 0) + using_64toc = TRUE; + else + using_64toc = FALSE; + + if(using_64toc == FALSE){ + if(toc_offset + sizeof(uint32_t) > toc_size){ + error_with_arch(arch_name, "truncated table of contents in: " + "%s(%.*s) (size of ranlib structs extends past the end " + "of the table of contents member)", library_name, + (int)toc_name_size, toc_name); + return; + } + memcpy((char *)&ran_size, toc_addr + toc_offset, sizeof(uint32_t)); + } + else{ + if(toc_offset + sizeof(uint64_t) > toc_size){ + error_with_arch(arch_name, "truncated table of contents in: " + "%s(%.*s) (size of ranlib_64 structs extends past the end " + "of the table of contents member)", library_name, + (int)toc_name_size, toc_name); + return; + } + memcpy((char *)&ran_size64, toc_addr +toc_offset, sizeof(uint64_t)); } - memcpy((char *)&ran_size, toc_addr + toc_offset, sizeof(uint32_t)); /* * With the advent of things like LTO object files we may end up getting * handed UNKNOWN_BYTE_SEX for the table of contents byte sex. So at @@ -1208,49 +1332,101 @@ enum bool verbose) */ if(toc_byte_sex == UNKNOWN_BYTE_SEX) toc_byte_sex = host_byte_sex; - if(toc_byte_sex != host_byte_sex) - ran_size = SWAP_INT(ran_size); - toc_offset += sizeof(uint32_t); + if(toc_byte_sex != host_byte_sex){ + if(using_64toc == FALSE) + ran_size = SWAP_INT(ran_size); + else + ran_size64 = SWAP_LONG_LONG(ran_size64); + } + if(using_64toc == FALSE) + toc_offset += sizeof(uint32_t); + else + toc_offset += sizeof(uint64_t); big_size = toc_offset; - big_size += ran_size; + if(using_64toc == FALSE) + big_size += ran_size; + else + big_size += ran_size64; if(big_size > toc_size){ - error_with_arch(arch_name, "truncated table of contents in: " - "%s(%.*s) (ranlib structures extends past the end of the " - "table of contents member)", library_name, (int)toc_name_size, - toc_name); - return; - } - ranlibs = allocate(ran_size); - memcpy((char *)ranlibs, toc_addr + toc_offset, ran_size); - nranlibs = ran_size / sizeof(struct ranlib); - if(toc_byte_sex != host_byte_sex) - swap_ranlib(ranlibs, nranlibs, host_byte_sex); - toc_offset += ran_size; - - if(verbose){ - if(toc_offset + sizeof(uint32_t) > toc_size){ + if(using_64toc == FALSE) error_with_arch(arch_name, "truncated table of contents in: " - "%s(%.*s) (size of ranlib strings extends past the end of " + "%s(%.*s) (ranlib structures extends past the end of " "the table of contents member)", library_name, (int)toc_name_size, toc_name); - free(ranlibs); - return; - } - memcpy((char *)&str_size, toc_addr + toc_offset, - sizeof(uint32_t)); + else + error_with_arch(arch_name, "truncated table of contents in: " + "%s(%.*s) (ranlib_64 structures extends past the end of " + "the table of contents member)", library_name, + (int)toc_name_size, toc_name); + return; + } + if(using_64toc == FALSE){ + ranlibs = allocate(ran_size); + ranlibs64 = NULL; + memcpy((char *)ranlibs, toc_addr + toc_offset, ran_size); + nranlibs = ran_size / sizeof(struct ranlib); if(toc_byte_sex != host_byte_sex) - str_size = SWAP_INT(str_size); - toc_offset += sizeof(uint32_t); + swap_ranlib(ranlibs, (uint32_t)nranlibs, host_byte_sex); + sizeof_rans = ran_size; + toc_offset += ran_size; + } + else{ + ranlibs64 = allocate(ran_size64); + ranlibs = NULL; + memcpy((char *)ranlibs64, toc_addr + toc_offset, ran_size64); + nranlibs = ran_size64 / sizeof(struct ranlib_64); + if(toc_byte_sex != host_byte_sex) + swap_ranlib_64(ranlibs64, nranlibs, host_byte_sex); + sizeof_rans = ran_size64; + toc_offset += ran_size64; + } + + if(verbose){ + if(using_64toc == FALSE){ + if(toc_offset + sizeof(uint32_t) > toc_size){ + error_with_arch(arch_name, "truncated table of contents " + "in: %s(%.*s) (size of ranlib strings extends past " + "the end of the table of contents member)", + library_name, (int)toc_name_size, toc_name); + free(ranlibs); + return; + } + memcpy((char *)&str_size, toc_addr + toc_offset, + sizeof(uint32_t)); + if(toc_byte_sex != host_byte_sex) + str_size = SWAP_INT(str_size); + string_size = str_size; + toc_offset += sizeof(uint32_t); + } + else{ + if(toc_offset + sizeof(uint64_t) > toc_size){ + error_with_arch(arch_name, "truncated table of contents " + "in: %s(%.*s) (size of ranlib strings extends past " + "the end of the table of contents member)", + library_name, (int)toc_name_size, toc_name); + free(ranlibs64); + return; + } + memcpy((char *)&str_size64, toc_addr + toc_offset, + sizeof(uint64_t)); + if(toc_byte_sex != host_byte_sex) + str_size64 = SWAP_LONG_LONG(str_size64); + string_size = str_size64; + toc_offset += sizeof(uint64_t); + } big_size = toc_offset; - big_size += str_size; + big_size += string_size; if(big_size > toc_size){ error_with_arch(arch_name, "truncated table of contents in: " "%s(%.*s) (ranlib strings extends past the end of the " "table of contents member)", library_name, (int)toc_name_size, toc_name); - free(ranlibs); + if(ranlibs != NULL) + free(ranlibs); + if(ranlibs64 != NULL) + free(ranlibs64); return; } strings = toc_addr + toc_offset; @@ -1262,14 +1438,19 @@ enum bool verbose) printf(" (for architecture %s)\n", arch_name); else printf("\n"); - printf("size of ranlib structures: %u (number %u)\n", ran_size, + printf("size of ranlib structures: %llu (number %llu)\n", sizeof_rans, nranlibs); if(verbose){ - printf("size of strings: %u", str_size); - if(str_size % sizeof(int32_t) != 0) - printf(" (not multiple of sizeof(int32_t))\n"); - else - printf("\n"); + printf("size of strings: %llu", string_size); + if(using_64toc == FALSE){ + if(string_size % sizeof(int32_t) != 0) + printf(" (not multiple of sizeof(int32_t))"); + } + else{ + if(string_size % sizeof(int64_t) != 0) + printf(" (not multiple of sizeof(int64_t))"); + } + printf("\n"); } if(verbose) printf("object symbol name\n"); @@ -1277,14 +1458,22 @@ enum bool verbose) printf("object offset string index\n"); for(i = 0; i < nranlibs; i++){ + if(using_64toc == FALSE){ + ran_off = ranlibs[i].ran_off; + ran_strx = ranlibs[i].ran_un.ran_strx; + } + else{ + ran_off = ranlibs64[i].ran_off; + ran_strx = ranlibs64[i].ran_un.ran_strx; + } if(verbose){ - if(ranlibs[i].ran_off + sizeof(struct ar_hdr) <= library_size){ + if(ran_off + sizeof(struct ar_hdr) <= library_size){ ar_hdr = (struct ar_hdr *) - (library_addr + ranlibs[i].ran_off); + (library_addr + ran_off); if(strncmp(ar_hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){ member_name = ar_hdr->ar_name + sizeof(struct ar_hdr); - member_name_size = strtoul(ar_hdr->ar_name + + member_name_size = (uint32_t)strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1, NULL, 10); while(member_name_size > 0 && member_name[member_name_size - 1] == '\0') @@ -1299,21 +1488,23 @@ enum bool verbose) } } else{ - n = sprintf(buf, "?(%u) ", (uint32_t)ranlibs[i].ran_off); + n = sprintf(buf, "?(%llu) ", ran_off); printf("%s%.*s", buf, 17 - n, " "); } - if(ranlibs[i].ran_un.ran_strx < str_size) - printf("%s\n", strings + ranlibs[i].ran_un.ran_strx); + if(ran_strx < string_size) + printf("%s\n", strings + ran_strx); else - printf("?(%u)\n", (uint32_t)ranlibs[i].ran_un.ran_strx); + printf("?(%llu)\n", ran_strx); } else{ - printf("%-14u %u\n", (uint32_t)ranlibs[i].ran_off, - (uint32_t)ranlibs[i].ran_un.ran_strx); + printf("%-14llu %llu\n", ran_off, ran_strx); } } - free(ranlibs); + if(ranlibs != NULL) + free(ranlibs); + if(ranlibs64 != NULL) + free(ranlibs64); } /* @@ -1393,7 +1584,7 @@ enum bool verbose) * order as the member offset references above. */ sym_names = toc_addr + toc_offset; - sym_names_size = toc_size - toc_offset; + sym_names_size = (uint32_t)(toc_size - toc_offset); /* * Long archive member names are stored in the archive member contents @@ -1402,16 +1593,17 @@ enum bool verbose) * the format "/offset" where the "offset" is a decimal offset into the * archive member string names. */ - library_size_after_toc = library_size - + library_size_after_toc = (uint32_t)(library_size - (((char *)toc_ar_hdr + sizeof(struct ar_hdr) + toc_size) - - library_addr); + library_addr)); ar_strtab = NULL; ar_strtab_size = 0; if(library_size_after_toc >= sizeof(struct ar_hdr)){ strtab_ar_hdr = (struct ar_hdr *) ((char *)toc_ar_hdr + sizeof(struct ar_hdr) + toc_size); if(strncmp(strtab_ar_hdr->ar_name, "// ", sizeof("// ")-1) == 0){ - ar_strtab_size = strtoul(strtab_ar_hdr->ar_size, NULL, 10); + ar_strtab_size = (uint32_t)strtoul(strtab_ar_hdr->ar_size, + NULL, 10); if(ar_strtab_size > library_size_after_toc - sizeof(struct ar_hdr)) ar_strtab_size = library_size_after_toc - @@ -1463,8 +1655,8 @@ enum bool verbose) * it that is the offset into the member name string table. */ if(ar_hdr->ar_name[0] == '/'){ - member_name_offset = strtoul(ar_hdr->ar_name + 1, - NULL, 10); + member_name_offset = + (uint32_t)strtoul(ar_hdr->ar_name + 1, NULL, 10); if(member_name_offset < ar_strtab_size){ for(n = member_name_offset; n < ar_strtab_size; n++){ @@ -1897,6 +2089,20 @@ NS32: case CPU_SUBTYPE_ARM64_V8: printf(" V8"); break; + case CPU_SUBTYPE_ARM64E: + printf(" E"); + break; + default: + printf(" %10d", cpusubtype & ~CPU_SUBTYPE_MASK); + break; + } + break; + case CPU_TYPE_ARM64_32: + printf(" ARM64_32"); + switch(cpusubtype & ~CPU_SUBTYPE_MASK){ + case CPU_SUBTYPE_ARM64_32_V8: + printf(" V8"); + break; default: printf(" %10d", cpusubtype & ~CPU_SUBTYPE_MASK); break; @@ -2025,17 +2231,25 @@ NS32: printf(" ALLOW_STACK_EXECUTION"); f &= ~MH_ALLOW_STACK_EXECUTION; } - if(f & MH_DEAD_STRIPPABLE_DYLIB){ - printf(" DEAD_STRIPPABLE_DYLIB"); - f &= ~MH_DEAD_STRIPPABLE_DYLIB; + if(f & MH_ROOT_SAFE){ + printf(" ROOT_SAFE"); + f &= ~MH_ROOT_SAFE; + } + if(f & MH_SETUID_SAFE){ + printf(" SETUID_SAFE"); + f &= ~MH_SETUID_SAFE; + } + if(f & MH_NO_REEXPORTED_DYLIBS){ + printf(" NO_REEXPORTED_DYLIBS"); + f &= ~MH_NO_REEXPORTED_DYLIBS; } if(f & MH_PIE){ printf(" PIE"); f &= ~MH_PIE; } - if(f & MH_NO_REEXPORTED_DYLIBS){ - printf(" NO_REEXPORTED_DYLIBS"); - f &= ~MH_NO_REEXPORTED_DYLIBS; + if(f & MH_DEAD_STRIPPABLE_DYLIB){ + printf(" DEAD_STRIPPABLE_DYLIB"); + f &= ~MH_DEAD_STRIPPABLE_DYLIB; } if(f & MH_HAS_TLV_DESCRIPTORS){ printf(" MH_HAS_TLV_DESCRIPTORS"); @@ -2049,6 +2263,14 @@ NS32: printf(" APP_EXTENSION_SAFE"); f &= ~MH_APP_EXTENSION_SAFE; } + if(f & MH_NLIST_OUTOFSYNC_WITH_DYLDINFO){ + printf(" NLIST_OUTOFSYNC_WITH_DYLDINFO"); + f &= ~MH_NLIST_OUTOFSYNC_WITH_DYLDINFO; + } + if(f & MH_SIM_SUPPORT){ + printf(" SIM_SUPPORT"); + f &= ~MH_SIM_SUPPORT; + } if(f != 0 || flags == 0) printf(" 0x%08x", (unsigned int)f); printf("\n"); @@ -2075,7 +2297,7 @@ uint32_t sizeofcmds, cpu_type_t cputype, uint32_t filetype, enum byte_sex load_commands_byte_sex, -uint32_t object_size, +uint64_t object_size, enum bool verbose, enum bool very_verbose) { @@ -2112,8 +2334,11 @@ enum bool very_verbose) struct linker_option_command lo; struct dyld_info_command dyld_info; struct version_min_command vd; + struct build_version_command bv; + struct build_tool_version btv; struct entry_point_command ep; struct source_version_command sv; + struct note_command nc; uint64_t big_load_end; host_byte_sex = get_host_byte_sex(); @@ -2135,7 +2360,7 @@ enum bool very_verbose) if(big_load_end > sizeofcmds) printf("load command %u extends past end of load commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_SEGMENT: @@ -2156,7 +2381,7 @@ enum bool very_verbose) printf("section structure command extends past end of " "load commands\n"); } - left = sizeofcmds - (p - (char *)load_commands); + left = sizeofcmds - (uint32_t)(p - (char *)load_commands); memset((char *)&s, '\0', sizeof(struct section)); size = left < sizeof(struct section) ? left : sizeof(struct section); @@ -2192,7 +2417,7 @@ enum bool very_verbose) printf("section structure command extends past end of " "load commands\n"); } - left = sizeofcmds - (p - (char *)load_commands); + left = sizeofcmds - (uint32_t)(p - (char *)load_commands); memset((char *)&s64, '\0', sizeof(struct section_64)); size = left < sizeof(struct section_64) ? left : sizeof(struct section_64); @@ -2446,6 +2671,8 @@ enum bool very_verbose) case LC_DATA_IN_CODE: case LC_DYLIB_CODE_SIGN_DRS: case LC_LINKER_OPTIMIZATION_HINT: + case LC_DYLD_EXPORTS_TRIE: + case LC_DYLD_CHAINED_FIXUPS: memset((char *)&ld, '\0', sizeof(struct linkedit_data_command)); size = left < sizeof(struct linkedit_data_command) ? left : sizeof(struct linkedit_data_command); @@ -2523,6 +2750,36 @@ enum bool very_verbose) print_version_min_command(&vd); break; + case LC_BUILD_VERSION: + memset((char *)&bv, '\0', sizeof(struct build_version_command)); + size = left < sizeof(struct build_version_command) ? + left : sizeof(struct build_version_command); + memcpy((char *)&bv, (char *)lc, size); + if(swapped) + swap_build_version_command(&bv, host_byte_sex); + print_build_version_command(&bv, verbose); + p = (char *)lc + sizeof(struct build_version_command); + for(j = 0 ; j < bv.ntools ; j++){ + if(p + sizeof(struct build_tool_version) > + (char *)load_commands + sizeofcmds){ + printf("build_tool_version structure command extends " + "past end of load commands\n"); + } + left = sizeofcmds - (uint32_t)(p - (char *)load_commands); + memset((char *)&s, '\0', sizeof(struct build_tool_version)); + size = left < sizeof(struct build_tool_version) ? + left : sizeof(struct build_tool_version); + memcpy((char *)&btv, p, size); + if(swapped) + swap_build_tool_version(&btv, 1, host_byte_sex); + print_build_tool_version(btv.tool, btv.version, verbose); + if(p + sizeof(struct build_tool_version) > + (char *)load_commands + sizeofcmds) + return; + p += size; + } + break; + case LC_SOURCE_VERSION: memset((char *)&sv, '\0',sizeof(struct source_version_command)); size = left < sizeof(struct source_version_command) ? @@ -2533,6 +2790,16 @@ enum bool very_verbose) print_source_version_command(&sv); break; + case LC_NOTE: + memset((char *)&nc, '\0',sizeof(struct note_command)); + size = left < sizeof(struct note_command) ? + left : sizeof(struct note_command); + memcpy((char *)&nc, (char *)lc, size); + if(swapped) + swap_note_command(&nc, host_byte_sex); + print_note_command(&nc, object_size); + break; + case LC_MAIN: memset((char *)&ep, '\0', sizeof(struct entry_point_command)); size = left < sizeof(struct entry_point_command) ? @@ -2612,7 +2879,7 @@ enum bool verbose) if((char *)lc + l.cmdsize > (char *)load_commands + sizeofcmds) printf("load command %u extends past end of load commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_IDFVMLIB: @@ -2723,7 +2990,7 @@ vm_prot_t maxprot, vm_prot_t initprot, uint32_t nsects, uint32_t flags, -uint32_t object_size, +uint64_t object_size, enum bool verbose) { uint64_t expected_cmdsize; @@ -2826,6 +3093,10 @@ enum bool verbose) printf(" PROTECTED_VERSION_1"); flags &= ~SG_PROTECTED_VERSION_1; } + if(flags & SG_READ_ONLY){ + printf(" SG_READ_ONLY"); + flags &= ~SG_READ_ONLY; + } if(flags) printf(" 0x%x (unknown flags)\n", (unsigned int)flags); else @@ -2856,7 +3127,7 @@ uint32_t reserved2, uint32_t cmd, char *sg_segname, uint32_t filetype, -uint32_t object_size, +uint64_t object_size, enum bool verbose) { uint32_t section_type, section_attributes; @@ -2997,7 +3268,7 @@ void print_symtab_command( struct symtab_command *st, cpu_type_t cputype, -uint32_t object_size) +uint64_t object_size) { uint64_t big_size; @@ -3053,7 +3324,7 @@ void print_dysymtab_command( struct dysymtab_command *dyst, uint32_t nsyms, -uint32_t object_size, +uint64_t object_size, cpu_type_t cputype) { uint64_t modtabend, big_size; @@ -3195,7 +3466,7 @@ cpu_type_t cputype) void print_symseg_command( struct symseg_command *ss, -uint32_t object_size) +uint64_t object_size) { uint64_t big_size; @@ -3305,17 +3576,17 @@ uint32_t left) printf("n/a\n"); else printf("%u.%u.%u\n", - dl->dylib.current_version >> 16, - (dl->dylib.current_version >> 8) & 0xff, - dl->dylib.current_version & 0xff); + dl->dylib.current_version >> 16, + (dl->dylib.current_version >> 8) & 0xff, + dl->dylib.current_version & 0xff); printf("compatibility version "); if(dl->dylib.compatibility_version == 0xffffffff) printf("n/a\n"); else printf("%u.%u.%u\n", - dl->dylib.compatibility_version >> 16, - (dl->dylib.compatibility_version >> 8) & 0xff, - dl->dylib.compatibility_version & 0xff); + dl->dylib.compatibility_version >> 16, + (dl->dylib.compatibility_version >> 8) & 0xff, + dl->dylib.compatibility_version & 0xff); } /* @@ -3621,7 +3892,7 @@ struct routines_command_64 *rc64) void print_twolevel_hints_command( struct twolevel_hints_command *hints, -uint32_t object_size) +uint64_t object_size) { uint64_t big_size; @@ -3696,7 +3967,7 @@ struct uuid_command *uuid) void print_linkedit_data_command( struct linkedit_data_command *ld, -uint32_t object_size) +uint64_t object_size) { uint64_t big_size; @@ -3712,6 +3983,10 @@ uint32_t object_size) printf(" cmd LC_DYLIB_CODE_SIGN_DRS\n"); else if(ld->cmd == LC_LINKER_OPTIMIZATION_HINT) printf(" cmd LC_LINKER_OPTIMIZATION_HINT\n"); + else if(ld->cmd == LC_DYLD_EXPORTS_TRIE) + printf(" cmd LC_DYLD_EXPORTS_TRIE\n"); + else if(ld->cmd == LC_DYLD_CHAINED_FIXUPS) + printf(" cmd LC_DYLD_CHAINED_FIXUPS\n"); else printf(" cmd %u (?)\n", ld->cmd); printf(" cmdsize %u", ld->cmdsize); @@ -3756,28 +4031,108 @@ struct version_min_command *vd) printf(" Incorrect size\n"); else printf("\n"); - if((vd->version & 0xff) == 0) - printf(" version %u.%u\n", - vd->version >> 16, - (vd->version >> 8) & 0xff); - else - printf(" version %u.%u.%u\n", - vd->version >> 16, - (vd->version >> 8) & 0xff, - vd->version & 0xff); + print_version_xyz(" version", vd->version); if(vd->sdk == 0) printf(" sdk n/a\n"); - else{ - if((vd->sdk & 0xff) == 0) - printf(" sdk %u.%u\n", - vd->sdk >> 16, - (vd->sdk >> 8) & 0xff); - else - printf(" sdk %u.%u.%u\n", - vd->sdk >> 16, - (vd->sdk >> 8) & 0xff, - vd->sdk & 0xff); + else + print_version_xyz(" sdk", vd->sdk); +} + +/* + * print a build_version_command. The build_version_command structure + * specified must be aligned correctly and in the host byte sex. + */ +void +print_build_version_command( +struct build_version_command *bv, +enum bool verbose) +{ + if(bv->cmd == LC_BUILD_VERSION) + printf(" cmd LC_BUILD_VERSION\n"); + else + printf(" cmd %u (?)\n", bv->cmd); + printf(" cmdsize %u", bv->cmdsize); + if(bv->cmdsize != sizeof(struct build_version_command) + + bv->ntools * sizeof(struct build_tool_version)) + printf(" Incorrect size\n"); + else + printf("\n"); + if(verbose){ + printf(" platform "); + switch(bv->platform){ + case PLATFORM_MACOS: + printf("MACOS\n"); + break; + case PLATFORM_IOS: + printf("IOS\n"); + break; + case PLATFORM_TVOS: + printf("TVOS\n"); + break; + case PLATFORM_WATCHOS: + printf("WATCHOS\n"); + break; + case PLATFORM_BRIDGEOS: + printf("BRIDGEOS\n"); + break; + case PLATFORM_MACCATALYST: + printf("MACCATALYST\n"); + break; + case PLATFORM_IOSSIMULATOR: + printf("IOSSIMULATOR\n"); + break; + case PLATFORM_TVOSSIMULATOR: + printf("TVOSSIMULATOR\n"); + break; + case PLATFORM_WATCHOSSIMULATOR: + printf("WATCHOSSIMULATOR\n"); + break; + case PLATFORM_DRIVERKIT: + printf("DRIVERKIT\n"); + break; + default: + printf("%u\n", bv->platform); + break; + } } + else{ + printf(" platform %u\n", bv->platform); + } + print_version_xyz(" minos", bv->minos); + if(bv->sdk == 0) + printf(" sdk n/a\n"); + else{ + print_version_xyz(" sdk", bv->sdk); + } + printf(" ntools %u\n", bv->ntools); +} + +void +print_build_tool_version( +uint32_t tool, +uint32_t version, +enum bool verbose) +{ + if(verbose){ + printf(" tool "); + switch(tool){ + case TOOL_CLANG: + printf("CLANG\n"); + break; + case TOOL_SWIFT: + printf("SWIFT\n"); + break; + case TOOL_LD: + printf("LD\n"); + break; + default: + printf("%u\n", tool); + break; + } + } + else + printf(" tool %u\n", tool); + print_version_xyz(" version", version); } /* @@ -3811,6 +4166,38 @@ struct source_version_command *sv) printf(" version %llu.%llu\n", a, b); } +/* + * print a note_command. The note_command structure specified must aligned and + * in the host byte sex. + */ +void +print_note_command( +struct note_command *nc, +uint64_t object_size) +{ + uint64_t big_size; + + printf(" cmd LC_NOTE\n"); + printf(" cmdsize %u", nc->cmdsize); + if(nc->cmdsize != sizeof(struct note_command)) + printf(" Incorrect size\n"); + else + printf("\n"); + printf("data_owner %.16s\n", nc->data_owner); + printf(" offset %llu", nc->offset); + if(nc->offset > object_size) + printf(" (past end of file)\n"); + else + printf("\n"); + printf(" size %llu", nc->size); + big_size = nc->offset; + big_size += nc->size; + if(big_size > object_size) + printf(" (past end of file)\n"); + else + printf("\n"); +} + /* * print a entry_point_command. The entry_point_command structure * specified must be aligned correctly and in the host byte sex. @@ -3821,7 +4208,7 @@ struct entry_point_command *ep) { printf(" cmd LC_MAIN\n"); printf(" cmdsize %u", ep->cmdsize); - if(ep->cmdsize < sizeof(struct entry_point_command)) + if(ep->cmdsize != sizeof(struct entry_point_command)) printf(" Incorrect size\n"); else printf("\n"); @@ -3862,13 +4249,13 @@ struct load_command *lc) void print_encryption_info_command( struct encryption_info_command *ec, -uint32_t object_size) +uint64_t object_size) { uint64_t big_size; printf(" cmd LC_ENCRYPTION_INFO\n"); printf(" cmdsize %u", ec->cmdsize); - if(ec->cmdsize < sizeof(struct encryption_info_command)) + if(ec->cmdsize != sizeof(struct encryption_info_command)) printf(" Incorrect size\n"); else printf("\n"); @@ -3894,13 +4281,13 @@ uint32_t object_size) void print_encryption_info_command_64( struct encryption_info_command_64 *ec, -uint32_t object_size) +uint64_t object_size) { uint64_t big_size; printf(" cmd LC_ENCRYPTION_INFO_64\n"); printf(" cmdsize %u", ec->cmdsize); - if(ec->cmdsize < sizeof(struct encryption_info_command_64)) + if(ec->cmdsize != sizeof(struct encryption_info_command_64)) printf(" Incorrect size\n"); else printf("\n"); @@ -3933,7 +4320,8 @@ struct linker_option_command *lo, struct load_command *lc, uint32_t cmdleft) { - int left, len, i; + int left, i; + size_t len; char *string; printf(" cmd LC_LINKER_OPTION\n"); @@ -3973,7 +4361,7 @@ uint32_t cmdleft) void print_dyld_info_info_command( struct dyld_info_command *dc, -uint32_t object_size) +uint64_t object_size) { uint64_t big_size; @@ -3982,7 +4370,7 @@ uint32_t object_size) else printf(" cmd LC_DYLD_INFO_ONLY\n"); printf(" cmdsize %u", dc->cmdsize); - if(dc->cmdsize < sizeof(struct dyld_info_command)) + if(dc->cmdsize != sizeof(struct dyld_info_command)) printf(" Incorrect size\n"); else printf("\n"); @@ -4110,7 +4498,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not M68K_THREAD_STATE_" "REGS_COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(struct m68k_thread_state_regs)){ memcpy((char *)&cpu, begin, sizeof(struct m68k_thread_state_regs)); @@ -4146,7 +4534,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not M68K_THREAD_STATE_" "68882_COUNT\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(struct m68k_thread_state_68882)){ memcpy((char *)&fpu, begin, sizeof(struct m68k_thread_state_68882)); @@ -4178,7 +4566,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not M68K_THREAD_STATE_" "USER_REG_COUNT", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(struct m68k_thread_state_user_reg)){ memcpy((char *)&user_reg, begin, sizeof(struct m68k_thread_state_user_reg)); @@ -4240,7 +4628,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not HPPA_INTEGER_THREAD_STATE_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(struct hp_pa_integer_thread_state)){ memcpy((char *)&frame, begin, sizeof(struct hp_pa_integer_thread_state)); @@ -4283,7 +4671,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not HPPA_FRAME_THREAD_STATE_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(struct hp_pa_frame_thread_state)){ memcpy((char *)&frame, begin, sizeof(struct hp_pa_frame_thread_state)); @@ -4313,7 +4701,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not HPPA_FP_THREAD_STATE_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(struct hp_pa_fp_thread_state)){ memcpy((char *)&frame, begin, sizeof(struct hp_pa_fp_thread_state)); @@ -4387,7 +4775,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not SPARC_THREAD_STATE_REGS_COUNT)\n", count); - left = begin - end; + left = (uint32_t)(end - begin); if (left >= sizeof(struct sparc_thread_state_regs)) { memcpy((char *) &cpu, begin, sizeof(struct sparc_thread_state_regs)); @@ -4425,7 +4813,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not SPARC_THREAD_STATE_FPU_COUNT)\n", count); - left = begin - end; + left = (uint32_t)(end - begin); if (left >= sizeof(struct sparc_thread_state_fpu)) { memcpy((char *) &fpu, begin, sizeof(struct sparc_thread_state_fpu)); @@ -4514,7 +4902,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not PPC_THREAD_STATE_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(ppc_thread_state_t)){ memcpy((char *)&cpu, begin, sizeof(ppc_thread_state_t)); @@ -4559,7 +4947,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not PPC_FLOAT_STATE_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(ppc_float_state_t)){ memcpy((char *)&fpu, begin, sizeof(ppc_float_state_t)); @@ -4602,7 +4990,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not PPC_EXCEPTION_STATE_COUNT" ")\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(ppc_exception_state_t)){ memcpy((char *)&except, begin, sizeof(ppc_exception_state_t)); @@ -4634,7 +5022,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not PPC_THREAD_STATE64_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(ppc_thread_state64_t)){ memcpy((char *)&cpu64, begin, sizeof(ppc_thread_state64_t)); @@ -4717,7 +5105,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not M88K_THREAD_STATE_GRF_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(m88k_thread_state_grf_t)){ memcpy((char *)&cpu, begin, sizeof(m88k_thread_state_grf_t)); @@ -4760,7 +5148,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not M88K_THREAD_STATE_XRF_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(m88k_thread_state_xrf_t)){ memcpy((char *)&fpu, begin, sizeof(m88k_thread_state_xrf_t)); @@ -4866,7 +5254,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not M88K_THREAD_STATE_USER_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(m88k_thread_state_user_t)){ memcpy((char *)&user, begin, sizeof(m88k_thread_state_user_t)); @@ -4890,7 +5278,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not M88110_THREAD_STATE_IMPL_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(m88110_thread_state_impl_t)){ memcpy((char *)&spu, begin, sizeof(m88110_thread_state_impl_t)); @@ -5005,7 +5393,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not I860_THREAD_STATE_REGS_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(struct i860_thread_state_regs)){ memcpy((char *)&cpu, begin, sizeof(struct i860_thread_state_regs)); @@ -5127,7 +5515,7 @@ enum byte_sex thread_states_byte_sex) else printf(" count %u (not i386_THREAD_STATE_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(i386_thread_state_t)){ memcpy((char *)&cpu, begin, sizeof(i386_thread_state_t)); @@ -5163,7 +5551,7 @@ print_x86_thread_state32: else printf(" count %u (not i386_FLOAT_STATE_COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); #ifndef i386_EXCEPTION_STATE_COUNT fpu = begin; if(left >= sizeof(struct i386_float_state)){ @@ -5329,7 +5717,7 @@ print_x86_float_state32: else printf(" count %u (not I386_EXCEPTION_STATE_COUNT" ")\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(i386_exception_state_t)){ memcpy((char *)&exc, begin, sizeof(i386_exception_state_t)); @@ -5358,7 +5746,7 @@ print_x86_exception_state32: else printf(" count %u (not x86_DEBUG_STATE32_COUNT" ")\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(x86_debug_state32_t)){ memcpy((char *)&debug, begin, sizeof(x86_debug_state32_t)); @@ -5388,7 +5776,7 @@ print_x86_debug_state32: else printf(" count %u (not x86_THREAD_STATE64_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(x86_thread_state64_t)){ memcpy((char *)&cpu64, begin, sizeof(x86_thread_state64_t)); @@ -5426,7 +5814,7 @@ print_x86_thread_state64: else printf(" count %u (not x86_FLOAT_STATE64_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(x86_float_state64_t)){ memcpy((char *)&fpu64, begin, sizeof(x86_float_state64_t)); @@ -5585,7 +5973,7 @@ print_x86_float_state64: else printf(" count %u (not x86_EXCEPTION_STATE64_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(x86_exception_state64_t)){ memcpy((char *)&exc64, begin, sizeof(x86_exception_state64_t)); @@ -5612,7 +6000,7 @@ print_x86_exception_state64: else printf(" count %u (not x86_DEBUG_STATE64_COUNT" ")\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(x86_debug_state64_t)){ memcpy((char *)&debug64, begin, sizeof(x86_debug_state32_t)); @@ -5642,7 +6030,7 @@ print_x86_debug_state64: else printf(" count %u (not x86_THREAD_STATE_COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(x86_thread_state_t)){ memcpy((char *)&ts, begin, sizeof(x86_thread_state_t)); @@ -5689,7 +6077,7 @@ print_x86_debug_state64: else printf(" count %u (not x86_FLOAT_STATE_COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(x86_float_state_t)){ memcpy((char *)&fs, begin, sizeof(x86_float_state_t)); @@ -5736,7 +6124,7 @@ print_x86_debug_state64: else printf(" count %u (not x86_EXCEPTION_STATE_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(x86_exception_state_t)){ memcpy((char *)&es, begin, sizeof(x86_exception_state_t)); @@ -5785,7 +6173,7 @@ print_x86_debug_state64: else printf(" count %u (not x86_DEBUG_STATE_COUNT" "\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(x86_debug_state_t)){ memcpy((char *)&ds, begin, sizeof(x86_debug_state_t)); @@ -5836,7 +6224,7 @@ print_x86_debug_state64: else printf(" count %u (not i386_THREAD_FPSTATE_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(i386_thread_fpstate_t)){ memcpy((char *)&fpu, begin, sizeof(i386_thread_fpstate_t)); @@ -5981,7 +6369,7 @@ print_x86_debug_state64: else printf(" count %u (not i386_THREAD_EXCEPTSTATE_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(i386_thread_exceptstate_t)){ memcpy((char *)&exc, begin, sizeof(i386_thread_exceptstate_t)); @@ -6029,7 +6417,7 @@ print_x86_debug_state64: else printf(" count %u (not i386_THREAD_CTHREADSTATE_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(i386_thread_cthreadstate_t)){ memcpy((char *)&user, begin, sizeof(i386_thread_cthreadstate_t)); @@ -6088,7 +6476,7 @@ print_x86_debug_state64: else printf(" count %u (not ARM_THREAD_STATE_" "COUNT)\n", count); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(arm_thread_state_t)){ memcpy((char *)&cpu, begin, sizeof(arm_thread_state_t)); @@ -6123,8 +6511,9 @@ print_x86_debug_state64: } } } - else if(cputype == CPU_TYPE_ARM64){ + else if(cputype == CPU_TYPE_ARM64 || cputype == CPU_TYPE_ARM64_32){ arm_thread_state64_t cpu; + arm_exception_state64_t except; while(begin < end){ if(end - begin > (ptrdiff_t)sizeof(uint32_t)){ memcpy((char *)&flavor, begin, sizeof(uint32_t)); @@ -6160,7 +6549,7 @@ print_x86_debug_state64: else printf(" count %u (not ARM_THREAD_STATE64_" "COUNT %u)\n", count, ARM_THREAD_STATE64_COUNT); - left = end - begin; + left = (uint32_t)(end - begin); if(left >= sizeof(arm_thread_state64_t)){ memcpy((char *)&cpu, begin, sizeof(arm_thread_state64_t)); @@ -6197,6 +6586,31 @@ print_x86_debug_state64: cpu.__x[28], cpu.__fp, cpu.__lr, cpu.__sp, cpu.__pc, cpu.__cpsr); break; + case ARM_EXCEPTION_STATE64: + printf(" flavor ARM_EXCEPTION_STATE64\n"); + if(count == ARM_EXCEPTION_STATE64_COUNT) + printf(" count ARM_EXCEPTION_STATE64_COUNT\n"); + else + printf(" count %u (not ARM_EXCEPTION_STATE64_COUNT" + " %u)\n", count, ARM_EXCEPTION_STATE64_COUNT); + left = (uint32_t)(end - begin); + if(left >= sizeof(arm_exception_state64_t)){ + memcpy((char *)&except, begin, + sizeof(arm_exception_state64_t)); + begin += sizeof(arm_exception_state64_t); + } + else{ + memset((char *)&except, '\0', + sizeof(arm_exception_state64_t)); + memcpy((char *)&except, begin, left); + begin += left; + } + if(swapped) + swap_arm_exception_state64_t(&except, host_byte_sex); + printf( + "\t far 0x%016llx esr 0x%08x exception 0x%08x\n", + except.__far, except.__esr, except.__exception); + break; default: printf(" flavor %u (unknown)\n", flavor); printf(" count %u\n", count); @@ -6290,7 +6704,7 @@ enum bool swapped) { uint32_t left, *state, i, j; - left = end - begin; + left = (uint32_t)(end - begin); if(left / sizeof(uint32_t) >= count){ state = allocate(count * sizeof(uint32_t)); memcpy((char *)state, begin, count * sizeof(uint32_t)); @@ -6325,7 +6739,7 @@ uint32_t sizeofcmds, cpu_type_t cputype, enum byte_sex load_commands_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct nlist *symbols, struct nlist_64 *symbols64, uint32_t nsymbols, @@ -6369,7 +6783,7 @@ enum bool verbose) (char *)load_commands + sizeofcmds) printf("load command %u extends past end of load " "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_SEGMENT: @@ -6399,7 +6813,7 @@ enum bool verbose) sizeof(struct reloc_section_info) * sg.nsects); p = (char *)lc + sizeof(struct segment_command); for(j = 0 ; j < sg.nsects ; j++){ - left = sizeofcmds - (p - (char *)load_commands); + left = sizeofcmds - (uint32_t)(p - (char *)load_commands); size = left < sizeof(struct section) ? left : sizeof(struct section); memcpy((char *)&s, p, size); @@ -6444,7 +6858,7 @@ enum bool verbose) sizeof(struct reloc_section_info) * sg64.nsects); p = (char *)lc + sizeof(struct segment_command_64); for(j = 0 ; j < sg64.nsects ; j++){ - left = sizeofcmds - (p - (char *)load_commands); + left = sizeofcmds - (uint32_t)(p - (char *)load_commands); size = left < sizeof(struct section_64) ? left : sizeof(struct section_64); memcpy((char *)&s64, p, size); @@ -6550,7 +6964,7 @@ uint32_t nsects, enum bool swapped, cpu_type_t cputype, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct nlist *symbols, struct nlist_64 *symbols64, uint32_t nsymbols, @@ -6906,7 +7320,8 @@ enum bool verbose) reloc.r_type == ARM_RELOC_PAIR) printf("other_half = 0x%04x\n", (unsigned int)reloc.r_address); - else if(cputype == CPU_TYPE_ARM64 && + else if((cputype == CPU_TYPE_ARM64 || + cputype == CPU_TYPE_ARM64_32) && reloc.r_type == ARM64_RELOC_ADDEND) printf("addend = 0x%06x\n", (unsigned int)reloc.r_symbolnum); @@ -7001,7 +7416,9 @@ static char *arm_r_types[] = { static char *arm64_r_types[] = { "UNSIGND ", "SUB ", "BR26 ", "PAGE21 ", "PAGOF12 ", "GOTLDP ", "GOTLDPOF", "PTRTGOT ", "TLVLDP ", "TLVLDPOF", - "ADDEND ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " + "ADDEND ", + "AUTH ", + " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " }; static @@ -7050,6 +7467,7 @@ enum bool predicted) printf("%s", arm_r_types[r_type]); break; case CPU_TYPE_ARM64: + case CPU_TYPE_ARM64_32: printf("%s", arm64_r_types[r_type]); break; default: @@ -7067,7 +7485,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct dylib_table_of_contents *tocs, uint32_t ntocs, struct dylib_module *mods, @@ -7420,7 +7838,7 @@ enum bool verbose) if(big_load_end > sizeofcmds) printf("load command %u extends past end of load " "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_SEGMENT: @@ -7446,7 +7864,7 @@ enum bool verbose) sizeof(struct section_indirect_info) * sg.nsects); p = (char *)lc + sizeof(struct segment_command); for(j = 0 ; j < sg.nsects ; j++){ - left = sizeofcmds - (p - (char *)load_commands); + left = sizeofcmds - (uint32_t)(p - (char *)load_commands); size = left < sizeof(struct section) ? left : sizeof(struct section); memcpy((char *)&s, p, size); @@ -7490,7 +7908,7 @@ enum bool verbose) sizeof(struct section_indirect_info) * sg64.nsects); p = (char *)lc + sizeof(struct segment_command_64); for(j = 0 ; j < sg64.nsects ; j++){ - left = sizeofcmds - (p - (char *)load_commands); + left = sizeofcmds - (uint32_t)(p - (char *)load_commands); size = left < sizeof(struct section_64) ? left : sizeof(struct section_64); memcpy((char *)&s64, p, size); @@ -7547,7 +7965,7 @@ enum bool verbose) else continue; - count = sect_ind[i].size / stride; + count = (uint32_t)(sect_ind[i].size / stride); printf("Indirect symbols for (%.16s,%.16s) %u entries", sect_ind[i].segname, sect_ind[i].sectname, count); @@ -7667,7 +8085,7 @@ enum bool verbose) if(big_load_end > sizeofcmds) printf("load command %u extends past end of load " "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_DYSYMTAB: @@ -7884,11 +8302,11 @@ void print_cstring_section( cpu_type_t cputype, char *sect, -uint32_t sect_size, +uint64_t sect_size, uint64_t sect_addr, enum bool print_addresses) { - uint32_t i; + uint64_t i; for(i = 0; i < sect_size ; i++){ if(print_addresses == TRUE){ @@ -7949,14 +8367,14 @@ void print_literal4_section( cpu_type_t cputype, char *sect, -uint32_t sect_size, +uint64_t sect_size, uint64_t sect_addr, enum byte_sex literal_byte_sex, enum bool print_addresses) { enum byte_sex host_byte_sex; enum bool swapped; - uint32_t i, l; + uint64_t i, l; float f; host_byte_sex = get_host_byte_sex(); @@ -7975,7 +8393,7 @@ enum bool print_addresses) f = SWAP_FLOAT(f); l = SWAP_INT(l); } - print_literal4(l, f); + print_literal4((uint32_t)l, f); } } @@ -8005,14 +8423,15 @@ void print_literal8_section( cpu_type_t cputype, char *sect, -uint32_t sect_size, +uint64_t sect_size, uint64_t sect_addr, enum byte_sex literal_byte_sex, enum bool print_addresses) { enum byte_sex host_byte_sex; enum bool swapped; - uint32_t i, l0, l1; + uint64_t i; + uint32_t l0, l1; double d; host_byte_sex = get_host_byte_sex(); @@ -8075,14 +8494,15 @@ void print_literal16_section( cpu_type_t cputype, char *sect, -uint32_t sect_size, +uint64_t sect_size, uint64_t sect_addr, enum byte_sex literal_byte_sex, enum bool print_addresses) { enum byte_sex host_byte_sex; enum bool swapped; - uint32_t i, l0, l1, l2, l3; + uint64_t i; + uint32_t l0, l1, l2, l3; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != literal_byte_sex; @@ -8126,14 +8546,16 @@ uint32_t l3) void print_literal_pointer_section( cpu_type_t cputype, +cpu_subtype_t cpusubtype, struct load_command *load_commands, uint32_t ncmds, uint32_t sizeofcmds, +uint32_t filetype, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, char *sect, -uint32_t sect_size, +uint64_t sect_size, uint64_t sect_addr, struct nlist *symbols, struct nlist_64 *symbols64, @@ -8146,8 +8568,8 @@ enum bool print_addresses) { enum byte_sex host_byte_sex; enum bool swapped, found; - uint32_t i, j, k, li, l0, l1, l2, l3, left, size, lp_size; - uint64_t lp; + uint32_t i, j, li, l0, l1, l2, l3, left, size, lp_size; + uint64_t k, lp; struct load_command lcmd, *lc; struct segment_command sg; struct section s; @@ -8164,7 +8586,7 @@ enum bool print_addresses) char *p; uint32_t nliteral_sections; float f; - double d; + double d = 0.; struct relocation_info *reloc; uint32_t n_strx; uint64_t big_load_end, big_size; @@ -8190,7 +8612,7 @@ enum bool print_addresses) if(big_load_end > sizeofcmds) printf("load command %u extends past end of load " "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); switch(lcmd.cmd){ case LC_SEGMENT: @@ -8208,7 +8630,7 @@ enum bool print_addresses) printf("section structure command extends past " "end of load commands\n"); } - left = sizeofcmds - (p - (char *)load_commands); + left = sizeofcmds - (uint32_t)(p - (char *)load_commands); memset((char *)&s, '\0', sizeof(struct section)); size = left < sizeof(struct section) ? left : sizeof(struct section); @@ -8243,7 +8665,7 @@ enum bool print_addresses) "is past end of file\n", s.segname, s.sectname); literal_sections[nliteral_sections].size = - object_size - s.offset; + (uint32_t)(object_size - s.offset); } else literal_sections[nliteral_sections].size = s.size; @@ -8271,7 +8693,7 @@ enum bool print_addresses) printf("section structure command extends past " "end of load commands\n"); } - left = sizeofcmds - (p - (char *)load_commands); + left = sizeofcmds - (uint32_t)(p - (char *)load_commands); memset((char *)&s64, '\0', sizeof(struct section_64)); size = left < sizeof(struct section_64) ? left : sizeof(struct section_64); @@ -8306,10 +8728,11 @@ enum bool print_addresses) "is past end of file\n", s64.segname, s64.sectname); literal_sections[nliteral_sections].size = - object_size - s64.offset; + (uint32_t)(object_size - s64.offset); } else - literal_sections[nliteral_sections].size = s64.size; + literal_sections[nliteral_sections].size = + (uint32_t)s64.size; nliteral_sections++; } @@ -8347,6 +8770,23 @@ enum bool print_addresses) memcpy((char *)&lp, sect + i, sizeof(uint64_t)); if(swapped) lp = SWAP_LONG_LONG(lp); + /* Clear out the bits for threaded rebase/bind */ + if(cputype == CPU_TYPE_ARM64 && + cpusubtype == CPU_SUBTYPE_ARM64E){ + if(filetype == MH_OBJECT){ + if(lp & 0x8000000000000000ULL){ + lp = 0xffffffffULL & lp; + if((lp & 0x80000000ULL) != 0) + lp |= 0xffffffff00000000ULL; + } + } + else{ + if(lp & 0x8000000000000000ULL) + lp = 0xffffffffULL & lp; + else + lp = 0x0007ffffffffffffULL & lp; + } + } } else{ li = (int32_t)*((int32_t *)(sect + i)); @@ -8482,18 +8922,28 @@ void print_init_term_pointer_section( cpu_type_t cputype, char *sect, -uint32_t sect_size, +uint64_t sect_size, uint64_t sect_addr, enum byte_sex object_byte_sex, struct symbol *sorted_symbols, uint32_t nsorted_symbols, +struct nlist *symbols, +struct nlist_64 *symbols64, +uint32_t nsymbols, +char *strings, +uint32_t strings_size, +struct relocation_info *relocs, +uint32_t nrelocs, enum bool verbose) { - uint32_t i, stride, p; - uint64_t q; + uint64_t i, stride; + uint32_t p; + uint64_t q, lp; enum byte_sex host_byte_sex; enum bool swapped; const char *name; + struct relocation_info *reloc; + uint32_t n_strx; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != object_byte_sex; @@ -8522,22 +8972,56 @@ enum bool verbose) else p = SWAP_INT(p); } - if(cputype & CPU_ARCH_ABI64) + if(cputype & CPU_ARCH_ABI64){ printf("0x%016llx", q); - else + lp = q; + } else { printf("0x%08x", p); + lp = p; + } if(verbose == TRUE){ - if(cputype & CPU_ARCH_ABI64) - name = guess_symbol(q, sorted_symbols, nsorted_symbols, - verbose); - else - name = guess_symbol(p, sorted_symbols, nsorted_symbols, - verbose); - if(name != NULL) - printf(" %s\n", name); - else - printf("\n"); + /* + * If there is an external relocation entry for this pointer then + * print the symbol and any offset. + */ + reloc = bsearch(&i, relocs, nrelocs, + sizeof(struct relocation_info), + (int (*)(const void *, const void *)) + rel_bsearch); + if(reloc != NULL && (reloc->r_address & R_SCATTERED) == 0 && + reloc->r_extern == 1){ + if(reloc->r_symbolnum < nsymbols){ + if(symbols != NULL) + n_strx = symbols[reloc->r_symbolnum].n_un.n_strx; + else + n_strx = symbols64[reloc->r_symbolnum].n_un.n_strx; + if(n_strx < strings_size){ + if(lp != 0) + printf(" %s+0x%llx\n", strings + n_strx, lp); + else + printf(" %s\n", strings + n_strx); + } + else{ + printf("bad string index for symbol: %u\n", + reloc->r_symbolnum); + } + } + else{ + printf("bad relocation entry\n"); + } + } else { + if(cputype & CPU_ARCH_ABI64) + name = guess_symbol(q, sorted_symbols, nsorted_symbols, + verbose); + else + name = guess_symbol(p, sorted_symbols, nsorted_symbols, + verbose); + if(name != NULL) + printf(" %s\n", name); + else + printf("\n"); + } } else{ printf("\n"); @@ -8579,8 +9063,8 @@ void print_shlib_init( enum byte_sex object_byte_sex, char *sect, -uint32_t sect_size, -uint32_t sect_addr, +uint64_t sect_size, +uint64_t sect_addr, struct symbol *sorted_symbols, uint32_t nsorted_symbols, struct nlist *symbols, @@ -8594,7 +9078,7 @@ enum bool verbose) { enum byte_sex host_byte_sex; enum bool swapped; - uint32_t i; + uint64_t i; struct shlib_init { int32_t value; /* the value to be stored at the address */ int32_t address; /* the address to store the value */ @@ -8610,13 +9094,14 @@ enum bool verbose) shlib_init.address = SWAP_INT(shlib_init.address); } printf("\tvalue 0x%08x ", (unsigned int)shlib_init.value); - (void)print_symbol(shlib_init.value, sect_addr + i, 0, relocs, - nrelocs, symbols, symbols64, nsymbols, + (void)print_symbol(shlib_init.value, (uint32_t)(sect_addr + i), 0, + relocs, nrelocs, symbols, symbols64, nsymbols, sorted_symbols, nsorted_symbols, strings, strings_size, verbose); printf("\n"); printf("\taddress 0x%08x ", (unsigned int)shlib_init.address); - (void)print_symbol(shlib_init.address, sect_addr+i+sizeof(int32_t), 0, + (void)print_symbol(shlib_init.address, + (uint32_t)(sect_addr+i+sizeof(int32_t)), 0, relocs, nrelocs, symbols, symbols64, nsymbols, sorted_symbols, nsorted_symbols, strings, strings_size, verbose); @@ -8666,7 +9151,7 @@ enum bool verbose) if(sreloc->r_address == r_address){ name = guess_symbol(sreloc->r_value, sorted_symbols, nsorted_symbols, verbose); - offset = value - sreloc->r_value; + offset = (uint32_t)(value - sreloc->r_value); if(name != NULL){ printf("%s+0x%x", name, (unsigned int)offset); return(TRUE); @@ -8701,7 +9186,8 @@ enum bool verbose) nsorted_symbols, verbose); sub = guess_symbol(pair->r_value, sorted_symbols, nsorted_symbols, verbose); - offset = value - (sreloc->r_value - pair->r_value); + offset = (uint32_t)(value - + (sreloc->r_value - pair->r_value)); if(add != NULL) printf("%s", add); else @@ -8859,7 +9345,8 @@ const uint32_t strings_size) stride = 4; if(stride == 0) return(NULL); - index = s.reserved1 + (value - s.addr) / stride; + index = (uint32_t)(s.reserved1 + (value - s.addr) / + stride); if(index < nindirect_symbols && symbols != NULL && strings != NULL && indirect_symbols[index] < nsymbols && @@ -8899,7 +9386,8 @@ const uint32_t strings_size) stride = 8; if(stride == 0) return(NULL); - index = s64.reserved1 + (value - s64.addr) / stride; + index = (uint32_t)(s64.reserved1 + (value - s64.addr) / + stride); if(index < nindirect_symbols && symbols64 != NULL && strings != NULL && indirect_symbols[index] < nsymbols && @@ -8980,7 +9468,7 @@ uint64_t addr) for(j = 0; j < 4 * sizeof(int32_t) && i + j < size; j += sizeof(int32_t)){ - if(i + j + sizeof(int32_t) < size){ + if(i + j + sizeof(int32_t) <= size){ memcpy(&long_word, sect + i + j, sizeof(int32_t)); if(swapped) long_word = SWAP_INT(long_word); diff --git a/cctools/otool/ofile_print.h b/cctools/otool/ofile_print.h index 0b0353e..97b9ae3 100644 --- a/cctools/otool/ofile_print.h +++ b/cctools/otool/ofile_print.h @@ -40,14 +40,15 @@ extern void print_fat_headers( struct fat_header *fat_header, struct fat_arch *fat_archs, - uint64_t size, + struct fat_arch_64 *fat_archs64, + uint64_t filesize, enum bool verbose); extern void print_ar_hdr( struct ar_hdr *ar_hdr, char *member_name, uint32_t member_name_size, - uint32_t member_offset, + uint64_t member_offset, enum bool verbose, enum bool print_offset); @@ -97,7 +98,7 @@ extern void print_loadcmds( cpu_type_t cputype, uint32_t filetype, enum byte_sex load_commands_byte_sex, - uint32_t object_size, + uint64_t object_size, enum bool verbose, enum bool very_verbose); @@ -116,7 +117,7 @@ extern void print_reloc( cpu_type_t cputype, enum byte_sex load_commands_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct nlist *symbols, struct nlist_64 *symbols64, uint32_t nsymbols, @@ -130,7 +131,7 @@ extern void print_toc( uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct dylib_table_of_contents *tocs, uint32_t ntocs, struct dylib_module *mods, @@ -220,7 +221,7 @@ extern void print_segment_command( vm_prot_t initprot, uint32_t nsects, uint32_t flags, - uint32_t object_size, + uint64_t object_size, enum bool verbose); extern void print_section( @@ -238,23 +239,23 @@ extern void print_section( uint32_t cmd, char *sg_segname, uint32_t filetype, - uint32_t object_size, + uint64_t object_size, enum bool verbose); extern void print_symtab_command( struct symtab_command *sg, cpu_type_t cputype, - uint32_t object_size); + uint64_t object_size); extern void print_dysymtab_command( struct dysymtab_command *dyst, uint32_t nsyms, - uint32_t object_size, + uint64_t object_size, cpu_type_t cputype); extern void print_symseg_command( struct symseg_command *ss, - uint32_t object_size); + uint64_t object_size); extern void print_fvmlib_command( struct fvmlib_command *fl, @@ -310,7 +311,7 @@ extern void print_routines_command_64( extern void print_twolevel_hints_command( struct twolevel_hints_command *hints, - uint32_t object_size); + uint64_t object_size); extern void print_prebind_cksum_command( struct prebind_cksum_command *cksum); @@ -320,14 +321,27 @@ extern void print_uuid_command( extern void print_linkedit_data_command( struct linkedit_data_command *ld, - uint32_t object_size); + uint64_t object_size); extern void print_version_min_command( struct version_min_command *vd); +extern void print_build_version_command( + struct build_version_command *bv, + enum bool verbose); + +extern void print_build_tool_version( + uint32_t tool, + uint32_t version, + enum bool verbose); + extern void print_source_version_command( struct source_version_command *sv); +extern void print_note_command( + struct note_command *nc, + uint64_t object_size); + extern void print_entry_point_command( struct entry_point_command *ep); @@ -337,11 +351,11 @@ extern void print_rpath_command( extern void print_encryption_info_command( struct encryption_info_command *ec, - uint32_t object_size); + uint64_t object_size); extern void print_encryption_info_command_64( struct encryption_info_command_64 *ec, - uint32_t object_size); + uint64_t object_size); extern void print_linker_option_command( struct linker_option_command *lo, @@ -350,7 +364,7 @@ extern void print_linker_option_command( extern void print_dyld_info_info_command( struct dyld_info_command *dc, - uint32_t object_size); + uint64_t object_size); extern void print_thread_states( char *begin, @@ -361,14 +375,14 @@ extern void print_thread_states( extern void print_cstring_section( cpu_type_t cputype, char *sect, - uint32_t sect_size, + uint64_t sect_size, uint64_t sect_addr, enum bool print_addresses); extern void print_literal4_section( cpu_type_t cputype, char *sect, - uint32_t sect_size, + uint64_t sect_size, uint64_t sect_addr, enum byte_sex literal_byte_sex, enum bool print_addresses); @@ -376,7 +390,7 @@ extern void print_literal4_section( extern void print_literal8_section( cpu_type_t cputype, char *sect, - uint32_t sect_size, + uint64_t sect_size, uint64_t sect_addr, enum byte_sex literal_byte_sex, enum bool print_addresses); @@ -384,21 +398,23 @@ extern void print_literal8_section( extern void print_literal16_section( cpu_type_t cputype, char *sect, - uint32_t sect_size, + uint64_t sect_size, uint64_t sect_addr, enum byte_sex literal_byte_sex, enum bool print_addresses); extern void print_literal_pointer_section( cpu_type_t cputype, + cpu_subtype_t cpusubtype, struct load_command *lc, uint32_t ncmds, uint32_t sizeofcmds, + uint32_t filetype, enum byte_sex object_byte_sex, char *addr, - uint32_t size, + uint64_t object_size, char *sect, - uint32_t sect_size, + uint64_t sect_size, uint64_t sect_addr, struct nlist *symbols, struct nlist_64 *symbols64, @@ -412,18 +428,25 @@ extern void print_literal_pointer_section( extern void print_init_term_pointer_section( cpu_type_t cputype, char *sect, - uint32_t sect_size, + uint64_t sect_size, uint64_t sect_addr, enum byte_sex object_byte_sex, struct symbol *sorted_symbols, uint32_t nsorted_symbols, + struct nlist *symbols, + struct nlist_64 *symbols64, + uint32_t nsymbols, + char *strings, + uint32_t strings_size, + struct relocation_info *relocs, + uint32_t nrelocs, enum bool verbose); extern void print_shlib_init( enum byte_sex object_byte_sex, char *sect, - uint32_t sect_size, - uint32_t sect_addr, + uint64_t sect_size, + uint64_t sect_addr, struct symbol *sorted_symbols, uint32_t nsorted_symbols, struct nlist *symbols, @@ -484,19 +507,20 @@ extern enum bool print_objc_segment( uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct symbol *sorted_symbols, uint32_t nsorted_symbols, enum bool verbose); extern void print_objc2_64bit( cpu_type_t cputype, + cpu_subtype_t cpusubtype, struct load_command *load_commands, uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct nlist_64 *symbols64, uint32_t nsymbols, char *strings, @@ -509,6 +533,7 @@ extern void print_objc2_64bit( uint32_t nloc_relocs, struct dyld_bind_info *dbi, uint64_t ndbi, + enum chain_format_t chain_format, enum bool verbose, enum bool Vflag); @@ -519,7 +544,7 @@ extern void print_objc2_32bit( uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct nlist *symbols, uint32_t nsymbols, char *strings, @@ -530,6 +555,9 @@ extern void print_objc2_32bit( uint32_t next_relocs, struct relocation_info *loc_relocs, uint32_t nloc_relocs, + struct dyld_bind_info* dbi, + uint64_t ndbi, + enum chain_format_t chain_format, enum bool verbose); extern void print_objc_protocol_section( @@ -538,7 +566,7 @@ extern void print_objc_protocol_section( uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, enum bool verbose); extern void print_objc_string_object_section( @@ -548,7 +576,7 @@ extern void print_objc_string_object_section( uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, enum bool verbose); extern void print_objc_string_object_section_64( @@ -558,7 +586,7 @@ extern void print_objc_string_object_section_64( uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, cpu_type_t cputype, struct nlist_64 *symbols64, uint32_t nsymbols, @@ -574,7 +602,7 @@ extern void print_objc_runtime_setup_section( uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, enum bool verbose); extern void print_bitcode_section( @@ -592,7 +620,7 @@ extern char *get_objc2_64bit_cfstring_name( uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct nlist_64 *symbols64, uint32_t nsymbols, char *strings, @@ -607,7 +635,7 @@ extern char *get_objc2_64bit_class_name( uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct nlist_64 *symbols64, uint32_t nsymbols, char *strings, @@ -621,7 +649,7 @@ extern uint64_t get_objc2_64bit_selref( uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct nlist_64 *symbols64, uint32_t nsymbols, char *strings, @@ -635,7 +663,7 @@ extern void print_coff_reloc_section( uint32_t filetype, enum byte_sex object_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, enum bool verbose); extern char *get_label( @@ -658,7 +686,7 @@ extern enum bool get_sect_info( uint32_t filetype, enum byte_sex load_commands_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, char **sect_pointer, uint64_t *sect_size, uint64_t *sect_addr, @@ -666,3 +694,12 @@ extern enum bool get_sect_info( uint32_t *sect_nrelocs, uint32_t *sect_flags, uint64_t *seg_addr); + +extern void get_seg_names( + struct load_command *load_commands, + uint32_t ncmds, + uint32_t sizeofcmds, + enum byte_sex load_commands_byte_sex, + char* sectname, + char*** segnames, + uint32_t* nsegname); diff --git a/cctools/otool/print_bitcode.c b/cctools/otool/print_bitcode.c index 516d342..3f21734 100644 --- a/cctools/otool/print_bitcode.c +++ b/cctools/otool/print_bitcode.c @@ -214,6 +214,7 @@ const char *xar_member_name) return; xar_fd = mkstemp(xar_filename); + /* MDT: write(2) is OK here, sect_size is less than 2^31-1 */ if(write(xar_fd, sect, sect_size) != sect_size){ system_error("Can't write (__LLVM,__bundle) section contents " "to temporary file: %s\n", xar_filename); @@ -453,7 +454,7 @@ xar_t xar) name = val; } if(mode != NULL){ - mode_value = strtoul(mode, &endp, 8); + mode_value = (uint32_t)strtoul(mode, &endp, 8); if(*endp != '\0') printf("(mode: \"%s\" contains non-octal chars) ", mode); if(strcmp(type, "file") == 0) diff --git a/cctools/otool/print_objc.c b/cctools/otool/print_objc.c index 7d7e4a6..33fb081 100644 --- a/cctools/otool/print_objc.c +++ b/cctools/otool/print_objc.c @@ -333,7 +333,7 @@ static void get_objc_sections( uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct section_info **objc_sections, uint32_t *nobjc_sections, char *sectname, @@ -347,7 +347,7 @@ static void get_cstring_section( uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct section_info *cstring_section_ptr); static enum bool print_method_list( @@ -513,7 +513,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct symbol *sorted_symbols, uint32_t nsorted_symbols, enum bool verbose) @@ -566,7 +566,7 @@ enum bool verbose) m = (struct objc_module_t *)((char *)m + module.size) ){ memset(&module, '\0', sizeof(struct objc_module_t)); - left = modules_size - (m - modules); + left = (uint32_t)(modules_size - (m - modules)); size = left < sizeof(struct objc_module_t) ? left : sizeof(struct objc_module_t); memcpy(&module, m, size); @@ -899,7 +899,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, enum bool verbose) { enum byte_sex host_byte_sex; @@ -926,7 +926,7 @@ enum bool verbose) for(p = protocols; (char *)p < (char *)protocols + protocols_size; p++){ memset(&protocol, '\0', sizeof(struct objc_protocol_t)); - left = protocols_size - (p - protocols); + left = (uint32_t)(protocols_size - (p - protocols)); size = left < sizeof(struct objc_protocol_t) ? left : sizeof(struct objc_protocol_t); memcpy(&protocol, p, size); @@ -951,7 +951,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, enum bool verbose) { enum byte_sex host_byte_sex; @@ -981,7 +981,7 @@ enum bool verbose) s++){ memset(&string_object, '\0', sizeof(struct objc_string_object_t)); - left = string_objects_size - (s - string_objects); + left = (uint32_t)(string_objects_size - (s - string_objects)); size = left < sizeof(struct objc_string_object_t) ? left : sizeof(struct objc_string_object_t); memcpy(&string_object, s, size); @@ -1023,7 +1023,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, enum bool verbose) { @@ -1110,7 +1110,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct section_info **objc_sections, uint32_t *nobjc_sections, char *sectname, @@ -1152,7 +1152,7 @@ uint32_t *sect_size) (char *)load_commands + sizeofcmds) printf("load command %u extends past end of load " "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + left = (uint32_t)(sizeofcmds - ((char *)lc-(char *)load_commands)); switch(lcmd.cmd){ case LC_SEGMENT: @@ -1170,7 +1170,7 @@ uint32_t *sect_size) printf("section structure command extends past " "end of load commands\n"); } - left = sizeofcmds - (p - (char *)load_commands); + left = (uint32_t)(sizeofcmds - (p - (char *)load_commands)); memset((char *)&s, '\0', sizeof(struct section)); size = left < sizeof(struct section) ? left : sizeof(struct section); @@ -1197,7 +1197,7 @@ uint32_t *sect_size) "is past end of file\n", s.segname, s.sectname); (*objc_sections)[*nobjc_sections].size = - object_size - s.offset; + (uint32_t)(object_size - s.offset); } else (*objc_sections)[*nobjc_sections].size = s.size; @@ -1304,7 +1304,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct section_info *cstring_section) { enum byte_sex host_byte_sex; @@ -1333,7 +1333,7 @@ struct section_info *cstring_section) (char *)load_commands + sizeofcmds) printf("load command %u extends past end of load " "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + left = (uint32_t)(sizeofcmds - ((char *)lc-(char *)load_commands)); switch(lcmd.cmd){ case LC_SEGMENT: @@ -1351,7 +1351,7 @@ struct section_info *cstring_section) printf("section structure command extends past " "end of load commands\n"); } - left = sizeofcmds - (p - (char *)load_commands); + left = (uint32_t)(sizeofcmds - (p - (char *)load_commands)); memset((char *)&s, '\0', sizeof(struct section)); size = left < sizeof(struct section) ? left : sizeof(struct section); @@ -1372,7 +1372,8 @@ struct section_info *cstring_section) printf("part of section contents of: (%.16s,%.16s) " "is past end of file\n", s.segname, s.sectname); - cstring_section->size = object_size - s.offset; + cstring_section->size = + (uint32_t)(object_size - s.offset); } else cstring_section->size = s.size; diff --git a/cctools/otool/print_objc2_32bit.c b/cctools/otool/print_objc2_32bit.c index e5dba9c..c578cb5 100644 --- a/cctools/otool/print_objc2_32bit.c +++ b/cctools/otool/print_objc2_32bit.c @@ -39,6 +39,8 @@ #include "dyld_bind_info.h" #include "ofile_print.h" +#include + extern char *oname; /* @@ -63,11 +65,11 @@ swap_class_t( struct class_t *c, enum byte_sex target_byte_sex) { - c->isa = SWAP_INT(c->isa); - c->superclass = SWAP_INT(c->superclass); - c->cache = SWAP_INT(c->cache); - c->vtable = SWAP_INT(c->vtable); - c->data = SWAP_INT(c->data); + c->isa = SWAP_INT(c->isa); + c->superclass = SWAP_INT(c->superclass); + c->cache = SWAP_INT(c->cache); + c->vtable = SWAP_INT(c->vtable); + c->data = SWAP_INT(c->data); } struct class_ro_t { @@ -96,16 +98,16 @@ swap_class_ro_t( struct class_ro_t *cro, enum byte_sex target_byte_sex) { - cro->flags = SWAP_INT(cro->flags); - cro->instanceStart = SWAP_INT(cro->instanceStart); - cro->instanceSize = SWAP_INT(cro->instanceSize); - cro->ivarLayout = SWAP_INT(cro->ivarLayout); - cro->name = SWAP_INT(cro->name); - cro->baseMethods = SWAP_INT(cro->baseMethods); - cro->baseProtocols = SWAP_INT(cro->baseProtocols); - cro->ivars = SWAP_INT(cro->ivars); - cro->weakIvarLayout = SWAP_INT(cro->weakIvarLayout); - cro->baseProperties = SWAP_INT(cro->baseProperties); + cro->flags = SWAP_INT(cro->flags); + cro->instanceStart = SWAP_INT(cro->instanceStart); + cro->instanceSize = SWAP_INT(cro->instanceSize); + cro->ivarLayout = SWAP_INT(cro->ivarLayout); + cro->name = SWAP_INT(cro->name); + cro->baseMethods = SWAP_INT(cro->baseMethods); + cro->baseProtocols = SWAP_INT(cro->baseProtocols); + cro->ivars = SWAP_INT(cro->ivars); + cro->weakIvarLayout = SWAP_INT(cro->weakIvarLayout); + cro->baseProperties = SWAP_INT(cro->baseProperties); } struct method_list_t { @@ -120,8 +122,8 @@ swap_method_list_t( struct method_list_t *ml, enum byte_sex target_byte_sex) { - ml->entsize = SWAP_INT(ml->entsize); - ml->count = SWAP_INT(ml->count); + ml->entsize = SWAP_INT(ml->entsize); + ml->count = SWAP_INT(ml->count); } struct method_t { @@ -136,9 +138,9 @@ swap_method_t( struct method_t *m, enum byte_sex target_byte_sex) { - m->name = SWAP_INT(m->name); - m->types = SWAP_INT(m->types); - m->imp = SWAP_INT(m->imp); + m->name = SWAP_INT(m->name); + m->types = SWAP_INT(m->types); + m->imp = SWAP_INT(m->imp); } struct ivar_list_t { @@ -153,8 +155,8 @@ swap_ivar_list_t( struct ivar_list_t *il, enum byte_sex target_byte_sex) { - il->entsize = SWAP_INT(il->entsize); - il->count = SWAP_INT(il->count); + il->entsize = SWAP_INT(il->entsize); + il->count = SWAP_INT(il->count); } struct ivar_t { @@ -171,11 +173,11 @@ swap_ivar_t( struct ivar_t *i, enum byte_sex target_byte_sex) { - i->offset = SWAP_INT(i->offset); - i->name = SWAP_INT(i->name); - i->type = SWAP_INT(i->type); - i->alignment = SWAP_INT(i->alignment); - i->size = SWAP_INT(i->size); + i->offset = SWAP_INT(i->offset); + i->name = SWAP_INT(i->name); + i->type = SWAP_INT(i->type); + i->alignment = SWAP_INT(i->alignment); + i->size = SWAP_INT(i->size); } struct protocol_list_t { @@ -189,7 +191,7 @@ swap_protocol_list_t( struct protocol_list_t *pl, enum byte_sex target_byte_sex) { - pl->count = SWAP_INT(pl->count); + pl->count = SWAP_INT(pl->count); } struct protocol_t { @@ -211,14 +213,14 @@ swap_protocol_t( struct protocol_t *p, enum byte_sex target_byte_sex) { - p->isa = SWAP_INT(p->isa); - p->name = SWAP_INT(p->name); - p->protocols = SWAP_INT(p->protocols); - p->instanceMethods = SWAP_INT(p->instanceMethods); - p->classMethods = SWAP_INT(p->classMethods); - p->optionalInstanceMethods = SWAP_INT(p->optionalInstanceMethods); - p->optionalClassMethods = SWAP_INT(p->optionalClassMethods); - p->instanceProperties = SWAP_INT(p->instanceProperties); + p->isa = SWAP_INT(p->isa); + p->name = SWAP_INT(p->name); + p->protocols = SWAP_INT(p->protocols); + p->instanceMethods = SWAP_INT(p->instanceMethods); + p->classMethods = SWAP_INT(p->classMethods); + p->optionalInstanceMethods = SWAP_INT(p->optionalInstanceMethods); + p->optionalClassMethods = SWAP_INT(p->optionalClassMethods); + p->instanceProperties = SWAP_INT(p->instanceProperties); } struct objc_property_list { @@ -233,8 +235,8 @@ swap_objc_property_list( struct objc_property_list *pl, enum byte_sex target_byte_sex) { - pl->entsize = SWAP_INT(pl->entsize); - pl->count = SWAP_INT(pl->count); + pl->entsize = SWAP_INT(pl->entsize); + pl->count = SWAP_INT(pl->count); } struct objc_property { @@ -248,8 +250,8 @@ swap_objc_property( struct objc_property *op, enum byte_sex target_byte_sex) { - op->name = SWAP_INT(op->name); - op->attributes = SWAP_INT(op->attributes); + op->name = SWAP_INT(op->name); + op->attributes = SWAP_INT(op->attributes); } struct category_t { @@ -268,12 +270,12 @@ swap_category_t( struct category_t *c, enum byte_sex target_byte_sex) { - c->name = SWAP_INT(c->name); - c->cls = SWAP_INT(c->cls); - c->instanceMethods = SWAP_INT(c->instanceMethods); - c->classMethods = SWAP_INT(c->classMethods); - c->protocols = SWAP_INT(c->protocols); - c->instanceProperties = SWAP_INT(c->instanceProperties); + c->name = SWAP_INT(c->name); + c->cls = SWAP_INT(c->cls); + c->instanceMethods = SWAP_INT(c->instanceMethods); + c->classMethods = SWAP_INT(c->classMethods); + c->protocols = SWAP_INT(c->protocols); + c->instanceProperties = SWAP_INT(c->instanceProperties); } struct message_ref { @@ -287,8 +289,8 @@ swap_message_ref( struct message_ref *mr, enum byte_sex target_byte_sex) { - mr->imp = SWAP_INT(mr->imp); - mr->sel = SWAP_INT(mr->sel); + mr->imp = SWAP_INT(mr->imp); + mr->sel = SWAP_INT(mr->sel); } struct objc_image_info { @@ -299,17 +301,18 @@ struct objc_image_info { #define OBJC_IMAGE_IS_REPLACEMENT (1<<0) #define OBJC_IMAGE_SUPPORTS_GC (1<<1) - static void swap_objc_image_info( struct objc_image_info *o, enum byte_sex target_byte_sex) { - o->version = SWAP_INT(o->version); - o->flags = SWAP_INT(o->flags); + o->version = SWAP_INT(o->version); + o->flags = SWAP_INT(o->flags); } +#define MAXINDENT 10 + struct info { enum bool swapped; enum byte_sex host_byte_sex; @@ -328,6 +331,11 @@ struct info { struct relocation_info *loc_relocs; uint32_t nloc_relocs; enum bool verbose; + struct dyld_bind_info *dbi; + uint64_t ndbi; + enum chain_format_t chain_format; + uint32_t indent_level; + uint32_t indent_widths[MAXINDENT]; }; struct section_info_32 { @@ -364,8 +372,7 @@ static void print_layout_map( static void print_method_list_t( uint32_t p, - struct info *info, - char *indent); + struct info *info); static void print_ivar_list_t( uint32_t p, @@ -383,6 +390,10 @@ static void print_category_t( uint32_t p, struct info *info); +static void print_protocol_t( + uint32_t p, + struct info *info); + static void print_message_refs( struct section_info_32 *s, struct info *info); @@ -397,7 +408,7 @@ static void get_sections_32( uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct section_info_32 **sections, uint32_t *nsections, uint32_t *database); @@ -418,10 +429,46 @@ static void *get_pointer_32( static const char *get_symbol_32( uint32_t sect_offset, + uint32_t sect_addr, uint32_t database_offset, uint64_t value, struct relocation_info *relocs, uint32_t nrelocs, + struct info *info, + uint32_t* n_value); + +static +void +print_field_scalar( + struct info *info, + const char* label, + const char* fmt, + ...); + +static +void +print_field_label( + struct info *info, + const char* label, + ...); + +static +void +print_field_value( + uint32_t offset, + uint32_t p, + enum bool print_data, + const char* type_name, + const char* suffix, + struct info *info, + struct section_info_32 *s, + uint32_t *out_n_value); + +static void indent_push( + struct info *info, + uint32_t width); + +static void indent_pop( struct info *info); /* @@ -435,7 +482,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct nlist *symbols, uint32_t nsymbols, char *strings, @@ -446,98 +493,126 @@ struct relocation_info *ext_relocs, uint32_t next_relocs, struct relocation_info *loc_relocs, uint32_t nloc_relocs, +struct dyld_bind_info* dbi, +uint64_t ndbi, +enum chain_format_t chain_format, enum bool verbose) { struct section_info_32 *s; struct info info; + + info.host_byte_sex = get_host_byte_sex(); + info.swapped = info.host_byte_sex != object_byte_sex; + info.cputype = cputype; + info.symbols = symbols; + info.nsymbols = nsymbols; + info.strings = strings; + info.strings_size = strings_size; + info.sorted_symbols = sorted_symbols; + info.nsorted_symbols = nsorted_symbols; + info.ext_relocs = ext_relocs; + info.next_relocs = next_relocs; + info.loc_relocs = loc_relocs; + info.nloc_relocs = nloc_relocs; + info.verbose = verbose; + info.dbi = dbi; + info.ndbi = ndbi; + info.chain_format = chain_format; - info.host_byte_sex = get_host_byte_sex(); - info.swapped = info.host_byte_sex != object_byte_sex; - info.cputype = cputype; - info.symbols = symbols; - info.nsymbols = nsymbols; - info.strings = strings; - info.strings_size = strings_size; - info.sorted_symbols = sorted_symbols; - info.nsorted_symbols = nsorted_symbols; - info.ext_relocs = ext_relocs; - info.next_relocs = next_relocs; - info.loc_relocs = loc_relocs; - info.nloc_relocs = nloc_relocs; - info.verbose = verbose; - get_sections_32(load_commands, ncmds, sizeofcmds, object_byte_sex, - object_addr, object_size, &info.sections, - &info.nsections, &info.database); + get_sections_32(load_commands, ncmds, sizeofcmds, object_byte_sex, + object_addr, object_size, &info.sections, + &info.nsections, &info.database); - s = get_section_32(info.sections, info.nsections, - "__OBJC2", "__class_list"); - if(s == NULL) - s = get_section_32(info.sections, info.nsections, - "__DATA", "__objc_classlist"); - if(s == NULL) - s = get_section_32(info.sections, info.nsections, - "__DATA_CONST", "__objc_classlist"); - walk_pointer_list("class", s, &info, print_class_t); + s = get_section_32(info.sections, info.nsections, + "__OBJC2", "__class_list"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA", "__objc_classlist"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA_CONST", "__objc_classlist"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA_DIRTY", "__objc_classlist"); + walk_pointer_list("class", s, &info, print_class_t); - s = get_section_32(info.sections, info.nsections, - "__OBJC2", "__class_refs"); - if(s == NULL) - s = get_section_32(info.sections, info.nsections, - "__DATA", "__objc_classrefs"); - if(s == NULL) - s = get_section_32(info.sections, info.nsections, - "__DATA_CONST", "__objc_classrefs"); - walk_pointer_list("class refs", s, &info, NULL); + s = get_section_32(info.sections, info.nsections, + "__OBJC2", "__class_refs"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA", "__objc_classrefs"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA_CONST", "__objc_classrefs"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA_DIRTY", "__objc_classrefs"); + walk_pointer_list("class refs", s, &info, NULL); - s = get_section_32(info.sections, info.nsections, - "__OBJC2", "__super_refs"); - if(s == NULL) - s = get_section_32(info.sections, info.nsections, - "__DATA", "__objc_superrefs"); - if(s == NULL) - s = get_section_32(info.sections, info.nsections, - "__DATA_CONST", "__objc_superrefs"); - walk_pointer_list("super refs", s, &info, NULL); + s = get_section_32(info.sections, info.nsections, + "__OBJC2", "__super_refs"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA", "__objc_superrefs"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA_CONST", "__objc_superrefs"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA_DIRTY", "__objc_superrefs"); + walk_pointer_list("super refs", s, &info, NULL); - s = get_section_32(info.sections, info.nsections, - "__OBJC2", "__category_list"); - if(s == NULL) - s = get_section_32(info.sections, info.nsections, - "__DATA", "__objc_catlist"); - if(s == NULL) - s = get_section_32(info.sections, info.nsections, - "__DATA_CONST", "__objc_catlist"); - walk_pointer_list("category", s, &info, print_category_t); + s = get_section_32(info.sections, info.nsections, + "__OBJC2", "__category_list"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA", "__objc_catlist"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA_CONST", "__objc_catlist"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA_DIRTY", "__objc_catlist"); + walk_pointer_list("category", s, &info, print_category_t); + + s = get_section_32(info.sections, info.nsections, + "__OBJC2", "__protocol_list"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA", "__objc_protolist"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA_CONST", "__objc_protolist"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA_DIRTY", "__objc_protolist"); + walk_pointer_list("protocol", s, &info, print_protocol_t); - s = get_section_32(info.sections, info.nsections, - "__OBJC2", "__protocol_list"); - if(s == NULL) - s = get_section_32(info.sections, info.nsections, - "__DATA", "__objc_protolist"); - if(s == NULL) - s = get_section_32(info.sections, info.nsections, - "__DATA_CONST", "__objc_protolist"); - walk_pointer_list("protocol", s, &info, NULL); + s = get_section_32(info.sections, info.nsections, + "__OBJC2", "__message_refs"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA", "__objc_msgrefs"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA_CONST", "__objc_msgrefs"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA_DIRTY", "__objc_msgrefs"); + print_message_refs(s, &info); - s = get_section_32(info.sections, info.nsections, - "__OBJC2", "__message_refs"); - if(s == NULL) - s = get_section_32(info.sections, info.nsections, - "__DATA", "__objc_msgrefs"); - if(s == NULL) - s = get_section_32(info.sections, info.nsections, - "__DATA_CONST", "__objc_msgrefs"); - print_message_refs(s, &info); - - s = get_section_32(info.sections, info.nsections, - "__OBJC", "__image_info"); - if(s == NULL) - s = get_section_32(info.sections, info.nsections, - "__DATA", "__objc_imageinfo"); - if(s == NULL) - s = get_section_32(info.sections, info.nsections, - "__DATA_CONST", "__objc_imageinfo"); - print_image_info(s, &info); + s = get_section_32(info.sections, info.nsections, + "__OBJC", "__image_info"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA", "__objc_imageinfo"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA_CONST", "__objc_imageinfo"); + if(s == NULL) + s = get_section_32(info.sections, info.nsections, + "__DATA_DIRTY", "__objc_imageinfo"); + print_image_info(s, &info); } static @@ -550,38 +625,36 @@ void (*func)(uint32_t, struct info *)) { uint32_t i, size, left; uint32_t p; - const char *name; + uint32_t n_value; - if(s == NULL) - return; + if(s == NULL) + return; - printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname); - for(i = 0; i < s->size; i += sizeof(uint32_t)){ + info->indent_level = 0; + info->indent_widths[info->indent_level] = 0; - memset(&p, '\0', sizeof(uint32_t)); - left = s->size - i; - size = left < sizeof(uint32_t) ? - left : sizeof(uint32_t); - memcpy(&p, s->contents + i, size); + printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname); + for(i = 0; i < s->size; i += sizeof(uint32_t)){ - if(i + sizeof(uint32_t) > s->size) - printf("%s list pointer extends past end of (%.16s,%.16s) " - "section\n", listname, s->segname, s->sectname); - printf("%08x ", s->addr + i); + memset(&p, '\0', sizeof(uint32_t)); + left = s->size - i; + size = left < sizeof(uint32_t) ? + left : sizeof(uint32_t); + memcpy(&p, s->contents + i, size); - if(info->swapped) - p = SWAP_INT(p); - printf("0x%x", p); + if(i + sizeof(uint32_t) > s->size) + printf("%s list pointer extends past end of (%.16s,%.16s) " + "section\n", listname, s->segname, s->sectname); + printf("%08x ", s->addr + i); - name = get_symbol_32(i, s->addr - info->database, p, - s->relocs, s->nrelocs, info); - if(name != NULL) - printf(" %s\n", name); - else - printf("\n"); - if(func != NULL) - func(p, info); - } + if(info->swapped) + p = SWAP_INT(p); + + print_field_value(i, p, FALSE, NULL, "\n", info, s, &n_value); + + if(func != NULL) + func(n_value, info); + } } static @@ -594,70 +667,75 @@ struct info *info) void *r; uint32_t offset, left; struct section_info_32 *s; - const char *name; enum bool is_meta_class; + uint32_t n_value, isa_n_value; + static uint32_t recursion_depth; - is_meta_class = FALSE; - r = get_pointer_32(p, &offset, &left, &s, - info->sections, info->nsections); - if(r == NULL) - return; - memset(&c, '\0', sizeof(struct class_t)); - if(left < sizeof(struct class_t)){ - memcpy(&c, r, left); - printf(" (class_t entends past the end of the section)\n"); - } - else - memcpy(&c, r, sizeof(struct class_t)); - if(info->swapped) - swap_class_t(&c, info->host_byte_sex); - printf(" isa 0x%x", c.isa); - name = get_symbol_32(offset + offsetof(struct class_t, isa), - s->addr - info->database, c.isa, s->relocs, - s->nrelocs, info); - if(name != NULL) - printf(" %s\n", name); - else - printf("\n"); - printf(" superclass 0x%x", c.superclass); - name = get_symbol_32(offset + offsetof(struct class_t, superclass), - s->addr - info->database, c.superclass, s->relocs, - s->nrelocs, info); - if(name != NULL) - printf(" %s\n", name); - else - printf("\n"); - printf(" cache 0x%x", c.cache); - name = get_symbol_32(offset + offsetof(struct class_t, cache), - s->addr - info->database, c.cache, s->relocs, - s->nrelocs, info); - if(name != NULL) - printf(" %s\n", name); - else - printf("\n"); - printf(" vtable 0x%x", c.vtable); - name = get_symbol_32(offset + offsetof(struct class_t, vtable), - s->addr - info->database, c.vtable, s->relocs, - s->nrelocs, info); - if(name != NULL) - printf(" %s\n", name); - else - printf("\n"); - printf(" data 0x%x (struct class_ro_t *)", c.data); - /* - * This is a Swift class if some of the low bits of the pointer - * are set. - */ - if(c.data & 0x3) - printf(" Swift class"); - printf("\n"); - print_class_ro_t(c.data & ~0x3, info, &is_meta_class); + is_meta_class = FALSE; + r = get_pointer_32(p, &offset, &left, &s, info->sections, info->nsections); + if(r == NULL) + return; - if(! is_meta_class) - { - printf("Meta Class\n"); - print_class_t(c.isa, info); - } + memset(&c, '\0', sizeof(struct class_t)); + if(left < sizeof(struct class_t)){ + memcpy(&c, r, left); + printf(" (class_t entends past the end of the section)\n"); + } + else + memcpy(&c, r, sizeof(struct class_t)); + if(info->swapped) + swap_class_t(&c, info->host_byte_sex); + + indent_push(info, sizeof("superclass") - 1); + + print_field_label(info, "isa"); + print_field_value(offset + offsetof(struct class_t, isa), c.isa, + FALSE, NULL, "\n", info, s, &isa_n_value); + + print_field_label(info, "superclass"); + print_field_value(offset + offsetof(struct class_t, superclass), + c.superclass, FALSE, NULL, "\n", info, s, + &n_value); + + print_field_label(info, "cache"); + print_field_value(offset + offsetof(struct class_t, cache), + c.cache, FALSE, NULL, "\n", info, s, &n_value); + + print_field_label(info, "vtable"); + print_field_value(offset + offsetof(struct class_t, vtable), + c.vtable, FALSE, NULL, "\n", info, s, &n_value); + + print_field_label(info, "data"); + print_field_value(offset + offsetof(struct class_t, data), c.data, FALSE, + "(struct class_ro_t *)", NULL, info, s, &n_value); + /* + * This is a Swift class if some of the low bits of the pointer + * are set. Note that this value is 7 in 64-bit. + * + * bit 0: is Swift + * bit 1: is Swift-stable API + * bit 2: has custom retain/release (runtime only) + */ + if(n_value & 0x3) + printf(" Swift class"); + printf("\n"); + + /* Descend into the read only data */ + print_class_ro_t(n_value & ~0x3, info, &is_meta_class); + + indent_pop(info); + + /* Walk the class hierarchy, but be wary of cycles or bad chains */ + if (!is_meta_class && + isa_n_value != p && + isa_n_value != 0 && + recursion_depth < 100) + { + recursion_depth++; + printf("Meta Class\n"); + print_class_t(isa_n_value, info); + recursion_depth--; + } } static @@ -672,56 +750,100 @@ enum bool *is_meta_class) uint32_t offset, left; struct section_info_32 *s; const char *name; + uint32_t n_value; - r = get_pointer_32(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&cro, '\0', sizeof(struct class_ro_t)); - if(left < sizeof(struct class_ro_t)){ - memcpy(&cro, r, left); - printf(" (class_ro_t entends past the end of the section)\n"); - } - else - memcpy(&cro, r, sizeof(struct class_ro_t)); - if(info->swapped) - swap_class_ro_t(&cro, info->host_byte_sex); - printf(" flags 0x%x", cro.flags); - if(cro.flags & RO_META) - printf(" RO_META"); - if(cro.flags & RO_ROOT) - printf(" RO_ROOT"); - if(cro.flags & RO_HAS_CXX_STRUCTORS) - printf(" RO_HAS_CXX_STRUCTORS"); - printf("\n"); - printf(" instanceStart %u\n", cro.instanceStart); - printf(" instanceSize %u\n", cro.instanceSize); - printf(" ivarLayout 0x%x\n", cro.ivarLayout); - print_layout_map(cro.ivarLayout, info); - printf(" name 0x%x", cro.name); - name = get_pointer_32(cro.name, NULL, &left, NULL, info->sections, - info->nsections); - if(name != NULL) - printf(" %.*s\n", (int)left, name); - else - printf("\n"); - printf(" baseMethods 0x%x (struct method_list_t *)\n", - cro.baseMethods); - if(cro.baseMethods != 0) - print_method_list_t(cro.baseMethods, info, ""); - printf(" baseProtocols 0x%x\n", cro.baseProtocols); - if(cro.baseProtocols != 0) - print_protocol_list_t(cro.baseProtocols, info); - printf(" ivars 0x%x\n", cro.ivars); - if(cro.ivars != 0) - print_ivar_list_t(cro.ivars, info); - printf(" weakIvarLayout 0x%x\n", cro.weakIvarLayout); - print_layout_map(cro.weakIvarLayout, info); - printf(" baseProperties 0x%x\n", cro.baseProperties); - if(cro.baseProperties != 0) - print_objc_property_list(cro.baseProperties, info); - if (is_meta_class) - *is_meta_class = (cro.flags & RO_META) ? TRUE : FALSE; + r = get_pointer_32(p, &offset, &left, &s, info->sections, + info->nsections); + if(r == NULL) + return; + + memset(&cro, '\0', sizeof(struct class_ro_t)); + if(left < sizeof(struct class_ro_t)){ + memcpy(&cro, r, left); + printf(" (class_ro_t entends past the end of the section)\n"); + } + else + memcpy(&cro, r, sizeof(struct class_ro_t)); + if(info->swapped) + swap_class_ro_t(&cro, info->host_byte_sex); + + indent_push(info, sizeof("weakIvarLayout") - 1); + + print_field_scalar(info, "flags", "0x%x", cro.flags); + + if(info->verbose){ + if(cro.flags & RO_META) + printf(" RO_META"); + if(cro.flags & RO_ROOT) + printf(" RO_ROOT"); + if(cro.flags & RO_HAS_CXX_STRUCTORS) + printf(" RO_HAS_CXX_STRUCTORS"); + } + printf("\n"); + + print_field_scalar(info, "instanceStart", "%u\n", cro.instanceStart); + print_field_scalar(info, "instanceSize", "%u\n", cro.instanceSize); + + print_field_label(info, "ivarLayout"); + print_field_value(offset + offsetof(struct class_ro_t, ivarLayout), + cro.ivarLayout, FALSE, NULL, "\n", info, s, + &n_value); + print_layout_map(n_value, info); + + print_field_label(info, "name"); + print_field_value(offset + offsetof(struct class_ro_t, name), + cro.name, FALSE, NULL, NULL, info, s, &n_value); + if (info->verbose) { + name = get_pointer_32(n_value, NULL, &left, NULL, + info->sections, info->nsections); + if (name != NULL) + printf(" %.*s", (int)left, name); + } + printf("\n"); + + print_field_label(info, "baseMethods"); + print_field_value(offset + offsetof(struct class_ro_t, baseMethods), + cro.baseMethods, FALSE, "(struct method_list_t *)", "\n", + info, s, &n_value); + if(n_value != 0) { + print_method_list_t(n_value, info); + } + + print_field_label(info, "baseProtocols"); + print_field_value(offset + offsetof(struct class_ro_t, baseProtocols), + cro.baseProtocols, FALSE, "(struct protocol_list_t *)", + "\n", info, s, &n_value); + if(n_value != 0) { + print_protocol_list_t(n_value, info); + } + + print_field_label(info, "ivars"); + print_field_value(offset + offsetof(struct class_ro_t, ivars), + cro.ivars, FALSE, "(struct ivar_list_t *)", "\n", info, s, + &n_value); + if(n_value != 0) { + print_ivar_list_t(n_value, info); + } + + print_field_label(info, "weakIvarLayout"); + print_field_value(offset + offsetof(struct class_ro_t, weakIvarLayout), + cro.weakIvarLayout, FALSE, NULL, "\n", info, s, + &n_value); + print_layout_map(n_value, info); + + print_field_label(info, "baseProperties"); + print_field_value(offset + offsetof(struct class_ro_t, baseProperties), + cro.baseProperties, FALSE, + "(struct objc_property_list *)", "\n", info, s, + &n_value); + if(n_value != 0) { + print_objc_property_list(n_value, info); + } + + if (is_meta_class) + *is_meta_class = (cro.flags & RO_META) ? TRUE : FALSE; + + indent_pop(info); } static @@ -733,97 +855,91 @@ struct info *info) uint32_t offset, left; struct section_info_32 *s; char *layout_map; - - if(p == 0) - return; - layout_map = get_pointer_32(p, &offset, &left, &s, - info->sections, info->nsections); - if(layout_map != NULL){ - printf(" layout map: "); - do{ - printf("0x%02x ", (*layout_map) & 0xff); - left--; - layout_map++; - }while(*layout_map != '\0' && left != 0); - printf("\n"); - } + + if(p == 0) + return; + layout_map = get_pointer_32(p, &offset, &left, &s, + info->sections, info->nsections); + if(layout_map != NULL){ + print_field_label(info, "layout map"); + do{ + printf("0x%02x ", (*layout_map) & 0xff); + left--; + layout_map++; + }while(*layout_map != '\0' && left != 0); + printf("\n"); + } } static void print_method_list_t( uint32_t p, -struct info *info, -char *indent) +struct info *info) { struct method_list_t ml; struct method_t m; void *r; uint32_t offset, left, i; struct section_info_32 *s; - const char *name; + uint32_t n_value; - r = get_pointer_32(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&ml, '\0', sizeof(struct method_list_t)); - if(left < sizeof(struct method_list_t)){ - memcpy(&ml, r, left); - printf("%s (method_list_t entends past the end of the " - "section)\n", indent); - } - else - memcpy(&ml, r, sizeof(struct method_list_t)); - if(info->swapped) - swap_method_list_t(&ml, info->host_byte_sex); - printf("%s\t\t entsize %u\n", indent, ml.entsize); - printf("%s\t\t count %u\n", indent, ml.count); + r = get_pointer_32(p, &offset, &left, &s, info->sections, info->nsections); + if(r == NULL) + return; + + memset(&ml, '\0', sizeof(struct method_list_t)); + if(left < sizeof(struct method_list_t)){ + memcpy(&ml, r, left); + print_field_scalar(info, "", "(method_list_t entends past the end " + "of the section)\n)"); + } + else + memcpy(&ml, r, sizeof(struct method_list_t)); + if(info->swapped) + swap_method_list_t(&ml, info->host_byte_sex); - p += sizeof(struct method_list_t); - offset += sizeof(struct method_list_t); - for(i = 0; i < ml.count; i++){ - r = get_pointer_32(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&m, '\0', sizeof(struct method_t)); - if(left < sizeof(struct method_t)){ - memcpy(&m, r, left); - printf("%s (method_t entends past the end of the " - "section)\n", indent); - } - else - memcpy(&m, r, sizeof(struct method_t)); - if(info->swapped) - swap_method_t(&m, info->host_byte_sex); + indent_push(info, sizeof("entsize") - 1); - printf("%s\t\t name 0x%x", indent, m.name); - name = get_pointer_32(m.name, NULL, &left, NULL, info->sections, - info->nsections); - if(name != NULL) - printf(" %.*s\n", (int)left, name); - else - printf("\n"); - printf("%s\t\t types 0x%x", indent, m.types); - name = get_pointer_32(m.types, NULL, &left, NULL, info->sections, - info->nsections); - if(name != NULL) - printf(" %.*s\n", (int)left, name); - else - printf("\n"); - printf("%s\t\t imp 0x%x", indent, m.imp); - name = get_symbol_32(offset + offsetof(struct method_t, imp), - s->addr - info->database, m.imp, s->relocs, - s->nrelocs, info); - if(name != NULL) - printf(" %s\n", name); - else - printf("\n"); + print_field_scalar(info, "entsize", "%u\n", ml.entsize); + print_field_scalar(info, "count", "%u\n", ml.count); - p += sizeof(struct method_t); - offset += sizeof(struct method_t); - } + p += sizeof(struct method_list_t); + offset += sizeof(struct method_list_t); + for(i = 0; i < ml.count; i++){ + r = get_pointer_32(p, &offset, &left, &s, + info->sections, info->nsections); + if(r == NULL) + return; + + memset(&m, '\0', sizeof(struct method_t)); + if(left < sizeof(struct method_t)){ + memcpy(&m, r, left); + print_field_scalar(info, "", "(method_t entends past the end " + "of the section)\n)"); + } + else + memcpy(&m, r, sizeof(struct method_t)); + if(info->swapped) + swap_method_t(&m, info->host_byte_sex); + + print_field_label(info, "name"); + print_field_value(offset + offsetof(struct method_t, name), + m.name, TRUE, NULL, "\n", info, s, &n_value); + + print_field_label(info, "types"); + print_field_value(offset + offsetof(struct method_t, types), + m.types, TRUE, NULL, "\n", info, s, &n_value); + + print_field_label(info, "imp"); + print_field_value(offset + offsetof(struct method_t, imp), + m.imp, FALSE, NULL, "\n", info, s, &n_value); + + p += sizeof(struct method_t); + offset += sizeof(struct method_t); + } + + indent_pop(info); } static @@ -837,74 +953,78 @@ struct info *info) void *r; uint32_t offset, left, j; struct section_info_32 *s; - const char *name; uint32_t *ivar_offset_p, ivar_offset; + uint32_t n_value; - r = get_pointer_32(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&il, '\0', sizeof(struct ivar_list_t)); - if(left < sizeof(struct ivar_list_t)){ - memcpy(&il, r, left); - printf(" (ivar_list_t entends past the end of the section)\n"); - } - else - memcpy(&il, r, sizeof(struct ivar_list_t)); - if(info->swapped) - swap_ivar_list_t(&il, info->host_byte_sex); - printf(" entsize %u\n", il.entsize); - printf(" count %u\n", il.count); + r = get_pointer_32(p, &offset, &left, &s, info->sections, info->nsections); + if(r == NULL) + return; - p += sizeof(struct ivar_list_t); - offset += sizeof(struct ivar_list_t); - for(j = 0; j < il.count; j++){ - r = get_pointer_32(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&i, '\0', sizeof(struct ivar_t)); - if(left < sizeof(struct ivar_t)){ - memcpy(&i, r, left); - printf(" (ivar_t entends past the end of the section)\n"); - } - else - memcpy(&i, r, sizeof(struct ivar_t)); - if(info->swapped) - swap_ivar_t(&i, info->host_byte_sex); + memset(&il, '\0', sizeof(struct ivar_list_t)); + if(left < sizeof(struct ivar_list_t)){ + memcpy(&il, r, left); + printf(" (ivar_list_t entends past the end of the section)\n"); + } + else + memcpy(&il, r, sizeof(struct ivar_list_t)); + if(info->swapped) + swap_ivar_list_t(&il, info->host_byte_sex); - printf("\t\t\t offset 0x%x", i.offset); - ivar_offset_p = get_pointer_32(i.offset, NULL, &left, NULL, - info->sections, info->nsections); - if(ivar_offset_p != NULL && left >= sizeof(*ivar_offset_p)){ - memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); - if(info->swapped) - ivar_offset = SWAP_INT(ivar_offset); - printf(" %u\n", ivar_offset); + indent_push(info, sizeof("alignment") - 1); + + print_field_scalar(info, "entsize", "%u\n", il.entsize); + print_field_scalar(info, "count", "%u\n", il.count); + + p += sizeof(struct ivar_list_t); + offset += sizeof(struct ivar_list_t); + for(j = 0; j < il.count; j++){ + r = get_pointer_32(p, &offset, &left, &s, + info->sections, info->nsections); + if(r == NULL) + break; + + memset(&i, '\0', sizeof(struct ivar_t)); + if(left < sizeof(struct ivar_t)){ + memcpy(&i, r, left); + printf(" (ivar_t entends past the end of the section)\n"); + } + else + memcpy(&i, r, sizeof(struct ivar_t)); + if(info->swapped) + swap_ivar_t(&i, info->host_byte_sex); + + print_field_label(info, "offset"); + print_field_value(offset + offsetof(struct ivar_t, offset), + i.offset, FALSE, NULL, NULL, info, s, + &n_value); + if (info->verbose) { + ivar_offset_p = get_pointer_32(n_value, NULL, &left, NULL, + info->sections, info->nsections); + if(ivar_offset_p != NULL && left >= sizeof(ivar_offset)){ + memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); + if(info->swapped) + ivar_offset = SWAP_INT(ivar_offset); + printf(" %u", ivar_offset); } - else - printf("\n"); + } + printf("\n"); - printf("\t\t\t name 0x%x", i.name); - name = get_pointer_32(i.name, NULL, &left, NULL, info->sections, - info->nsections); - if(name != NULL) - printf(" %.*s\n", (int)left, name); - else - printf("\n"); - printf("\t\t\t type 0x%x", i.type); - name = get_pointer_32(i.type, NULL, &left, NULL, info->sections, - info->nsections); - if(name != NULL) - printf(" %.*s\n", (int)left, name); - else - printf("\n"); - printf("\t\t\talignment %u\n", i.alignment); - printf("\t\t\t size %u\n", i.size); + print_field_label(info, "name"); + print_field_value(offset + offsetof(struct ivar_t, name), + i.name, TRUE, NULL, "\n", info, s, &n_value); - p += sizeof(struct ivar_t); - offset += sizeof(struct ivar_t); - } + print_field_label(info, "type"); + print_field_value(offset + offsetof(struct ivar_t, type), + i.type, TRUE, NULL, "\n", info, s, &n_value); + + print_field_scalar(info, "alignment", "%u\n", i.alignment); + print_field_scalar(info, "size", "%u\n", i.size); + + p += sizeof(struct ivar_t); + offset += sizeof(struct ivar_t); + } + + indent_pop(info); } static @@ -915,88 +1035,67 @@ struct info *info) { struct protocol_list_t pl; uint32_t q; - struct protocol_t pc; void *r; uint32_t offset, left, i; struct section_info_32 *s; - const char *name; + uint32_t n_value; + static uint32_t recursive_depth; - r = get_pointer_32(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&pl, '\0', sizeof(struct protocol_list_t)); - if(left < sizeof(struct protocol_list_t)){ - memcpy(&pl, r, left); - printf(" (protocol_list_t entends past the end of the " - "section)\n"); - } - else - memcpy(&pl, r, sizeof(struct protocol_list_t)); - if(info->swapped) - swap_protocol_list_t(&pl, info->host_byte_sex); - printf(" count %u\n", pl.count); + r = get_pointer_32(p, &offset, &left, &s, info->sections, info->nsections); + if(r == NULL) + return; - p += sizeof(struct protocol_list_t); - offset += sizeof(struct protocol_list_t); - for(i = 0; i < pl.count; i++){ - r = get_pointer_32(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - q = 0; - if(left < sizeof(uint32_t)){ - memcpy(&q, r, left); - printf(" (protocol_t * entends past the end of the " - "section)\n"); - } - else - memcpy(&q, r, sizeof(uint32_t)); - if(info->swapped) - q = SWAP_INT(q); - printf("\t\t list[%u] 0x%x (struct protocol_t *)\n", i, q); + memset(&pl, '\0', sizeof(struct protocol_list_t)); + if(left < sizeof(struct protocol_list_t)){ + memcpy(&pl, r, left); + printf(" (protocol_list_t entends past the end of the " + "section)\n"); + } + else + memcpy(&pl, r, sizeof(struct protocol_list_t)); + if(info->swapped) + swap_protocol_list_t(&pl, info->host_byte_sex); - r = get_pointer_32(q, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&pc, '\0', sizeof(struct protocol_t)); - if(left < sizeof(struct protocol_t)){ - memcpy(&pc, r, left); - printf(" (protocol_t entends past the end of the section)\n"); - } - else - memcpy(&pc, r, sizeof(struct protocol_t)); - if(info->swapped) - swap_protocol_t(&pc, info->host_byte_sex); + indent_push(info, sizeof("list[99]") - 1); - printf("\t\t\t isa 0x%x\n", pc.isa); - printf("\t\t\t name 0x%x", pc.name); - name = get_pointer_32(pc.name, NULL, &left, NULL, info->sections, - info->nsections); - if(name != NULL) - printf(" %.*s\n", (int)left, name); - else - printf("\n"); - printf("\t\t\tprotocols 0x%x\n", pc.protocols); - printf("\t\t instanceMethods 0x%x (struct method_list_t *)\n", - pc.instanceMethods); - if(pc.instanceMethods != 0) - print_method_list_t(pc.instanceMethods, info, "\t"); - printf("\t\t classMethods 0x%x (struct method_list_t *)\n", - pc.classMethods); - if(pc.classMethods != 0) - print_method_list_t(pc.classMethods, info, "\t"); - printf("\t optionalInstanceMethods 0x%x\n", - pc.optionalInstanceMethods); - printf("\t optionalClassMethods 0x%x\n", - pc.optionalClassMethods); - printf("\t instanceProperties 0x%x\n", - pc.instanceProperties); + print_field_scalar(info, "count", "%llu\n", pl.count); - p += sizeof(uint32_t); - offset += sizeof(uint32_t); - } + p += sizeof(struct protocol_list_t); + offset += sizeof(struct protocol_list_t); + for(i = 0; i < pl.count; i++){ + r = get_pointer_32(p, &offset, &left, &s, + info->sections, info->nsections); + if(r == NULL) + break; + + q = 0; + if(left < sizeof(uint32_t)){ + memcpy(&q, r, left); + printf(" (protocol_t * entends past the end of the " + "section)\n"); + } + else + memcpy(&q, r, sizeof(uint32_t)); + if(info->swapped) + q = SWAP_INT(q); + + print_field_label(info, "list[%u]", i); + print_field_value(offset, q, FALSE, "(struct protocol_t *)", "\n", + info, s, &n_value); + + if (n_value && + recursive_depth < 100) + { + recursive_depth += 1; + print_protocol_t(n_value, info); + recursive_depth -= 1; + } + + p += sizeof(uint32_t); + offset += sizeof(uint32_t); + } + + indent_pop(info); } static @@ -1010,61 +1109,62 @@ struct info *info) void *r; uint32_t offset, left, j; struct section_info_32 *s; - const char *name; + uint32_t n_value; - r = get_pointer_32(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&opl, '\0', sizeof(struct objc_property_list)); - if(left < sizeof(struct objc_property_list)){ - memcpy(&opl, r, left); - printf(" (objc_property_list entends past the end of the " - "section)\n"); - } - else - memcpy(&opl, r, sizeof(struct objc_property_list)); - if(info->swapped) - swap_objc_property_list(&opl, info->host_byte_sex); - printf(" entsize %u\n", opl.entsize); - printf(" count %u\n", opl.count); + r = get_pointer_32(p, &offset, &left, &s, info->sections, info->nsections); + if(r == NULL) + return; - p += sizeof(struct objc_property_list); - offset += sizeof(struct objc_property_list); - for(j = 0; j < opl.count; j++){ - r = get_pointer_32(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&op, '\0', sizeof(struct objc_property)); - if(left < sizeof(struct objc_property)){ - memcpy(&op, r, left); - printf(" (objc_property entends past the end of the " - "section)\n"); - } - else - memcpy(&op, r, sizeof(struct objc_property)); - if(info->swapped) - swap_objc_property(&op, info->host_byte_sex); + memset(&opl, '\0', sizeof(struct objc_property_list)); + if(left < sizeof(struct objc_property_list)){ + memcpy(&opl, r, left); + printf(" (objc_property_list entends past the end of the " + "section)\n"); + } + else + memcpy(&opl, r, sizeof(struct objc_property_list)); + if(info->swapped) + swap_objc_property_list(&opl, info->host_byte_sex); - printf("\t\t\t name 0x%x", op.name); - name = get_pointer_32(op.name, NULL, &left, NULL, info->sections, - info->nsections); - if(name != NULL) - printf(" %.*s\n", (int)left, name); - else - printf("\n"); - printf("\t\t\tattributes 0x%x", op.attributes); - name = get_pointer_32(op.attributes, NULL, &left, NULL, - info->sections, info->nsections); - if(name != NULL) - printf(" %.*s\n", (int)left, name); - else - printf("\n"); + indent_push(info, sizeof("attributes") - 1); - p += sizeof(struct objc_property); - offset += sizeof(struct objc_property); - } + print_field_scalar(info, "entsize", "%u\n", opl.entsize); + print_field_scalar(info, "count", "%u\n", opl.count); + + p += sizeof(struct objc_property_list); + offset += sizeof(struct objc_property_list); + for(j = 0; j < opl.count; j++){ + r = get_pointer_32(p, &offset, &left, &s, + info->sections, info->nsections); + if(r == NULL) + break; + + memset(&op, '\0', sizeof(struct objc_property)); + if(left < sizeof(struct objc_property)){ + memcpy(&op, r, left); + printf(" (objc_property entends past the end of the " + "section)\n"); + } + else + memcpy(&op, r, sizeof(struct objc_property)); + if(info->swapped) + swap_objc_property(&op, info->host_byte_sex); + + print_field_label(info, "name"); + print_field_value(offset + offsetof(struct objc_property, name), + op.name, TRUE, NULL, "\n", info, s, + &n_value); + + print_field_label(info, "attributes"); + print_field_value(offset + offsetof(struct objc_property, attributes), + op.attributes, TRUE, NULL, "\n", info, s, + &n_value); + + p += sizeof(struct objc_property); + offset += sizeof(struct objc_property); + } + + indent_pop(info); } static @@ -1077,44 +1177,176 @@ struct info *info) void *r; uint32_t offset, left; struct section_info_32 *s; - const char *name; + uint32_t n_value; - r = get_pointer_32(p, &offset, &left, &s, - info->sections, info->nsections); - if(r == NULL) - return; - memset(&c, '\0', sizeof(struct category_t)); - if(left < sizeof(struct category_t)){ - memcpy(&c, r, left); - printf(" (category_t entends past the end of the section)\n"); - } - else - memcpy(&c, r, sizeof(struct category_t)); - if(info->swapped) - swap_category_t(&c, info->host_byte_sex); - printf(" name 0x%x", c.name); - name = get_symbol_32(offset + offsetof(struct category_t, name), - s->addr - info->database, c.name, s->relocs, - s->nrelocs, info); - if(name != NULL) - printf(" %s\n", name); - else - printf("\n"); - printf(" cls 0x%x\n", c.cls); - if(c.cls != 0) - print_class_t(c.cls, info); - printf(" instanceMethods 0x%x\n", c.instanceMethods); - if(c.instanceMethods != 0) - print_method_list_t(c.instanceMethods, info, ""); - printf(" classMethods 0x%x\n", c.classMethods); - if(c.classMethods != 0) - print_method_list_t(c.classMethods, info, ""); - printf(" protocols 0x%x\n", c.protocols); - if(c.protocols != 0) - print_protocol_list_t(c.protocols, info); - printf("instanceProperties 0x%x\n", c.instanceProperties); - if(c.instanceProperties) - print_objc_property_list(c.instanceProperties, info); + r = get_pointer_32(p, &offset, &left, &s, info->sections, info->nsections); + if(r == NULL) + return; + + memset(&c, '\0', sizeof(struct category_t)); + if(left < sizeof(struct category_t)){ + memcpy(&c, r, left); + printf(" (category_t entends past the end of the section)\n"); + } + else + memcpy(&c, r, sizeof(struct category_t)); + if(info->swapped) + swap_category_t(&c, info->host_byte_sex); + + /* + * The shortest and the longest fields are: + * cls + * instanceProperties + * which is just too great. Pick a middle-length field to align this + * structure, such as "protocols" + */ + indent_push(info, sizeof("protocols") - 1); + + print_field_label(info, "name"); + print_field_value(offset + offsetof(struct category_t, name), + c.name, TRUE, NULL, "\n", info, s, &n_value); + + print_field_label(info, "cls"); + print_field_value(offset + offsetof(struct category_t, cls), + c.cls, FALSE, "(struct class_t *)", "\n", info, s, + &n_value); + if(n_value != 0) { + print_class_t(n_value, info); + } + + print_field_label(info, "instanceMethods"); + print_field_value(offset + offsetof(struct category_t, instanceMethods), + c.instanceMethods, FALSE, "(struct method_list_t *)", + "\n", info, s, &n_value); + if(n_value != 0) { + print_method_list_t(n_value, info); + } + + print_field_label(info, "classMethods"); + print_field_value(offset + offsetof(struct category_t, classMethods), + c.classMethods, FALSE, "(struct method_list_t *)", + "\n", info, s, &n_value); + if(n_value != 0) { + print_method_list_t(n_value, info); + } + + print_field_label(info, "protocols"); + print_field_value(offset + offsetof(struct category_t, protocols), + c.protocols, FALSE, "(struct protocol_list_t *)", "\n", + info, s, &n_value); + if(n_value != 0) { + print_protocol_list_t(n_value, info); + } + + print_field_label(info, "instanceProperties"); + print_field_value(offset + offsetof(struct category_t, instanceProperties), + c.instanceProperties, FALSE, + "(struct objc_property_list *)", "\n", info, s, + &n_value); + if(n_value) { + print_objc_property_list(n_value, info); + } + + indent_pop(info); +} + +static void +print_protocol_t(uint32_t p, + struct info *info) +{ + struct protocol_t pt; + void *r; + uint32_t offset, left; + struct section_info_32 *s; + uint32_t n_value; + + r = get_pointer_32(p, &offset, &left, &s, info->sections, info->nsections); + if(r == NULL) + return; + + memset(&pt, '\0', sizeof(struct protocol_t)); + if(left < sizeof(struct protocol_t)){ + memcpy(&pt, r, left); + printf(" (protocol_t entends past the end of the section)\n"); + } + else + memcpy(&pt, r, sizeof(struct protocol_t)); + if(info->swapped) + swap_protocol_t(&pt, info->host_byte_sex); + + /* + * The shortest and the longest fields are: + * isa + * optionalInstanceMethods + * which is just too great. Pick a middle-length field to align this + * structure, such as "protocols" + */ + indent_push(info, sizeof("protocols") - 1); + + print_field_label(info, "isa"); + print_field_value(offset + offsetof(struct protocol_t, isa), + pt.isa, TRUE, NULL, "\n", info, s, &n_value); + + print_field_label(info, "name"); + print_field_value(offset + offsetof(struct protocol_t, name), + pt.name, TRUE, NULL, "\n", info, s, &n_value); + + print_field_label(info, "protocols"); + print_field_value(offset + offsetof(struct protocol_t, protocols), + pt.protocols, FALSE, "(struct protocol_list_t *)", "\n", + info, s, &n_value); + if(n_value != 0) { + print_protocol_list_t(n_value, info); + } + + print_field_label(info, "instanceMethods"); + print_field_value(offset + offsetof(struct protocol_t, instanceMethods), + pt.instanceMethods, FALSE, "(struct method_list_t *)", + "\n", info, s, &n_value); + if(n_value != 0) { + print_method_list_t(n_value, info); + } + + print_field_label(info, "classMethods"); + print_field_value(offset + offsetof(struct protocol_t, classMethods), + pt.classMethods, FALSE, "(struct method_list_t *)", + "\n", info, s, &n_value); + if(n_value != 0) { + print_method_list_t(n_value, info); + } + + print_field_label(info, "optionalInstanceMethods"); + print_field_value(offset + offsetof(struct protocol_t, + optionalInstanceMethods), + pt.optionalInstanceMethods, FALSE, + "(struct method_list_t *)", "\n", info, s, + &n_value); + if(n_value != 0) { + print_method_list_t(n_value, info); + } + + print_field_label(info, "optionalClassMethods"); + print_field_value(offset + offsetof(struct protocol_t, + optionalClassMethods), + pt.optionalClassMethods, FALSE, + "(struct method_list_t *)", "\n", info, s, + &n_value); + if(n_value != 0) { + print_method_list_t(n_value, info); + } + + print_field_label(info, "instanceProperties"); + print_field_value(offset + offsetof(struct protocol_t, + instanceProperties), + pt.instanceProperties, FALSE, + "(struct objc_property_list *)", "\n", info, s, + &n_value); + + if(n_value) { + print_objc_property_list(n_value, info); + } + + indent_pop(info); } static @@ -1126,46 +1358,49 @@ struct info *info) uint32_t i, left, offset; uint32_t p; struct message_ref mr; - const char *name; void *r; + uint32_t n_value; + + if(s == NULL) + return; - if(s == NULL) - return; + info->indent_level = 0; + info->indent_widths[info->indent_level] = 0; - printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname); - offset = 0; - for(i = 0; i < s->size; i += sizeof(struct message_ref)){ - p = s->addr + i; - r = get_pointer_32(p, &offset, &left, &s, - info->sections, info->nsections); - if(r == NULL) - return; - memset(&mr, '\0', sizeof(struct message_ref)); - if(left < sizeof(struct message_ref)){ - memcpy(&mr, r, left); - printf(" (message_ref entends past the end of the section)\n"); - } - else - memcpy(&mr, r, sizeof(struct message_ref)); - if(info->swapped) - swap_message_ref(&mr, info->host_byte_sex); - printf(" imp 0x%x", mr.imp); - name = get_symbol_32(offset + offsetof(struct message_ref, imp), - s->addr - info->database, mr.imp, s->relocs, - s->nrelocs, info); - if(name != NULL) - printf(" %s\n", name); - else - printf("\n"); - printf(" sel 0x%x", mr.sel); - name = get_pointer_32(mr.sel, NULL, &left, NULL, info->sections, - info->nsections); - if(name != NULL) - printf(" %.*s\n", (int)left, name); - else - printf("\n"); - offset += sizeof(struct message_ref); - } + printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname); + + indent_push(info, sizeof("imp") - 1); + + offset = 0; + for(i = 0; i < s->size; i += sizeof(struct message_ref)){ + p = s->addr + i; + r = get_pointer_32(p, &offset, &left, &s, + info->sections, info->nsections); + if(r == NULL) + return; + + memset(&mr, '\0', sizeof(struct message_ref)); + if(left < sizeof(struct message_ref)){ + memcpy(&mr, r, left); + printf(" (message_ref entends past the end of the section)\n"); + } + else + memcpy(&mr, r, sizeof(struct message_ref)); + if(info->swapped) + swap_message_ref(&mr, info->host_byte_sex); + + print_field_label(info, "imp"); + print_field_value(offset + offsetof(struct message_ref, imp), + mr.imp, FALSE, NULL, "\n", info, s, &n_value); + + print_field_label(info, "sel"); + print_field_value(offset + offsetof(struct message_ref, sel), + mr.sel, FALSE, NULL, "\n", info, s, &n_value); + + offset += sizeof(struct message_ref); + } + + indent_pop(info); } static @@ -1178,41 +1413,61 @@ struct info *info) uint32_t p; struct objc_image_info o; void *r; + + if(s == NULL) + return; - if(s == NULL) - return; + info->indent_level = 0; + info->indent_widths[info->indent_level] = 0; - printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname); - p = s->addr; - r = get_pointer_32(p, &offset, &left, &s, - info->sections, info->nsections); - if(r == NULL) - return; - memset(&o, '\0', sizeof(struct objc_image_info)); - if(left < sizeof(struct objc_image_info)){ - memcpy(&o, r, left); - printf(" (objc_image_info entends past the end of the section)\n"); - } - else - memcpy(&o, r, sizeof(struct objc_image_info)); - if(info->swapped) - swap_objc_image_info(&o, info->host_byte_sex); - printf(" version %u\n", o.version); - printf(" flags 0x%x", o.flags); - if(o.flags & OBJC_IMAGE_IS_REPLACEMENT) - printf(" OBJC_IMAGE_IS_REPLACEMENT"); - if(o.flags & OBJC_IMAGE_SUPPORTS_GC) - printf(" OBJC_IMAGE_SUPPORTS_GC"); - swift_version = (o.flags >> 8) & 0xff; - if(swift_version != 0){ - if(swift_version == 1) - printf(" Swift 1.0"); - else if(swift_version == 2) - printf(" Swift 1.1"); - else - printf(" unknown future Swift version (%d)", swift_version); - } - printf("\n"); + printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname); + p = s->addr; + r = get_pointer_32(p, &offset, &left, &s, + info->sections, info->nsections); + if(r == NULL) + return; + + memset(&o, '\0', sizeof(struct objc_image_info)); + if(left < sizeof(struct objc_image_info)){ + memcpy(&o, r, left); + printf(" (objc_image_info entends past the end of the section)\n"); + } + else + memcpy(&o, r, sizeof(struct objc_image_info)); + if(info->swapped) + swap_objc_image_info(&o, info->host_byte_sex); + + indent_push(info, sizeof("version") - 1); + + print_field_scalar(info, "version", "%u\n", o.version); + print_field_scalar(info, "flags", "0x%x", o.flags); + + if(o.flags & OBJC_IMAGE_IS_REPLACEMENT) + printf(" OBJC_IMAGE_IS_REPLACEMENT"); + if(o.flags & OBJC_IMAGE_SUPPORTS_GC) + printf(" OBJC_IMAGE_SUPPORTS_GC"); + swift_version = (o.flags >> 8) & 0xff; + if(swift_version != 0){ + if(swift_version == 1) + printf(" Swift 1.0"); + else if(swift_version == 2) + printf(" Swift 1.1"); + else if(swift_version == 3) + printf(" Swift 2.0"); + else if(swift_version == 4) + printf(" Swift 3.0"); + else if(swift_version == 5) + printf(" Swift 4.0"); + else if(swift_version == 6) + printf(" Swift 4.1/4.2"); + else if(swift_version == 7) + printf(" Swift 5 or later"); + else + printf(" unknown future Swift version (%d)", swift_version); + } + printf("\n"); + + indent_pop(info); } static @@ -1223,14 +1478,14 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct section_info_32 **sections, uint32_t *nsections, uint32_t *database) { enum byte_sex host_byte_sex; enum bool swapped, database_set, zerobased, encrypt_found, encrypt64_found; - + uint32_t i, j, left, size; struct load_command lcmd, *lc; char *p; @@ -1238,196 +1493,197 @@ uint32_t *database) struct section s; struct encryption_info_command encrypt; struct encryption_info_command_64 encrypt64; - - host_byte_sex = get_host_byte_sex(); - swapped = host_byte_sex != object_byte_sex; - - *sections = NULL; - *nsections = 0; - database_set = FALSE; - *database = 0; - zerobased = FALSE; - encrypt_found = FALSE; - encrypt64_found = FALSE; - - lc = load_commands; - for(i = 0 ; i < ncmds; i++){ - memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command)); - if(swapped) - swap_load_command(&lcmd, host_byte_sex); - if(lcmd.cmdsize % sizeof(int32_t) != 0) - printf("load command %u size not a multiple of " - "sizeof(int32_t)\n", i); - if((char *)lc + lcmd.cmdsize > - (char *)load_commands + sizeofcmds) - printf("load command %u extends past end of load " - "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); - - switch(lcmd.cmd){ - case LC_SEGMENT: - memset((char *)&sg, '\0', sizeof(struct segment_command)); - size = left < sizeof(struct segment_command) ? - left : sizeof(struct segment_command); - memcpy((char *)&sg, (char *)lc, size); - if(swapped) - swap_segment_command(&sg, host_byte_sex); - if((sg.initprot & VM_PROT_WRITE) == VM_PROT_WRITE && - database_set == FALSE){ - *database = sg.vmaddr; - database_set = TRUE; - } - if((sg.initprot & VM_PROT_READ) == VM_PROT_READ && - sg.vmaddr == 0) - zerobased = TRUE; - p = (char *)lc + sizeof(struct segment_command); - for(j = 0 ; j < sg.nsects ; j++){ - if(p + sizeof(struct section) > - (char *)load_commands + sizeofcmds){ - printf("section structure command extends past " - "end of load commands\n"); - } - left = sizeofcmds - (p - (char *)load_commands); - memset((char *)&s, '\0', sizeof(struct section)); - size = left < sizeof(struct section) ? - left : sizeof(struct section); - memcpy((char *)&s, p, size); - if(swapped) - swap_section(&s, 1, host_byte_sex); - - *sections = reallocate(*sections, - sizeof(struct section_info_32) * (*nsections + 1)); - memcpy((*sections)[*nsections].segname, - s.segname, 16); - memcpy((*sections)[*nsections].sectname, - s.sectname, 16); - (*sections)[*nsections].addr = s.addr; - (*sections)[*nsections].contents = object_addr + s.offset; - (*sections)[*nsections].offset = s.offset; - (*sections)[*nsections].zerofill = (s.flags & SECTION_TYPE) - == S_ZEROFILL ? TRUE : FALSE; - if(s.offset > object_size){ - printf("section contents of: (%.16s,%.16s) is past " - "end of file\n", s.segname, s.sectname); - (*sections)[*nsections].size = 0; - } - else if(s.offset + s.size > object_size){ - printf("part of section contents of: (%.16s,%.16s) " - "is past end of file\n", - s.segname, s.sectname); - (*sections)[*nsections].size = object_size - s.offset; - } - else - (*sections)[*nsections].size = s.size; - if(s.reloff >= object_size){ - printf("relocation entries offset for (%.16s,%.16s)" - ": is past end of file\n", s.segname, - s.sectname); - (*sections)[*nsections].nrelocs = 0; - } - else{ - (*sections)[*nsections].relocs = - (struct relocation_info *)(object_addr + - s.reloff); - if(s.reloff + - s.nreloc * sizeof(struct relocation_info) > - object_size){ - printf("relocation entries for section (%.16s," - "%.16s) extends past end of file\n", - s.segname, s.sectname); - (*sections)[*nsections].nrelocs = - (object_size - s.reloff) / - sizeof(struct relocation_info); - } - else - (*sections)[*nsections].nrelocs = s.nreloc; - if(swapped) - swap_relocation_info( - (*sections)[*nsections].relocs, - (*sections)[*nsections].nrelocs, - host_byte_sex); - } - if(sg.flags & SG_PROTECTED_VERSION_1) - (*sections)[*nsections].protected = TRUE; - else - (*sections)[*nsections].protected = FALSE; - (*nsections)++; - - if(p + sizeof(struct section) > - (char *)load_commands + sizeofcmds) - break; - p += size; - } - break; - case LC_ENCRYPTION_INFO: - memset((char *)&encrypt, '\0', - sizeof(struct encryption_info_command)); - size = left < sizeof(struct encryption_info_command) ? - left : sizeof(struct encryption_info_command); - memcpy((char *)&encrypt, (char *)lc, size); - if(swapped) - swap_encryption_command(&encrypt, host_byte_sex); - encrypt_found = TRUE; - break; - case LC_ENCRYPTION_INFO_64: - memset((char *)&encrypt64, '\0', - sizeof(struct encryption_info_command_64)); - size = left < sizeof(struct encryption_info_command_64) ? - left : sizeof(struct encryption_info_command_64); - memcpy((char *)&encrypt64, (char *)lc, size); - if(swapped) - swap_encryption_command_64(&encrypt64, host_byte_sex); - encrypt64_found = TRUE; - break; - } - if(lcmd.cmdsize == 0){ - printf("load command %u size zero (can't advance to other " - "load commands)\n", i); - break; - } - lc = (struct load_command *)((char *)lc + lcmd.cmdsize); - if((char *)lc > (char *)load_commands + sizeofcmds) - break; - } - if(zerobased == TRUE) - *database = 0; - - if(encrypt_found == TRUE && encrypt.cryptid != 0){ - for(i = 0; i < *nsections; i++){ - if((*sections)[i].size > 0 && (*sections)[i].zerofill == FALSE){ - if((*sections)[i].offset > - encrypt.cryptoff + encrypt.cryptsize){ - /* section starts past encryption area */ ; - } - else if((*sections)[i].offset + (*sections)[i].size < - encrypt.cryptoff){ - /* section ends before encryption area */ ; - } - else{ - /* section has part in the encrypted area */ - (*sections)[i].protected = TRUE; - } - } - } - } - if(encrypt64_found == TRUE && encrypt64.cryptid != 0){ - for(i = 0; i < *nsections; i++){ - if((*sections)[i].size > 0 && (*sections)[i].zerofill == FALSE){ - if((*sections)[i].offset > - encrypt64.cryptoff + encrypt64.cryptsize){ - /* section starts past encryption area */ ; - } - else if((*sections)[i].offset + (*sections)[i].size < - encrypt64.cryptoff){ - /* section ends before encryption area */ ; - } - else{ - /* section has part in the encrypted area */ - (*sections)[i].protected = TRUE; - } - } - } - } + + host_byte_sex = get_host_byte_sex(); + swapped = host_byte_sex != object_byte_sex; + + *sections = NULL; + *nsections = 0; + database_set = FALSE; + *database = 0; + zerobased = FALSE; + encrypt_found = FALSE; + encrypt64_found = FALSE; + + lc = load_commands; + for(i = 0 ; i < ncmds; i++){ + memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command)); + if(swapped) + swap_load_command(&lcmd, host_byte_sex); + if(lcmd.cmdsize % sizeof(int32_t) != 0) + printf("load command %u size not a multiple of " + "sizeof(int32_t)\n", i); + if((char *)lc + lcmd.cmdsize > + (char *)load_commands + sizeofcmds) + printf("load command %u extends past end of load " + "commands\n", i); + left = (uint32_t)(sizeofcmds - ((char *)lc - (char *)load_commands)); + + switch(lcmd.cmd){ + case LC_SEGMENT: + memset((char *)&sg, '\0', sizeof(struct segment_command)); + size = left < sizeof(struct segment_command) ? + left : sizeof(struct segment_command); + memcpy((char *)&sg, (char *)lc, size); + if(swapped) + swap_segment_command(&sg, host_byte_sex); + if((sg.initprot & VM_PROT_WRITE) == VM_PROT_WRITE && + database_set == FALSE){ + *database = sg.vmaddr; + database_set = TRUE; + } + if((sg.initprot & VM_PROT_READ) == VM_PROT_READ && + sg.vmaddr == 0) + zerobased = TRUE; + p = (char *)lc + sizeof(struct segment_command); + for(j = 0 ; j < sg.nsects ; j++){ + if(p + sizeof(struct section) > + (char *)load_commands + sizeofcmds){ + printf("section structure command extends past " + "end of load commands\n"); + } + left = (uint32_t)(sizeofcmds - (p - (char *)load_commands)); + memset((char *)&s, '\0', sizeof(struct section)); + size = left < sizeof(struct section) ? + left : sizeof(struct section); + memcpy((char *)&s, p, size); + if(swapped) + swap_section(&s, 1, host_byte_sex); + + *sections = reallocate(*sections, + sizeof(struct section_info_32) * (*nsections + 1)); + memcpy((*sections)[*nsections].segname, + s.segname, 16); + memcpy((*sections)[*nsections].sectname, + s.sectname, 16); + (*sections)[*nsections].addr = s.addr; + (*sections)[*nsections].contents = object_addr + s.offset; + (*sections)[*nsections].offset = s.offset; + (*sections)[*nsections].zerofill = (s.flags & SECTION_TYPE) + == S_ZEROFILL ? TRUE : FALSE; + if(s.offset > object_size){ + printf("section contents of: (%.16s,%.16s) is past " + "end of file\n", s.segname, s.sectname); + (*sections)[*nsections].size = 0; + } + else if(s.offset + s.size > object_size){ + printf("part of section contents of: (%.16s,%.16s) " + "is past end of file\n", + s.segname, s.sectname); + (*sections)[*nsections].size = (uint32_t)(object_size + - s.offset); + } + else + (*sections)[*nsections].size = s.size; + if(s.reloff >= object_size){ + printf("relocation entries offset for (%.16s,%.16s)" + ": is past end of file\n", s.segname, + s.sectname); + (*sections)[*nsections].nrelocs = 0; + } + else{ + (*sections)[*nsections].relocs = + (struct relocation_info *)(object_addr + + s.reloff); + if(s.reloff + + s.nreloc * sizeof(struct relocation_info) > + object_size){ + printf("relocation entries for section (%.16s," + "%.16s) extends past end of file\n", + s.segname, s.sectname); + (*sections)[*nsections].nrelocs = + (uint32_t)((object_size - s.reloff) / + sizeof(struct relocation_info)); + } + else + (*sections)[*nsections].nrelocs = s.nreloc; + if(swapped) + swap_relocation_info( + (*sections)[*nsections].relocs, + (*sections)[*nsections].nrelocs, + host_byte_sex); + } + if(sg.flags & SG_PROTECTED_VERSION_1) + (*sections)[*nsections].protected = TRUE; + else + (*sections)[*nsections].protected = FALSE; + (*nsections)++; + + if(p + sizeof(struct section) > + (char *)load_commands + sizeofcmds) + break; + p += size; + } + break; + case LC_ENCRYPTION_INFO: + memset((char *)&encrypt, '\0', + sizeof(struct encryption_info_command)); + size = left < sizeof(struct encryption_info_command) ? + left : sizeof(struct encryption_info_command); + memcpy((char *)&encrypt, (char *)lc, size); + if(swapped) + swap_encryption_command(&encrypt, host_byte_sex); + encrypt_found = TRUE; + break; + case LC_ENCRYPTION_INFO_64: + memset((char *)&encrypt64, '\0', + sizeof(struct encryption_info_command_64)); + size = left < sizeof(struct encryption_info_command_64) ? + left : sizeof(struct encryption_info_command_64); + memcpy((char *)&encrypt64, (char *)lc, size); + if(swapped) + swap_encryption_command_64(&encrypt64, host_byte_sex); + encrypt64_found = TRUE; + break; + } + if(lcmd.cmdsize == 0){ + printf("load command %u size zero (can't advance to other " + "load commands)\n", i); + break; + } + lc = (struct load_command *)((char *)lc + lcmd.cmdsize); + if((char *)lc > (char *)load_commands + sizeofcmds) + break; + } + if(zerobased == TRUE) + *database = 0; + + if(encrypt_found == TRUE && encrypt.cryptid != 0){ + for(i = 0; i < *nsections; i++){ + if((*sections)[i].size > 0 && (*sections)[i].zerofill == FALSE){ + if((*sections)[i].offset > + encrypt.cryptoff + encrypt.cryptsize){ + /* section starts past encryption area */ ; + } + else if((*sections)[i].offset + (*sections)[i].size < + encrypt.cryptoff){ + /* section ends before encryption area */ ; + } + else{ + /* section has part in the encrypted area */ + (*sections)[i].protected = TRUE; + } + } + } + } + if(encrypt64_found == TRUE && encrypt64.cryptid != 0){ + for(i = 0; i < *nsections; i++){ + if((*sections)[i].size > 0 && (*sections)[i].zerofill == FALSE){ + if((*sections)[i].offset > + encrypt64.cryptoff + encrypt64.cryptsize){ + /* section starts past encryption area */ ; + } + else if((*sections)[i].offset + (*sections)[i].size < + encrypt64.cryptoff){ + /* section ends before encryption area */ ; + } + else{ + /* section has part in the encrypted area */ + (*sections)[i].protected = TRUE; + } + } + } + } } static @@ -1439,14 +1695,14 @@ char *segname, char *sectname) { uint32_t i; - - for(i = 0; i < nsections; i++){ - if(strncmp(sections[i].segname, segname, 16) == 0 && - strncmp(sections[i].sectname, sectname, 16) == 0){ - return(sections + i); - } - } - return(NULL); + + for(i = 0; i < nsections; i++){ + if(strncmp(sections[i].segname, segname, 16) == 0 && + strncmp(sections[i].sectname, sectname, 16) == 0){ + return(sections + i); + } + } + return(NULL); } static @@ -1462,31 +1718,31 @@ uint32_t nsections) void *r; uint32_t addr; uint32_t i; - - addr = p; - for(i = 0; i < nsections; i++){ - if(addr >= sections[i].addr && - addr < sections[i].addr + sections[i].size){ - if(s != NULL) - *s = sections + i; - if(offset != NULL) - *offset = addr - sections[i].addr; - if(left != NULL) - *left = sections[i].size - (addr - sections[i].addr); - if(sections[i].protected == TRUE) - r = "some string from a protected section"; - else - r = sections[i].contents + (addr - sections[i].addr); - return(r); - } - } - if(s != NULL) - *s = NULL; - if(offset != NULL) - *offset = 0; - if(left != NULL) - *left = 0; - return(NULL); + + addr = p; + for(i = 0; i < nsections; i++){ + if(addr >= sections[i].addr && + addr < sections[i].addr + sections[i].size){ + if(s != NULL) + *s = sections + i; + if(offset != NULL) + *offset = addr - sections[i].addr; + if(left != NULL) + *left = sections[i].size - (addr - sections[i].addr); + if(sections[i].protected == TRUE) + r = "some string from a protected section"; + else + r = sections[i].contents + (addr - sections[i].addr); + return(r); + } + } + if(s != NULL) + *s = NULL; + if(offset != NULL) + *offset = 0; + if(left != NULL) + *left = 0; + return(NULL); } /* @@ -1497,52 +1753,267 @@ static const char * get_symbol_32( uint32_t sect_offset, +uint32_t sect_addr, uint32_t database_offset, uint64_t value, struct relocation_info *relocs, uint32_t nrelocs, -struct info *info) +struct info *info, +uint32_t* n_value) { uint32_t i; unsigned int r_symbolnum; uint32_t n_strx; + const char* name; + + if(n_value != NULL) + *n_value = (uint32_t)0; + if(info->verbose == FALSE) + return(NULL); + + for(i = 0; i < nrelocs; i++){ + if((uint32_t)relocs[i].r_address == sect_offset){ + r_symbolnum = relocs[i].r_symbolnum; + if(relocs[i].r_extern){ + if(r_symbolnum >= info->nsymbols) + break; + n_strx = info->symbols[r_symbolnum].n_un.n_strx; + if(n_strx <= 0 || n_strx >= info->strings_size) + break; + return(info->strings + n_strx); + } + break; + } + if(reloc_has_pair(info->cputype, relocs[i].r_type) == TRUE) + i++; + } + for(i = 0; i < info->next_relocs; i++){ + if((uint32_t)info->ext_relocs[i].r_address == + database_offset + sect_offset){ + r_symbolnum = info->ext_relocs[i].r_symbolnum; + if(info->ext_relocs[i].r_extern){ + if(r_symbolnum >= info->nsymbols) + break; + n_strx = info->symbols[r_symbolnum].n_un.n_strx; + if(n_strx <= 0 || n_strx >= info->strings_size) + break; + return(info->strings + n_strx); + } + break; + } + if(reloc_has_pair(info->cputype, info->ext_relocs[i].r_type) ==TRUE) + i++; + } + + /* + * If this is a chained format, the symbol information may be part of + * the dyld info. If we find one, return early before hitting the + * symbol table. + */ + name = get_dyld_bind_info_symbolname(sect_addr + sect_offset, + info->dbi, info->ndbi, + info->chain_format, NULL); + if (name) + return name; + + /* + * If this is a chained rebase, we will need to convert the value on + * disk into its proper logical value, before guessing at the symbol + * name. + */ + value = get_chained_rebase_value(value, info->chain_format, NULL); + if(n_value != NULL) + *n_value = (uint32_t)value; - if(info->verbose == FALSE) - return(NULL); - - for(i = 0; i < nrelocs; i++){ - if((uint32_t)relocs[i].r_address == sect_offset){ - r_symbolnum = relocs[i].r_symbolnum; - if(relocs[i].r_extern){ - if(r_symbolnum >= info->nsymbols) - break; - n_strx = info->symbols[r_symbolnum].n_un.n_strx; - if(n_strx <= 0 || n_strx >= info->strings_size) - break; - return(info->strings + n_strx); - } - break; - } - if(reloc_has_pair(info->cputype, relocs[i].r_type) == TRUE) - i++; - } - for(i = 0; i < info->next_relocs; i++){ - if((uint32_t)info->ext_relocs[i].r_address == - database_offset + sect_offset){ - r_symbolnum = info->ext_relocs[i].r_symbolnum; - if(info->ext_relocs[i].r_extern){ - if(r_symbolnum >= info->nsymbols) - break; - n_strx = info->symbols[r_symbolnum].n_un.n_strx; - if(n_strx <= 0 || n_strx >= info->strings_size) - break; - return(info->strings + n_strx); - } - break; - } - if(reloc_has_pair(info->cputype, info->ext_relocs[i].r_type) ==TRUE) - i++; - } - return(guess_symbol(value, info->sorted_symbols, info->nsorted_symbols, - info->verbose)); + return(guess_symbol(value, info->sorted_symbols, info->nsorted_symbols, + info->verbose)); +} + +/* + * print_field_scalar() prints a label followed by a formatted value. the label + * is idented to fit within the info's indent state. + */ +/* This is identical to the 64-bit implementaton. */ +static +void +print_field_scalar( +struct info *info, +const char* label, +const char* fmt, +...) +{ + /* print the label */ + print_field_label(info, label); + + /* print the data, if any */ + if (fmt) { + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + } +} + +/* + * print_field_label() prints a formatted label. the label is indented to fit + * within the info's indent state. A single space character will follow the + * label so that the next value can simply be printed. + */ +/* This is identical to the 64-bit implementaton. */ +static +void +print_field_label( +struct info *info, +const char* label, +...) +{ + va_list ap; + int width = 0; + uint32_t label_indent; + uint32_t label_width; + + /* get the current label field width from the indent state */ + label_indent = info->indent_level * 4; +#if 1 + /* + * use the curent indent width. if the indent level is too deep, just print + * the value immediately after the label. + */ + label_width = (info->indent_level < MAXINDENT ? + info->indent_widths[info->indent_level] : 0); +#else + /* + * use the current indent width unless that would cause the value at this + * level to print to the left of the previous value. In practice, we need + * to loop over all the indent widths, compute the right edge of the label + * field, and use the largest such value. + */ + uint32_t right = 0; + for (uint32_t i = 0; i < MAXINDENT; ++i) { + if (i > info->indent_level) + break; + + uint32_t r = i * 4 + info->indent_widths[i]; + if (r > right) + right = r; + } + label_width = right - label_indent; +#endif + + /* measure the width of the string data */ + va_start(ap, label); + if (label) { + width = vsnprintf(NULL, 0, label, ap); + } + va_end(ap); + + /* adjust the width to represent the space following the label */ + width = width < label_width ? label_width - width : 0; + + /* print the indent spaces */ + printf("%*s", label_indent, ""); + + /* print the label */ + if (label) { + va_start(ap, label); + vprintf(label, ap); + va_end(ap); + } + + /* print right padding */ + printf("%*s", width + 1, ""); +} + +/* + * print_field_value() prints the following information: + * + * ( pointer | n_value [symbol]) [data] [type] [suffix] + * + * pointer - the raw pointer on disk, only displaying when -v is not specified. + * n_value - the adjusted pointer view, correcting for chained-fixups and + * authenticated pointers. + * symbol - the symbol name corresponding to pointer + * data - C-string data within the file pointed to by the n_value / addend. + * type - an optional C-string that is printed only if supplied and if + * n_value != 0. + * suffix - an optional C-string that prints after the other field elements, + * often used to print a newline. + * + * print_field_value usually follows a call to print_field_label, but this is + * not required. + */ +/* + * The primary difference from the 64-bit version, other than the datatypes, + * is print_field_value here does not print or return an addend. Also, the + * arguments to get_symbol_32 do not match those required by get_symbol_64. + */ +static +void +print_field_value( +uint32_t offset, +uint32_t p, +enum bool print_data, +const char* type_name, +const char* suffix, +struct info *info, +struct section_info_32 *s, +uint32_t *out_n_value) +{ + uint32_t n_value; + const char* sym_name; + + /* read the symbol name, n_value, and addend. */ + sym_name = get_symbol_32(offset, s->addr, info->database, p, + s->relocs, s->nrelocs, info, &n_value); + + /* print the numeric pointer value */ + if (info->verbose) { + printf("0x%x", n_value); + if (sym_name) + printf(" %s", sym_name); + } + else { + printf("0x%x", p); + } + + /* print the pointer data if any, if requested */ + if (info->verbose && print_data) { + const char* ptr_data; + ptr_data = get_pointer_32(n_value, NULL, NULL, NULL, + info->sections, info->nsections); + if (ptr_data) + printf(" %s", ptr_data); + } + +#if 0 + if (info->verbose && type_name && (n_value > 0)) { + printf(" %s", type_name); + } +#endif + + /* print the suffix field */ + if (suffix) + printf("%s", suffix); + + /* return the n_value */ + if (out_n_value) + *out_n_value = n_value; +} + +void +indent_push( + struct info *info, + uint32_t width) +{ + info->indent_level += 1; + if (info->indent_level < MAXINDENT) + info->indent_widths[info->indent_level] = width; +} + +void +indent_pop( + struct info *info) +{ + if (info->indent_level) + info->indent_level -= 1; } diff --git a/cctools/otool/print_objc2_64bit.c b/cctools/otool/print_objc2_64bit.c index e8d047f..2e3e048 100644 --- a/cctools/otool/print_objc2_64bit.c +++ b/cctools/otool/print_objc2_64bit.c @@ -32,7 +32,9 @@ #include "stdlib.h" #include "stddef.h" #include "string.h" +#include /* cctools-port: For bcmp, bzero ... */ #include "mach-o/loader.h" +#include "mach-o/arm64/reloc.h" #include "stuff/allocate.h" #include "stuff/bytesex.h" #include "stuff/symbol.h" @@ -40,6 +42,8 @@ #include "dyld_bind_info.h" #include "ofile_print.h" +#include + extern char *oname; /* @@ -65,11 +69,11 @@ swap_class_t( struct class_t *c, enum byte_sex target_byte_sex) { - c->isa = SWAP_LONG_LONG(c->isa); - c->superclass = SWAP_LONG_LONG(c->superclass); - c->cache = SWAP_LONG_LONG(c->cache); - c->vtable = SWAP_LONG_LONG(c->vtable); - c->data = SWAP_LONG_LONG(c->data); + c->isa = SWAP_LONG_LONG(c->isa); + c->superclass = SWAP_LONG_LONG(c->superclass); + c->cache = SWAP_LONG_LONG(c->cache); + c->vtable = SWAP_LONG_LONG(c->vtable); + c->data = SWAP_LONG_LONG(c->data); } struct class_ro_t { @@ -92,24 +96,23 @@ struct class_ro_t { #define RO_ROOT (1<<1) #define RO_HAS_CXX_STRUCTORS (1<<2) - static void swap_class_ro_t( struct class_ro_t *cro, enum byte_sex target_byte_sex) { - cro->flags = SWAP_INT(cro->flags); - cro->instanceStart = SWAP_INT(cro->instanceStart); - cro->instanceSize = SWAP_INT(cro->instanceSize); - cro->reserved = SWAP_INT(cro->reserved); - cro->ivarLayout = SWAP_LONG_LONG(cro->ivarLayout); - cro->name = SWAP_LONG_LONG(cro->name); - cro->baseMethods = SWAP_LONG_LONG(cro->baseMethods); - cro->baseProtocols = SWAP_LONG_LONG(cro->baseProtocols); - cro->ivars = SWAP_LONG_LONG(cro->ivars); - cro->weakIvarLayout = SWAP_LONG_LONG(cro->weakIvarLayout); - cro->baseProperties = SWAP_LONG_LONG(cro->baseProperties); + cro->flags = SWAP_INT(cro->flags); + cro->instanceStart = SWAP_INT(cro->instanceStart); + cro->instanceSize = SWAP_INT(cro->instanceSize); + cro->reserved = SWAP_INT(cro->reserved); + cro->ivarLayout = SWAP_LONG_LONG(cro->ivarLayout); + cro->name = SWAP_LONG_LONG(cro->name); + cro->baseMethods = SWAP_LONG_LONG(cro->baseMethods); + cro->baseProtocols = SWAP_LONG_LONG(cro->baseProtocols); + cro->ivars = SWAP_LONG_LONG(cro->ivars); + cro->weakIvarLayout = SWAP_LONG_LONG(cro->weakIvarLayout); + cro->baseProperties = SWAP_LONG_LONG(cro->baseProperties); } struct method_list_t { @@ -124,8 +127,8 @@ swap_method_list_t( struct method_list_t *ml, enum byte_sex target_byte_sex) { - ml->entsize = SWAP_INT(ml->entsize); - ml->count = SWAP_INT(ml->count); + ml->entsize = SWAP_INT(ml->entsize); + ml->count = SWAP_INT(ml->count); } struct method_t { @@ -140,9 +143,9 @@ swap_method_t( struct method_t *m, enum byte_sex target_byte_sex) { - m->name = SWAP_LONG_LONG(m->name); - m->types = SWAP_LONG_LONG(m->types); - m->imp = SWAP_LONG_LONG(m->imp); + m->name = SWAP_LONG_LONG(m->name); + m->types = SWAP_LONG_LONG(m->types); + m->imp = SWAP_LONG_LONG(m->imp); } struct ivar_list_t { @@ -157,8 +160,8 @@ swap_ivar_list_t( struct ivar_list_t *il, enum byte_sex target_byte_sex) { - il->entsize = SWAP_INT(il->entsize); - il->count = SWAP_INT(il->count); + il->entsize = SWAP_INT(il->entsize); + il->count = SWAP_INT(il->count); } struct ivar_t { @@ -175,11 +178,11 @@ swap_ivar_t( struct ivar_t *i, enum byte_sex target_byte_sex) { - i->offset = SWAP_LONG_LONG(i->offset); - i->name = SWAP_LONG_LONG(i->name); - i->type = SWAP_LONG_LONG(i->type); - i->alignment = SWAP_INT(i->alignment); - i->size = SWAP_INT(i->size); + i->offset = SWAP_LONG_LONG(i->offset); + i->name = SWAP_LONG_LONG(i->name); + i->type = SWAP_LONG_LONG(i->type); + i->alignment = SWAP_INT(i->alignment); + i->size = SWAP_INT(i->size); } struct protocol_list_t { @@ -193,7 +196,7 @@ swap_protocol_list_t( struct protocol_list_t *pl, enum byte_sex target_byte_sex) { - pl->count = SWAP_LONG_LONG(pl->count); + pl->count = SWAP_LONG_LONG(pl->count); } struct protocol_t { @@ -215,14 +218,14 @@ swap_protocol_t( struct protocol_t *p, enum byte_sex target_byte_sex) { - p->isa = SWAP_LONG_LONG(p->isa); - p->name = SWAP_LONG_LONG(p->name); - p->protocols = SWAP_LONG_LONG(p->protocols); - p->instanceMethods = SWAP_LONG_LONG(p->instanceMethods); - p->classMethods = SWAP_LONG_LONG(p->classMethods); - p->optionalInstanceMethods = SWAP_LONG_LONG(p->optionalInstanceMethods); - p->optionalClassMethods = SWAP_LONG_LONG(p->optionalClassMethods); - p->instanceProperties = SWAP_LONG_LONG(p->instanceProperties); + p->isa = SWAP_LONG_LONG(p->isa); + p->name = SWAP_LONG_LONG(p->name); + p->protocols = SWAP_LONG_LONG(p->protocols); + p->instanceMethods = SWAP_LONG_LONG(p->instanceMethods); + p->classMethods = SWAP_LONG_LONG(p->classMethods); + p->optionalInstanceMethods = SWAP_LONG_LONG(p->optionalInstanceMethods); + p->optionalClassMethods = SWAP_LONG_LONG(p->optionalClassMethods); + p->instanceProperties = SWAP_LONG_LONG(p->instanceProperties); } struct objc_property_list { @@ -237,8 +240,8 @@ swap_objc_property_list( struct objc_property_list *pl, enum byte_sex target_byte_sex) { - pl->entsize = SWAP_INT(pl->entsize); - pl->count = SWAP_INT(pl->count); + pl->entsize = SWAP_INT(pl->entsize); + pl->count = SWAP_INT(pl->count); } struct objc_property { @@ -252,8 +255,8 @@ swap_objc_property( struct objc_property *op, enum byte_sex target_byte_sex) { - op->name = SWAP_LONG_LONG(op->name); - op->attributes = SWAP_LONG_LONG(op->attributes); + op->name = SWAP_LONG_LONG(op->name); + op->attributes = SWAP_LONG_LONG(op->attributes); } struct category_t { @@ -272,12 +275,12 @@ swap_category_t( struct category_t *c, enum byte_sex target_byte_sex) { - c->name = SWAP_LONG_LONG(c->name); - c->cls = SWAP_LONG_LONG(c->cls); - c->instanceMethods = SWAP_LONG_LONG(c->instanceMethods); - c->classMethods = SWAP_LONG_LONG(c->classMethods); - c->protocols = SWAP_LONG_LONG(c->protocols); - c->instanceProperties = SWAP_LONG_LONG(c->instanceProperties); + c->name = SWAP_LONG_LONG(c->name); + c->cls = SWAP_LONG_LONG(c->cls); + c->instanceMethods = SWAP_LONG_LONG(c->instanceMethods); + c->classMethods = SWAP_LONG_LONG(c->classMethods); + c->protocols = SWAP_LONG_LONG(c->protocols); + c->instanceProperties = SWAP_LONG_LONG(c->instanceProperties); } struct message_ref { @@ -291,27 +294,27 @@ swap_message_ref( struct message_ref *mr, enum byte_sex target_byte_sex) { - mr->imp = SWAP_LONG_LONG(mr->imp); - mr->sel = SWAP_LONG_LONG(mr->sel); + mr->imp = SWAP_LONG_LONG(mr->imp); + mr->sel = SWAP_LONG_LONG(mr->sel); } struct objc_image_info { uint32_t version; uint32_t flags; }; + /* masks for objc_image_info.flags */ #define OBJC_IMAGE_IS_REPLACEMENT (1<<0) #define OBJC_IMAGE_SUPPORTS_GC (1<<1) - static void swap_objc_image_info( struct objc_image_info *o, enum byte_sex target_byte_sex) { - o->version = SWAP_INT(o->version); - o->flags = SWAP_INT(o->flags); + o->version = SWAP_INT(o->version); + o->flags = SWAP_INT(o->flags); } struct objc_string_object_64 { @@ -327,10 +330,10 @@ swap_string_object_64( struct objc_string_object_64 *string_object, enum byte_sex target_byte_sex) { - string_object->isa = SWAP_LONG_LONG(string_object->isa); - string_object->characters = SWAP_LONG_LONG(string_object->characters); - string_object->_length = SWAP_INT(string_object->_length); - string_object->_pad = SWAP_INT(string_object->_pad); + string_object->isa = SWAP_LONG_LONG(string_object->isa); + string_object->characters = SWAP_LONG_LONG(string_object->characters); + string_object->_length = SWAP_INT(string_object->_length); + string_object->_pad = SWAP_INT(string_object->_pad); } struct cfstring_t { @@ -346,24 +349,30 @@ swap_cfstring_t( struct cfstring_t *cfstring, enum byte_sex target_byte_sex) { - cfstring->isa = SWAP_LONG_LONG(cfstring->isa); - cfstring->flags = SWAP_LONG_LONG(cfstring->flags); - cfstring->characters = SWAP_LONG_LONG(cfstring->characters); - cfstring->length = SWAP_LONG_LONG(cfstring->length); + cfstring->isa = SWAP_LONG_LONG(cfstring->isa); + cfstring->flags = SWAP_LONG_LONG(cfstring->flags); + cfstring->characters = SWAP_LONG_LONG(cfstring->characters); + cfstring->length = SWAP_LONG_LONG(cfstring->length); } +#define MAXINDENT 10 + struct info { + char *object_addr; + uint64_t object_size; enum bool swapped; enum byte_sex host_byte_sex; struct section_info_64 *sections; uint32_t nsections; cpu_type_t cputype; + cpu_subtype_t cpusubtype; struct nlist_64 *symbols64; uint32_t nsymbols; char *strings; uint32_t strings_size; struct symbol *sorted_symbols; uint32_t nsorted_symbols; + uint64_t textbase; uint64_t database; struct relocation_info *ext_relocs; uint32_t next_relocs; @@ -371,9 +380,11 @@ struct info { uint32_t nloc_relocs; struct dyld_bind_info *dbi; uint64_t ndbi; + enum chain_format_t chain_format; enum bool verbose; enum bool Vflag; - uint32_t depth; + uint32_t indent_level; + uint32_t indent_widths[MAXINDENT]; }; struct section_info_64 { @@ -411,8 +422,7 @@ static void print_layout_map( static void print_method_list_t( uint64_t p, - struct info *info, - char *indent); + struct info *info); static void print_ivar_list_t( uint64_t p, @@ -430,6 +440,10 @@ static void print_category_t( uint64_t p, struct info *info); +static void print_protocol_t( + uint64_t p, + struct info *info); + static void print_message_refs( struct section_info_64 *s, struct info *info); @@ -444,9 +458,10 @@ static void get_sections_64( uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct section_info_64 **sections, uint32_t *nsections, + uint64_t *textbase, uint64_t *database); static struct section_info_64 *get_section_64( @@ -461,7 +476,7 @@ static void get_cstring_section_64( uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, - uint32_t object_size, + uint64_t object_size, struct section_info_64 *cstring_section_ptr); static void *get_pointer_64( @@ -473,13 +488,44 @@ static void *get_pointer_64( uint32_t nsections); static const char *get_symbol_64( - uint32_t sect_offset, - uint64_t database_offset, + uint64_t sect_offset, + uint64_t sect_addr, + uint64_t textbase, + uint64_t database, uint64_t value, struct relocation_info *relocs, uint32_t nrelocs, struct info *info, - uint64_t *n_value); + uint64_t *n_value, + int64_t *addend); + +static void print_field_value( + uint64_t offset, + uint64_t pointer, + enum bool print_data, + const char* type_name, + const char* suffix, + struct info *info, + struct section_info_64 *s, + uint64_t *out_n_value, + int64_t *out_addend); + +static void print_field_label( + struct info *info, + const char* label, + ...); + +static void print_field_scalar( + struct info *info, + const char* label, + const char* fmt,...); + +static void indent_push( + struct info *info, + uint32_t width); + +static void indent_pop( + struct info *info); /* * Print the objc2 meta data in 64-bit Mach-O files. @@ -487,12 +533,13 @@ static const char *get_symbol_64( void print_objc2_64bit( cpu_type_t cputype, +cpu_subtype_t cpusubtype, struct load_command *load_commands, uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct nlist_64 *symbols64, uint32_t nsymbols, char *strings, @@ -505,103 +552,129 @@ struct relocation_info *loc_relocs, uint32_t nloc_relocs, struct dyld_bind_info *dbi, uint64_t ndbi, +enum chain_format_t chain_format, enum bool verbose, enum bool Vflag) { struct section_info_64 *s; struct info info; + + info.object_addr = object_addr; + info.object_size = object_size; + info.host_byte_sex = get_host_byte_sex(); + info.swapped = info.host_byte_sex != object_byte_sex; + info.cputype = cputype; + info.cpusubtype = cpusubtype; + info.symbols64 = symbols64; + info.nsymbols = nsymbols; + info.strings = strings; + info.strings_size = strings_size; + info.sorted_symbols = sorted_symbols; + info.nsorted_symbols = nsorted_symbols; + info.ext_relocs = ext_relocs; + info.next_relocs = next_relocs; + info.loc_relocs = loc_relocs; + info.nloc_relocs = nloc_relocs; + info.dbi = dbi; + info.ndbi = ndbi; + info.chain_format = chain_format; + info.verbose = verbose; + info.Vflag = Vflag; - info.host_byte_sex = get_host_byte_sex(); - info.swapped = info.host_byte_sex != object_byte_sex; - info.cputype = cputype; - info.symbols64 = symbols64; - info.nsymbols = nsymbols; - info.strings = strings; - info.strings_size = strings_size; - info.sorted_symbols = sorted_symbols; - info.nsorted_symbols = nsorted_symbols; - info.ext_relocs = ext_relocs; - info.next_relocs = next_relocs; - info.loc_relocs = loc_relocs; - info.nloc_relocs = nloc_relocs; - info.dbi = dbi; - info.ndbi = ndbi; - info.verbose = verbose; - info.Vflag = Vflag; - get_sections_64(load_commands, ncmds, sizeofcmds, object_byte_sex, - object_addr, object_size, &info.sections, - &info.nsections, &info.database); + get_sections_64(load_commands, ncmds, sizeofcmds, object_byte_sex, + object_addr, object_size, &info.sections, + &info.nsections, &info.textbase, &info.database); - s = get_section_64(info.sections, info.nsections, - "__OBJC2", "__class_list"); - if(s == NULL) - s = get_section_64(info.sections, info.nsections, - "__DATA", "__objc_classlist"); - if(s == NULL) - s = get_section_64(info.sections, info.nsections, - "__DATA_CONST", "__objc_classlist"); - info.depth = 0; - walk_pointer_list("class", s, &info, print_class_t); + s = get_section_64(info.sections, info.nsections, + "__OBJC2", "__class_list"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA", "__objc_classlist"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA_CONST", "__objc_classlist"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA_DIRTY", "__objc_classlist"); + walk_pointer_list("class", s, &info, print_class_t); - s = get_section_64(info.sections, info.nsections, - "__OBJC2", "__class_refs"); - if(s == NULL) - s = get_section_64(info.sections, info.nsections, - "__DATA", "__objc_classrefs"); - if(s == NULL) - s = get_section_64(info.sections, info.nsections, - "__DATA_CONST", "__objc_classrefs"); - walk_pointer_list("class refs", s, &info, NULL); + s = get_section_64(info.sections, info.nsections, + "__OBJC2", "__class_refs"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA", "__objc_classrefs"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA_CONST", "__objc_classrefs"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA_DIRTY", "__objc_classrefs"); + walk_pointer_list("class refs", s, &info, NULL); - s = get_section_64(info.sections, info.nsections, - "__OBJC2", "__super_refs"); - if(s == NULL) - s = get_section_64(info.sections, info.nsections, - "__DATA", "__objc_superrefs"); - if(s == NULL) - s = get_section_64(info.sections, info.nsections, - "__DATA_CONST", "__objc_superrefs"); - walk_pointer_list("super refs", s, &info, NULL); + s = get_section_64(info.sections, info.nsections, + "__OBJC2", "__super_refs"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA", "__objc_superrefs"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA_CONST", "__objc_superrefs"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA_DIRTY", "__objc_superrefs"); + walk_pointer_list("super refs", s, &info, NULL); - s = get_section_64(info.sections, info.nsections, - "__OBJC2", "__category_list"); - if(s == NULL) - s = get_section_64(info.sections, info.nsections, - "__DATA", "__objc_catlist"); - if(s == NULL) - s = get_section_64(info.sections, info.nsections, - "__DATA_CONST", "__objc_catlist"); - walk_pointer_list("category", s, &info, print_category_t); + s = get_section_64(info.sections, info.nsections, + "__OBJC2", "__category_list"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA", "__objc_catlist"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA_CONST", "__objc_catlist"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA_DIRTY", "__objc_catlist"); + walk_pointer_list("category", s, &info, print_category_t); - s = get_section_64(info.sections, info.nsections, - "__OBJC2", "__protocol_list"); - if(s == NULL) - s = get_section_64(info.sections, info.nsections, - "__DATA", "__objc_protolist"); - if(s == NULL) - s = get_section_64(info.sections, info.nsections, - "__DATA_CONST", "__objc_protolist"); - walk_pointer_list("protocol", s, &info, NULL); - - s = get_section_64(info.sections, info.nsections, - "__OBJC2", "__message_refs"); - if(s == NULL) - s = get_section_64(info.sections, info.nsections, - "__DATA", "__objc_msgrefs"); - if(s == NULL) - s = get_section_64(info.sections, info.nsections, - "__DATA_CONST", "__objc_msgrefs"); - print_message_refs(s, &info); - - s = get_section_64(info.sections, info.nsections, - "__OBJC", "__image_info"); - if(s == NULL) - s = get_section_64(info.sections, info.nsections, - "__DATA", "__objc_imageinfo"); - if(s == NULL) - s = get_section_64(info.sections, info.nsections, - "__DATA_CONST", "__objc_imageinfo"); - print_image_info(s, &info); + s = get_section_64(info.sections, info.nsections, + "__OBJC2", "__protocol_list"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA", "__objc_protolist"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA_CONST", "__objc_protolist"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA_DIRTY", "__objc_protolist"); + walk_pointer_list("protocol", s, &info, print_protocol_t); + + s = get_section_64(info.sections, info.nsections, + "__OBJC2", "__message_refs"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA", "__objc_msgrefs"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA_CONST", "__objc_msgrefs"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA_DIRTY", "__objc_msgrefs"); + print_message_refs(s, &info); + + s = get_section_64(info.sections, info.nsections, + "__OBJC", "__image_info"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA", "__objc_imageinfo"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA_CONST", "__objc_imageinfo"); + if(s == NULL) + s = get_section_64(info.sections, info.nsections, + "__DATA_DIRTY", "__objc_imageinfo"); + print_image_info(s, &info); } static @@ -612,50 +685,40 @@ struct section_info_64 *s, struct info *info, void (*func)(uint64_t, struct info *)) { - uint32_t i, size, left; + uint64_t i, size, left; uint64_t p, n_value; - const char *name; + int64_t addend; + + if(s == NULL) + return; + + info->indent_level = 0; + info->indent_widths[info->indent_level] = 0; - if(s == NULL) - return; + printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname); + for(i = 0; i < s->size; i += sizeof(uint64_t)) + { + left = s->size - i; + size = left < sizeof(uint64_t) ? + left : sizeof(uint64_t); + if(s->contents + i + size > info->object_addr + info->object_size) + return; + + if(i + sizeof(uint64_t) > s->size) + printf("%s list pointer extends past end of (%s,%s) " + "section\n", listname, s->segname, s->sectname); + printf("%016llx ", s->addr + i); - printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname); - for(i = 0; i < s->size; i += sizeof(uint64_t)){ + memset(&p, '\0', sizeof(uint64_t)); + memcpy(&p, s->contents + i, size); + if(info->swapped) + p = SWAP_LONG_LONG(p); - memset(&p, '\0', sizeof(uint64_t)); - left = s->size - i; - size = left < sizeof(uint64_t) ? - left : sizeof(uint64_t); - memcpy(&p, s->contents + i, size); - - if(i + sizeof(uint64_t) > s->size) - printf("%s list pointer extends past end of (%s,%s) " - "section\n", listname, s->segname, s->sectname); - printf("%016llx ", s->addr + i); - - if(info->swapped) - p = SWAP_LONG_LONG(p); - - name = get_symbol_64(i, s->addr - info->database, p, - s->relocs, s->nrelocs, info, &n_value); - if(name == NULL) - name = get_dyld_bind_info_symbolname(s->addr + i, info->dbi, - info->ndbi); - if(n_value != 0){ - printf("0x%llx", n_value); - if(p != 0) - printf(" + 0x%llx", p); - } - else - printf("0x%llx", p); - if(name != NULL) - printf(" %s", name); - printf("\n"); - - p += n_value; - if(func != NULL) - func(p, info); - } + print_field_value(i, p, FALSE, NULL, "\n", info, s, &n_value, &addend); + + if(func != NULL) + func(n_value + addend, info); + } } /* @@ -670,7 +733,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct nlist_64 *symbols64, uint32_t nsymbols, char *strings, @@ -679,54 +742,52 @@ cpu_type_t cputype) { struct section_info_64 *sections, *s; uint32_t nsections, left, offset; - uint64_t database, n_value, cfs_characters; + uint64_t textbase, database, n_value, cfs_characters; + int64_t addend; struct cfstring_t cfs; char *name; const char *symbol_name; void *r; struct info info; - memset(&info, '\0', sizeof(struct info)); - info.symbols64 = symbols64; - info.nsymbols = nsymbols; - info.strings = strings; - info.strings_size = strings_size; - info.cputype = cputype; - info.verbose = TRUE; + memset(&info, '\0', sizeof(struct info)); + info.symbols64 = symbols64; + info.nsymbols = nsymbols; + info.strings = strings; + info.strings_size = strings_size; + info.cputype = cputype; + info.verbose = TRUE; - get_sections_64(load_commands, ncmds, sizeofcmds, object_byte_sex, - object_addr, object_size, §ions, &nsections, - &database); + get_sections_64(load_commands, ncmds, sizeofcmds, object_byte_sex, + object_addr, object_size, §ions, &nsections, + &textbase, &database); + + r = get_pointer_64(p, &offset, &left, &s, sections, nsections); + if(r == NULL || left < sizeof(struct cfstring_t)) + return(NULL); - r = get_pointer_64(p, &offset, &left, &s, sections, nsections); - if(r == NULL || left < sizeof(struct cfstring_t)) - return(NULL); - memcpy(&cfs, r, sizeof(struct cfstring_t)); - if(get_host_byte_sex() != object_byte_sex) - swap_cfstring_t(&cfs, get_host_byte_sex()); - if(cfs.characters == 0){ - symbol_name = get_symbol_64(offset + - offsetof(struct cfstring_t, characters), - s->addr - database, p, - s->relocs, s->nrelocs, &info, &n_value); - if(symbol_name == NULL){ - if(sections != NULL) - free(sections); - return(NULL); - } - cfs_characters = n_value; - } - else{ - cfs_characters = cfs.characters; - } + memcpy(&cfs, r, sizeof(struct cfstring_t)); + if(get_host_byte_sex() != object_byte_sex) + swap_cfstring_t(&cfs, get_host_byte_sex()); - name = get_pointer_64(cfs_characters, NULL, &left, NULL, - sections, nsections); + symbol_name = get_symbol_64(offset + + offsetof(struct cfstring_t, characters), + s->addr, textbase, database, p, s->relocs, + s->nrelocs, &info, &n_value, &addend); + if(symbol_name == NULL){ + if(sections != NULL) + free(sections); + return(NULL); + } + cfs_characters = n_value + addend; - if(sections != NULL) - free(sections); + name = get_pointer_64(cfs_characters, NULL, &left, NULL, + sections, nsections); - return(name); + if(sections != NULL) + free(sections); + + return(name); } /* @@ -745,7 +806,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct nlist_64 *symbols64, uint32_t nsymbols, char *strings, @@ -754,7 +815,8 @@ cpu_type_t cputype) { struct section_info_64 *sections, *s; uint32_t nsections, left, offset; - uint64_t database, n_value; + uint64_t textbase, database, n_value; + int64_t addend; struct class_t c; struct class_ro_t cro; char *name, *class_name; @@ -762,84 +824,90 @@ cpu_type_t cputype) void *r; struct info info; - memset(&info, '\0', sizeof(struct info)); - info.symbols64 = symbols64; - info.nsymbols = nsymbols; - info.strings = strings; - info.strings_size = strings_size; - info.cputype = cputype; - info.verbose = TRUE; + memset(&info, '\0', sizeof(struct info)); + info.symbols64 = symbols64; + info.nsymbols = nsymbols; + info.strings = strings; + info.strings_size = strings_size; + info.cputype = cputype; + info.verbose = TRUE; - get_sections_64(load_commands, ncmds, sizeofcmds, object_byte_sex, - object_addr, object_size, §ions, &nsections, - &database); - if(p == 0){ - r = get_pointer_64(address_of_p, &offset, &left, &s, sections, - nsections); - if(r == NULL || left < sizeof(uint64_t)){ - if(sections != NULL) - free(sections); - return(NULL); - } - symbol_name = get_symbol_64(offset, s->addr - database, - address_of_p, s->relocs, s->nrelocs, - &info, &n_value); - if(symbol_name == NULL){ - if(sections != NULL) - free(sections); - return(NULL); - } - class_name = rindex(symbol_name, '$'); - if(class_name != NULL && - class_name[1] == '_' && class_name[2] != '\0'){ - if(sections != NULL) - free(sections); - return(class_name + 2); - } - else{ - if(sections != NULL) - free(sections); - return(NULL); - } - } + get_sections_64(load_commands, ncmds, sizeofcmds, object_byte_sex, + object_addr, object_size, §ions, &nsections, + &textbase, &database); - r = get_pointer_64(p, NULL, &left, NULL, sections, nsections); - if(r == NULL || left < sizeof(struct class_t)){ - if(sections != NULL) - free(sections); - return(NULL); - } - memcpy(&c, r, sizeof(struct class_t)); - if(get_host_byte_sex() != object_byte_sex) - swap_class_t(&c, get_host_byte_sex()); - if(c.data == 0){ - if(sections != NULL) - free(sections); - return(NULL); + if(p == 0){ + r = get_pointer_64(address_of_p, &offset, &left, &s, sections, + nsections); + if(r == NULL || left < sizeof(uint64_t)){ + if(sections != NULL) + free(sections); + return(NULL); } - r = get_pointer_64(c.data, NULL, &left, NULL, sections, nsections); - if(r == NULL || left < sizeof(struct class_ro_t)){ - if(sections != NULL) - free(sections); - return(NULL); - } - memcpy(&cro, r, sizeof(struct class_ro_t)); - if(get_host_byte_sex() != object_byte_sex) - swap_class_ro_t(&cro, get_host_byte_sex()); - - if(cro.name == 0){ - if(sections != NULL) - free(sections); - return(NULL); - } + symbol_name = get_symbol_64(offset, s->addr, textbase, database, + address_of_p, s->relocs, s->nrelocs, + &info, &n_value, &addend); + if(symbol_name == NULL){ + if(sections != NULL) + free(sections); + return(NULL); + } - name = get_pointer_64(cro.name, NULL, &left, NULL, sections, nsections); + class_name = rindex(symbol_name, '$'); + if(class_name != NULL && + class_name[1] == '_' && class_name[2] != '\0'){ + if(sections != NULL) + free(sections); + return(class_name + 2); + } + else{ + if(sections != NULL) + free(sections); + return(NULL); + } + } - if(sections != NULL) - free(sections); + r = get_pointer_64(p, NULL, &left, NULL, sections, nsections); + if(r == NULL || left < sizeof(struct class_t)){ + if(sections != NULL) + free(sections); + return(NULL); + } - return(name); + memcpy(&c, r, sizeof(struct class_t)); + if(get_host_byte_sex() != object_byte_sex) + swap_class_t(&c, get_host_byte_sex()); + + if(c.data == 0){ + if(sections != NULL) + free(sections); + return(NULL); + } + + r = get_pointer_64(c.data, NULL, &left, NULL, sections, nsections); + if(r == NULL || left < sizeof(struct class_ro_t)){ + if(sections != NULL) + free(sections); + return(NULL); + } + + memcpy(&cro, r, sizeof(struct class_ro_t)); + if(get_host_byte_sex() != object_byte_sex) + swap_class_ro_t(&cro, get_host_byte_sex()); + + if(cro.name == 0){ + if(sections != NULL) + free(sections); + return(NULL); + } + + name = get_pointer_64(cro.name, NULL, &left, NULL, sections, nsections); + + if(sections != NULL) + free(sections); + + return(name); } /* @@ -858,7 +926,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct nlist_64 *symbols64, uint32_t nsymbols, char *strings, @@ -867,38 +935,41 @@ cpu_type_t cputype) { struct section_info_64 *sections, *s; uint32_t nsections, left, offset; - uint64_t database, n_value; + uint64_t textbase, database, n_value; + int64_t addend; void *r; const char *symbol_name; struct info info; - memset(&info, '\0', sizeof(struct info)); - info.symbols64 = symbols64; - info.nsymbols = nsymbols; - info.strings = strings; - info.strings_size = strings_size; - info.cputype = cputype; - info.verbose = TRUE; + memset(&info, '\0', sizeof(struct info)); + info.symbols64 = symbols64; + info.nsymbols = nsymbols; + info.strings = strings; + info.strings_size = strings_size; + info.cputype = cputype; + info.verbose = TRUE; - get_sections_64(load_commands, ncmds, sizeofcmds, object_byte_sex, - object_addr, object_size, §ions, &nsections, - &database); - r = get_pointer_64(address_of_p, &offset, &left, &s, sections, - nsections); - if(r == NULL || left < sizeof(uint64_t)){ - if(sections != NULL) - free(sections); - return(0); - } - symbol_name = get_symbol_64(offset, s->addr - database, - address_of_p, s->relocs, s->nrelocs, - &info, &n_value); - if(symbol_name == NULL){ - if(sections != NULL) - free(sections); - return(0); - } - return(n_value); + get_sections_64(load_commands, ncmds, sizeofcmds, object_byte_sex, + object_addr, object_size, §ions, &nsections, + &textbase, &database); + r = get_pointer_64(address_of_p, &offset, &left, &s, sections, + nsections); + if(r == NULL || left < sizeof(uint64_t)){ + if(sections != NULL) + free(sections); + return(0); + } + + symbol_name = get_symbol_64(offset, s->addr, textbase, database, + address_of_p, s->relocs, s->nrelocs, + &info, &n_value, &addend); + + if(symbol_name == NULL){ + if(sections != NULL) + free(sections); + return(0); + } + return(n_value); } static @@ -911,90 +982,78 @@ struct info *info) void *r; uint32_t offset, left; struct section_info_64 *s; - const char *name; enum bool is_meta_class; uint64_t n_value, isa_n_value; + int64_t addend, isa_addend; + static uint32_t recursive_depth; - is_meta_class = FALSE; - r = get_pointer_64(p, &offset, &left, &s, - info->sections, info->nsections); - if(r == NULL) - return; - memset(&c, '\0', sizeof(struct class_t)); - if(left < sizeof(struct class_t)){ - memcpy(&c, r, left); - printf(" (class_t entends past the end of the section)\n"); - } - else - memcpy(&c, r, sizeof(struct class_t)); - if(info->swapped) - swap_class_t(&c, info->host_byte_sex); - printf(" isa 0x%llx", c.isa); - name = get_symbol_64(offset + offsetof(struct class_t, isa), - s->addr - info->database, c.isa, s->relocs, - s->nrelocs, info, &isa_n_value); - if(name != NULL) - printf(" %s\n", name); - else - printf("\n"); - printf(" superclass 0x%llx", c.superclass); - name = get_symbol_64(offset + offsetof(struct class_t, superclass), - s->addr - info->database, c.superclass, s->relocs, - s->nrelocs, info, NULL); - if(name != NULL) - printf(" %s\n", name); - else - printf("\n"); - printf(" cache 0x%llx", c.cache); - name = get_symbol_64(offset + offsetof(struct class_t, cache), - s->addr - info->database, c.cache, s->relocs, - s->nrelocs, info, NULL); - if(name != NULL) - printf(" %s\n", name); - else - printf("\n"); - printf(" vtable 0x%llx", c.vtable); - name = get_symbol_64(offset + offsetof(struct class_t, vtable), - s->addr - info->database, c.vtable, s->relocs, - s->nrelocs, info, NULL); - if(name != NULL) - printf(" %s\n", name); - else - printf("\n"); + is_meta_class = FALSE; - name = get_symbol_64(offset + offsetof(struct class_t, data), - s->addr - info->database, c.data, s->relocs, - s->nrelocs, info, &n_value); - printf(" data "); - if(n_value != 0){ - if(info->Vflag && name != NULL) - printf("%s", name); - else - printf("0x%llx", n_value); - if(c.data != 0) - printf(" + 0x%llx", c.data); - } - else{ - printf("0x%llx", c.data); - } - printf(" (struct class_ro_t *)"); - /* - * This is a Swift class if some of the low bits of the pointer - * are set. - */ - if((c.data + n_value) & 0x7) - printf(" Swift class"); - printf("\n"); - print_class_ro_t((c.data + n_value) & ~0x7, info, &is_meta_class); + r = get_pointer_64(p, &offset, &left, &s, + info->sections, info->nsections); + if(r == NULL) + return; - if(is_meta_class == FALSE && - c.isa + isa_n_value != p && - c.isa + isa_n_value != 0 && - info->depth < 100){ - info->depth++; - printf("Meta Class\n"); - print_class_t(c.isa + isa_n_value, info); - } + memset(&c, '\0', sizeof(struct class_t)); + if(left < sizeof(struct class_t)){ + memcpy(&c, r, left); + printf(" (class_t entends past the end of the section)\n"); + } + else + memcpy(&c, r, sizeof(struct class_t)); + if(info->swapped) + swap_class_t(&c, info->host_byte_sex); + + indent_push(info, sizeof("superclass") - 1); + + print_field_label(info, "isa"); + print_field_value(offset + offsetof(struct class_t, isa), c.isa, + FALSE, NULL, "\n", info, s, &isa_n_value, &isa_addend); + + print_field_label(info, "superclass"); + print_field_value(offset + offsetof(struct class_t, superclass), + c.superclass, FALSE, NULL, "\n", info, s, + &n_value, &addend); + + print_field_label(info, "cache"); + print_field_value(offset + offsetof(struct class_t, cache), + c.cache, FALSE, NULL, "\n", info, s, &n_value, &addend); + + print_field_label(info, "vtable"); + print_field_value(offset + offsetof(struct class_t, vtable), + c.vtable, FALSE, NULL, "\n", info, s, &n_value, &addend); + + print_field_label(info, "data"); + print_field_value(offset + offsetof(struct class_t, data), c.data, FALSE, + "(struct class_ro_t *)", NULL, info, s, &n_value, &addend); + /* + * This is a Swift class if some of the low bits of the pointer + * are set. Note that this value is 3 in 32-bit. + * + * bit 0: is Swift + * bit 1: is Swift-stable API + * bit 2: has custom retain/release (runtime only) + */ + if((c.data + n_value) & 0x7) + printf(" Swift class"); + printf("\n"); + + /* Descend into the read only data */ + print_class_ro_t((n_value + addend) & ~0x7, info, &is_meta_class); + + indent_pop(info); + + /* Walk the class hierarchy, but be wary of cycles or bad chains */ + if(is_meta_class == FALSE && + isa_n_value + isa_addend != p && + isa_n_value + isa_addend != 0 && + recursive_depth < 100) + { + recursive_depth++; + printf("Meta Class\n"); + print_class_t(isa_n_value + isa_addend, info); + recursive_depth--; + } } static @@ -1008,152 +1067,103 @@ enum bool *is_meta_class) void *r; uint32_t offset, left; struct section_info_64 *s; - const char *name, *sym_name; + const char *name; uint64_t n_value; + int64_t addend; - r = get_pointer_64(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&cro, '\0', sizeof(struct class_ro_t)); - if(left < sizeof(struct class_ro_t)){ - memcpy(&cro, r, left); - printf(" (class_ro_t entends past the end of the section)\n"); - } - else - memcpy(&cro, r, sizeof(struct class_ro_t)); - if(info->swapped) - swap_class_ro_t(&cro, info->host_byte_sex); - printf(" flags 0x%x", cro.flags); - if(cro.flags & RO_META) - printf(" RO_META"); - if(cro.flags & RO_ROOT) - printf(" RO_ROOT"); - if(cro.flags & RO_HAS_CXX_STRUCTORS) - printf(" RO_HAS_CXX_STRUCTORS"); - printf("\n"); - printf(" instanceStart %u\n", cro.instanceStart); - printf(" instanceSize %u\n", cro.instanceSize); - printf(" reserved 0x%x\n", cro.reserved); - printf(" ivarLayout 0x%llx\n", cro.ivarLayout); - print_layout_map(cro.ivarLayout, info); + r = get_pointer_64(p, &offset, &left, &s, info->sections, + info->nsections); + if(r == NULL) + return; - printf(" name "); - sym_name = get_symbol_64(offset + offsetof(struct class_ro_t, name), - s->addr - info->database, cro.name, s->relocs, - s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(cro.name != 0) - printf(" + 0x%llx", cro.name); - } - else - printf("0x%llx", cro.name); - name = get_pointer_64(cro.name + n_value, NULL, &left, NULL, - info->sections, info->nsections); - if(name != NULL) - printf(" %.*s", (int)left, name); - printf("\n"); + memset(&cro, '\0', sizeof(struct class_ro_t)); + if(left < sizeof(struct class_ro_t)){ + memcpy(&cro, r, left); + printf(" (class_ro_t entends past the end of the section)\n"); + } + else + memcpy(&cro, r, sizeof(struct class_ro_t)); + if(info->swapped) + swap_class_ro_t(&cro, info->host_byte_sex); - printf(" baseMethods "); - sym_name = get_symbol_64(offset + - offsetof(struct class_ro_t, baseMethods), - s->addr - info->database, cro.baseMethods, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(cro.baseMethods != 0) - printf(" + 0x%llx", cro.baseMethods); - } - else - printf("0x%llx", cro.baseMethods); - printf(" (struct method_list_t *)\n"); - if(cro.baseMethods + n_value != 0) - print_method_list_t(cro.baseMethods + n_value, info, ""); + indent_push(info, sizeof("weakIvarLayout") - 1); - printf(" baseProtocols "); - sym_name = get_symbol_64(offset + - offsetof(struct class_ro_t, baseProtocols), - s->addr - info->database, cro.baseProtocols, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(cro.baseProtocols != 0) - printf(" + 0x%llx", cro.baseProtocols); - } - else - printf("0x%llx", cro.baseProtocols); - printf("\n"); - if(cro.baseProtocols + n_value != 0) - print_protocol_list_t(cro.baseProtocols + n_value, info); + print_field_scalar(info, "flags", "0x%x", cro.flags); - printf(" ivars "); - sym_name = get_symbol_64(offset + - offsetof(struct class_ro_t, ivars), - s->addr - info->database, cro.ivars, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(cro.ivars != 0) - printf(" + 0x%llx", cro.ivars); - } - else - printf("0x%llx", cro.ivars); - printf("\n"); - if(cro.ivars + n_value != 0) - print_ivar_list_t(cro.ivars + n_value, info); + if(info->verbose){ + if(cro.flags & RO_META) + printf(" RO_META"); + if(cro.flags & RO_ROOT) + printf(" RO_ROOT"); + if(cro.flags & RO_HAS_CXX_STRUCTORS) + printf(" RO_HAS_CXX_STRUCTORS"); + } + printf("\n"); - printf(" weakIvarLayout "); - sym_name = get_symbol_64(offset + - offsetof(struct class_ro_t, weakIvarLayout), - s->addr - info->database, cro.weakIvarLayout, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(cro.weakIvarLayout != 0) - printf(" + 0x%llx", cro.weakIvarLayout); - } - else - printf("0x%llx", cro.weakIvarLayout); - printf("\n"); - print_layout_map(cro.weakIvarLayout + n_value, info); + print_field_scalar(info, "instanceStart", "%u\n", cro.instanceStart); + print_field_scalar(info, "instanceSize", "%u\n", cro.instanceSize); + print_field_scalar(info, "reserved", "0x%x\n", cro.reserved); - printf(" baseProperties "); - sym_name = get_symbol_64(offset + - offsetof(struct class_ro_t, baseProperties), - s->addr - info->database, cro.baseProperties, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(cro.baseProperties != 0) - printf(" + 0x%llx", cro.baseProperties); - } - else - printf("0x%llx", cro.baseProperties); - printf("\n"); - if(cro.baseProperties + n_value != 0) - print_objc_property_list(cro.baseProperties + n_value, info); + print_field_label(info, "ivarLayout"); + print_field_value(offset + offsetof(struct class_ro_t, ivarLayout), + cro.ivarLayout, FALSE, NULL, "\n", info, s, + &n_value, &addend); + print_layout_map(n_value + addend, info); - if(is_meta_class) - *is_meta_class = (cro.flags & RO_META) ? TRUE : FALSE; + print_field_label(info, "name"); + print_field_value(offset + offsetof(struct class_ro_t, name), + cro.name, FALSE, NULL, NULL, info, s, &n_value, &addend); + if (info->verbose) { + name = get_pointer_64(n_value + addend, NULL, &left, NULL, + info->sections, info->nsections); + if (name != NULL) + printf(" %.*s", (int)left, name); + } + printf("\n"); + + print_field_label(info, "baseMethods"); + print_field_value(offset + offsetof(struct class_ro_t, baseMethods), + cro.baseMethods, FALSE, "(struct method_list_t *)", "\n", + info, s, &n_value, &addend); + if(n_value + addend != 0) { + print_method_list_t(n_value + addend, info); + } + + print_field_label(info, "baseProtocols"); + print_field_value(offset + offsetof(struct class_ro_t, baseProtocols), + cro.baseProtocols, FALSE, "(struct protocol_list_t *)", + "\n", info, s, &n_value, &addend); + if(n_value + addend != 0) { + print_protocol_list_t(n_value + addend, info); + } + + print_field_label(info, "ivars"); + print_field_value(offset + offsetof(struct class_ro_t, ivars), + cro.ivars, FALSE, "(struct ivar_list_t *)", "\n", info, s, + &n_value, &addend); + if(n_value + addend != 0) { + print_ivar_list_t(n_value + addend, info); + } + + print_field_label(info, "weakIvarLayout"); + print_field_value(offset + offsetof(struct class_ro_t, weakIvarLayout), + cro.weakIvarLayout, FALSE, NULL, "\n", info, s, + &n_value, &addend); + print_layout_map(n_value + addend, info); + + print_field_label(info, "baseProperties"); + print_field_value(offset + offsetof(struct class_ro_t, baseProperties), + cro.baseProperties, FALSE, + "(struct objc_property_list *)", "\n", info, s, + &n_value, &addend); + if(n_value + addend != 0) { + print_objc_property_list(n_value + addend, info); + } + + if(is_meta_class) + *is_meta_class = (cro.flags & RO_META) ? TRUE : FALSE; + + indent_pop(info); } static @@ -1166,131 +1176,92 @@ struct info *info) struct section_info_64 *s; char *layout_map; - if(p == 0) - return; - layout_map = get_pointer_64(p, &offset, &left, &s, - info->sections, info->nsections); - if(layout_map != NULL){ - printf(" layout map: "); - do{ - printf("0x%02x ", (*layout_map) & 0xff); - left--; - layout_map++; - }while(*layout_map != '\0' && left != 0); - printf("\n"); - } + if(p == 0) + return; + + layout_map = get_pointer_64(p, &offset, &left, &s, + info->sections, info->nsections); + if(layout_map != NULL){ + print_field_label(info, "layout map"); + do{ + printf("0x%02x ", (*layout_map) & 0xff); + left--; + layout_map++; + }while(*layout_map != '\0' && left != 0); + printf("\n"); + } } static void print_method_list_t( uint64_t p, -struct info *info, -char *indent) +struct info *info) { struct method_list_t ml; struct method_t m; void *r; uint32_t offset, left, i; struct section_info_64 *s; - const char *name, *sym_name; uint64_t n_value; + int64_t addend; + + r = get_pointer_64(p, &offset, &left, &s, info->sections, info->nsections); + if(r == NULL) + return; - r = get_pointer_64(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&ml, '\0', sizeof(struct method_list_t)); - if(left < sizeof(struct method_list_t)){ - memcpy(&ml, r, left); - printf("%s (method_list_t entends past the end of the " - "section)\n", indent); - } - else - memcpy(&ml, r, sizeof(struct method_list_t)); - if(info->swapped) - swap_method_list_t(&ml, info->host_byte_sex); - printf("%s\t\t entsize %u\n", indent, ml.entsize); - printf("%s\t\t count %u\n", indent, ml.count); + memset(&ml, '\0', sizeof(struct method_list_t)); + if(left < sizeof(struct method_list_t)){ + memcpy(&ml, r, left); + print_field_scalar(info, "", "(method_list_t entends past the end " + "of the section)\n)"); + } + else + memcpy(&ml, r, sizeof(struct method_list_t)); + if(info->swapped) + swap_method_list_t(&ml, info->host_byte_sex); - p += sizeof(struct method_list_t); - offset += sizeof(struct method_list_t); - for(i = 0; i < ml.count; i++){ - r = get_pointer_64(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&m, '\0', sizeof(struct method_t)); - if(left < sizeof(struct method_t)){ - memcpy(&m, r, left); - printf("%s (method_t entends past the end of the " - "section)\n", indent); - } - else - memcpy(&m, r, sizeof(struct method_t)); - if(info->swapped) - swap_method_t(&m, info->host_byte_sex); + indent_push(info, sizeof("entsize") - 1); - printf("%s\t\t name ", indent); - sym_name = get_symbol_64(offset + offsetof(struct method_t, name), - s->addr - info->database, m.name, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(m.name != 0) - printf(" + 0x%llx", m.name); - } - else - printf("0x%llx", m.name); - name = get_pointer_64(m.name + n_value, NULL, &left, NULL, - info->sections, info->nsections); - if(name != NULL) - printf(" %.*s", (int)left, name); - printf("\n"); + print_field_scalar(info, "entsize", "%u\n", ml.entsize); + print_field_scalar(info, "count", "%u\n", ml.count); - printf("%s\t\t types ", indent); - sym_name = get_symbol_64(offset + offsetof(struct method_t, types), - s->addr - info->database, m.types, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(m.name != 0) - printf(" + 0x%llx", m.types); - } - else - printf("0x%llx", m.types); - name = get_pointer_64(m.types + n_value, NULL, &left, NULL, - info->sections, info->nsections); - if(name != NULL) - printf(" %.*s", (int)left, name); - printf("\n"); + p += sizeof(struct method_list_t); + offset += sizeof(struct method_list_t); + for(i = 0; i < ml.count; i++){ + r = get_pointer_64(p, &offset, &left, &s, + info->sections, info->nsections); + if(r == NULL) + break; - printf("%s\t\t imp ", indent); - name = get_symbol_64(offset + offsetof(struct method_t, imp), - s->addr - info->database, m.imp, s->relocs, - s->nrelocs, info, &n_value); - if(info->Vflag == FALSE || name == NULL){ - if(n_value != 0){ - printf("0x%llx ", n_value); - if(m.imp != 0) - printf("+ 0x%llx ", m.imp); - } - else - printf("0x%llx ", m.imp); - } - if(name != NULL) - printf("%s", name); - printf("\n"); + memset(&m, '\0', sizeof(struct method_t)); + if(left < sizeof(struct method_t)){ + memcpy(&m, r, left); + print_field_scalar(info, "", "(method_t entends past the end " + "of the section)\n)"); + } + else + memcpy(&m, r, sizeof(struct method_t)); + if(info->swapped) + swap_method_t(&m, info->host_byte_sex); - p += sizeof(struct method_t); - offset += sizeof(struct method_t); - } + print_field_label(info, "name"); + print_field_value(offset + offsetof(struct method_t, name), + m.name, TRUE, NULL, "\n", info, s, &n_value, &addend); + + print_field_label(info, "types"); + print_field_value(offset + offsetof(struct method_t, types), + m.types, TRUE, NULL, "\n", info, s, &n_value,&addend); + + print_field_label(info, "imp"); + print_field_value(offset + offsetof(struct method_t, imp), + m.imp, FALSE, NULL, "\n", info, s, &n_value, &addend); + + p += sizeof(struct method_t); + offset += sizeof(struct method_t); + } + + indent_pop(info); } static @@ -1304,114 +1275,80 @@ struct info *info) void *r; uint32_t offset, left, j; struct section_info_64 *s; - const char *name, *sym_name; - uint64_t *ivar_offset_p, ivar_offset, n_value; + uint64_t *ivar_offset_p, n_value; + uint32_t ivar_offset; + int64_t addend; + + r = get_pointer_64(p, &offset, &left, &s, info->sections, + info->nsections); + if(r == NULL) + return; + memset(&il, '\0', sizeof(struct ivar_list_t)); + if(left < sizeof(struct ivar_list_t)){ + memcpy(&il, r, left); + printf(" (ivar_list_t entends past the end of the section)\n"); + } + else + memcpy(&il, r, sizeof(struct ivar_list_t)); + if(info->swapped) + swap_ivar_list_t(&il, info->host_byte_sex); - r = get_pointer_64(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&il, '\0', sizeof(struct ivar_list_t)); - if(left < sizeof(struct ivar_list_t)){ - memcpy(&il, r, left); - printf(" (ivar_list_t entends past the end of the section)\n"); - } - else - memcpy(&il, r, sizeof(struct ivar_list_t)); - if(info->swapped) - swap_ivar_list_t(&il, info->host_byte_sex); - printf(" entsize %u\n", il.entsize); - printf(" count %u\n", il.count); + indent_push(info, sizeof("alignment") - 1); - p += sizeof(struct ivar_list_t); - offset += sizeof(struct ivar_list_t); - for(j = 0; j < il.count; j++){ - r = get_pointer_64(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&i, '\0', sizeof(struct ivar_t)); - if(left < sizeof(struct ivar_t)){ - memcpy(&i, r, left); - printf(" (ivar_t entends past the end of the section)\n"); - } - else - memcpy(&i, r, sizeof(struct ivar_t)); - if(info->swapped) - swap_ivar_t(&i, info->host_byte_sex); + print_field_scalar(info, "entsize", "%u\n", il.entsize); + print_field_scalar(info, "count", "%u\n", il.count); - printf("\t\t\t offset "); - sym_name = get_symbol_64(offset + offsetof(struct ivar_t, offset), - s->addr - info->database, i.offset, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(i.offset != 0) - printf(" + 0x%llx", i.offset); - } - else - printf("0x%llx", i.offset); - ivar_offset_p = get_pointer_64(i.offset + n_value, NULL, &left, - NULL,info->sections,info->nsections); - if(ivar_offset_p != NULL && left >= sizeof(*ivar_offset_p)){ - memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); - if(info->swapped) - ivar_offset = SWAP_LONG_LONG(ivar_offset); - printf(" %llu\n", ivar_offset); + p += sizeof(struct ivar_list_t); + offset += sizeof(struct ivar_list_t); + for(j = 0; j < il.count; j++){ + r = get_pointer_64(p, &offset, &left, &s, info->sections, + info->nsections); + if(r == NULL) + break; + + memset(&i, '\0', sizeof(struct ivar_t)); + if(left < sizeof(struct ivar_t)){ + memcpy(&i, r, left); + printf(" (ivar_t entends past the end of the section)\n"); + } + else + memcpy(&i, r, sizeof(struct ivar_t)); + if(info->swapped) + swap_ivar_t(&i, info->host_byte_sex); + + print_field_label(info, "offset"); + print_field_value(offset + offsetof(struct ivar_t, offset), + i.offset, FALSE, NULL, NULL, info, s, + &n_value, &addend); + if (info->verbose) { + ivar_offset_p = get_pointer_64(n_value + addend, NULL, &left, NULL, + info->sections, info->nsections); + if(ivar_offset_p != NULL && left >= sizeof(ivar_offset)){ + memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); + if(info->swapped) + ivar_offset = SWAP_INT(ivar_offset); + printf(" %u", ivar_offset); } - else - printf("\n"); + } + printf("\n"); - printf("\t\t\t name "); - sym_name = get_symbol_64(offset + offsetof(struct ivar_t, name), - s->addr - info->database, i.name, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(i.name != 0) - printf(" + 0x%llx", i.name); - } - else - printf("0x%llx", i.name); - name = get_pointer_64(i.name + n_value, NULL, &left, NULL, - info->sections, info->nsections); - if(name != NULL) - printf(" %.*s", (int)left, name); - printf("\n"); + print_field_label(info, "name"); + print_field_value(offset + offsetof(struct ivar_t, name), + i.name, TRUE, NULL, "\n", info, s, &n_value, &addend); - printf("\t\t\t type "); - sym_name = get_symbol_64(offset + offsetof(struct ivar_t, type), - s->addr - info->database, i.type, - s->relocs, s->nrelocs, info, &n_value); - name = get_pointer_64(i.type + n_value, NULL, &left, NULL, - info->sections, info->nsections); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(i.type != 0) - printf(" + 0x%llx", i.type); - } - else - printf("0x%llx", i.type); - if(name != NULL) - printf(" %.*s", (int)left, name); - printf("\n"); + print_field_label(info, "type"); + print_field_value(offset + offsetof(struct ivar_t, type), + i.type, TRUE, NULL, "\n", info, s, &n_value, &addend); - printf("\t\t\talignment %u\n", i.alignment); - printf("\t\t\t size %u\n", i.size); + print_field_scalar(info, "alignment", "%u\n", i.alignment); + print_field_scalar(info, "size", "%u\n", i.size); - p += sizeof(struct ivar_t); - offset += sizeof(struct ivar_t); - } + p += sizeof(struct ivar_t); + offset += sizeof(struct ivar_t); + } + + indent_pop(info); } static @@ -1422,149 +1359,68 @@ struct info *info) { struct protocol_list_t pl; uint64_t q, n_value; - struct protocol_t pc; + int64_t addend; void *r; uint32_t offset, left, i; struct section_info_64 *s; - const char *name, *sym_name; + static uint32_t recursive_depth; - r = get_pointer_64(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&pl, '\0', sizeof(struct protocol_list_t)); - if(left < sizeof(struct protocol_list_t)){ - memcpy(&pl, r, left); - printf(" (protocol_list_t entends past the end of the " - "section)\n"); - } - else - memcpy(&pl, r, sizeof(struct protocol_list_t)); - if(info->swapped) - swap_protocol_list_t(&pl, info->host_byte_sex); - printf(" count %llu\n", pl.count); + r = get_pointer_64(p, &offset, &left, &s, info->sections, + info->nsections); + if(r == NULL) + return; - p += sizeof(struct protocol_list_t); - offset += sizeof(struct protocol_list_t); - for(i = 0; i < pl.count; i++){ - r = get_pointer_64(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - q = 0; - if(left < sizeof(uint64_t)){ - memcpy(&q, r, left); - printf(" (protocol_t * entends past the end of the " - "section)\n"); - } - else - memcpy(&q, r, sizeof(uint64_t)); - if(info->swapped) - q = SWAP_LONG_LONG(q); + memset(&pl, '\0', sizeof(struct protocol_list_t)); + if(left < sizeof(struct protocol_list_t)){ + memcpy(&pl, r, left); + printf(" (protocol_list_t entends past the end of the " + "section)\n"); + } + else + memcpy(&pl, r, sizeof(struct protocol_list_t)); + if(info->swapped) + swap_protocol_list_t(&pl, info->host_byte_sex); - printf("\t\t list[%u] ", i); - sym_name = get_symbol_64(offset, s->addr - info->database, q, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(q != 0) - printf(" + 0x%llx", q); - } - else - printf("0x%llx", q); - printf(" (struct protocol_t *)\n"); + indent_push(info, sizeof("list[99]") - 1); - r = get_pointer_64(q + n_value, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&pc, '\0', sizeof(struct protocol_t)); - if(left < sizeof(struct protocol_t)){ - memcpy(&pc, r, left); - printf(" (protocol_t entends past the end of the section)\n"); - } - else - memcpy(&pc, r, sizeof(struct protocol_t)); - if(info->swapped) - swap_protocol_t(&pc, info->host_byte_sex); + print_field_scalar(info, "count", "%llu\n", pl.count); - printf("\t\t\t isa 0x%llx\n", pc.isa); + p += sizeof(struct protocol_list_t); + offset += sizeof(struct protocol_list_t); + for(i = 0; i < pl.count; i++){ + r = get_pointer_64(p, &offset, &left, &s, info->sections, + info->nsections); + if(r == NULL) + break; - printf("\t\t\t name "); - sym_name = get_symbol_64(offset + offsetof(struct protocol_t, name), - s->addr - info->database, pc.name, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(pc.name != 0) - printf(" + 0x%llx", pc.name); - } - else - printf("0x%llx", pc.name); - name = get_pointer_64(pc.name + n_value , NULL, &left, NULL, - info->sections, info->nsections); - if(name != NULL) - printf(" %.*s", (int)left, name); - printf("\n"); + q = 0; + if(left < sizeof(uint64_t)){ + memcpy(&q, r, left); + printf(" (protocol_t * entends past the end of the " + "section)\n"); + } + else + memcpy(&q, r, sizeof(uint64_t)); + if(info->swapped) + q = SWAP_LONG_LONG(q); - printf("\t\t\tprotocols 0x%llx\n", pc.protocols); + print_field_label(info, "list[%u]", i); + print_field_value(offset, q, FALSE, "(struct protocol_t *)", "\n", + info, s, &n_value, &addend); + + if (n_value + addend && + recursive_depth < 100) + { + recursive_depth += 1; + print_protocol_t(n_value + addend, info); + recursive_depth -= 1; + } + + p += sizeof(uint64_t); + offset += sizeof(uint64_t); + } - printf("\t\t instanceMethods "); - sym_name = get_symbol_64(offset + offsetof(struct protocol_t, - instanceMethods), - s->addr - info->database, - pc.instanceMethods, s->relocs, s->nrelocs, - info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(pc.instanceMethods != 0) - printf(" + 0x%llx", pc.instanceMethods); - } - else - printf("0x%llx", pc.instanceMethods); - printf(" (struct method_list_t *)\n"); - if(pc.instanceMethods + n_value != 0) - print_method_list_t(pc.instanceMethods + n_value, info, "\t"); - - printf("\t\t classMethods "); - sym_name = get_symbol_64(offset + offsetof(struct protocol_t, - classMethods), - s->addr - info->database, - pc.classMethods, s->relocs, s->nrelocs, - info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(pc.classMethods != 0) - printf(" + 0x%llx", pc.classMethods); - } - else - printf("0x%llx", pc.classMethods); - printf(" (struct method_list_t *)\n"); - - if(pc.classMethods + n_value != 0) - print_method_list_t(pc.classMethods + n_value, info, "\t"); - printf("\t optionalInstanceMethods 0x%llx\n", - pc.optionalInstanceMethods); - printf("\t optionalClassMethods 0x%llx\n", - pc.optionalClassMethods); - printf("\t instanceProperties 0x%llx\n", - pc.instanceProperties); - - p += sizeof(uint64_t); - offset += sizeof(uint64_t); - } + indent_pop(info); } static @@ -1578,89 +1434,63 @@ struct info *info) void *r; uint32_t offset, left, j; struct section_info_64 *s; - const char *name, *sym_name; uint64_t n_value; + int64_t addend; + + r = get_pointer_64(p, &offset, &left, &s, info->sections, info->nsections); + if(r == NULL) + return; - r = get_pointer_64(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&opl, '\0', sizeof(struct objc_property_list)); - if(left < sizeof(struct objc_property_list)){ - memcpy(&opl, r, left); - printf(" (objc_property_list entends past the end of the " - "section)\n"); - } - else - memcpy(&opl, r, sizeof(struct objc_property_list)); - if(info->swapped) - swap_objc_property_list(&opl, info->host_byte_sex); - printf(" entsize %u\n", opl.entsize); - printf(" count %u\n", opl.count); + memset(&opl, '\0', sizeof(struct objc_property_list)); + if(left < sizeof(struct objc_property_list)){ + memcpy(&opl, r, left); + printf(" (objc_property_list entends past the end of the " + "section)\n"); + } + else + memcpy(&opl, r, sizeof(struct objc_property_list)); + if(info->swapped) + swap_objc_property_list(&opl, info->host_byte_sex); - p += sizeof(struct objc_property_list); - offset += sizeof(struct objc_property_list); - for(j = 0; j < opl.count; j++){ - r = get_pointer_64(p, &offset, &left, &s, info->sections, - info->nsections); - if(r == NULL) - return; - memset(&op, '\0', sizeof(struct objc_property)); - if(left < sizeof(struct objc_property)){ - memcpy(&op, r, left); - printf(" (objc_property entends past the end of the " - "section)\n"); - } - else - memcpy(&op, r, sizeof(struct objc_property)); - if(info->swapped) - swap_objc_property(&op, info->host_byte_sex); + indent_push(info, sizeof("attributes") - 1); - printf("\t\t\t name "); - sym_name = get_symbol_64(offset + offsetof(struct objc_property, - name), - s->addr - info->database, op.name, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(op.name != 0) - printf(" + 0x%llx", op.name); - } - else - printf("0x%llx", op.name); - name = get_pointer_64(op.name + n_value, NULL, &left, NULL, - info->sections, info->nsections); - if(name != NULL) - printf(" %.*s", (int)left, name); - printf("\n"); + print_field_scalar(info, "entsize", "%u\n", opl.entsize); + print_field_scalar(info, "count", "%u\n", opl.count); - printf("\t\t\tattributes "); - sym_name = get_symbol_64(offset + offsetof(struct objc_property, - attributes), - s->addr - info->database, op.attributes, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(op.attributes != 0) - printf(" + 0x%llx", op.attributes); - } - else - printf("0x%llx", op.attributes); - name = get_pointer_64(op.attributes + n_value, NULL, &left, NULL, - info->sections, info->nsections); - if(name != NULL) - printf(" %.*s", (int)left, name); - printf("\n"); + p += sizeof(struct objc_property_list); + offset += sizeof(struct objc_property_list); + for(j = 0; j < opl.count; j++){ + r = get_pointer_64(p, &offset, &left, &s, + info->sections, info->nsections); + if(r == NULL) + break; - p += sizeof(struct objc_property); - offset += sizeof(struct objc_property); - } + memset(&op, '\0', sizeof(struct objc_property)); + if(left < sizeof(struct objc_property)){ + memcpy(&op, r, left); + printf(" (objc_property entends past the end of the " + "section)\n"); + } + else + memcpy(&op, r, sizeof(struct objc_property)); + if(info->swapped) + swap_objc_property(&op, info->host_byte_sex); + + print_field_label(info, "name"); + print_field_value(offset + offsetof(struct objc_property, name), + op.name, TRUE, NULL, "\n", info, s, + &n_value, &addend); + + print_field_label(info, "attributes"); + print_field_value(offset + offsetof(struct objc_property, attributes), + op.attributes, TRUE, NULL, "\n", info, s, + &n_value, &addend); + + p += sizeof(struct objc_property); + offset += sizeof(struct objc_property); + } + + indent_pop(info); } static @@ -1673,136 +1503,179 @@ struct info *info) void *r; uint32_t offset, left; struct section_info_64 *s; - const char *name, *sym_name; uint64_t n_value; + int64_t addend; - r = get_pointer_64(p, &offset, &left, &s, - info->sections, info->nsections); - if(r == NULL) - return; - memset(&c, '\0', sizeof(struct category_t)); - if(left < sizeof(struct category_t)){ - memcpy(&c, r, left); - printf(" (category_t entends past the end of the section)\n"); - } - else - memcpy(&c, r, sizeof(struct category_t)); - if(info->swapped) - swap_category_t(&c, info->host_byte_sex); + r = get_pointer_64(p, &offset, &left, &s, + info->sections, info->nsections); + if(r == NULL) + return; - printf(" name "); - sym_name = get_symbol_64(offset + offsetof(struct category_t, name), - s->addr - info->database, c.name, s->relocs, - s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(c.name != 0) - printf(" + 0x%llx", c.name); - } - else - printf("0x%llx", c.name); - name = get_pointer_64(c.name + n_value, NULL, &left, NULL, - info->sections, info->nsections); - if(name != NULL) - printf(" %.*s", (int)left, name); - printf("\n"); + memset(&c, '\0', sizeof(struct category_t)); + if(left < sizeof(struct category_t)){ + memcpy(&c, r, left); + printf(" (category_t entends past the end of the section)\n"); + } + else + memcpy(&c, r, sizeof(struct category_t)); + if(info->swapped) + swap_category_t(&c, info->host_byte_sex); - printf(" cls "); - sym_name = get_symbol_64(offset + offsetof(struct category_t, cls), - s->addr - info->database, c.cls, s->relocs, - s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(c.cls != 0) - printf(" + 0x%llx", c.cls); - } - else - printf("0x%llx", c.cls); - printf("\n"); - if(c.cls + n_value != 0) - print_class_t(c.cls + n_value, info); + /* + * The shortest and the longest fields are: + * cls + * instanceProperties + * which is just too great. Pick a middle-length field to align this + * structure, such as "protocols" + */ + indent_push(info, sizeof("protocols") - 1); - printf(" instanceMethods "); - sym_name = get_symbol_64(offset + offsetof(struct category_t, - instanceMethods), - s->addr - info->database, c.instanceMethods, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(c.instanceMethods != 0) - printf(" + 0x%llx", c.instanceMethods); - } - else - printf("0x%llx", c.instanceMethods); - printf("\n"); - if(c.instanceMethods + n_value != 0) - print_method_list_t(c.instanceMethods + n_value, info, ""); + print_field_label(info, "name"); + print_field_value(offset + offsetof(struct category_t, name), + c.name, TRUE, NULL, "\n", info, s, &n_value, &addend); - printf(" classMethods "); - sym_name = get_symbol_64(offset + offsetof(struct category_t, - classMethods), - s->addr - info->database, c.classMethods, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(c.classMethods != 0) - printf(" + 0x%llx", c.classMethods); - } - else - printf("0x%llx", c.classMethods); - printf("\n"); - if(c.classMethods + n_value != 0) - print_method_list_t(c.classMethods + n_value, info, ""); + print_field_label(info, "cls"); + print_field_value(offset + offsetof(struct category_t, cls), + c.cls, FALSE, "(struct class_t *)", "\n", info, s, + &n_value, &addend); + if(n_value + addend != 0) { + print_class_t(n_value + addend, info); + } - printf(" protocols "); - sym_name = get_symbol_64(offset + offsetof(struct category_t, - protocols), - s->addr - info->database, c.protocols, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(c.protocols != 0) - printf(" + 0x%llx", c.protocols); - } - else - printf("0x%llx", c.protocols); - printf("\n"); - if(c.protocols + n_value != 0) - print_protocol_list_t(c.protocols + n_value, info); + print_field_label(info, "instanceMethods"); + print_field_value(offset + offsetof(struct category_t, instanceMethods), + c.instanceMethods, FALSE, "(struct method_list_t *)", + "\n", info, s, &n_value, &addend); + if(n_value + addend != 0) { + print_method_list_t(n_value + addend, info); + } - printf("instanceProperties "); - sym_name = get_symbol_64(offset + offsetof(struct category_t, - instanceProperties), - s->addr - info->database, c.instanceProperties, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(c.instanceProperties != 0) - printf(" + 0x%llx", c.instanceProperties); - } - else - printf("0x%llx", c.instanceProperties); - printf("\n"); - if(c.instanceProperties + n_value) - print_objc_property_list(c.instanceProperties + n_value, info); + print_field_label(info, "classMethods"); + print_field_value(offset + offsetof(struct category_t, classMethods), + c.classMethods, FALSE, "(struct method_list_t *)", + "\n", info, s, &n_value, &addend); + if(n_value + addend != 0) { + print_method_list_t(n_value + addend, info); + } + + print_field_label(info, "protocols"); + print_field_value(offset + offsetof(struct category_t, protocols), + c.protocols, FALSE, "(struct protocol_list_t *)", "\n", + info, s, &n_value, &addend); + if(n_value + addend != 0) { + print_protocol_list_t(n_value + addend, info); + } + + print_field_label(info, "instanceProperties"); + print_field_value(offset + offsetof(struct category_t, instanceProperties), + c.instanceProperties, FALSE, + "(struct objc_property_list *)", "\n", info, s, + &n_value, &addend); + if(n_value + addend) { + print_objc_property_list(n_value + addend, info); + } + + indent_pop(info); +} + +void +print_protocol_t(uint64_t p, + struct info *info) +{ + struct protocol_t pt; + void *r; + uint32_t offset, left; + struct section_info_64 *s; + uint64_t n_value; + int64_t addend; + + r = get_pointer_64(p, &offset, &left, &s, info->sections, info->nsections); + if(r == NULL) + return; + + memset(&pt, '\0', sizeof(struct protocol_t)); + if(left < sizeof(struct protocol_t)){ + memcpy(&pt, r, left); + printf(" (protocol_t entends past the end of the section)\n"); + } + else + memcpy(&pt, r, sizeof(struct protocol_t)); + if(info->swapped) + swap_protocol_t(&pt, info->host_byte_sex); + + /* + * The shortest and the longest fields are: + * isa + * optionalInstanceMethods + * which is just too great. Pick a middle-length field to align this + * structure, such as "protocols" + */ + indent_push(info, sizeof("protocols") - 1); + + print_field_label(info, "isa"); + print_field_value(offset + offsetof(struct protocol_t, isa), + pt.isa, TRUE, NULL, "\n", info, s, &n_value, &addend); + + print_field_label(info, "name"); + print_field_value(offset + offsetof(struct protocol_t, name), + pt.name, TRUE, NULL, "\n", info, s, &n_value, &addend); + + print_field_label(info, "protocols"); + print_field_value(offset + offsetof(struct protocol_t, protocols), + pt.protocols, FALSE, "(struct protocol_list_t *)", "\n", + info, s, &n_value, &addend); + if(n_value + addend != 0) { + print_protocol_list_t(n_value + addend, info); + } + + print_field_label(info, "instanceMethods"); + print_field_value(offset + offsetof(struct protocol_t, instanceMethods), + pt.instanceMethods, FALSE, "(struct method_list_t *)", + "\n", info, s, &n_value, &addend); + if(n_value + addend != 0) { + print_method_list_t(n_value + addend, info); + } + + print_field_label(info, "classMethods"); + print_field_value(offset + offsetof(struct protocol_t, classMethods), + pt.classMethods, FALSE, "(struct method_list_t *)", + "\n", info, s, &n_value, &addend); + if(n_value + addend != 0) { + print_method_list_t(n_value + addend, info); + } + + print_field_label(info, "optionalInstanceMethods"); + print_field_value(offset + offsetof(struct protocol_t, + optionalInstanceMethods), + pt.optionalInstanceMethods, FALSE, + "(struct method_list_t *)", "\n", info, s, + &n_value, &addend); + if(n_value + addend != 0) { + print_method_list_t(n_value + addend, info); + } + + print_field_label(info, "optionalClassMethods"); + print_field_value(offset + offsetof(struct protocol_t, + optionalClassMethods), + pt.optionalClassMethods, FALSE, + "(struct method_list_t *)", "\n", info, s, + &n_value, &addend); + if(n_value + addend != 0) { + print_method_list_t(n_value + addend, info); + } + + print_field_label(info, "instanceProperties"); + print_field_value(offset + offsetof(struct protocol_t, + instanceProperties), + pt.instanceProperties, FALSE, + "(struct objc_property_list *)", "\n", info, s, + &n_value, &addend); + + if(n_value + addend) { + print_objc_property_list(n_value + addend, info); + } + + indent_pop(info); } static @@ -1813,68 +1686,50 @@ struct info *info) { uint32_t i, left, offset; uint64_t p, n_value; + int64_t addend; struct message_ref mr; - const char *name, *sym_name; void *r; - if(s == NULL) - return; + if(s == NULL) + return; - printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname); - offset = 0; - for(i = 0; i < s->size; i += sizeof(struct message_ref)){ - p = s->addr + i; - r = get_pointer_64(p, &offset, &left, &s, - info->sections, info->nsections); - if(r == NULL) - return; - memset(&mr, '\0', sizeof(struct message_ref)); - if(left < sizeof(struct message_ref)){ - memcpy(&mr, r, left); - printf(" (message_ref entends past the end of the section)\n"); - } - else - memcpy(&mr, r, sizeof(struct message_ref)); - if(info->swapped) - swap_message_ref(&mr, info->host_byte_sex); + info->indent_level = 0; + info->indent_widths[info->indent_level] = 0; - printf(" imp "); - name = get_symbol_64(offset + offsetof(struct message_ref, imp), - s->addr - info->database, mr.imp, s->relocs, - s->nrelocs, info, &n_value); - if(n_value != 0){ - printf("0x%llx", n_value); - if(mr.imp != 0) - printf(" + 0x%llx", mr.imp); - } - else - printf("0x%llx", mr.imp); - if(name != NULL) - printf(" %s", name); - printf("\n"); + printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname); - printf(" sel "); - sym_name = get_symbol_64(offset + offsetof(struct message_ref, sel), - s->addr - info->database, mr.sel, - s->relocs, s->nrelocs, info, &n_value); - if(n_value != 0){ - if(info->Vflag && sym_name != NULL) - printf("%s", sym_name); - else - printf("0x%llx", n_value); - if(mr.sel != 0) - printf(" + 0x%llx", mr.sel); - } - else - printf("0x%llx", mr.sel); - name = get_pointer_64(mr.sel + n_value, NULL, &left, NULL, - info->sections, info->nsections); - if(name != NULL) - printf(" %.*s", (int)left, name); - printf("\n"); + indent_push(info, sizeof("imp") - 1); - offset += sizeof(struct message_ref); - } + offset = 0; + for(i = 0; i < s->size; i += sizeof(struct message_ref)){ + p = s->addr + i; + r = get_pointer_64(p, &offset, &left, &s, + info->sections, info->nsections); + if(r == NULL) + break; + + memset(&mr, '\0', sizeof(struct message_ref)); + if(left < sizeof(struct message_ref)){ + memcpy(&mr, r, left); + printf(" (message_ref entends past the end of the section)\n"); + } + else + memcpy(&mr, r, sizeof(struct message_ref)); + if(info->swapped) + swap_message_ref(&mr, info->host_byte_sex); + + print_field_label(info, "imp"); + print_field_value(offset + offsetof(struct message_ref, imp), + mr.imp, FALSE, NULL, "\n", info, s, &n_value, &addend); + + print_field_label(info, "sel"); + print_field_value(offset + offsetof(struct message_ref, sel), + mr.sel, FALSE, NULL, "\n", info, s, &n_value, &addend); + + offset += sizeof(struct message_ref); + } + + indent_pop(info); } static @@ -1888,40 +1743,60 @@ struct info *info) struct objc_image_info o; void *r; - if(s == NULL) - return; + if(s == NULL) + return; - printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname); - p = s->addr; - r = get_pointer_64(p, &offset, &left, &s, - info->sections, info->nsections); - if(r == NULL) - return; - memset(&o, '\0', sizeof(struct objc_image_info)); - if(left < sizeof(struct objc_image_info)){ - memcpy(&o, r, left); - printf(" (objc_image_info entends past the end of the section)\n"); - } - else - memcpy(&o, r, sizeof(struct objc_image_info)); - if(info->swapped) - swap_objc_image_info(&o, info->host_byte_sex); - printf(" version %u\n", o.version); - printf(" flags 0x%x", o.flags); - if(o.flags & OBJC_IMAGE_IS_REPLACEMENT) - printf(" OBJC_IMAGE_IS_REPLACEMENT"); - if(o.flags & OBJC_IMAGE_SUPPORTS_GC) - printf(" OBJC_IMAGE_SUPPORTS_GC"); - swift_version = (o.flags >> 8) & 0xff; - if(swift_version != 0){ - if(swift_version == 1) - printf(" Swift 1.0"); - else if(swift_version == 2) - printf(" Swift 1.1"); - else - printf(" unknown future Swift version (%d)", swift_version); - } - printf("\n"); + info->indent_level = 0; + info->indent_widths[info->indent_level] = 0; + + printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname); + p = s->addr; + r = get_pointer_64(p, &offset, &left, &s, + info->sections, info->nsections); + if(r == NULL) + return; + + memset(&o, '\0', sizeof(struct objc_image_info)); + if(left < sizeof(struct objc_image_info)){ + memcpy(&o, r, left); + printf(" (objc_image_info entends past the end of the section)\n"); + } + else + memcpy(&o, r, sizeof(struct objc_image_info)); + if(info->swapped) + swap_objc_image_info(&o, info->host_byte_sex); + + indent_push(info, sizeof("version") - 1); + + print_field_scalar(info, "version", "%u\n", o.version); + print_field_scalar(info, "flags", "0x%x", o.flags); + + if(o.flags & OBJC_IMAGE_IS_REPLACEMENT) + printf(" OBJC_IMAGE_IS_REPLACEMENT"); + if(o.flags & OBJC_IMAGE_SUPPORTS_GC) + printf(" OBJC_IMAGE_SUPPORTS_GC"); + swift_version = (o.flags >> 8) & 0xff; + if(swift_version != 0){ + if(swift_version == 1) + printf(" Swift 1.0"); + else if(swift_version == 2) + printf(" Swift 1.1"); + else if(swift_version == 3) + printf(" Swift 2.0"); + else if(swift_version == 4) + printf(" Swift 3.0"); + else if(swift_version == 5) + printf(" Swift 4.0"); + else if(swift_version == 6) + printf(" Swift 4.1/4.2"); + else if(swift_version == 7) + printf(" Swift 5 or later"); + else + printf(" unknown future Swift version (%d)", swift_version); + } + printf("\n"); + + indent_pop(info); } void @@ -1932,7 +1807,7 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, cpu_type_t cputype, struct nlist_64 *symbols64, uint32_t nsymbols, @@ -1946,72 +1821,89 @@ enum bool verbose) struct section_info_64 *o, cstring_section; struct objc_string_object_64 *string_objects, *s, string_object; uint64_t string_objects_addr, string_objects_size; - uint32_t size, left; + uint64_t size, left; + uint32_t left32; char *p; const char *name; - printf("Contents of (" SEG_OBJC ",%s) section\n", sectname); - info.host_byte_sex = get_host_byte_sex(); - info.swapped = info.host_byte_sex != object_byte_sex; - info.cputype = cputype; - info.symbols64 = symbols64; - info.nsymbols = nsymbols; - info.strings = strings; - info.strings_size = strings_size; - info.sorted_symbols = sorted_symbols; - info.nsorted_symbols = nsorted_symbols; - info.verbose = verbose; - get_sections_64(load_commands, ncmds, sizeofcmds, object_byte_sex, - object_addr, object_size, &info.sections, - &info.nsections, &info.database); - o = get_section_64(info.sections, info.nsections, SEG_OBJC, sectname); - if(o == NULL) - return; - get_cstring_section_64(load_commands, ncmds, sizeofcmds,object_byte_sex, - object_addr, object_size, &cstring_section); + printf("Contents of (" SEG_OBJC ",%s) section\n", sectname); + info.object_addr = object_addr; + info.object_size = object_size; + info.host_byte_sex = get_host_byte_sex(); + info.swapped = info.host_byte_sex != object_byte_sex; + info.cputype = cputype; + info.symbols64 = symbols64; + info.nsymbols = nsymbols; + info.strings = strings; + info.strings_size = strings_size; + info.sorted_symbols = sorted_symbols; + info.nsorted_symbols = nsorted_symbols; + info.verbose = verbose; + info.indent_level = 0; + info.indent_widths[info.indent_level] = 0; - string_objects = (struct objc_string_object_64 *)o->contents; - string_objects_addr = o->addr; - string_objects_size = o->size; - for(s = string_objects; - (char *)s < (char *)string_objects + string_objects_size; - s++){ + get_sections_64(load_commands, ncmds, sizeofcmds, object_byte_sex, + object_addr, object_size, &info.sections, + &info.nsections, &info.textbase, &info.database); - memset(&string_object, '\0', sizeof(struct objc_string_object_64)); - left = string_objects_size - (s - string_objects); - size = left < sizeof(struct objc_string_object_64) ? - left : sizeof(struct objc_string_object_64); - memcpy(&string_object, s, size); + o = get_section_64(info.sections, info.nsections, SEG_OBJC, sectname); + if(o == NULL) + return; - if((char *)s + sizeof(struct objc_string_object_64) > - (char *)s + string_objects_size) - printf("String Object extends past end of %s section\n", - sectname); - printf("String Object 0x%llx\n", - string_objects_addr + ((char *)s - (char *)string_objects)); + get_cstring_section_64(load_commands, ncmds, sizeofcmds,object_byte_sex, + object_addr, object_size, &cstring_section); - if(info.swapped) - swap_string_object_64(&string_object, info.host_byte_sex); - printf(" isa 0x%llx", string_object.isa); - name = get_symbol_64((uintptr_t)s - (uintptr_t)string_objects, - o->addr - info.database, string_object.isa, - o->relocs, o->nrelocs, &info, NULL); - if(name != NULL) - printf(" %s\n", name); - else - printf("\n"); - printf(" characters 0x%llx", string_object.characters); - if(verbose){ - p = get_pointer_64(string_object.characters, NULL, &left, - NULL, info.sections, info.nsections); - if(p != NULL) - printf(" %.*s\n", (int)left, p); - } - else - printf("\n"); - printf(" _length %u\n", string_object._length); - printf(" _pad %u\n", string_object._pad); - } + string_objects = (struct objc_string_object_64 *)o->contents; + string_objects_addr = o->addr; + string_objects_size = o->size; + for(s = string_objects; + (char *)s < (char *)string_objects + string_objects_size; + s++) + { + memset(&string_object, '\0', sizeof(struct objc_string_object_64)); + left = string_objects_size - (s - string_objects); + size = left < sizeof(struct objc_string_object_64) ? + left : sizeof(struct objc_string_object_64); + memcpy(&string_object, s, size); + if(info.swapped) + swap_string_object_64(&string_object, info.host_byte_sex); + + if((char *)s + sizeof(struct objc_string_object_64) > + (char *)s + string_objects_size) { + printf("String Object extends past end of %s section\n", + sectname); + } + + indent_push(&info, sizeof("characters") - 1); + + printf("String Object 0x%llx\n", + string_objects_addr + ((char *)s - (char *)string_objects)); + print_field_scalar(&info, "isa", "0x%llx", string_object.isa); + + name = get_symbol_64((uintptr_t)s - (uintptr_t)string_objects, + o->addr, info.textbase, info.database, + string_object.isa, o->relocs, o->nrelocs, + &info, NULL, NULL); + if(name != NULL) + printf(" %s\n", name); + else + printf("\n"); + + print_field_scalar(&info, "characters", "0x%llx", + string_object.characters); + if(verbose){ + p = get_pointer_64(string_object.characters, NULL, &left32, + NULL, info.sections, info.nsections); + if(p != NULL) + printf(" %.*s", (int)left32, p); + } + printf("\n"); + + print_field_scalar(&info, "_length", "%u\n", string_object._length); + print_field_scalar(&info, "_pad", "%u\n", string_object._pad); + + indent_pop(&info); + } } static @@ -2022,15 +1914,17 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct section_info_64 **sections, uint32_t *nsections, +uint64_t *textbase, uint64_t *database) { enum byte_sex host_byte_sex; - enum bool swapped, database_set, zerobased, encrypt_found, encrypt64_found; - - uint32_t i, j, left, size; + enum bool swapped, textbase_set, database_set, encrypt_found, + encrypt64_found; + uint32_t i, j; + uint64_t left, size; struct load_command lcmd, *lc; char *p; struct segment_command_64 sg64; @@ -2038,197 +1932,200 @@ uint64_t *database) struct encryption_info_command encrypt; struct encryption_info_command_64 encrypt64; - host_byte_sex = get_host_byte_sex(); - swapped = host_byte_sex != object_byte_sex; + host_byte_sex = get_host_byte_sex(); + swapped = host_byte_sex != object_byte_sex; - *sections = NULL; - *nsections = 0; - database_set = FALSE; - *database = 0; - zerobased = FALSE; - encrypt_found = FALSE; - encrypt64_found = FALSE; + *sections = NULL; + *nsections = 0; + textbase_set = FALSE; + *textbase = 0; + database_set = FALSE; + *database = 0; + encrypt_found = FALSE; + encrypt64_found = FALSE; - lc = load_commands; - for(i = 0 ; i < ncmds; i++){ - memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command)); - if(swapped) - swap_load_command(&lcmd, host_byte_sex); - if(lcmd.cmdsize % sizeof(int32_t) != 0) - printf("load command %u size not a multiple of " - "sizeof(int32_t)\n", i); - if((char *)lc + lcmd.cmdsize > - (char *)load_commands + sizeofcmds) - printf("load command %u extends past end of load " - "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + lc = load_commands; + for(i = 0 ; i < ncmds; i++){ + memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command)); + if(swapped) + swap_load_command(&lcmd, host_byte_sex); + if(lcmd.cmdsize % sizeof(int32_t) != 0) + printf("load command %u size not a multiple of " + "sizeof(int32_t)\n", i); + if((char *)lc + lcmd.cmdsize > + (char *)load_commands + sizeofcmds) + printf("load command %u extends past end of load " + "commands\n", i); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); - switch(lcmd.cmd){ - case LC_SEGMENT_64: - memset((char *)&sg64, '\0', sizeof(struct segment_command_64)); - size = left < sizeof(struct segment_command_64) ? - left : sizeof(struct segment_command_64); - memcpy((char *)&sg64, (char *)lc, size); - if(swapped) - swap_segment_command_64(&sg64, host_byte_sex); - if((sg64.initprot & VM_PROT_WRITE) == VM_PROT_WRITE && - database_set == FALSE){ - *database = sg64.vmaddr; - database_set = TRUE; - } - if((sg64.initprot & VM_PROT_READ) == VM_PROT_READ && - sg64.vmaddr == 0) - zerobased = TRUE; - p = (char *)lc + sizeof(struct segment_command_64); - for(j = 0 ; j < sg64.nsects ; j++){ - if(p + sizeof(struct section_64) > - (char *)load_commands + sizeofcmds){ - printf("section structure command extends past " - "end of load commands\n"); - } - left = sizeofcmds - (p - (char *)load_commands); - memset((char *)&s64, '\0', sizeof(struct section_64)); - size = left < sizeof(struct section_64) ? - left : sizeof(struct section_64); - memcpy((char *)&s64, p, size); - if(swapped) - swap_section_64(&s64, 1, host_byte_sex); + switch(lcmd.cmd){ + case LC_SEGMENT_64: + memset((char *)&sg64, '\0', sizeof(struct segment_command_64)); + size = left < sizeof(struct segment_command_64) ? + left : sizeof(struct segment_command_64); + memcpy((char *)&sg64, (char *)lc, size); + if(swapped) + swap_segment_command_64(&sg64, host_byte_sex); + if((sg64.initprot & VM_PROT_WRITE) == VM_PROT_WRITE && + database_set == FALSE){ + *database = sg64.vmaddr; + database_set = TRUE; + } + if((sg64.initprot & VM_PROT_READ) == VM_PROT_READ && + textbase_set == FALSE){ + *textbase = sg64.vmaddr; + textbase_set = TRUE; + } + p = (char *)lc + sizeof(struct segment_command_64); + for(j = 0 ; j < sg64.nsects ; j++){ + if(p + sizeof(struct section_64) > + (char *)load_commands + sizeofcmds){ + printf("section structure command extends past " + "end of load commands\n"); + } + left = sizeofcmds - (uint32_t)(p - (char *)load_commands); + memset((char *)&s64, '\0', sizeof(struct section_64)); + size = left < sizeof(struct section_64) ? + left : sizeof(struct section_64); + memcpy((char *)&s64, p, size); + if(swapped) + swap_section_64(&s64, 1, host_byte_sex); - *sections = reallocate(*sections, - sizeof(struct section_info_64) * (*nsections + 1)); - memcpy((*sections)[*nsections].segname, - s64.segname, 16); - memcpy((*sections)[*nsections].sectname, - s64.sectname, 16); - (*sections)[*nsections].addr = s64.addr; - (*sections)[*nsections].contents = object_addr + s64.offset; - (*sections)[*nsections].offset = s64.offset; - (*sections)[*nsections].zerofill = - (s64.flags & SECTION_TYPE) == S_ZEROFILL ? TRUE : FALSE; - if(s64.offset > object_size){ - printf("section contents of: (%.16s,%.16s) is past " - "end of file\n", s64.segname, s64.sectname); - (*sections)[*nsections].size = 0; - } - else if(s64.offset + s64.size > object_size){ - printf("part of section contents of: (%.16s,%.16s) " - "is past end of file\n", - s64.segname, s64.sectname); - (*sections)[*nsections].size = object_size - s64.offset; - } - else - (*sections)[*nsections].size = s64.size; - if(s64.reloff >= object_size){ - printf("relocation entries offset for (%.16s,%.16s)" - ": is past end of file\n", s64.segname, - s64.sectname); - (*sections)[*nsections].nrelocs = 0; - } - else{ - (*sections)[*nsections].relocs = - (struct relocation_info *)(object_addr + - s64.reloff); - if(s64.reloff + - s64.nreloc * sizeof(struct relocation_info) > - object_size){ - printf("relocation entries for section (%.16s," - "%.16s) extends past end of file\n", - s64.segname, s64.sectname); - (*sections)[*nsections].nrelocs = - (object_size - s64.reloff) / - sizeof(struct relocation_info); - } - else - (*sections)[*nsections].nrelocs = s64.nreloc; - if(swapped) - swap_relocation_info( - (*sections)[*nsections].relocs, - (*sections)[*nsections].nrelocs, - host_byte_sex); - } - if(sg64.flags & SG_PROTECTED_VERSION_1) - (*sections)[*nsections].protected = TRUE; - else - (*sections)[*nsections].protected = FALSE; - if((s64.flags & SECTION_TYPE) == S_CSTRING_LITERALS) - (*sections)[*nsections].cstring = TRUE; - else - (*sections)[*nsections].cstring = FALSE; - (*nsections)++; + *sections = reallocate(*sections, + sizeof(struct section_info_64) * (*nsections + 1)); + memcpy((*sections)[*nsections].segname, + s64.segname, 16); + memcpy((*sections)[*nsections].sectname, + s64.sectname, 16); + (*sections)[*nsections].addr = s64.addr; + (*sections)[*nsections].contents = object_addr + s64.offset; + (*sections)[*nsections].offset = s64.offset; + (*sections)[*nsections].zerofill = + (s64.flags & SECTION_TYPE) == S_ZEROFILL ? TRUE : FALSE; + if(s64.offset > object_size){ + printf("section contents of: (%.16s,%.16s) is past " + "end of file\n", s64.segname, s64.sectname); + (*sections)[*nsections].size = 0; + } + else if(s64.offset + s64.size > object_size){ + printf("part of section contents of: (%.16s,%.16s) " + "is past end of file\n", + s64.segname, s64.sectname); + (*sections)[*nsections].size = object_size - s64.offset; + } + else + (*sections)[*nsections].size = s64.size; + if(s64.reloff >= object_size){ + printf("relocation entries offset for (%.16s,%.16s)" + ": is past end of file\n", s64.segname, + s64.sectname); + (*sections)[*nsections].nrelocs = 0; + } + else{ + (*sections)[*nsections].relocs = + (struct relocation_info *)(object_addr + + s64.reloff); + if(s64.reloff + + s64.nreloc * sizeof(struct relocation_info) > + object_size){ + printf("relocation entries for section (%.16s," + "%.16s) extends past end of file\n", + s64.segname, s64.sectname); + (*sections)[*nsections].nrelocs = + (uint32_t)((object_size - s64.reloff) / + sizeof(struct relocation_info)); + } + else + (*sections)[*nsections].nrelocs = s64.nreloc; + if(swapped) + swap_relocation_info( + (*sections)[*nsections].relocs, + (*sections)[*nsections].nrelocs, + host_byte_sex); + } + if(sg64.flags & SG_PROTECTED_VERSION_1) + (*sections)[*nsections].protected = TRUE; + else + (*sections)[*nsections].protected = FALSE; + if((s64.flags & SECTION_TYPE) == S_CSTRING_LITERALS) + (*sections)[*nsections].cstring = TRUE; + else + (*sections)[*nsections].cstring = FALSE; + (*nsections)++; + + if(p + sizeof(struct section_64) > + (char *)load_commands + sizeofcmds) + break; + p += size; + } + break; + case LC_ENCRYPTION_INFO: + memset((char *)&encrypt, '\0', + sizeof(struct encryption_info_command)); + size = left < sizeof(struct encryption_info_command) ? + left : sizeof(struct encryption_info_command); + memcpy((char *)&encrypt, (char *)lc, size); + if(swapped) + swap_encryption_command(&encrypt, host_byte_sex); + encrypt_found = TRUE; + break; + case LC_ENCRYPTION_INFO_64: + memset((char *)&encrypt64, '\0', + sizeof(struct encryption_info_command_64)); + size = left < sizeof(struct encryption_info_command_64) ? + left : sizeof(struct encryption_info_command_64); + memcpy((char *)&encrypt64, (char *)lc, size); + if(swapped) + swap_encryption_command_64(&encrypt64, host_byte_sex); + encrypt64_found = TRUE; + break; + } + if(lcmd.cmdsize == 0){ + printf("load command %u size zero (can't advance to other " + "load commands)\n", i); + break; + } + lc = (struct load_command *)((char *)lc + lcmd.cmdsize); + if((char *)lc > (char *)load_commands + sizeofcmds) + break; + } - if(p + sizeof(struct section_64) > - (char *)load_commands + sizeofcmds) - break; - p += size; - } - break; - case LC_ENCRYPTION_INFO: - memset((char *)&encrypt, '\0', - sizeof(struct encryption_info_command)); - size = left < sizeof(struct encryption_info_command) ? - left : sizeof(struct encryption_info_command); - memcpy((char *)&encrypt, (char *)lc, size); - if(swapped) - swap_encryption_command(&encrypt, host_byte_sex); - encrypt_found = TRUE; - break; - case LC_ENCRYPTION_INFO_64: - memset((char *)&encrypt64, '\0', - sizeof(struct encryption_info_command_64)); - size = left < sizeof(struct encryption_info_command_64) ? - left : sizeof(struct encryption_info_command_64); - memcpy((char *)&encrypt64, (char *)lc, size); - if(swapped) - swap_encryption_command_64(&encrypt64, host_byte_sex); - encrypt64_found = TRUE; - break; - } - if(lcmd.cmdsize == 0){ - printf("load command %u size zero (can't advance to other " - "load commands)\n", i); - break; - } - lc = (struct load_command *)((char *)lc + lcmd.cmdsize); - if((char *)lc > (char *)load_commands + sizeofcmds) - break; - } - - if(encrypt_found == TRUE && encrypt.cryptid != 0){ - for(i = 0; i < *nsections; i++){ - if((*sections)[i].size > 0 && (*sections)[i].zerofill == FALSE){ - if((*sections)[i].offset > - encrypt.cryptoff + encrypt.cryptsize){ - /* section starts past encryption area */ ; - } - else if((*sections)[i].offset + (*sections)[i].size < - encrypt.cryptoff){ - /* section ends before encryption area */ ; - } - else{ - /* section has part in the encrypted area */ - (*sections)[i].protected = TRUE; - } - } - } - } - if(encrypt64_found == TRUE && encrypt64.cryptid != 0){ - for(i = 0; i < *nsections; i++){ - if((*sections)[i].size > 0 && (*sections)[i].zerofill == FALSE){ - if((*sections)[i].offset > - encrypt64.cryptoff + encrypt64.cryptsize){ - /* section starts past encryption area */ ; - } - else if((*sections)[i].offset + (*sections)[i].size < - encrypt64.cryptoff){ - /* section ends before encryption area */ ; - } - else{ - /* section has part in the encrypted area */ - (*sections)[i].protected = TRUE; - } - } - } - } + if(encrypt_found == TRUE && encrypt.cryptid != 0){ + for(i = 0; i < *nsections; i++){ + if((*sections)[i].size > 0 && (*sections)[i].zerofill == FALSE){ + if((*sections)[i].offset > + encrypt.cryptoff + encrypt.cryptsize){ + /* section starts past encryption area */ ; + } + else if((*sections)[i].offset + (*sections)[i].size < + encrypt.cryptoff){ + /* section ends before encryption area */ ; + } + else{ + /* section has part in the encrypted area */ + (*sections)[i].protected = TRUE; + } + } + } + } + if(encrypt64_found == TRUE && encrypt64.cryptid != 0){ + for(i = 0; i < *nsections; i++){ + if((*sections)[i].size > 0 && (*sections)[i].zerofill == FALSE){ + if((*sections)[i].offset > + encrypt64.cryptoff + encrypt64.cryptsize){ + /* section starts past encryption area */ ; + } + else if((*sections)[i].offset + (*sections)[i].size < + encrypt64.cryptoff){ + /* section ends before encryption area */ ; + } + else{ + /* section has part in the encrypted area */ + (*sections)[i].protected = TRUE; + } + } + } + } } static @@ -2240,14 +2137,14 @@ char *segname, char *sectname) { uint32_t i; - - for(i = 0; i < nsections; i++){ - if(strncmp(sections[i].segname, segname, 16) == 0 && - strncmp(sections[i].sectname, sectname, 16) == 0){ - return(sections + i); - } - } - return(NULL); + + for(i = 0; i < nsections; i++){ + if(strncmp(sections[i].segname, segname, 16) == 0 && + strncmp(sections[i].sectname, sectname, 16) == 0){ + return(sections + i); + } + } + return(NULL); } static @@ -2258,102 +2155,103 @@ uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, -uint32_t object_size, +uint64_t object_size, struct section_info_64 *cstring_section) { enum byte_sex host_byte_sex; enum bool swapped; - uint32_t i, j, left, size; + uint32_t i, j; + uint64_t left, size; struct load_command lcmd, *lc; char *p; struct segment_command_64 sg64; struct section_64 s64; - host_byte_sex = get_host_byte_sex(); - swapped = host_byte_sex != object_byte_sex; + host_byte_sex = get_host_byte_sex(); + swapped = host_byte_sex != object_byte_sex; - memset(cstring_section, '\0', sizeof(struct section_info_64)); + memset(cstring_section, '\0', sizeof(struct section_info_64)); - lc = load_commands; - for(i = 0 ; i < ncmds; i++){ - memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command)); - if(swapped) - swap_load_command(&lcmd, host_byte_sex); - if(lcmd.cmdsize % sizeof(int32_t) != 0) - printf("load command %u size not a multiple of " - "sizeof(int32_t)\n", i); - if((char *)lc + lcmd.cmdsize > - (char *)load_commands + sizeofcmds) - printf("load command %u extends past end of load " - "commands\n", i); - left = sizeofcmds - ((char *)lc - (char *)load_commands); + lc = load_commands; + for(i = 0 ; i < ncmds; i++){ + memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command)); + if(swapped) + swap_load_command(&lcmd, host_byte_sex); + if(lcmd.cmdsize % sizeof(int32_t) != 0) + printf("load command %u size not a multiple of " + "sizeof(int32_t)\n", i); + if((char *)lc + lcmd.cmdsize > + (char *)load_commands + sizeofcmds) + printf("load command %u extends past end of load " + "commands\n", i); + left = sizeofcmds - (uint32_t)((char *)lc - (char *)load_commands); - switch(lcmd.cmd){ - case LC_SEGMENT_64: - memset((char *)&sg64, '\0', sizeof(struct segment_command_64)); - size = left < sizeof(struct segment_command_64) ? - left : sizeof(struct segment_command_64); - memcpy((char *)&sg64, (char *)lc, size); - if(swapped) - swap_segment_command_64(&sg64, host_byte_sex); + switch(lcmd.cmd){ + case LC_SEGMENT_64: + memset((char *)&sg64, '\0', sizeof(struct segment_command_64)); + size = left < sizeof(struct segment_command_64) ? + left : sizeof(struct segment_command_64); + memcpy((char *)&sg64, (char *)lc, size); + if(swapped) + swap_segment_command_64(&sg64, host_byte_sex); + + p = (char *)lc + sizeof(struct segment_command_64); + for(j = 0 ; j < sg64.nsects ; j++){ + if(p + sizeof(struct section_64) > + (char *)load_commands + sizeofcmds){ + printf("section structure command extends past " + "end of load commands\n"); + } + left = sizeofcmds - (uint32_t)(p - (char *)load_commands); + memset((char *)&s64, '\0', sizeof(struct section_64)); + size = left < sizeof(struct section_64) ? + left : sizeof(struct section_64); + memcpy((char *)&s64, p, size); + if(swapped) + swap_section_64(&s64, 1, host_byte_sex); - p = (char *)lc + sizeof(struct segment_command_64); - for(j = 0 ; j < sg64.nsects ; j++){ - if(p + sizeof(struct section_64) > - (char *)load_commands + sizeofcmds){ - printf("section structure command extends past " - "end of load commands\n"); - } - left = sizeofcmds - (p - (char *)load_commands); - memset((char *)&s64, '\0', sizeof(struct section_64)); - size = left < sizeof(struct section_64) ? - left : sizeof(struct section_64); - memcpy((char *)&s64, p, size); - if(swapped) - swap_section_64(&s64, 1, host_byte_sex); - - if(strcmp(s64.segname, SEG_TEXT) == 0 && - strcmp(s64.sectname, "__cstring") == 0){ - cstring_section->addr = s64.addr; - cstring_section->contents = object_addr + s64.offset; - if(s64.offset > object_size){ - printf("section contents of: (%.16s,%.16s) is past " - "end of file\n", s64.segname, s64.sectname); - cstring_section->size = 0; - } - else if(s64.offset + s64.size > object_size){ - printf("part of section contents of: (%.16s,%.16s) " - "is past end of file\n", - s64.segname, s64.sectname); - cstring_section->size = object_size - s64.offset; - } - else - cstring_section->size = s64.size; - if(sg64.flags & SG_PROTECTED_VERSION_1) - cstring_section->protected = TRUE; - else - cstring_section->protected = FALSE; - cstring_section->cstring = TRUE; - return; - } - - if(p + sizeof(struct section) > - (char *)load_commands + sizeofcmds) - break; - p += size; - } - break; - } - if(lcmd.cmdsize == 0){ - printf("load command %u size zero (can't advance to other " - "load commands)\n", i); - break; - } - lc = (struct load_command *)((char *)lc + lcmd.cmdsize); - if((char *)lc > (char *)load_commands + sizeofcmds) - break; - } + if(strcmp(s64.segname, SEG_TEXT) == 0 && + strcmp(s64.sectname, "__cstring") == 0){ + cstring_section->addr = s64.addr; + cstring_section->contents = object_addr + s64.offset; + if(s64.offset > object_size){ + printf("section contents of: (%.16s,%.16s) is past " + "end of file\n", s64.segname, s64.sectname); + cstring_section->size = 0; + } + else if(s64.offset + s64.size > object_size){ + printf("part of section contents of: (%.16s,%.16s) " + "is past end of file\n", + s64.segname, s64.sectname); + cstring_section->size = object_size - s64.offset; + } + else + cstring_section->size = s64.size; + if(sg64.flags & SG_PROTECTED_VERSION_1) + cstring_section->protected = TRUE; + else + cstring_section->protected = FALSE; + cstring_section->cstring = TRUE; + return; + } + + if(p + sizeof(struct section) > + (char *)load_commands + sizeofcmds) + break; + p += size; + } + break; + } + if(lcmd.cmdsize == 0){ + printf("load command %u size zero (can't advance to other " + "load commands)\n", i); + break; + } + lc = (struct load_command *)((char *)lc + lcmd.cmdsize); + if((char *)lc > (char *)load_commands + sizeofcmds) + break; + } } static @@ -2369,97 +2267,388 @@ uint32_t nsections) void *r; uint64_t addr; uint32_t i; - - addr = p; - for(i = 0; i < nsections; i++){ - if(addr >= sections[i].addr && - addr < sections[i].addr + sections[i].size){ - if(s != NULL) - *s = sections + i; - if(offset != NULL) - *offset = addr - sections[i].addr; - if(left != NULL) - *left = sections[i].size - (addr - sections[i].addr); - if(sections[i].protected == TRUE && sections[i].cstring == TRUE) - r = "some string from a protected section"; - else - r = sections[i].contents + (addr - sections[i].addr); - return(r); - } - } - if(s != NULL) - *s = NULL; - if(offset != NULL) - *offset = 0; - if(left != NULL) - *left = 0; - return(NULL); + + addr = p; + for(i = 0; i < nsections; i++){ + if(addr >= sections[i].addr && + addr < sections[i].addr + sections[i].size){ + if(s != NULL) + *s = sections + i; + if(offset != NULL) + *offset = (uint32_t)(addr - sections[i].addr); + if(left != NULL) + *left = (uint32_t)(sections[i].size - (addr-sections[i].addr)); + if(sections[i].protected == TRUE && sections[i].cstring == TRUE) + r = "some string from a protected section"; + else + r = sections[i].contents + (addr - sections[i].addr); + return(r); + } + } + if(s != NULL) + *s = NULL; + if(offset != NULL) + *offset = 0; + if(left != NULL) + *left = 0; + return(NULL); } /* * get_symbol_64() returns the name of a symbol (or NULL). Based on the - * relocation information at the specified section offset or the value. + * relocation information at the specified section offset, address and database + * or the (pointer) value. It indirectly returns the symbol's value through + * *n_value and the relocation's addend through *addend. Since the later values + * are needed to walk the pointers it is up to the caller to check the + * info->verbose flag to print the name or the *n_value + *addend or raw + * pointer value. */ static const char * get_symbol_64( -uint32_t sect_offset, -uint64_t database_offset, +uint64_t sect_offset, +uint64_t sect_addr, +uint64_t textbase, +uint64_t database, uint64_t value, struct relocation_info *relocs, uint32_t nrelocs, struct info *info, -uint64_t *n_value) +uint64_t *n_value, +int64_t *addend) { uint32_t i; unsigned int r_symbolnum; uint32_t n_strx; + const char *name; + enum bool has_auth; - if(n_value != NULL) - *n_value = 0; + if(n_value != NULL) + *n_value = 0; + if(addend != NULL) + *addend = value; + has_auth = FALSE; - if(info->verbose == FALSE) - return(NULL); + /* + * In the info->verbose == FALSE case we can't simply return now as for + * the ThreadedRebaseBind case we need to return the real pointer value + * in "n_value + addend" without the bits from the ThreadedRebaseBind. + * To do this we need look through the bind entries or in the rebase + * case move the original pointer value masked with the right bits off + * into n_value and zero out the addend so the caller can get the real + * pointer value from n_value + addend and indirect through that. + * The caller now has to check info->verbose == FALSE to print the + * original pointer but use the n_value + addend to follow the pointer. + */ - for(i = 0; i < nrelocs; i++){ - if((uint32_t)relocs[i].r_address == sect_offset){ - r_symbolnum = relocs[i].r_symbolnum; - if(relocs[i].r_extern){ - if(r_symbolnum >= info->nsymbols) - break; - n_strx = info->symbols64[r_symbolnum].n_un.n_strx; - if(n_strx <= 0 || n_strx >= info->strings_size) - break; - if(n_value != NULL) - *n_value = info->symbols64[r_symbolnum].n_value; - return(info->strings + n_strx); - } - break; - } - if(reloc_has_pair(info->cputype, relocs[i].r_type) == TRUE) - i++; - } - for(i = 0; i < info->next_relocs; i++){ - if((uint32_t)info->ext_relocs[i].r_address == - database_offset + sect_offset){ - r_symbolnum = info->ext_relocs[i].r_symbolnum; - if(info->ext_relocs[i].r_extern){ - if(r_symbolnum >= info->nsymbols) - break; - n_strx = info->symbols64[r_symbolnum].n_un.n_strx; - if(n_strx <= 0 || n_strx >= info->strings_size) - break; - if(n_value != NULL) - *n_value = info->symbols64[r_symbolnum].n_value; - return(info->strings + n_strx); - } - break; - } - if(reloc_has_pair(info->cputype, info->ext_relocs[i].r_type) ==TRUE) - i++; - } - if(value == 0) - return(NULL); - return(guess_symbol(value, info->sorted_symbols, info->nsorted_symbols, - info->verbose)); + /* + * First look in section's relocation entries if it has them which is + * the .o file case to find the name, n_value and added. + */ + for(i = 0; i < nrelocs; i++){ + if((uint32_t)relocs[i].r_address == sect_offset){ + r_symbolnum = relocs[i].r_symbolnum; + if(relocs[i].r_extern){ + if(r_symbolnum >= info->nsymbols) + break; + n_strx = info->symbols64[r_symbolnum].n_un.n_strx; + if(n_strx <= 0 || n_strx >= info->strings_size) + break; + /* + * If this is arm64e and if r_type is a + * ARM64_RELOC_AUTHENTICATED_POINTER we need to adjust + * addend to just the low 32-bits (signed) of the pointer + * value. + */ + if(info->cputype == CPU_TYPE_ARM64 && + info->cpusubtype == CPU_SUBTYPE_ARM64E && + relocs[i].r_type == ARM64_RELOC_AUTHENTICATED_POINTER){ + if(addend != NULL){ + *addend = 0xffffffffULL & value; + if((*addend & 0x80000000ULL) != 0) + *addend |= 0xffffffff00000000ULL; + } + } + if(n_value != NULL) + *n_value = info->symbols64[r_symbolnum].n_value; + return(info->strings + n_strx); + } + break; + } + if(reloc_has_pair(info->cputype, relocs[i].r_type) == TRUE) + i++; + } + + /* + * Next look in external relocation entries of if it has them which is + * the original dyld image case to find the name, n_value and added. + */ + for(i = 0; i < info->next_relocs; i++){ + if((uint32_t)info->ext_relocs[i].r_address == + database + sect_offset){ + r_symbolnum = info->ext_relocs[i].r_symbolnum; + if(info->ext_relocs[i].r_extern){ + if(r_symbolnum >= info->nsymbols) + break; + n_strx = info->symbols64[r_symbolnum].n_un.n_strx; + if(n_strx <= 0 || n_strx >= info->strings_size) + break; + if(n_value != NULL) + *n_value = info->symbols64[r_symbolnum].n_value; + return(info->strings + n_strx); + } + break; + } + if(reloc_has_pair(info->cputype, info->ext_relocs[i].r_type) ==TRUE) + i++; + } + + /* + * Lastly look in the dyld bind entries if it has them which is + * the modern fully linked dyld image case to find the name and added. + */ + name = get_dyld_bind_info_symbolname(sect_addr + sect_offset, + info->dbi, info->ndbi, + info->chain_format, addend); + /* + * If we find a bind entry we return the name which may not be printed + * if not in verbose mode. But we needed to make the call above to + * get the correct addend if info->ThreadedRebaseBind was true. + */ + if(name != NULL) + return(name); + + /* + * Fully linked modern images for dyld get will get here if it is has + * a rebase entry, and the pointer value in "value" would be what this + * pointer is pointing to in this image normally. + * + * But if info->ThreadedRebaseBind is true, to get the correct pointer + * value we need to know to mask off the upper bits and only keep the + * low 51-bits. + */ + /* + * Unless this is arm64e we have to look for the high authenticated bit + * to know to use only the low 32-bits as the pointer value. + */ + /* So at this point, we set n_value as the masked pointer value + * and zero as the addend for return or the value to call guess_symbol() + * with for a guess at which symbol has this address. + */ + value = get_chained_rebase_value(value, info->chain_format, &has_auth); + if(n_value != NULL) + *n_value = value; + if(addend != NULL) + *addend = 0; + + /* + * We don't guess for symbol values of zero as it is wrong most of the + * time. + */ + if(value == 0) + return(NULL); + + /* + * Remember that authenticated Threaded Rebase Value is a relative + * vmaddr to the start of text. So a symbol may be encoded as 0x7d70 + * when it really represents 0x0000000100007d70. So we need to add the + * start of text to "value" before guessing the symbol name. + * + * Also note that we're returning the raw, unadjusted value in *n_value + * so that otool continues to print the bits as they are ... + */ + if(info->chain_format && has_auth == TRUE){ + value += textbase; + } + + return(guess_symbol(value, info->sorted_symbols, info->nsorted_symbols, + info->verbose)); +} + +/* + * print_field_scalar() prints a label followed by a formatted value. the label + * is idented to fit within the info's indent state. + */ +static +void +print_field_scalar( +struct info *info, +const char* label, +const char* fmt, +...) +{ + /* print the label */ + print_field_label(info, label); + + /* print the data, if any */ + if (fmt) { + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + } +} + +/* + * print_field_label() prints a formatted label. the label is indented to fit + * within the info's indent state. A single space character will follow the + * label so that the next value can simply be printed. + */ +static +void +print_field_label( +struct info *info, +const char* label, +...) +{ + va_list ap; + int width = 0; + uint32_t label_indent; + uint32_t label_width; + + /* get the current label field width from the indent state */ + label_indent = info->indent_level * 4; +#if 1 + /* + * use the curent indent width. if the indent level is too deep, just print + * the value immediately after the label. + */ + label_width = (info->indent_level < MAXINDENT ? + info->indent_widths[info->indent_level] : 0); +#else + /* + * use the current indent width unless that would cause the value at this + * level to print to the left of the previous value. In practice, we need + * to loop over all the indent widths, compute the right edge of the label + * field, and use the largest such value. + */ + uint32_t right = 0; + for (uint32_t i = 0; i < MAXINDENT; ++i) { + if (i > info->indent_level) + break; + + uint32_t r = i * 4 + info->indent_widths[i]; + if (r > right) + right = r; + } + label_width = right - label_indent; +#endif + + /* measure the width of the string data */ + va_start(ap, label); + if (label) { + width = vsnprintf(NULL, 0, label, ap); + } + va_end(ap); + + /* adjust the width to represent the space following the label */ + width = width < label_width ? label_width - width : 0; + + /* print the indent spaces */ + printf("%*s", label_indent, ""); + + /* print the label */ + if (label) { + va_start(ap, label); + vprintf(label, ap); + va_end(ap); + } + + /* print right padding */ + printf("%*s", width + 1, ""); +} + +/* + * print_field_value() prints the following information: + * + * ( pointer | n_value [ + addend ] [symbol]) [data] [type] [suffix] + * + * pointer - the raw pointer on disk, only displaying when -v is not specified. + * n_value - the adjusted pointer view, correcting for chained-fixups and + * authenticated pointers. + * symbol - the symbol name corresponding to pointer + * data - C-string data within the file pointed to by the n_value / addend. + * type - an optional C-string that is printed only if supplied and if + * n_value + addend != 0. + * suffix - an optional C-string that prints after the other field elements, + * often used to print a newline. + * + * print_field_value usually follows a call to print_field_label, but this is + * not required. + */ +static +void +print_field_value( +uint64_t offset, +uint64_t p, +enum bool print_data, +const char* type_name, +const char* suffix, +struct info *info, +struct section_info_64 *s, +uint64_t *out_n_value, +int64_t *out_addend) +{ + uint64_t n_value; + int64_t addend; + const char* sym_name; + + /* read the symbol name, n_value, and addend. */ + sym_name = get_symbol_64(offset, s->addr, info->textbase, info->database, + p, s->relocs, s->nrelocs, info, &n_value, &addend); + + /* print the numeric pointer value */ + if (info->verbose) { + printf("0x%llx", n_value); + if (addend) + printf(" + 0x%llx", addend); + if (sym_name) + printf(" %s", sym_name); + } + else { + printf("0x%llx", p); + } + + /* print the pointer data if any, if requested */ + if (info->verbose && print_data) { + const char* ptr_data; + ptr_data = get_pointer_64(n_value + addend, NULL, NULL, NULL, + info->sections, info->nsections); + if (ptr_data) + printf(" %s", ptr_data); + } + +#if 0 + if (info->verbose && type_name && (n_value + addend > 0)) { + printf(" %s", type_name); + } +#endif + + /* print the suffix field */ + if (suffix) + printf("%s", suffix); + + /* return the n_value and addend */ + if (out_n_value) + *out_n_value = n_value; + if (out_addend) + *out_addend = addend; +} + +void +indent_push( +struct info *info, +uint32_t width) +{ + info->indent_level += 1; + if (info->indent_level < MAXINDENT) + info->indent_widths[info->indent_level] = width; +} + +void +indent_pop( +struct info *info) +{ + if (info->indent_level) + info->indent_level -= 1; } diff --git a/cctools/otool/sparc_disasm.c b/cctools/otool/sparc_disasm.c index 0a1e297..933d2d6 100644 --- a/cctools/otool/sparc_disasm.c +++ b/cctools/otool/sparc_disasm.c @@ -29,6 +29,7 @@ * @APPLE_LICENSE_HEADER_END@ */ #include +#include #include #include #include @@ -41,9 +42,6 @@ #include "ofile_print.h" #include "../as/sparc-opcode.h" -#define DEBUG - - /* Sign-extend a value which is N bits long. */ #define SEX(value, bits) \ ((((int)(value)) << ((8 * sizeof (int)) - bits)) \ @@ -153,8 +151,7 @@ union sparc_insn strings_size, verbose) static int opcodes_sorted = 0; -extern void qsort(); -static int compare_opcodes (); +static int compare_opcodes (const void* a, const void* b); #ifdef NOT_USED /* Nonzero if INSN is the opcode for a delayed branch. */ @@ -809,7 +806,7 @@ enum bool verbose) static int compare_opcodes (a, b) - char *a, *b; + const void *a, *b; { struct sparc_opcode *op0 = (struct sparc_opcode *) a; struct sparc_opcode *op1 = (struct sparc_opcode *) b; @@ -882,7 +879,7 @@ compare_opcodes (a, b) /* Fewer arguments are preferred. */ { - int length_diff = strlen (op0->args) - strlen (op1->args); + int length_diff = (int)(strlen(op0->args)) - ((int)strlen(op1->args)); if (length_diff != 0) /* Put the one with fewer arguments first. */ return length_diff; diff --git a/tools/create_cctools_merge_patch.sh b/tools/create_cctools_merge_patch.sh index 37c30b6..608c8ad 100755 --- a/tools/create_cctools_merge_patch.sh +++ b/tools/create_cctools_merge_patch.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash -BASE_VERSION=877.8 -NEW_VERSION=886 +BASE_VERSION=927.0.2 +NEW_VERSION=949.0.1 set -e @@ -15,6 +15,7 @@ wget http://www.opensource.apple.com/tarballs/cctools/cctools-$NEW_VERSION.tar.g tar xzf cctools-$BASE_VERSION* &>/dev/null tar xzf cctools-$NEW_VERSION* &>/dev/null +rm *.tar.gz pushd cctools-$NEW_VERSION* diff --git a/tools/create_ld64_merge_patch.sh b/tools/create_ld64_merge_patch.sh index bc9acf0..c4be7d8 100755 --- a/tools/create_ld64_merge_patch.sh +++ b/tools/create_ld64_merge_patch.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash -BASE_VERSION=253.9 -NEW_VERSION=264.3.102 +BASE_VERSION=450.3 +NEW_VERSION=512.4 set -e @@ -15,6 +15,7 @@ wget http://www.opensource.apple.com/tarballs/ld64/ld64-$NEW_VERSION.tar.gz tar xzf ld64-$BASE_VERSION.tar.gz &>/dev/null tar xzf ld64-$NEW_VERSION.tar.gz &>/dev/null +rm *.tar.gz pushd ld64-$NEW_VERSION* diff --git a/tools/fix_liblto.sh b/tools/fix_liblto.sh index 6cb05e8..02e6efc 100755 --- a/tools/fix_liblto.sh +++ b/tools/fix_liblto.sh @@ -30,8 +30,25 @@ if [ -n "$V" ]; then exit 1 fi +if readelf -p .comment $LIBDIR/libLTO.so | grep clang &>/dev/null; then + CC=clang + CXX=clang++ +else + CC=gcc + CXX=g++ +fi + + VERSION=$($LLVM_CONFIG --version | awk -F \. {'print $1$2'} | sed 's/svn//g') +if [ $VERSION -le 39 ]; then + BRANCH=$($LLVM_CONFIG --version| tr '.' ' ' | awk '{print $1, $2}' | tr ' ' '.') +else + BRANCH=$($LLVM_CONFIG --version| tr '.' ' ' | awk '{print $1}' | tr ' ' '.') +fi + +BRANCH+=".x" + if [ $VERSION -lt 34 ]; then echo "This tool requires LLVM 3.4 or later." 1>&2 exit 1 @@ -45,14 +62,27 @@ if [ $VERSION -ge 35 ]; then SYSLIBS+=" -ledit" fi +echo "int main(){Z3_mk_config();} " | \ + $CC -Wno-implicit-function-declaration -o /dev/null -xc - -lz3 + +if [ $? -eq 0 ]; then + SYSLIBS+=" -lz3" +fi + + set -e + TMP=$(mktemp -d) -set +e pushd $TMP &>/dev/null -wget https://raw.githubusercontent.com/llvm-mirror/llvm/release_$VERSION/tools/lto/lto.cpp -wget https://raw.githubusercontent.com/llvm-mirror/llvm/release_$VERSION/tools/lto/LTODisassembler.cpp -wget https://raw.githubusercontent.com/llvm-mirror/llvm/release_$VERSION/tools/lto/lto.exports + +function download_sources() { + wget https://raw.githubusercontent.com/llvm/llvm-project/$1/llvm/tools/lto/lto.cpp + wget https://raw.githubusercontent.com/llvm/llvm-project/$1/llvm/tools/lto/LTODisassembler.cpp + wget https://raw.githubusercontent.com/llvm/llvm-project/$1/llvm/tools/lto/lto.exports +} + +download_sources "release/$BRANCH" || download_sources "master" echo "{" > lto.ls echo " global:" >> lto.ls @@ -66,8 +96,8 @@ popd &>/dev/null set -x -clang++ -shared \ - -L$LIBDIR -I$INCDIR -Wl,--whole-archive $LIBS -Wl,--no-whole-archive $SYSLIBS \ +$CXX -shared \ + -L$LIBDIR -I$INCDIR -Wl,--whole-archive $LIBS -Wl,--no-whole-archive $SYSLIBS \ $CXXFLAGS $TMP/lto.cpp $TMP/LTODisassembler.cpp -Wl,-version-script,$TMP/lto.ls \ -Wl,-no-undefined -fno-rtti -fPIC -o libLTO.so diff --git a/usage_examples/ios_toolchain/README b/usage_examples/ios_toolchain/README index fc85462..4752a80 100644 --- a/usage_examples/ios_toolchain/README +++ b/usage_examples/ios_toolchain/README @@ -1,6 +1,8 @@ PREREQUISITES: -See cctools/ld64 README + libssl-dev, git, bash and a jailbroken iOS device +See cctools/ld64 README + libssl-dev, git, bash, cmake and a jailbroken iOS device + +-------------------------------------------------------------------------------- USAGE: @@ -26,3 +28,32 @@ For example: export IPHONEOS_DEPLOYMENT_TARGET=5.0 will target iOS 5.0. + +-------------------------------------------------------------------------------- + +ISSUES: + +ISSUE: clang: error: invalid version number in '-miphoneos-version-min=10.2' +SOLUTION: Targeting iOS >= 10.0 requires Clang >= 4.0. + +-------------------------------------------------------------------------------- + +PACKAGING THE SDK: + +Ensure you have read and understood the Xcode license terms before continuing. +=> https://www.apple.com/legal/sla/docs/xcode.pdf + +Packaging recents SDKs requires Mac OS Sierra. + +Download Xcode 8.2.1 and extract its content. Then issue the following commands: + +SDK=$(ls -l Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs | grep " -> iPhoneOS.sdk" | head -n1 | awk '{print $9}') +cp -r Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk /tmp/$SDK 1>/dev/null +cp -r Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1 /tmp/$SDK/usr/include/c++ 1>/dev/null +pushd /tmp +tar -cvzf $SDK.tar.gz $SDK +rm -rf $SDK +mv $SDK.tar.gz ~ +popd + +The SDK should be now in your home directory. diff --git a/usage_examples/ios_toolchain/build.sh b/usage_examples/ios_toolchain/build.sh index a823fa3..bb78112 100755 --- a/usage_examples/ios_toolchain/build.sh +++ b/usage_examples/ios_toolchain/build.sh @@ -4,6 +4,12 @@ export LC_ALL=C pushd "${0%/*}" &>/dev/null PLATFORM=$(uname -s) +OPERATING_SYSTEM=$(uname -o || echo "-") + +if [ $OPERATING_SYSTEM == "Android" ]; then + export CC="clang -D__ANDROID_API__=26" + export CXX="clang++ -D__ANDROID_API__=26" +fi if [ -z "$LLVM_DSYMUTIL" ]; then LLVM_DSYMUTIL=llvm-dsymutil @@ -43,6 +49,38 @@ function extract() esac } +function git_clone_repository +{ + local url=$1 + local branch=$2 + local directory + + directory=$(basename $url) + directory=${directory/\.git/} + + if [ -n "$CCTOOLS_IOS_DEV" ]; then + rm -rf $directory + cp -r $CCTOOLS_IOS_DEV/$directory . + return + fi + + if [ ! -d $directory ]; then + local args="" + test "$branch" = "master" && args="--depth 1" + git clone $url $args + fi + + pushd $directory &>/dev/null + + git reset --hard + git clean -fdx + git checkout $branch + git pull origin $branch + + popd &>/dev/null +} + + if [ $# -lt 2 ]; then echo "usage: $0 iPhoneOS.sdk.tar* " 1>&2 echo "i.e. $0 /path/to/iPhoneOS.sdk.tar.xz armv7" 1>&2 @@ -67,7 +105,10 @@ echo "*** extracting SDK ***" echo "" pushd $SDKDIR &>/dev/null -SDK_VERSION=$(echo $1 | grep -P -o "[0-9].[0-9]+" | head -1) +SDK_VERSION=$(echo $1 | grep -P -o "[0-9][0-9].[0-9]+" | head -1) +if [ -z "$SDK_VERSION" ]; then + SDK_VERSION=$(echo $1 | grep -P -o "[0-9].[0-9]+" | head -1) +fi if [ -z "$SDK_VERSION" ]; then echo "iPhoneOS Version must be in the SDK filename!" 1>&2 exit 1 @@ -78,10 +119,11 @@ if [ -z "$SYSLIB" ]; then echo "SDK should contain libSystem{.dylib,.tbd}" 1>&2 exit 1 fi -SYSROOT="$(dirname $SYSLIB)/../.." -set +e -mv $SYSROOT/* $SDKDIR 2>/dev/null -set -e +WRAPPER_SDKDIR=$(echo iPhoneOS*sdk | head -n1) +if [ -z "$WRAPPER_SDKDIR" ]; then + echo "broken SDK" 1>&2 + exit 1 +fi popd &>/dev/null echo "" @@ -95,7 +137,7 @@ which $LLVM_DSYMUTIL &>/dev/null if [ $? -eq 0 ]; then case $($LLVM_DSYMUTIL --version | \ grep "LLVM version" | head -1 | awk '{print $3}') in - 3.8*|3.9*|4.0*) OK=1 ;; + 3.8*|3.9*|4.0*|5.0*|6.0*|7.0*|8.0*|9.0*) OK=1 ;; esac fi set -e @@ -105,11 +147,12 @@ if [ $OK -eq 1 ]; then pushd $TARGETDIR/bin &>/dev/null ln -sf $TRIPLE-lipo lipo popd &>/dev/null -else +elif ! which dsymutil &>/dev/null; then echo "int main(){return 0;}" | cc -xc -O2 -o $TARGETDIR/bin/dsymutil - fi verbose_cmd cc -O2 -Wall -Wextra -pedantic wrapper.c \ + -DSDK_DIR=\"\\\"$WRAPPER_SDKDIR\\\"\" \ -DTARGET_CPU=\"\\\"$2\\\"\" \ -DOS_VER_MIN=\"\\\"$SDK_VERSION\\\"\" \ -o $TARGETDIR/bin/$TRIPLE-clang @@ -123,24 +166,42 @@ echo "*** building ldid ***" echo "" rm -rf tmp + mkdir -p tmp pushd tmp &>/dev/null -git clone https://github.com/tpoechtrager/ldid.git +git_clone_repository https://github.com/tpoechtrager/ldid.git master pushd ldid &>/dev/null make INSTALLPREFIX=$TARGETDIR -j$JOBS install popd &>/dev/null popd &>/dev/null +echo "" +echo "*** building apple-libtapi ***" +echo "" + +pushd tmp &>/dev/null +git_clone_repository https://github.com/tpoechtrager/apple-libtapi.git 1000.10.8 +pushd apple-libtapi &>/dev/null +INSTALLPREFIX=$TARGETDIR ./build.sh +./install.sh +popd &>/dev/null +popd &>/dev/null + echo "" echo "*** building cctools / ld64 ***" echo "" pushd ../../cctools &>/dev/null -git clean -fdx . &>/dev/null || true -./autogen.sh -./configure --target=$TRIPLE --prefix=$TARGETDIR +git clean -fdx &>/dev/null || true +popd &>/dev/null + +pushd tmp &>/dev/null +mkdir -p cctools +pushd cctools &>/dev/null +../../../../cctools/configure --target=$TRIPLE --prefix=$TARGETDIR --with-libtapi=$TARGETDIR make -j$JOBS && make install popd &>/dev/null +popd &>/dev/null echo "" echo "*** checking toolchain ***" diff --git a/usage_examples/ios_toolchain/wrapper.c b/usage_examples/ios_toolchain/wrapper.c index 9f19e56..4d1bbf5 100644 --- a/usage_examples/ios_toolchain/wrapper.c +++ b/usage_examples/ios_toolchain/wrapper.c @@ -6,6 +6,10 @@ #define OS_VER_MIN "4.2" #endif +#ifndef SDK_DIR +#define SDK_DIR "" +#endif + #define _GNU_SOURCE #include @@ -57,23 +61,29 @@ char *get_executable_path(char *epath, size_t buflen) if (sysctl(mib, 4, argv, &len, NULL, 0) < 0) abort(); comm = argv[0]; - if (*comm == '/' || *comm == '.') { + if (*comm == '/' || *comm == '.') + { char *rpath; - if ((rpath = realpath(comm, NULL))) { - strlcpy(epath, rpath, buflen); - free(rpath); - ok = 1; + if ((rpath = realpath(comm, NULL))) + { + strlcpy(epath, rpath, buflen); + free(rpath); + ok = 1; } - } else { + } + else + { char *sp; char *xpath = strdup(getenv("PATH")); char *path = strtok_r(xpath, ":", &sp); struct stat st; if (!xpath) abort(); - while (path) { + while (path) + { snprintf(epath, buflen, "%s/%s", path, comm); - if (!stat(epath, &st) && (st.st_mode & S_IXUSR)) { + if (!stat(epath, &st) && (st.st_mode & S_IXUSR)) + { ok = 1; break; } @@ -137,7 +147,7 @@ int main(int argc, char *argv[]) target_info(argv, &target, &compiler); if (!get_executable_path(execpath, sizeof(execpath))) abort(); - snprintf(sdkpath, sizeof(sdkpath), "%s/../SDK", execpath); + snprintf(sdkpath, sizeof(sdkpath) - 1, "%s/../SDK/" SDK_DIR, execpath); snprintf(codesign_allocate, sizeof(codesign_allocate), "%s-codesign_allocate", target); @@ -177,7 +187,7 @@ int main(int argc, char *argv[]) } args[i++] = osvermin; - args[i++] = "-mlinker-version=253.3"; + args[i++] = "-mlinker-version=450.3"; for (j = 1; j < argc; ++i, ++j) args[i] = argv[j];