diff --git a/CMakeLists.txt b/CMakeLists.txt index d03058c1..ec26ce9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,7 +77,10 @@ else() message(STATUS "*Top Level* NO LTO") endif() -if(XTOOLS_TAPI_PATH AND +if(XTOOLS_USE_TAPILITE) + option(XTOOLS_TAPI_SUPPORT "Support TAPI in ld64." ON) + message(STATUS "*Top Level* WITH TAPIlite") +elseif(XTOOLS_TAPI_PATH AND EXISTS ${XTOOLS_TAPI_PATH}/include/tapi AND EXISTS ${XTOOLS_TAPI_PATH}/lib/libtapi.dylib) configure_file( @@ -173,6 +176,11 @@ if (NOT XTOOLS_HAS_MODERNXAR) COPYONLY) endif() +# build tapilite first, so ld64 can link against it +if(XTOOLS_USE_TAPILITE) + add_subdirectory(tapilite) +endif() + # Evaluate first so that we find out about libprunetrie. if( EXISTS ${CMAKE_SOURCE_DIR}/ld64/CMakeLists.txt ) add_subdirectory(ld64) diff --git a/cctools/CMakeLists.txt b/cctools/CMakeLists.txt index 7ecab4bf..bfcbc517 100644 --- a/cctools/CMakeLists.txt +++ b/cctools/CMakeLists.txt @@ -1,5 +1,5 @@ -set(CCTOOLS_VERSION_NUM 895.0) +set(CCTOOLS_VERSION_NUM 949.0.1) add_definitions(-DALLOW_64BIT_LEB_ON_32B_TARGET=1) diff --git a/cctools/Makefile b/cctools/Makefile index 73413fad..af824d80 100644 --- a/cctools/Makefile +++ b/cctools/Makefile @@ -5,7 +5,7 @@ RC_OS = macos RC_CFLAGS = INSTALLSRC_SUBDIRS = $(COMMON_SUBDIRS) $(SUBDIRS_32) ar include efitools \ - libmacho + libmacho tests COMMON_SUBDIRS = libstuff as gprof misc man cbtlibs otool APPLE_SUBDIRS = ar SUBDIRS_32 = ld @@ -53,9 +53,11 @@ all clean: $(DSTROOT) SYMROOT=$(SYMROOT)/$$i $@) || exit 1 ; \ done; \ SED_RC_CFLAGS=`echo "$(RC_CFLAGS)" | sed 's/-arch ppc64//' \ - | sed 's/-arch x86_64//' | sed 's/-arch armv5//' \ - | sed 's/-arch arm64//' | sed 's/-arch x86_64h//' \ - | sed 's/-arch armv6//' | sed 's/-arch armv7[f,k,s]*//g'`; \ + | sed 's/-arch x86_64h//' | sed 's/-arch x86_64//' \ + | sed 's/-arch armv5//' | sed 's/-arch armv6//' \ + | sed 's/-arch armv7[f,k,s]*//g' \ + | sed 's/-arch arm64_32//' | sed 's/-arch arm64e//' \ + | sed 's/-arch arm64//'`; \ EMPTY=`echo "$$SED_RC_CFLAGS" | sed 's/ //g' \ | sed 's/-pipe//'`; \ if [ "$$EMPTY"x != "x" ]; \ @@ -86,9 +88,11 @@ all clean: $(DSTROOT) RAW_DSTROOT="$(RAW_DSTROOT)" $@) || exit 1 ; \ done; \ SED_RC_CFLAGS=`echo "$(RC_CFLAGS)" | sed 's/-arch ppc64//' \ - | sed 's/-arch x86_64//' | sed 's/-arch armv5//' \ - | sed 's/-arch arm64//' | sed 's/-arch x86_64h//' \ - | sed 's/-arch armv6//' | sed 's/-arch armv7[f,k,s]*//g'`; \ + | sed 's/-arch x86_64h//' | sed 's/-arch x86_64//' \ + | sed 's/-arch armv5//' | sed 's/-arch armv6//' \ + | sed 's/-arch armv7[f,k,s]*//g' \ + | sed 's/-arch arm64_32//' | sed 's/-arch arm64e//' \ + | sed 's/-arch arm64//'`; \ EMPTY=`echo "$$SED_RC_CFLAGS" | sed 's/ //g' \ | sed 's/-pipe//'`; \ if [ "$$EMPTY"x != "x" ]; \ @@ -108,8 +112,9 @@ all clean: $(DSTROOT) install: @if [ $(SRCROOT) ]; \ then \ - projName=`basename $(SRCROOT) | \ - sed 's/-[-0-9.]*//' | sed 's/\.cvs//'`; \ + projName=`basename $(SRCROOT) | sed 's/Branch.*//' | \ + sed 's/_PONDEROSA//' | sed 's/_Fall2018//' | \ + sed 's/-[-0-9.]*//' | sed 's/\.cvs//'`; \ if [ "$$projName" = cctools ]; \ then \ target=install_tools; \ @@ -165,9 +170,11 @@ install_tools: installhdrs SYMROOT=$(SYMROOT)/$$i install) || exit 1; \ done; \ SED_RC_CFLAGS=`echo "$(RC_CFLAGS)" | sed 's/-arch ppc64//' \ - | sed 's/-arch x86_64//' | sed 's/-arch armv5//' \ - | sed 's/-arch arm64//' | sed 's/-arch x86_64h//' \ - | sed 's/-arch armv6//' | sed 's/-arch armv7[f,k,s]*//g'`; \ + | sed 's/-arch x86_64h//' | sed 's/-arch x86_64//' \ + | sed 's/-arch armv5//' | sed 's/-arch armv6//' \ + | sed 's/-arch armv7[f,k,s]*//g' \ + | sed 's/-arch arm64_32//' | sed 's/-arch arm64e//' \ + | sed 's/-arch arm64//'`; \ EMPTY=`echo "$$SED_RC_CFLAGS" | sed 's/ //g' \ | sed 's/-pipe//'`; \ if [ "$$EMPTY"x != "x" ]; \ @@ -200,9 +207,11 @@ install_tools: installhdrs install) || exit 1; \ done; \ SED_RC_CFLAGS=`echo "$(RC_CFLAGS)" | sed 's/-arch ppc64//' \ - | sed 's/-arch x86_64//' | sed 's/-arch armv5//' \ - | sed 's/-arch arm64//' | sed 's/-arch x86_64h//' \ - | sed 's/-arch armv6//' | sed 's/-arch armv7[f,k,s]*//g'`; \ + | sed 's/-arch x86_64h//' | sed 's/-arch x86_64//' \ + | sed 's/-arch armv5//' | sed 's/-arch armv6//' \ + | sed 's/-arch armv7[f,k,s]*//g' \ + | sed 's/-arch arm64_32//' | sed 's/-arch arm64e//' \ + | sed 's/-arch arm64//'`; \ EMPTY=`echo "$$SED_RC_CFLAGS" | sed 's/ //g' \ | sed 's/-pipe//'`; \ if [ "$$EMPTY"x != "x" ]; \ @@ -239,6 +248,8 @@ lib_ofiles lib_ofiles_install: installhdrs then \ CWD=`pwd`; cd "$(DSTROOT)"; DSTROOT=`pwd`; cd "$$CWD"; \ SED_RC_CFLAGS=`echo "$(RC_CFLAGS)" | sed 's/-arch ppc64//' \ + | sed 's/-arch arm64_32//' \ + | sed 's/-arch arm64e//' \ | sed 's/-arch arm64//' \ | sed 's/-arch x86_64h//' \ | sed 's/-arch x86_64//'`; \ @@ -301,6 +312,8 @@ lib_ofiles lib_ofiles_install: installhdrs else \ CWD=`pwd`; cd "$(DSTROOT)"; DSTROOT=`pwd`; cd "$$CWD"; \ SED_RC_CFLAGS=`echo "$(RC_CFLAGS)" | sed 's/-arch ppc64//' \ + | sed 's/-arch arm64_32//' \ + | sed 's/-arch arm64e//' \ | sed 's/-arch arm64//' \ | sed 's/-arch x86_64h//' \ | sed 's/-arch x86_64//'`; \ @@ -429,10 +442,14 @@ fromGASsrc: installhdrs: $(DSTROOT) @if [ $(SRCROOT) ]; \ then \ - projName=`basename $(SRCROOT) | sed 's/-[0-9.]*//'`; \ - if [ "$$projName" = cctools -a $(RC_OS) = macos ] && \ - [ "$(RC_ProjectName)" != "cctools_ofiles_Sim" ] && \ - [ "$(RC_FORCEHDRS)" != "YES" ]; \ + projName=`basename $(SRCROOT) | sed 's/Branch.*//' | \ + sed 's/_PONDEROSA//' | sed 's/_Fall2018//' | \ + sed 's/-[-0-9.]*//' | sed 's/\.cvs//'`; \ + rcName=`echo $(RC_ProjectName) | \ + sed 's/\(cctools_ofiles\).*/\1/'`; \ + if [ "$$projName" = cctools -a $(RC_OS) = macos ] && \ + [ "$$rcName" != "cctools_ofiles" ] && \ + [ "$(RC_FORCEHDRS)" != "YES" ]; \ then \ echo === cctools does not install headers for macos ===;\ else \ @@ -444,6 +461,28 @@ installhdrs: $(DSTROOT) install) || exit 1; \ fi +installapi: $(DSTROOT) + @if [ $(SRCROOT) ]; \ + then \ + projName=`basename $(SRCROOT) | sed 's/Branch.*//' | \ + sed 's/_PONDEROSA//' | sed 's/_Fall2018//' | \ + sed 's/-[-0-9.]*//' | sed 's/\.cvs//'`; \ + rcName=`echo $(RC_ProjectName) | \ + sed 's/\(cctools_ofiles\).*/\1/'`; \ + if [ "$$projName" = cctools -a $(RC_OS) = macos ] && \ + [ "$$rcName" != "cctools_ofiles" ] && \ + [ "$(RC_FORCEHDRS)" != "YES" ]; \ + then \ + echo === cctools does not installapi for macos ===;\ + else \ + (cd include; $(MAKE) DSTROOT=$(DSTROOT) \ + RC_OS="$(RC_OS)" installapi) || exit 1; \ + fi; \ + else \ + (cd include; $(MAKE) DSTROOT=$(DSTROOT) RC_OS=$(RC_OS) \ + installapi) || exit 1; \ + fi + $(DSTROOT): $(MKDIRS) $@ @@ -455,3 +494,6 @@ SRCROOT: echo Must define $@; \ exit 1; \ fi + +noop: + mkdir -p $(DSTROOT)/AppleInternal diff --git a/cctools/PB.project b/cctools/PB.project deleted file mode 100644 index 010d5a15..00000000 --- a/cctools/PB.project +++ /dev/null @@ -1,17 +0,0 @@ -{ - DYNAMIC_CODE_GEN = YES; - FILESTABLE = {}; - LANGUAGE = English; - NEXTSTEP_BUILDTOOL = /bin/gnumake; - NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; - NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; - PDO_UNIX_BUILDTOOL = $NEXT_ROOT/NextDeveloper/bin/make; - PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; - PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; - PROJECTNAME = cctools; - PROJECTTYPE = Legacy; - PROJECTVERSION = 2.8; - WINDOWS_BUILDTOOL = $NEXT_ROOT/NextDeveloper/Executables/make; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; -} diff --git a/cctools/ar/ar.c b/cctools/ar/ar.c index 90ed5706..b010b023 100644 --- a/cctools/ar/ar.c +++ b/cctools/ar/ar.c @@ -123,12 +123,12 @@ main(argc, argv) run_ranlib = 1; if (argc < 3) { - if(strcmp(argv[1], "--version") == 0){ + if(argc >= 2 && strcmp(argv[1], "--version") == 0){ /* Implement a gnu-style --version to be friendly to GCC. */ fprintf(stdout, "xtools-%s ar %s\nBased on Apple Inc. %s\n", xtools_version, package_version, apple_version); exit(0); - } else if(strcmp(argv[1], "--help") == 0){ + } else if(argc >= 2 && strcmp(argv[1], "--help") == 0){ usage(0); fprintf(stdout, "Please report bugs to %s\n", support_url); exit(0); diff --git a/cctools/ar/archive.c b/cctools/ar/archive.c index 12bd0edb..e52fd5d2 100644 --- a/cctools/ar/archive.c +++ b/cctools/ar/archive.c @@ -231,8 +231,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)) { @@ -252,8 +253,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); @@ -288,7 +291,7 @@ get_arobj(fd) return (1); } -static int already_written; +static size_t already_written; /* * put_arobj -- @@ -299,7 +302,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; @@ -343,7 +346,8 @@ put_arobj(cfp, sb) sb->st_mode, 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, @@ -371,13 +375,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); } @@ -407,7 +411,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/as/CMakeLists.txt b/cctools/as/CMakeLists.txt index 16d7b76b..7b24efd4 100644 --- a/cctools/as/CMakeLists.txt +++ b/cctools/as/CMakeLists.txt @@ -41,14 +41,24 @@ if(XTOOLS_C_HAS_WNODEPRECATED_FLAG) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated") endif() +if (XTOOLS_AS_USE_CLANG) + add_definitions(-DXTOOLS_AS_USE_CLANG) +endif() +if (XTOOLS_AS_CLANG_USE_HOST) + add_definitions(-DXTOOLS_AS_CLANG_USE_HOST) +endif() +if (XTOOLS_AS_SUBDIR) + add_definitions(-DXTOOLS_AS_SUBDIR="${XTOOLS_AS_SUBDIR}") +endif() + add_executable(as-driver driver.c) -set_target_properties(as-driver PROPERTIES COMPILE_FLAGS "-Di486 -Di586 -Di686") +set_target_properties(as-driver PROPERTIES COMPILE_FLAGS "-Di486 -Di586 -Di686 -UPPC") target_link_libraries(as-driver stuff) set_target_properties(as-driver PROPERTIES OUTPUT_NAME as) install(TARGETS as-driver DESTINATION bin ) add_executable(i386-as ${X86_SRCS}) -set_target_properties(i386-as PROPERTIES COMPILE_FLAGS "-DI386 -Di486 -Di586 -Di686") +set_target_properties(i386-as PROPERTIES COMPILE_FLAGS "-DI386 -Di486 -Di586 -Di686 -UPPC") set_target_properties(i386-as PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/i386) set_target_properties(i386-as PROPERTIES OUTPUT_NAME as) target_link_libraries(i386-as stuff) @@ -59,13 +69,13 @@ install(TARGETS i386-as DESTINATION bin/i386) if(BUILD_TESTING) add_executable(test-x86 i386-check.c) - set_target_properties(test-x86 PROPERTIES COMPILE_FLAGS "-DI386 -Di486 -Di586 -Di686") + set_target_properties(test-x86 PROPERTIES COMPILE_FLAGS "-DI386 -Di486 -Di586 -Di686 -UPPC") set_target_properties(test-x86 PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tests) add_test(NAME check-x86-as COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/check-as $ i386 $) endif() add_executable(x8664-as ${X86_SRCS}) -set_target_properties(x8664-as PROPERTIES COMPILE_FLAGS "-DI386 -Di486 -Di586 -Di686 -DARCH64") +set_target_properties(x8664-as PROPERTIES COMPILE_FLAGS "-DI386 -Di486 -Di586 -Di686 -DARCH64 -UPPC") set_target_properties(x8664-as PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/x86_64) set_target_properties(x8664-as PROPERTIES OUTPUT_NAME as) target_link_libraries(x8664-as stuff) @@ -76,7 +86,7 @@ install(TARGETS x8664-as DESTINATION bin/x86_64) if(BUILD_TESTING) add_executable(test-x86_64 i386-check.c) - set_target_properties(test-x86_64 PROPERTIES COMPILE_FLAGS "-DI386 -Di486 -Di586 -Di686 -DARCH64") + set_target_properties(test-x86_64 PROPERTIES COMPILE_FLAGS "-DI386 -Di486 -Di586 -Di686 -DARCH64 -UPPC") set_target_properties(test-x86_64 PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tests) add_test(NAME check-x86_86-as COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/check-as $ x86_64 $) endif() @@ -109,7 +119,7 @@ endif() install(TARGETS ppc64-as DESTINATION bin/ppc64) add_executable(arm-as ${ARM_SRCS}) -set_target_properties(arm-as PROPERTIES COMPILE_FLAGS "-DARM") +set_target_properties(arm-as PROPERTIES COMPILE_FLAGS "-DARM -UPPC") set_target_properties(arm-as PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/arm) set_target_properties(arm-as PROPERTIES OUTPUT_NAME as) target_link_libraries(arm-as stuff) diff --git a/cctools/as/app.c b/cctools/as/app.c index be2f63be..9ec697ca 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 611fc514..9689d0da 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 3bd27728..3d719255 100644 --- a/cctools/as/arm.c +++ b/cctools/as/arm.c @@ -1023,7 +1023,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 +1127,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 +1448,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 +2175,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 +2957,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 +3338,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 +3453,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 +3603,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 +3629,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 +3742,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,6 +4463,8 @@ parse_operands (char *str, const unsigned char *pattern) enum arm_reg_type rtype; parse_operand_result result; + val = SUCCESS; + #define po_char_or_fail(chr) do { \ if (skip_past_char (&str, chr) == FAIL) \ goto bad_args; \ @@ -5406,7 +5414,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. */ @@ -5416,7 +5425,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. */ @@ -6076,7 +6086,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; @@ -7206,7 +7216,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, @@ -7511,8 +7521,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; } @@ -8783,7 +8793,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; @@ -9069,7 +9079,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; @@ -9371,7 +9381,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; @@ -13096,7 +13106,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); @@ -13118,7 +13128,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. */ @@ -13128,11 +13138,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 @@ -13144,7 +13154,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 { @@ -13199,7 +13209,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); @@ -13641,7 +13651,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); } /* @@ -13747,7 +13757,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")) @@ -16512,7 +16522,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. */ @@ -16535,7 +16545,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 @@ -16546,12 +16556,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; } } @@ -16833,8 +16843,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; @@ -16956,10 +16966,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; @@ -17183,9 +17195,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) @@ -18520,7 +18535,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/atof-generic.c b/cctools/as/atof-generic.c index 8e1c4c9b..1b8e9b58 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 8edf5469..772d47ff 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 e453bf59..e6810aca 100644 --- a/cctools/as/driver.c +++ b/cctools/as/driver.c @@ -27,7 +27,11 @@ int argc, char **argv, char **envp) { +#ifdef XTOOLS_AS_SUBDIR + const char *SUB = XTOOLS_AS_SUBDIR; +#else const char *SUB = "./"; +#endif const char *LIB = "../libexec/as/"; const char *LOCALLIB = "../local/libexec/as/"; const char *AS = "/as"; @@ -240,18 +244,22 @@ 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; } +#ifndef XTOOLS_AS_USE_CLANG /* Default to the 'old way'. */ if (Qflag == FALSE && qflag == FALSE) Qflag = TRUE; +#endif if(qflag == TRUE && (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); @@ -268,9 +276,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; @@ -286,6 +296,13 @@ char **envp) arch_flag.cputype == CPU_TYPE_ARM) run_clang = 1; +#ifdef XTOOLS_AS_CLANG_USE_HOST + if ((run_clang || qflag) && !Qflag) { + AS = "/as-host"; + Qflag = TRUE; /* do not trigger clang callout below */ + } +#endif + /* * Use the clang as the assembler if is the default or asked to with * the -q flag. But don't use it asked to use the system assembler @@ -295,6 +312,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)){ as = makestr(prefix, CLANG, NULL); if(access(as, F_OK) != 0){ @@ -366,6 +384,11 @@ char **envp) /* * If this assembler exist try to run it else print an error message. */ +#ifdef XTOOLS_AS_SUBDIR + if (*SUB == '/') + as = makestr(SUB, arch_name, AS, NULL); + else +#endif as = makestr(prefix, SUB, arch_name, AS, NULL); new_argv = allocate((argc + 1) * sizeof(char *)); new_argv[0] = as; diff --git a/cctools/as/dwarf2dbg.c b/cctools/as/dwarf2dbg.c index 5c9231fc..d02f758a 100644 --- a/cctools/as/dwarf2dbg.c +++ b/cctools/as/dwarf2dbg.c @@ -227,8 +227,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 +268,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 +392,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 +535,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 +687,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 +701,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 +751,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 +781,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 +795,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 +825,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 +900,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 +908,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 +1018,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 +1041,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 +1084,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 +1124,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 +1132,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 +1143,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 +1474,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 +1494,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 +1511,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 +1700,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 +1754,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 +1788,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 +1842,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 +1992,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 +2007,13 @@ struct frchain *ranges_section) #else comp_dir = getwd(xmalloc(MAXPATHLEN + 1)); #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 +2021,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 +2052,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 +2094,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 b2b29b5b..9a4d210a 100644 --- a/cctools/as/expr.c +++ b/cctools/as/expr.c @@ -1366,7 +1366,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 32a685b0..c55620ac 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 13c8090e..12cc68c0 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 e490d04a..9a62de12 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 dd6cba88..07a38f9c 100644 --- a/cctools/as/frags.c +++ b/cctools/as/frags.c @@ -67,7 +67,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); @@ -119,8 +119,9 @@ int old_frags_var_max_size) /* Number of chars (already allocated on obstack "can begin"); } - frag_now->fr_fix = (char *) (obstack_next_free (&frags)) - - (frag_now->fr_literal) - old_frags_var_max_size; + frag_now->fr_fix = (int)((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 +133,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 e53d690a..72bb83e6 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, @@ -3888,9 +3889,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 /* @@ -3905,7 +3906,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, @@ -3927,7 +3928,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); @@ -3968,7 +3969,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 @@ -4038,10 +4039,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 /* @@ -4056,7 +4057,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, @@ -4141,7 +4142,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); @@ -4229,7 +4230,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) @@ -4250,7 +4251,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 @@ -4262,7 +4263,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. */ @@ -4804,7 +4805,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)) @@ -5408,6 +5409,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; @@ -5423,6 +5426,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; @@ -5863,6 +5868,8 @@ md_parse_option (c, arg) return 1; } +void md_show_usage (FILE *stream); + void md_show_usage (stream) FILE *stream; @@ -5989,6 +5996,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; @@ -6023,7 +6032,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 @@ -6161,7 +6170,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/input-file.c b/cctools/as/input-file.c index f7ec6009..4e13cab2 100644 --- a/cctools/as/input-file.c +++ b/cctools/as/input-file.c @@ -151,7 +151,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 5a6e41ae..18af9d9f 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 @@ char **bufp) ++ 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 @@ char **bufp) 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 ca561f49..2dced074 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 @@ int nsect) * 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/obstack.c b/cctools/as/obstack.c index 1910d861..6d8c3311 100644 --- a/cctools/as/obstack.c +++ b/cctools/as/obstack.c @@ -57,7 +57,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 */ @@ -80,8 +80,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; @@ -106,14 +106,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); @@ -144,7 +144,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. */ @@ -186,7 +186,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 4b166dbe..63f830e4 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/read.c b/cctools/as/read.c index 1e4222ef..643044fc 100644 --- a/cctools/as/read.c +++ b/cctools/as/read.c @@ -750,7 +750,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;", @@ -794,7 +794,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); } } @@ -828,7 +828,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); } } @@ -1429,8 +1429,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 @@ -1606,7 +1606,7 @@ void s_align_bytes( uintptr_t arg) { - s_align(arg, 1); + s_align((int)arg, 1); } /* @@ -1618,7 +1618,7 @@ void s_align_ptwo( uintptr_t arg) { - s_align(arg, 0); + s_align((int)arg, 0); } /* @@ -1650,10 +1650,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; @@ -1676,12 +1676,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 (); } } @@ -1814,7 +1814,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); @@ -1881,7 +1881,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; @@ -1925,7 +1925,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); } } @@ -1987,7 +1988,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. @@ -2122,7 +2123,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(); @@ -2169,7 +2171,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; @@ -2192,7 +2194,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; @@ -2323,7 +2325,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; @@ -2336,7 +2338,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(); @@ -2390,7 +2392,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; @@ -2464,7 +2466,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 ','. */ @@ -2635,7 +2637,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); @@ -2698,7 +2701,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; @@ -2751,7 +2754,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; @@ -2804,7 +2807,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; @@ -2827,7 +2830,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; @@ -3076,7 +3079,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); } } @@ -3184,8 +3188,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; @@ -3318,14 +3322,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; @@ -3333,7 +3337,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; @@ -3410,7 +3414,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 @@ -3424,7 +3428,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: /* @@ -3441,13 +3445,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; @@ -3464,9 +3468,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: @@ -3474,16 +3478,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); @@ -3706,7 +3710,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'){ @@ -3784,7 +3788,7 @@ emit_leb128_expr (expressionS *exp, int sign) #if ALLOW_64BIT_LEB_ON_32B_TARGET int64_t value = exp->X_add_number; #else - valueT value = exp->X_add_number; + valueT value = (valueT)exp->X_add_number; #endif int size; char *p; @@ -3823,8 +3827,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 @@ -3847,7 +3851,7 @@ uintptr_t sign) do { expression (&exp); - emit_leb128_expr (&exp, sign); + emit_leb128_expr (&exp, (int)sign); } while (*input_line_pointer++ == ','); @@ -4073,7 +4077,7 @@ void) } exp.X_add_number = 0; } - return(exp.X_add_number); + return (signed_target_addr_t)exp.X_add_number; } /* @@ -4086,7 +4090,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++); } @@ -4211,7 +4215,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; @@ -4247,7 +4251,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(); } @@ -4279,7 +4283,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(); } @@ -4483,6 +4487,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; @@ -4894,7 +4899,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; @@ -4905,11 +4910,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(); } } } @@ -5151,7 +5156,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); } @@ -5184,7 +5189,7 @@ output_sleb128 (char *p, offsetT value) } while (more); - return p - orig; + return (int)(p - orig); } #if ALLOW_64BIT_LEB_ON_32B_TARGET || defined(ARCH64) @@ -5209,7 +5214,7 @@ output_uleb128 (char *p, valueT value) } while (uval != 0); - return p - orig; + return (int)(p - orig); } #if ALLOW_64BIT_LEB_ON_32B_TARGET || defined(ARCH64) diff --git a/cctools/as/sections.c b/cctools/as/sections.c index 5b00b023..9027f0b2 100644 --- a/cctools/as/sections.c +++ b/cctools/as/sections.c @@ -174,8 +174,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); } @@ -216,7 +216,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; @@ -261,7 +262,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 e5d76b5c..bca29bd4 100644 --- a/cctools/as/symbols.c +++ b/cctools/as/symbols.c @@ -335,11 +335,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 +460,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 +604,7 @@ make_stab_for_symbol( symbolS *symbolP) { symbolS *stab; - int stabnamelen; + size_t stabnamelen; char *stabname; if(symbolP->sy_name[0] == 'L') @@ -694,7 +695,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 +723,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 +883,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 +899,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 a751daee..29f056cf 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 @@ -187,9 +188,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++; } @@ -277,9 +280,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; @@ -294,7 +298,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. @@ -309,7 +313,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){ @@ -371,7 +375,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)); /* @@ -635,7 +639,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"); @@ -1115,6 +1119,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. */ @@ -1165,8 +1172,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 || @@ -1252,6 +1259,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; @@ -1378,6 +1387,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/cbtlibs/CMakeLists.txt b/cctools/cbtlibs/CMakeLists.txt index 77cc8f8c..f9eac32c 100644 --- a/cctools/cbtlibs/CMakeLists.txt +++ b/cctools/cbtlibs/CMakeLists.txt @@ -11,3 +11,4 @@ add_library(syminfo libsyminfo.c) if(XTOOLS_C_HAS_FNOCOMMON_FLAG) set_target_properties(syminfo PROPERTIES COMPILE_FLAGS "-fno-common") endif() +target_link_libraries(syminfo stuff) diff --git a/cctools/cctools.xcodeproj/project.pbxproj b/cctools/cctools.xcodeproj/project.pbxproj new file mode 100644 index 00000000..8188d1cf --- /dev/null +++ b/cctools/cctools.xcodeproj/project.pbxproj @@ -0,0 +1,10489 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXAggregateTarget section */ + DE09611421CC205D00C4ADA1 /* cctools */ = { + isa = PBXAggregateTarget; + buildConfigurationList = DE09611521CC205D00C4ADA1 /* Build configuration list for PBXAggregateTarget "cctools" */; + buildPhases = ( + ); + dependencies = ( + DE09613621CC2BA200C4ADA1 /* PBXTargetDependency */, + DEC31BCE21F652520006E1D8 /* PBXTargetDependency */, + DE1F647621CD7219004CA2BF /* PBXTargetDependency */, + DE1F640021CD6555004CA2BF /* PBXTargetDependency */, + DE09617221CC4E4C00C4ADA1 /* PBXTargetDependency */, + DE0961F021CC560000C4ADA1 /* PBXTargetDependency */, + DE09630221CD61CA00C4ADA1 /* PBXTargetDependency */, + DE1F641B21CD6600004CA2BF /* PBXTargetDependency */, + DE0962D821CD616800C4ADA1 /* PBXTargetDependency */, + DE09630021CD61CA00C4ADA1 /* PBXTargetDependency */, + DE1F642C21CD66DF004CA2BF /* PBXTargetDependency */, + DE0962DE21CD616800C4ADA1 /* PBXTargetDependency */, + DE09626421CD593000C4ADA1 /* PBXTargetDependency */, + DE09620121CC784600C4ADA1 /* PBXTargetDependency */, + DE1F63E621CD64C0004CA2BF /* PBXTargetDependency */, + DE09623A21CC80C500C4ADA1 /* PBXTargetDependency */, + DE09627721CD598F00C4ADA1 /* PBXTargetDependency */, + DE09632421CD635900C4ADA1 /* PBXTargetDependency */, + DE0962DA21CD616800C4ADA1 /* PBXTargetDependency */, + DE1F646D21CD690B004CA2BF /* PBXTargetDependency */, + DE0962D621CD616800C4ADA1 /* PBXTargetDependency */, + DE09622621CC7FCF00C4ADA1 /* PBXTargetDependency */, + DE09622421CC7FCD00C4ADA1 /* PBXTargetDependency */, + DE09626221CD592E00C4ADA1 /* PBXTargetDependency */, + DEB23D9821DEA1EE007F9934 /* PBXTargetDependency */, + DEA2409F21CE096A0026D013 /* PBXTargetDependency */, + DE1F64A221CD858A004CA2BF /* PBXTargetDependency */, + DE1F64A421CD858A004CA2BF /* PBXTargetDependency */, + DE1F64A621CD858A004CA2BF /* PBXTargetDependency */, + ); + name = cctools; + productName = cctools; + }; + DE09611821CC207000C4ADA1 /* cctools_ofiles */ = { + isa = PBXAggregateTarget; + buildConfigurationList = DE09611921CC207000C4ADA1 /* Build configuration list for PBXAggregateTarget "cctools_ofiles" */; + buildPhases = ( + ); + dependencies = ( + DE8229FF21CDA419008CD150 /* PBXTargetDependency */, + DE000B4921CDBB29000CEC53 /* PBXTargetDependency */, + DE000B6021CDBEB4000CEC53 /* PBXTargetDependency */, + DE000B6F21CDEF81000CEC53 /* PBXTargetDependency */, + DEA2409321CDF1240026D013 /* PBXTargetDependency */, + ); + name = cctools_ofiles; + productName = cctools; + }; + DE09611C21CC208300C4ADA1 /* install */ = { + isa = PBXAggregateTarget; + buildConfigurationList = DE09611D21CC208300C4ADA1 /* Build configuration list for PBXAggregateTarget "install" */; + buildPhases = ( + ); + dependencies = ( + DE09612521CC209A00C4ADA1 /* PBXTargetDependency */, + ); + name = install; + productName = cctools; + }; + DE09612021CC209100C4ADA1 /* ofiles_install */ = { + isa = PBXAggregateTarget; + buildConfigurationList = DE09612121CC209100C4ADA1 /* Build configuration list for PBXAggregateTarget "ofiles_install" */; + buildPhases = ( + ); + dependencies = ( + DE09612721CC20A000C4ADA1 /* PBXTargetDependency */, + ); + name = ofiles_install; + productName = cctools; + }; + DE0961E321CC548B00C4ADA1 /* assemblers install */ = { + isa = PBXAggregateTarget; + buildConfigurationList = DE0961E421CC548B00C4ADA1 /* Build configuration list for PBXAggregateTarget "assemblers install" */; + buildPhases = ( + DE0961ED21CC54B800C4ADA1 /* ShellScript */, + ); + dependencies = ( + DE0961E821CC54AF00C4ADA1 /* PBXTargetDependency */, + DE0961EA21CC54AF00C4ADA1 /* PBXTargetDependency */, + DE0961EC21CC54AF00C4ADA1 /* PBXTargetDependency */, + ); + name = "assemblers install"; + productName = assemblers; + }; + DE1F647121CD71E0004CA2BF /* codesign_allocate install */ = { + isa = PBXAggregateTarget; + buildConfigurationList = DE1F647221CD71E1004CA2BF /* Build configuration list for PBXAggregateTarget "codesign_allocate install" */; + buildPhases = ( + DE1F647921CD7237004CA2BF /* ShellScript */, + ); + dependencies = ( + DE1F647821CD7222004CA2BF /* PBXTargetDependency */, + ); + name = "codesign_allocate install"; + productName = "codesign_allocate install"; + }; + DE1F647A21CD8443004CA2BF /* RelNotes */ = { + isa = PBXAggregateTarget; + buildConfigurationList = DE1F647B21CD8443004CA2BF /* Build configuration list for PBXAggregateTarget "RelNotes" */; + buildPhases = ( + DE1F647F21CD8451004CA2BF /* CopyFiles */, + ); + dependencies = ( + ); + name = RelNotes; + productName = RelNotes; + }; + DE1F648221CD84C7004CA2BF /* man3 */ = { + isa = PBXAggregateTarget; + buildConfigurationList = DE1F648321CD84C7004CA2BF /* Build configuration list for PBXAggregateTarget "man3" */; + buildPhases = ( + DE1F648621CD8500004CA2BF /* CopyFiles */, + DEA240A121CE0BF40026D013 /* CopyFiles */, + ); + dependencies = ( + ); + name = man3; + productName = man3; + }; + DE1F649721CD855C004CA2BF /* man5 */ = { + isa = PBXAggregateTarget; + buildConfigurationList = DE1F649821CD855C004CA2BF /* Build configuration list for PBXAggregateTarget "man5" */; + buildPhases = ( + DE1F649B21CD855F004CA2BF /* CopyFiles */, + ); + dependencies = ( + ); + name = man5; + productName = man5; + }; + DE5DC64E21F7EA4B00A7CA07 /* cctools_ofiles_driverkit */ = { + isa = PBXAggregateTarget; + buildConfigurationList = DE5DC65921F7EA4B00A7CA07 /* Build configuration list for PBXAggregateTarget "cctools_ofiles_driverkit" */; + buildPhases = ( + ); + dependencies = ( + DE5DC68A21F7F44200A7CA07 /* PBXTargetDependency */, + ); + name = cctools_ofiles_driverkit; + productName = cctools; + }; + DE5DC67C21F7EA8E00A7CA07 /* macho headers driverkit */ = { + isa = PBXAggregateTarget; + buildConfigurationList = DE5DC67E21F7EA8E00A7CA07 /* Build configuration list for PBXAggregateTarget "macho headers driverkit" */; + buildPhases = ( + DE5DC67D21F7EA8E00A7CA07 /* ShellScript */, + ); + dependencies = ( + ); + name = "macho headers driverkit"; + productName = "macho headers"; + }; + DE822A0021CDA455008CD150 /* macho headers */ = { + isa = PBXAggregateTarget; + buildConfigurationList = DE822A0121CDA455008CD150 /* Build configuration list for PBXAggregateTarget "macho headers" */; + buildPhases = ( + DE822A0521CDA49D008CD150 /* ShellScript */, + ); + dependencies = ( + ); + name = "macho headers"; + productName = "macho headers"; + }; + DEA2409721CE08830026D013 /* efi install */ = { + isa = PBXAggregateTarget; + buildConfigurationList = DEA2409821CE08830026D013 /* Build configuration list for PBXAggregateTarget "efi install" */; + buildPhases = ( + DEA2409D21CE089B0026D013 /* ShellScript */, + ); + dependencies = ( + DEA2409C21CE08940026D013 /* PBXTargetDependency */, + DEC00B69220012B10079FFD3 /* PBXTargetDependency */, + ); + name = "efi install"; + productName = "mtoc install"; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + DE000B3B21CDBA79000CEC53 /* arch.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6B21CC1ABB00C4ADA1 /* arch.c */; }; + DE000B3C21CDBA79000CEC53 /* get_end.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6C21CC1ABB00C4ADA1 /* get_end.c */; }; + DE000B3D21CDBA79000CEC53 /* getsecbyname.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7321CC1ABB00C4ADA1 /* getsecbyname.c */; }; + DE000B3E21CDBA79000CEC53 /* getsegbyname.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6621CC1ABB00C4ADA1 /* getsegbyname.c */; }; + DE000B3F21CDBA79000CEC53 /* hppa_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7221CC1ABB00C4ADA1 /* hppa_swap.c */; }; + DE000B4021CDBA79000CEC53 /* i386_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6821CC1ABB00C4ADA1 /* i386_swap.c */; }; + DE000B4121CDBA79000CEC53 /* i860_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7521CC1ABB00C4ADA1 /* i860_swap.c */; }; + DE000B4221CDBA79000CEC53 /* m68k_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7421CC1ABB00C4ADA1 /* m68k_swap.c */; }; + DE000B4321CDBA79000CEC53 /* m88k_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6921CC1ABB00C4ADA1 /* m88k_swap.c */; }; + DE000B4421CDBA79000CEC53 /* ppc_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6F21CC1ABB00C4ADA1 /* ppc_swap.c */; }; + DE000B4521CDBA79000CEC53 /* slot_name.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6721CC1ABB00C4ADA1 /* slot_name.c */; }; + DE000B4621CDBA79000CEC53 /* sparc_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7021CC1ABB00C4ADA1 /* sparc_swap.c */; }; + DE000B4721CDBA79000CEC53 /* swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7121CC1ABB00C4ADA1 /* swap.c */; }; + DE000B4D21CDBE77000CEC53 /* arch.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6B21CC1ABB00C4ADA1 /* arch.c */; }; + DE000B4E21CDBE77000CEC53 /* get_end.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6C21CC1ABB00C4ADA1 /* get_end.c */; }; + DE000B4F21CDBE77000CEC53 /* getsecbyname.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7321CC1ABB00C4ADA1 /* getsecbyname.c */; }; + DE000B5021CDBE77000CEC53 /* getsegbyname.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6621CC1ABB00C4ADA1 /* getsegbyname.c */; }; + DE000B5121CDBE77000CEC53 /* hppa_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7221CC1ABB00C4ADA1 /* hppa_swap.c */; }; + DE000B5221CDBE77000CEC53 /* i386_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6821CC1ABB00C4ADA1 /* i386_swap.c */; }; + DE000B5321CDBE77000CEC53 /* i860_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7521CC1ABB00C4ADA1 /* i860_swap.c */; }; + DE000B5421CDBE77000CEC53 /* m68k_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7421CC1ABB00C4ADA1 /* m68k_swap.c */; }; + DE000B5521CDBE77000CEC53 /* m88k_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6921CC1ABB00C4ADA1 /* m88k_swap.c */; }; + DE000B5621CDBE77000CEC53 /* ppc_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6F21CC1ABB00C4ADA1 /* ppc_swap.c */; }; + DE000B5721CDBE77000CEC53 /* slot_name.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6721CC1ABB00C4ADA1 /* slot_name.c */; }; + DE000B5821CDBE77000CEC53 /* sparc_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7021CC1ABB00C4ADA1 /* sparc_swap.c */; }; + DE000B5921CDBE77000CEC53 /* swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7121CC1ABB00C4ADA1 /* swap.c */; }; + DE000B6B21CDBEFD000CEC53 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE000B6C21CDBF1A000CEC53 /* redo_prebinding.h in Headers */ = {isa = PBXBuildFile; fileRef = DE0960A121CC1ABC00C4ADA1 /* redo_prebinding.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DE000B6D21CDBF2B000CEC53 /* redo_prebinding.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7921CC1ABB00C4ADA1 /* redo_prebinding.c */; }; + DE000B7821CDF007000CEC53 /* libsyminfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DE09603521CC1ABC00C4ADA1 /* libsyminfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DE09613721CC2BEC00C4ADA1 /* allocate.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FC821CC1ABB00C4ADA1 /* allocate.c */; }; + DE09613821CC2BEC00C4ADA1 /* apple_version.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09613321CC293000C4ADA1 /* apple_version.c */; }; + DE09613921CC2BEC00C4ADA1 /* arch_usage.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FE821CC1ABB00C4ADA1 /* arch_usage.c */; }; + DE09613A21CC2BEC00C4ADA1 /* arch.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FD321CC1ABB00C4ADA1 /* arch.c */; }; + DE09613B21CC2BEC00C4ADA1 /* best_arch.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FE521CC1ABB00C4ADA1 /* best_arch.c */; }; + DE09613C21CC2BEC00C4ADA1 /* breakout.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FEB21CC1ABB00C4ADA1 /* breakout.c */; }; + DE09613D21CC2BEC00C4ADA1 /* bytesex.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FDE21CC1ABB00C4ADA1 /* bytesex.c */; }; + DE09613E21CC2BEC00C4ADA1 /* checkout.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FD021CC1ABB00C4ADA1 /* checkout.c */; }; + DE09613F21CC2BEC00C4ADA1 /* coff_bytesex.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FD921CC1ABB00C4ADA1 /* coff_bytesex.c */; }; + DE09614021CC2BEC00C4ADA1 /* crc32.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FD821CC1ABB00C4ADA1 /* crc32.c */; }; + DE09614121CC2BEC00C4ADA1 /* dylib_roots.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FCD21CC1ABB00C4ADA1 /* dylib_roots.c */; }; + DE09614321CC2BEC00C4ADA1 /* errors.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FED21CC1ABB00C4ADA1 /* errors.c */; }; + DE09614421CC2BEC00C4ADA1 /* execute.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FCF21CC1ABB00C4ADA1 /* execute.c */; }; + DE09614521CC2BEC00C4ADA1 /* fatal_arch.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FD121CC1ABB00C4ADA1 /* fatal_arch.c */; }; + DE09614621CC2BEC00C4ADA1 /* fatals.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FE421CC1ABB00C4ADA1 /* fatals.c */; }; + DE09614721CC2BEC00C4ADA1 /* get_arch_from_host.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FE121CC1ABB00C4ADA1 /* get_arch_from_host.c */; }; + DE09614821CC2BEC00C4ADA1 /* get_toc_byte_sex.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FD421CC1ABB00C4ADA1 /* get_toc_byte_sex.c */; }; + DE09614921CC2BEC00C4ADA1 /* guess_short_name.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FD521CC1ABB00C4ADA1 /* guess_short_name.c */; }; + DE09614A21CC2BEC00C4ADA1 /* hash_string.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FDA21CC1ABB00C4ADA1 /* hash_string.c */; }; + DE09614B21CC2BEC00C4ADA1 /* hppa.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FEE21CC1ABB00C4ADA1 /* hppa.c */; }; + DE09614C21CC2BEC00C4ADA1 /* llvm.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FE921CC1ABB00C4ADA1 /* llvm.c */; }; + DE09614D21CC2BEC00C4ADA1 /* lto.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FD221CC1ABB00C4ADA1 /* lto.c */; }; + DE09614E21CC2BEC00C4ADA1 /* macosx_deployment_target.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FE621CC1ABB00C4ADA1 /* macosx_deployment_target.c */; }; + DE09614F21CC2BEC00C4ADA1 /* ofile_error.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FC921CC1ABB00C4ADA1 /* ofile_error.c */; }; + DE09615021CC2BEC00C4ADA1 /* ofile_get_word.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FD621CC1ABB00C4ADA1 /* ofile_get_word.c */; }; + DE09615121CC2BEC00C4ADA1 /* ofile.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FDB21CC1ABB00C4ADA1 /* ofile.c */; }; + DE09615221CC2BEC00C4ADA1 /* print.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FCC21CC1ABB00C4ADA1 /* print.c */; }; + DE09615321CC2BEC00C4ADA1 /* reloc.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FC621CC1ABB00C4ADA1 /* reloc.c */; }; + DE09615421CC2BEC00C4ADA1 /* rnd.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FDF21CC1ABB00C4ADA1 /* rnd.c */; }; + DE09615621CC2BEC00C4ADA1 /* set_arch_flag_name.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FC721CC1ABB00C4ADA1 /* set_arch_flag_name.c */; }; + DE09615721CC2BEC00C4ADA1 /* swap_headers.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FEA21CC1ABB00C4ADA1 /* swap_headers.c */; }; + DE09615821CC2BEC00C4ADA1 /* symbol_list.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FCB21CC1ABB00C4ADA1 /* symbol_list.c */; }; + DE09615921CC2BEC00C4ADA1 /* SymLoc.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FDD21CC1ABB00C4ADA1 /* SymLoc.c */; }; + DE09615A21CC2BEC00C4ADA1 /* unix_standard_mode.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FE321CC1ABB00C4ADA1 /* unix_standard_mode.c */; }; + DE09615B21CC2BEC00C4ADA1 /* version_number.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FE021CC1ABB00C4ADA1 /* version_number.c */; }; + DE09615C21CC2BEC00C4ADA1 /* vm_flush_cache.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FCA21CC1ABB00C4ADA1 /* vm_flush_cache.c */; }; + DE09615D21CC2BEC00C4ADA1 /* write64.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FE221CC1ABB00C4ADA1 /* write64.c */; }; + DE09615E21CC2BEC00C4ADA1 /* writeout.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FE721CC1ABB00C4ADA1 /* writeout.c */; }; + DE09616D21CC4DC900C4ADA1 /* driver.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09610D21CC1ABC00C4ADA1 /* driver.c */; }; + DE09616F21CC4DD500C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE09617021CC4E3C00C4ADA1 /* as.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095F9321CC1ABB00C4ADA1 /* as.1 */; }; + DE09618121CC523600C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE09618221CC52B100C4ADA1 /* app.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09610F21CC1ABC00C4ADA1 /* app.c */; }; + DE09618421CC52B100C4ADA1 /* as.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F521CC1ABC00C4ADA1 /* as.c */; }; + DE09618521CC52B100C4ADA1 /* atof-generic.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F321CC1ABC00C4ADA1 /* atof-generic.c */; }; + DE09618621CC52B100C4ADA1 /* atof-ieee.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960D321CC1ABC00C4ADA1 /* atof-ieee.c */; }; + DE09618721CC52B100C4ADA1 /* dwarf2dbg.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960CD21CC1ABC00C4ADA1 /* dwarf2dbg.c */; }; + DE09618821CC52B100C4ADA1 /* expr.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09610E21CC1ABC00C4ADA1 /* expr.c */; }; + DE09618921CC52B100C4ADA1 /* fixes.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960D821CC1ABC00C4ADA1 /* fixes.c */; }; + DE09618A21CC52B100C4ADA1 /* flonum-const.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960EC21CC1ABC00C4ADA1 /* flonum-const.c */; }; + DE09618B21CC52B100C4ADA1 /* flonum-copy.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F721CC1ABC00C4ADA1 /* flonum-copy.c */; }; + DE09618C21CC52B100C4ADA1 /* flonum-mult.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09610321CC1ABC00C4ADA1 /* flonum-mult.c */; }; + DE09618D21CC52B100C4ADA1 /* frags.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960FF21CC1ABC00C4ADA1 /* frags.c */; }; + DE09618E21CC52B100C4ADA1 /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960E421CC1ABC00C4ADA1 /* hash.c */; }; + DE09618F21CC52B100C4ADA1 /* hex-value.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960E321CC1ABC00C4ADA1 /* hex-value.c */; }; + DE09619021CC52B100C4ADA1 /* input-file.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960DC21CC1ABC00C4ADA1 /* input-file.c */; }; + DE09619121CC52B100C4ADA1 /* input-scrub.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F021CC1ABC00C4ADA1 /* input-scrub.c */; }; + DE09619221CC52B100C4ADA1 /* layout.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960C621CC1ABC00C4ADA1 /* layout.c */; }; + DE09619321CC52B100C4ADA1 /* messages.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960FD21CC1ABC00C4ADA1 /* messages.c */; }; + DE09619421CC52B100C4ADA1 /* obstack.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960D021CC1ABC00C4ADA1 /* obstack.c */; }; + DE09619521CC52B100C4ADA1 /* read.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960E521CC1ABC00C4ADA1 /* read.c */; }; + DE09619621CC52B100C4ADA1 /* sections.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F621CC1ABC00C4ADA1 /* sections.c */; }; + DE09619721CC52B100C4ADA1 /* symbols.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09610121CC1ABC00C4ADA1 /* symbols.c */; }; + DE09619821CC52B100C4ADA1 /* write_object.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F421CC1ABC00C4ADA1 /* write_object.c */; }; + DE09619921CC52B100C4ADA1 /* xmalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960FB21CC1ABC00C4ADA1 /* xmalloc.c */; }; + DE09619A21CC531B00C4ADA1 /* arm.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09610521CC1ABC00C4ADA1 /* arm.c */; }; + DE09619F21CC534200C4ADA1 /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960E421CC1ABC00C4ADA1 /* hash.c */; }; + DE0961A021CC534200C4ADA1 /* messages.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960FD21CC1ABC00C4ADA1 /* messages.c */; }; + DE0961A121CC534200C4ADA1 /* xmalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960FB21CC1ABC00C4ADA1 /* xmalloc.c */; }; + DE0961A221CC534200C4ADA1 /* app.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09610F21CC1ABC00C4ADA1 /* app.c */; }; + DE0961A321CC534200C4ADA1 /* flonum-copy.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F721CC1ABC00C4ADA1 /* flonum-copy.c */; }; + DE0961A421CC534200C4ADA1 /* layout.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960C621CC1ABC00C4ADA1 /* layout.c */; }; + DE0961A621CC534200C4ADA1 /* as.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F521CC1ABC00C4ADA1 /* as.c */; }; + DE0961A721CC534200C4ADA1 /* frags.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960FF21CC1ABC00C4ADA1 /* frags.c */; }; + DE0961A821CC534200C4ADA1 /* atof-ieee.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960D321CC1ABC00C4ADA1 /* atof-ieee.c */; }; + DE0961A921CC534200C4ADA1 /* flonum-mult.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09610321CC1ABC00C4ADA1 /* flonum-mult.c */; }; + DE0961AA21CC534200C4ADA1 /* symbols.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09610121CC1ABC00C4ADA1 /* symbols.c */; }; + DE0961AB21CC534200C4ADA1 /* dwarf2dbg.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960CD21CC1ABC00C4ADA1 /* dwarf2dbg.c */; }; + DE0961AC21CC534200C4ADA1 /* expr.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09610E21CC1ABC00C4ADA1 /* expr.c */; }; + DE0961AD21CC534200C4ADA1 /* input-scrub.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F021CC1ABC00C4ADA1 /* input-scrub.c */; }; + DE0961AE21CC534200C4ADA1 /* atof-generic.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F321CC1ABC00C4ADA1 /* atof-generic.c */; }; + DE0961AF21CC534200C4ADA1 /* fixes.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960D821CC1ABC00C4ADA1 /* fixes.c */; }; + DE0961B021CC534200C4ADA1 /* read.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960E521CC1ABC00C4ADA1 /* read.c */; }; + DE0961B121CC534200C4ADA1 /* write_object.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F421CC1ABC00C4ADA1 /* write_object.c */; }; + DE0961B221CC534200C4ADA1 /* flonum-const.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960EC21CC1ABC00C4ADA1 /* flonum-const.c */; }; + DE0961B321CC534200C4ADA1 /* obstack.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960D021CC1ABC00C4ADA1 /* obstack.c */; }; + DE0961B421CC534200C4ADA1 /* sections.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F621CC1ABC00C4ADA1 /* sections.c */; }; + DE0961B521CC534200C4ADA1 /* hex-value.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960E321CC1ABC00C4ADA1 /* hex-value.c */; }; + DE0961B621CC534200C4ADA1 /* input-file.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960DC21CC1ABC00C4ADA1 /* input-file.c */; }; + DE0961B821CC534200C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE0961BE21CC536A00C4ADA1 /* i386.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960D421CC1ABC00C4ADA1 /* i386.c */; }; + DE0961C321CC53E700C4ADA1 /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960E421CC1ABC00C4ADA1 /* hash.c */; }; + DE0961C421CC53E700C4ADA1 /* messages.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960FD21CC1ABC00C4ADA1 /* messages.c */; }; + DE0961C521CC53E700C4ADA1 /* xmalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960FB21CC1ABC00C4ADA1 /* xmalloc.c */; }; + DE0961C621CC53E700C4ADA1 /* app.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09610F21CC1ABC00C4ADA1 /* app.c */; }; + DE0961C721CC53E700C4ADA1 /* flonum-copy.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F721CC1ABC00C4ADA1 /* flonum-copy.c */; }; + DE0961C821CC53E700C4ADA1 /* layout.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960C621CC1ABC00C4ADA1 /* layout.c */; }; + DE0961C921CC53E700C4ADA1 /* as.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F521CC1ABC00C4ADA1 /* as.c */; }; + DE0961CA21CC53E700C4ADA1 /* frags.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960FF21CC1ABC00C4ADA1 /* frags.c */; }; + DE0961CB21CC53E700C4ADA1 /* atof-ieee.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960D321CC1ABC00C4ADA1 /* atof-ieee.c */; }; + DE0961CD21CC53E700C4ADA1 /* flonum-mult.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09610321CC1ABC00C4ADA1 /* flonum-mult.c */; }; + DE0961CE21CC53E700C4ADA1 /* symbols.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09610121CC1ABC00C4ADA1 /* symbols.c */; }; + DE0961CF21CC53E700C4ADA1 /* dwarf2dbg.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960CD21CC1ABC00C4ADA1 /* dwarf2dbg.c */; }; + DE0961D021CC53E700C4ADA1 /* expr.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09610E21CC1ABC00C4ADA1 /* expr.c */; }; + DE0961D121CC53E700C4ADA1 /* input-scrub.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F021CC1ABC00C4ADA1 /* input-scrub.c */; }; + DE0961D221CC53E700C4ADA1 /* atof-generic.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F321CC1ABC00C4ADA1 /* atof-generic.c */; }; + DE0961D321CC53E700C4ADA1 /* fixes.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960D821CC1ABC00C4ADA1 /* fixes.c */; }; + DE0961D421CC53E700C4ADA1 /* read.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960E521CC1ABC00C4ADA1 /* read.c */; }; + DE0961D521CC53E700C4ADA1 /* write_object.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F421CC1ABC00C4ADA1 /* write_object.c */; }; + DE0961D621CC53E700C4ADA1 /* flonum-const.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960EC21CC1ABC00C4ADA1 /* flonum-const.c */; }; + DE0961D721CC53E700C4ADA1 /* obstack.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960D021CC1ABC00C4ADA1 /* obstack.c */; }; + DE0961D821CC53E700C4ADA1 /* sections.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960F621CC1ABC00C4ADA1 /* sections.c */; }; + DE0961D921CC53E700C4ADA1 /* hex-value.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960E321CC1ABC00C4ADA1 /* hex-value.c */; }; + DE0961DA21CC53E700C4ADA1 /* input-file.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960DC21CC1ABC00C4ADA1 /* input-file.c */; }; + DE0961DC21CC53E700C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE0961E221CC540700C4ADA1 /* i386.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960D421CC1ABC00C4ADA1 /* i386.c */; }; + DE0961F721CC77FC00C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE0961FE21CC781400C4ADA1 /* lipo.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095F9121CC1ABB00C4ADA1 /* lipo.1 */; }; + DE0961FF21CC781C00C4ADA1 /* lipo.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F8721CC1ABB00C4ADA1 /* lipo.c */; }; + DE09620821CC78BD00C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE09620F21CC78DA00C4ADA1 /* strings.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7C21CC1ABB00C4ADA1 /* strings.c */; }; + DE09621021CC78E100C4ADA1 /* strings.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FAB21CC1ABB00C4ADA1 /* strings.1 */; }; + DE09621721CC78F500C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE09621E21CC790500C4ADA1 /* size.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F8921CC1ABB00C4ADA1 /* size.c */; }; + DE09621F21CC793400C4ADA1 /* size-classic.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FB921CC1ABB00C4ADA1 /* size-classic.1 */; }; + DE09622021CC793600C4ADA1 /* size.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095F9221CC1ABB00C4ADA1 /* size.1 */; }; + DE09622D21CC809300C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE09623621CC80A000C4ADA1 /* nm.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7F21CC1ABB00C4ADA1 /* nm.c */; }; + DE09623721CC80AC00C4ADA1 /* nm-classic.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095F9B21CC1ABB00C4ADA1 /* nm-classic.1 */; }; + DE09623821CC80AE00C4ADA1 /* nm.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FB721CC1ABB00C4ADA1 /* nm.1 */; }; + DE09624121CD4F8F00C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE09624A21CD4FA400C4ADA1 /* libtool.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FB821CC1ABB00C4ADA1 /* libtool.1 */; }; + DE09624B21CD4FA600C4ADA1 /* ranlib.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095F9821CC1ABB00C4ADA1 /* ranlib.1 */; }; + DE09624D21CD4FC100C4ADA1 /* libtool.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F8121CC1ABB00C4ADA1 /* libtool.c */; }; + DE09625521CD500600C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE09625F21CD56FB00C4ADA1 /* strip.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7D21CC1ABB00C4ADA1 /* strip.c */; }; + DE09626021CD572400C4ADA1 /* strip.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FB421CC1ABB00C4ADA1 /* strip.1 */; }; + DE09626B21CD594000C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE09627421CD596B00C4ADA1 /* strip.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7D21CC1ABB00C4ADA1 /* strip.c */; }; + DE09627521CD597700C4ADA1 /* nmedit.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095F9A21CC1ABB00C4ADA1 /* nmedit.1 */; }; + DE09627E21CD599B00C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE09628621CD59A400C4ADA1 /* segedit.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F8C21CC1ABB00C4ADA1 /* segedit.c */; }; + DE09628721CD59AE00C4ADA1 /* segedit.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FA021CC1ABB00C4ADA1 /* segedit.1 */; }; + DE09628E21CD59E800C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE09629521CD59F200C4ADA1 /* cmpdylib.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7A21CC1ABB00C4ADA1 /* cmpdylib.c */; }; + DE09629621CD59F900C4ADA1 /* cmpdylib.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FAA21CC1ABB00C4ADA1 /* cmpdylib.1 */; }; + DE09629D21CD5A0400C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE0962A421CD5A1300C4ADA1 /* pagestuff.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FC021CC1ABB00C4ADA1 /* pagestuff.1 */; }; + DE0962A521CD5A1700C4ADA1 /* pagestuff.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F8521CC1ABB00C4ADA1 /* pagestuff.c */; }; + DE0962AC21CD5A2300C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE0962B321CD5A3400C4ADA1 /* redo_prebinding.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FB121CC1ABB00C4ADA1 /* redo_prebinding.1 */; }; + DE0962B421CD5A3900C4ADA1 /* redo_prebinding.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7921CC1ABB00C4ADA1 /* redo_prebinding.c */; }; + DE0962BB21CD5A4900C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE0962C221CD5A5800C4ADA1 /* install_name_tool.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F8621CC1ABB00C4ADA1 /* install_name_tool.c */; }; + DE0962C321CD5A5D00C4ADA1 /* install_name_tool.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095F9521CC1ABB00C4ADA1 /* install_name_tool.1 */; }; + DE0962CA21CD5A6100C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE0962D121CD5A6C00C4ADA1 /* codesign_allocate.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F8B21CC1ABB00C4ADA1 /* codesign_allocate.c */; }; + DE0962D221CD5A7200C4ADA1 /* codesign_allocate.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095F9721CC1ABB00C4ADA1 /* codesign_allocate.1 */; }; + DE0962E721CD618200C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE0962EE21CD618D00C4ADA1 /* ctf_insert.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F8421CC1ABB00C4ADA1 /* ctf_insert.c */; }; + DE0962EF21CD619500C4ADA1 /* ctf_insert.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FC221CC1ABB00C4ADA1 /* ctf_insert.1 */; }; + DE0962F621CD61A600C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE0962FD21CD61B900C4ADA1 /* bitcode_strip.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095F9C21CC1ABB00C4ADA1 /* bitcode_strip.1 */; }; + DE0962FE21CD61BE00C4ADA1 /* bitcode_strip.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F8A21CC1ABB00C4ADA1 /* bitcode_strip.c */; }; + DE09630921CD621600C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE09631021CD622700C4ADA1 /* otool-classic.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FC121CC1ABB00C4ADA1 /* otool-classic.1 */; }; + DE09631121CD628900C4ADA1 /* arm_disasm.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FF221CC1ABC00C4ADA1 /* arm_disasm.c */; }; + DE09631221CD629A00C4ADA1 /* arm64_disasm.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FFA21CC1ABC00C4ADA1 /* arm64_disasm.c */; }; + DE09631321CD629A00C4ADA1 /* coff_print.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FFC21CC1ABC00C4ADA1 /* coff_print.c */; }; + DE09631421CD629A00C4ADA1 /* dyld_bind_info.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FF121CC1ABC00C4ADA1 /* dyld_bind_info.c */; }; + DE09631521CD629A00C4ADA1 /* hppa_disasm.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09600D21CC1ABC00C4ADA1 /* hppa_disasm.c */; }; + DE09631621CD629A00C4ADA1 /* i386_disasm.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FF621CC1ABC00C4ADA1 /* i386_disasm.c */; }; + DE09631721CD629A00C4ADA1 /* i860_disasm.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FF421CC1ABC00C4ADA1 /* i860_disasm.c */; }; + DE09631821CD629A00C4ADA1 /* m68k_disasm.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FF921CC1ABC00C4ADA1 /* m68k_disasm.c */; }; + DE09631921CD629A00C4ADA1 /* m88k_disasm.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09600821CC1ABC00C4ADA1 /* m88k_disasm.c */; }; + DE09631A21CD629A00C4ADA1 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09600421CC1ABC00C4ADA1 /* main.c */; }; + DE09631B21CD629A00C4ADA1 /* notify.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09601021CC1ABC00C4ADA1 /* notify.c */; }; + DE09631C21CD629A00C4ADA1 /* ofile_print.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09600721CC1ABC00C4ADA1 /* ofile_print.c */; }; + DE09631D21CD629A00C4ADA1 /* ppc_disasm.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FF021CC1ABC00C4ADA1 /* ppc_disasm.c */; }; + DE09631E21CD629A00C4ADA1 /* print_bitcode.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09600221CC1ABC00C4ADA1 /* print_bitcode.c */; }; + DE09631F21CD629A00C4ADA1 /* print_objc.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09601121CC1ABC00C4ADA1 /* print_objc.c */; }; + DE09632021CD629A00C4ADA1 /* print_objc2_32bit.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FF821CC1ABC00C4ADA1 /* print_objc2_32bit.c */; }; + DE09632121CD629A00C4ADA1 /* print_objc2_64bit.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FFD21CC1ABC00C4ADA1 /* print_objc2_64bit.c */; }; + DE09632221CD629A00C4ADA1 /* sparc_disasm.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09600F21CC1ABC00C4ADA1 /* sparc_disasm.c */; }; + DE09632621CD638600C4ADA1 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09632521CD638600C4ADA1 /* libc++.tbd */; }; + DE09632D21CD640900C4ADA1 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE175CB222A2248D0001D8CC /* test_util.c in Sources */ = {isa = PBXBuildFile; fileRef = DE175CB122A2248D0001D8CC /* test_util.c */; }; + DE1F63E021CD6438004CA2BF /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09600421CC1ABC00C4ADA1 /* main.c */; }; + DE1F63E121CD644F004CA2BF /* otool.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FBE21CC1ABB00C4ADA1 /* otool.1 */; }; + DE1F63E221CD6452004CA2BF /* llvm-otool.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FBB21CC1ABB00C4ADA1 /* llvm-otool.1 */; }; + DE1F63E321CD6494004CA2BF /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09632521CD638600C4ADA1 /* libc++.tbd */; }; + DE1F63ED21CD6511004CA2BF /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE1F63F421CD6525004CA2BF /* ar.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE09602721CC1ABC00C4ADA1 /* ar.1 */; }; + DE1F63F521CD653D004CA2BF /* append.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09602121CC1ABC00C4ADA1 /* append.c */; }; + DE1F63F621CD653D004CA2BF /* ar.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09602021CC1ABC00C4ADA1 /* ar.c */; }; + DE1F63F721CD653D004CA2BF /* archive.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09602221CC1ABC00C4ADA1 /* archive.c */; }; + DE1F63F821CD653D004CA2BF /* contents.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09601C21CC1ABC00C4ADA1 /* contents.c */; }; + DE1F63F921CD653D004CA2BF /* delete.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09602621CC1ABC00C4ADA1 /* delete.c */; }; + DE1F63FA21CD653D004CA2BF /* extract.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09601A21CC1ABC00C4ADA1 /* extract.c */; }; + DE1F63FB21CD653D004CA2BF /* misc.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09602921CC1ABC00C4ADA1 /* misc.c */; }; + DE1F63FC21CD653D004CA2BF /* move.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09601F21CC1ABC00C4ADA1 /* move.c */; }; + DE1F63FD21CD653D004CA2BF /* print.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09601B21CC1ABC00C4ADA1 /* print.c */; }; + DE1F63FE21CD653D004CA2BF /* replace.c in Sources */ = {isa = PBXBuildFile; fileRef = DE09602521CC1ABC00C4ADA1 /* replace.c */; }; + DE1F641121CD65BC004CA2BF /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE1F641821CD65E8004CA2BF /* checksyms.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7821CC1ABB00C4ADA1 /* checksyms.c */; }; + DE1F641921CD65F1004CA2BF /* checksyms.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FAE21CC1ABB00C4ADA1 /* checksyms.1 */; }; + DE1F642221CD66BA004CA2BF /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE1F642921CD66CF004CA2BF /* indr.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FC321CC1ABB00C4ADA1 /* indr.1 */; }; + DE1F642A21CD66D5004CA2BF /* indr.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F8321CC1ABB00C4ADA1 /* indr.c */; }; + DE1F643321CD66F5004CA2BF /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE1F643A21CD6705004CA2BF /* seg_addr_table.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FA221CC1ABB00C4ADA1 /* seg_addr_table.1 */; }; + DE1F643B21CD670D004CA2BF /* seg_addr_table.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F8E21CC1ABB00C4ADA1 /* seg_addr_table.c */; }; + DE1F644221CD6715004CA2BF /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE1F644921CD672B004CA2BF /* check_dylib.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FB521CC1ABB00C4ADA1 /* check_dylib.1 */; }; + DE1F644A21CD6730004CA2BF /* check_dylib.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F8221CC1ABB00C4ADA1 /* check_dylib.c */; }; + DE1F645121CD6734004CA2BF /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE1F645821CD6757004CA2BF /* seg_hack.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7B21CC1ABB00C4ADA1 /* seg_hack.c */; }; + DE1F646021CD67E8004CA2BF /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE1F646621CD680B004CA2BF /* mtoc.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FA921CC1ABB00C4ADA1 /* mtoc.1 */; }; + DE1F646721CD68C2004CA2BF /* mtoc.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0960BD21CC1ABC00C4ADA1 /* mtoc.c */; }; + DE1F648021CD84A3004CA2BF /* Private_CompilerTools.html in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE09601621CC1ABC00C4ADA1 /* Private_CompilerTools.html */; }; + DE1F648121CD84A5004CA2BF /* FatFiles.rtf in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE09601521CC1ABC00C4ADA1 /* FatFiles.rtf */; }; + DE1F648721CD8521004CA2BF /* arch.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FA621CC1ABB00C4ADA1 /* arch.3 */; }; + DE1F648A21CD8521004CA2BF /* end.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FB321CC1ABB00C4ADA1 /* end.3 */; }; + DE1F648B21CD8521004CA2BF /* get_end.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FA421CC1ABB00C4ADA1 /* get_end.3 */; }; + DE1F648C21CD8521004CA2BF /* getsectbyname.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FB621CC1ABB00C4ADA1 /* getsectbyname.3 */; }; + DE1F648D21CD8521004CA2BF /* getsectbynamefromheader.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FBA21CC1ABB00C4ADA1 /* getsectbynamefromheader.3 */; }; + DE1F648E21CD8521004CA2BF /* getsectdata.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FB021CC1ABB00C4ADA1 /* getsectdata.3 */; }; + DE1F648F21CD8521004CA2BF /* getsectdatafromheader.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095F9D21CC1ABB00C4ADA1 /* getsectdatafromheader.3 */; }; + DE1F649021CD8521004CA2BF /* getsegbyname.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095F9621CC1ABB00C4ADA1 /* getsegbyname.3 */; }; + DE1F649121CD8521004CA2BF /* kld.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FAC21CC1ABB00C4ADA1 /* kld.3 */; }; + DE1F649C21CD8574004CA2BF /* a.out.5 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095F9F21CC1ABB00C4ADA1 /* a.out.5 */; }; + DE1F649D21CD8574004CA2BF /* Mach-O.5 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FA121CC1ABB00C4ADA1 /* Mach-O.5 */; }; + DE1F649E21CD8574004CA2BF /* ranlib.5 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FB221CC1ABB00C4ADA1 /* ranlib.5 */; }; + DE1F649F21CD8574004CA2BF /* stab.5 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FBD21CC1ABB00C4ADA1 /* stab.5 */; }; + DE1F64A021CD8579004CA2BF /* ar.5 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE09601D21CC1ABC00C4ADA1 /* ar.5 */; }; + DE21482221F59BCE00FF8882 /* allocate_test.c in Sources */ = {isa = PBXBuildFile; fileRef = DE21482121F59BCE00FF8882 /* allocate_test.c */; }; + DE21482421F5AB0F00FF8882 /* arch_test.c in Sources */ = {isa = PBXBuildFile; fileRef = DE21482321F5AB0F00FF8882 /* arch_test.c */; }; + DE21482621F5B7D700FF8882 /* get_arch_from_host_test.c in Sources */ = {isa = PBXBuildFile; fileRef = DE21482521F5B7D700FF8882 /* get_arch_from_host_test.c */; }; + DE38751B21F13F2C00704209 /* ofile.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095FDB21CC1ABB00C4ADA1 /* ofile.c */; }; + DE5DC66221F7EA8000A7CA07 /* loader.h in Headers */ = {isa = PBXBuildFile; fileRef = DE0960A321CC1ABC00C4ADA1 /* loader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DE5DC66B21F7EA8000A7CA07 /* getsecbyname.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7321CC1ABB00C4ADA1 /* getsecbyname.c */; }; + DE5DC68621F7ED5200A7CA07 /* getsect.h in Headers */ = {isa = PBXBuildFile; fileRef = DE5DC68521F7ED5200A7CA07 /* getsect.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DE822A0821CDAB13008CD150 /* arch.h in Headers */ = {isa = PBXBuildFile; fileRef = DE0960B521CC1ABC00C4ADA1 /* arch.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DE822A0921CDAB13008CD150 /* fat.h in Headers */ = {isa = PBXBuildFile; fileRef = DE0960B121CC1ABC00C4ADA1 /* fat.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DE822A0A21CDAB13008CD150 /* getsect.h in Headers */ = {isa = PBXBuildFile; fileRef = DE09609021CC1ABC00C4ADA1 /* getsect.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DE822A0B21CDAB13008CD150 /* loader.h in Headers */ = {isa = PBXBuildFile; fileRef = DE0960A321CC1ABC00C4ADA1 /* loader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DE822A0C21CDAB13008CD150 /* ranlib.h in Headers */ = {isa = PBXBuildFile; fileRef = DE09609121CC1ABC00C4ADA1 /* ranlib.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DE822A0D21CDAB13008CD150 /* reloc.h in Headers */ = {isa = PBXBuildFile; fileRef = DE0960A421CC1ABC00C4ADA1 /* reloc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DE822A0E21CDAB13008CD150 /* stab.h in Headers */ = {isa = PBXBuildFile; fileRef = DE09609C21CC1ABC00C4ADA1 /* stab.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DE822A0F21CDAB13008CD150 /* swap.h in Headers */ = {isa = PBXBuildFile; fileRef = DE09609B21CC1ABC00C4ADA1 /* swap.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DE822A1021CDAB2B008CD150 /* arch.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6B21CC1ABB00C4ADA1 /* arch.c */; }; + DE822A1221CDAB2B008CD150 /* get_end.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6C21CC1ABB00C4ADA1 /* get_end.c */; }; + DE822A1321CDAB2B008CD150 /* getsecbyname.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7321CC1ABB00C4ADA1 /* getsecbyname.c */; }; + DE822A1421CDAB2B008CD150 /* getsegbyname.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6621CC1ABB00C4ADA1 /* getsegbyname.c */; }; + DE822A1521CDAB2B008CD150 /* hppa_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7221CC1ABB00C4ADA1 /* hppa_swap.c */; }; + DE822A1621CDAB2B008CD150 /* i386_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6821CC1ABB00C4ADA1 /* i386_swap.c */; }; + DE822A1721CDAB2B008CD150 /* i860_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7521CC1ABB00C4ADA1 /* i860_swap.c */; }; + DE822A1821CDAB2B008CD150 /* m68k_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7421CC1ABB00C4ADA1 /* m68k_swap.c */; }; + DE822A1921CDAB2B008CD150 /* m88k_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6921CC1ABB00C4ADA1 /* m88k_swap.c */; }; + DE822A1C21CDAB2B008CD150 /* ppc_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6F21CC1ABB00C4ADA1 /* ppc_swap.c */; }; + DE822A1E21CDAB2B008CD150 /* slot_name.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6721CC1ABB00C4ADA1 /* slot_name.c */; }; + DE822A1F21CDAB2B008CD150 /* sparc_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7021CC1ABB00C4ADA1 /* sparc_swap.c */; }; + DE822A2021CDAB2B008CD150 /* swap.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F7121CC1ABB00C4ADA1 /* swap.c */; }; + DE97E91B21F3B72700C7947D /* libstuff_test.c in Sources */ = {isa = PBXBuildFile; fileRef = DE97E91A21F3B72700C7947D /* libstuff_test.c */; }; + DE97E92421F3B86100C7947D /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DE97E92621F3B8EC00C7947D /* guess_short_name_test.c in Sources */ = {isa = PBXBuildFile; fileRef = DE97E92521F3B8EC00C7947D /* guess_short_name_test.c */; }; + DE97E92921F3B91900C7947D /* test.c in Sources */ = {isa = PBXBuildFile; fileRef = DE97E92721F3B91800C7947D /* test.c */; }; + DE97E92B21F3B97A00C7947D /* null_test.c in Sources */ = {isa = PBXBuildFile; fileRef = DE97E92A21F3B97A00C7947D /* null_test.c */; }; + DEA1B37B221F52A4003A9149 /* reloc.h in Headers */ = {isa = PBXBuildFile; fileRef = DE0960A421CC1ABC00C4ADA1 /* reloc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DEA1B37C221F52C8003A9149 /* fat.h in Headers */ = {isa = PBXBuildFile; fileRef = DE0960B121CC1ABC00C4ADA1 /* fat.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DEA240A221CE0C250026D013 /* libsyminfo.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095FC421CC1ABB00C4ADA1 /* libsyminfo.3 */; }; + DEA240A321CE0C3A0026D013 /* redo_prebinding.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE095F9021CC1ABB00C4ADA1 /* redo_prebinding.3 */; }; + DEA240A421CE12070026D013 /* libsyminfo.c in Sources */ = {isa = PBXBuildFile; fileRef = DE095F6321CC1ABB00C4ADA1 /* libsyminfo.c */; }; + DEB23D9621DEA192007F9934 /* vtool.c in Sources */ = {isa = PBXBuildFile; fileRef = DEB23D9421DEA192007F9934 /* vtool.c */; }; + DEB23D9921DEA214007F9934 /* vtool.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEB23D9521DEA192007F9934 /* vtool.1 */; }; + DEB5E8D1228B04D000263617 /* version_number_test.c in Sources */ = {isa = PBXBuildFile; fileRef = DEB5E8D0228B04D000263617 /* version_number_test.c */; }; + DEB7156122A194230031FD9F /* args.c in Sources */ = {isa = PBXBuildFile; fileRef = DEB7156022A194230031FD9F /* args.c */; }; + DEB7157722A1F27A0031FD9F /* args_test.c in Sources */ = {isa = PBXBuildFile; fileRef = DEB7157622A1F27A0031FD9F /* args_test.c */; }; + DEC00B61220012660079FFD3 /* libstuff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DE09612C21CC218E00C4ADA1 /* libstuff.a */; }; + DEC00B6B220012C80079FFD3 /* mtor.c in Sources */ = {isa = PBXBuildFile; fileRef = DEC00B6A220012C80079FFD3 /* mtor.c */; }; + DEC00B6D2200193E0079FFD3 /* mtor.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEC00B6C220012DA0079FFD3 /* mtor.1 */; }; + DEDFD7E42299C7F100230D7D /* rnd_test.c in Sources */ = {isa = PBXBuildFile; fileRef = DEDFD7E32299C7F100230D7D /* rnd_test.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + DE000B4821CDBB29000CEC53 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE000B3521CDB9DB000CEC53; + remoteInfo = "macho static"; + }; + DE000B5F21CDBEB4000CEC53 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE000B4A21CDBE77000CEC53; + remoteInfo = "macho static 2"; + }; + DE000B6921CDBEF7000CEC53 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE000B6E21CDEF81000CEC53 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE000B6421CDBEE8000CEC53; + remoteInfo = libredo_prebinding; + }; + DE09612421CC209A00C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09611421CC205D00C4ADA1; + remoteInfo = cctools; + }; + DE09612621CC20A000C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09611821CC207000C4ADA1; + remoteInfo = cctools_ofiles; + }; + DE09613521CC2BA200C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE09616B21CC4DB800C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE09617121CC4E4C00C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09616221CC4A7C00C4ADA1; + remoteInfo = "as driver"; + }; + DE09617F21CC523300C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE09619D21CC534200C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE0961C121CC53E700C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE0961E721CC54AF00C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09617621CC4F1B00C4ADA1; + remoteInfo = "as arm"; + }; + DE0961E921CC54AF00C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09619B21CC534200C4ADA1; + remoteInfo = "as i386"; + }; + DE0961EB21CC54AF00C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE0961BF21CC53E700C4ADA1; + remoteInfo = "as x86_64"; + }; + DE0961EF21CC560000C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE0961E321CC548B00C4ADA1; + remoteInfo = assemblers; + }; + DE0961F321CC77FC00C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE09620021CC784600C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE0961F121CC77FC00C4ADA1; + remoteInfo = lipo; + }; + DE09620421CC78BD00C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE09621321CC78F500C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE09622321CC7FCD00C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09620221CC78BD00C4ADA1; + remoteInfo = strings; + }; + DE09622521CC7FCF00C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09621121CC78F500C4ADA1; + remoteInfo = "size-classic"; + }; + DE09622921CC809300C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE09623921CC80C500C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09622721CC809300C4ADA1; + remoteInfo = "nm-classic"; + }; + DE09623D21CD4F8F00C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE09625121CD500600C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE09626121CD592E00C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09624F21CD500600C4ADA1; + remoteInfo = strip; + }; + DE09626321CD593000C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09623B21CD4F8F00C4ADA1; + remoteInfo = libtool; + }; + DE09626721CD594000C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE09627621CD598F00C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09626521CD594000C4ADA1; + remoteInfo = nmedit; + }; + DE09627A21CD599B00C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE09628A21CD59E800C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE09629921CD5A0400C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE0962A821CD5A2300C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE0962B721CD5A4900C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE0962C621CD5A6100C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE0962D521CD616800C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09627821CD599B00C4ADA1; + remoteInfo = segedit; + }; + DE0962D721CD616800C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09628821CD59E800C4ADA1; + remoteInfo = cmpdylib; + }; + DE0962D921CD616800C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09629721CD5A0400C4ADA1; + remoteInfo = pagestuff; + }; + DE0962DD21CD616800C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE0962B521CD5A4900C4ADA1; + remoteInfo = install_name_tool; + }; + DE0962E321CD618200C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE0962F221CD61A600C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE0962FF21CD61CA00C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE0962E121CD618200C4ADA1; + remoteInfo = ctf_insert; + }; + DE09630121CD61CA00C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE0962F021CD61A600C4ADA1; + remoteInfo = bitcode_strip; + }; + DE09630521CD621600C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE09632321CD635900C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09630321CD621600C4ADA1; + remoteInfo = "otool-classic"; + }; + DE09632921CD640900C4ADA1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE1F63E521CD64C0004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09632721CD640900C4ADA1; + remoteInfo = "llvm-otool"; + }; + DE1F63E921CD6511004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE1F63FF21CD6555004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE1F63E721CD6511004CA2BF; + remoteInfo = ar; + }; + DE1F640421CD65BC004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE1F641A21CD6600004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE1F640221CD65BC004CA2BF; + remoteInfo = checksyms; + }; + DE1F641E21CD66BA004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE1F642B21CD66DF004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE1F641C21CD66BA004CA2BF; + remoteInfo = indr; + }; + DE1F642F21CD66F5004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE1F643E21CD6715004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE1F644D21CD6734004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE1F645C21CD67E8004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DE1F646C21CD690B004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE1F644B21CD6734004CA2BF; + remoteInfo = seg_hack; + }; + DE1F647521CD7219004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE1F647121CD71E0004CA2BF; + remoteInfo = "codesign_allocate install"; + }; + DE1F647721CD7222004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE0962C421CD5A6100C4ADA1; + remoteInfo = codesign_allocate; + }; + DE1F64A121CD858A004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE1F647A21CD8443004CA2BF; + remoteInfo = RelNotes; + }; + DE1F64A321CD858A004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE1F648221CD84C7004CA2BF; + remoteInfo = man3; + }; + DE1F64A521CD858A004CA2BF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE1F649721CD855C004CA2BF; + remoteInfo = man5; + }; + DE5DC68121F7EAA400A7CA07 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE5DC67C21F7EA8E00A7CA07; + remoteInfo = "macho headers driverkit"; + }; + DE5DC68921F7F44200A7CA07 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE5DC65C21F7EA8000A7CA07; + remoteInfo = "macho dynamic driverkit"; + }; + DE8229FE21CDA419008CD150 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE8229F821CD8DD6008CD150; + remoteInfo = "macho dynamic"; + }; + DE822A0621CDAAAE008CD150 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE822A0021CDA455008CD150; + remoteInfo = "macho headers"; + }; + DE97E92221F3B85A00C7947D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DEA2409221CDF1240026D013 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE000B7321CDEFDF000CEC53; + remoteInfo = syminfo; + }; + DEA2409B21CE08940026D013 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE1F645A21CD67E8004CA2BF; + remoteInfo = mtoc; + }; + DEA2409E21CE096A0026D013 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DEA2409721CE08830026D013; + remoteInfo = "mtoc install"; + }; + DEB23D9721DEA1EE007F9934 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DEB23D8C21DEA11C007F9934; + remoteInfo = vtool; + }; + DEC00B5D220012660079FFD3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE09612B21CC218E00C4ADA1; + remoteInfo = stuff; + }; + DEC00B68220012B10079FFD3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DEC00B5B220012660079FFD3; + remoteInfo = mtor; + }; + DEC31BCD21F652520006E1D8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE76108421CC103000736984 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE97E91721F3B72700C7947D; + remoteInfo = libstuff_test; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + DE09616121CC4A7C00C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE09617021CC4E3C00C4ADA1 /* as.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE09617521CC4F1B00C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE0961B921CC534200C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE0961DD21CC53E700C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE0961F821CC77FC00C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE0961FE21CC781400C4ADA1 /* lipo.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE09620921CC78BD00C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE09621021CC78E100C4ADA1 /* strings.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE09621821CC78F500C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE09621F21CC793400C4ADA1 /* size-classic.1 in CopyFiles */, + DE09622021CC793600C4ADA1 /* size.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE09622E21CC809300C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE09623721CC80AC00C4ADA1 /* nm-classic.1 in CopyFiles */, + DE09623821CC80AE00C4ADA1 /* nm.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE09624221CD4F8F00C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE09624A21CD4FA400C4ADA1 /* libtool.1 in CopyFiles */, + DE09624B21CD4FA600C4ADA1 /* ranlib.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE09625621CD500600C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE09626021CD572400C4ADA1 /* strip.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE09626C21CD594000C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE09627521CD597700C4ADA1 /* nmedit.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE09627F21CD599B00C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE09628721CD59AE00C4ADA1 /* segedit.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE09628F21CD59E800C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE09629621CD59F900C4ADA1 /* cmpdylib.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE09629E21CD5A0400C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE0962A421CD5A1300C4ADA1 /* pagestuff.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE0962AD21CD5A2300C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE0962B321CD5A3400C4ADA1 /* redo_prebinding.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE0962BC21CD5A4900C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE0962C321CD5A5D00C4ADA1 /* install_name_tool.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE0962CB21CD5A6100C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE0962D221CD5A7200C4ADA1 /* codesign_allocate.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE0962E821CD618200C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE0962EF21CD619500C4ADA1 /* ctf_insert.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE0962F721CD61A600C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE0962FD21CD61B900C4ADA1 /* bitcode_strip.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE09630A21CD621600C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE09631021CD622700C4ADA1 /* otool-classic.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE09632E21CD640900C4ADA1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE1F63E121CD644F004CA2BF /* otool.1 in CopyFiles */, + DE1F63E221CD6452004CA2BF /* llvm-otool.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE1F63EE21CD6511004CA2BF /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE1F63F421CD6525004CA2BF /* ar.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE1F641221CD65BC004CA2BF /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRLOCALMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE1F641921CD65F1004CA2BF /* checksyms.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE1F642321CD66BA004CA2BF /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRLOCALMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE1F642921CD66CF004CA2BF /* indr.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE1F643421CD66F5004CA2BF /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRLOCALMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE1F643A21CD6705004CA2BF /* seg_addr_table.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE1F644321CD6715004CA2BF /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRLOCALMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DE1F644921CD672B004CA2BF /* check_dylib.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE1F645221CD6734004CA2BF /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRLOCALMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE1F646121CD67E8004CA2BF /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_EFI}/share/man/man1"; + dstSubfolderSpec = 0; + files = ( + DE1F646621CD680B004CA2BF /* mtoc.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE1F647F21CD8451004CA2BF /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "${CCTOOLS_USRLOCAL}/RelNotes"; + dstSubfolderSpec = 0; + files = ( + DE1F648021CD84A3004CA2BF /* Private_CompilerTools.html in CopyFiles */, + DE1F648121CD84A5004CA2BF /* FatFiles.rtf in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE1F648621CD8500004CA2BF /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "${CCTOOLS_USRMAN}/man3"; + dstSubfolderSpec = 0; + files = ( + DE1F648721CD8521004CA2BF /* arch.3 in CopyFiles */, + DE1F648A21CD8521004CA2BF /* end.3 in CopyFiles */, + DE1F648B21CD8521004CA2BF /* get_end.3 in CopyFiles */, + DE1F648C21CD8521004CA2BF /* getsectbyname.3 in CopyFiles */, + DE1F648D21CD8521004CA2BF /* getsectbynamefromheader.3 in CopyFiles */, + DE1F648E21CD8521004CA2BF /* getsectdata.3 in CopyFiles */, + DE1F648F21CD8521004CA2BF /* getsectdatafromheader.3 in CopyFiles */, + DE1F649021CD8521004CA2BF /* getsegbyname.3 in CopyFiles */, + DE1F649121CD8521004CA2BF /* kld.3 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE1F649B21CD855F004CA2BF /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "${CCTOOLS_USRMAN}/man5"; + dstSubfolderSpec = 0; + files = ( + DE1F649C21CD8574004CA2BF /* a.out.5 in CopyFiles */, + DE1F64A021CD8579004CA2BF /* ar.5 in CopyFiles */, + DE1F649D21CD8574004CA2BF /* Mach-O.5 in CopyFiles */, + DE1F649E21CD8574004CA2BF /* ranlib.5 in CopyFiles */, + DE1F649F21CD8574004CA2BF /* stab.5 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DE97E91621F3B72700C7947D /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DEA240A121CE0BF40026D013 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "${CCTOOLS_USRLOCALMAN}/man3"; + dstSubfolderSpec = 0; + files = ( + DEA240A221CE0C250026D013 /* libsyminfo.3 in CopyFiles */, + DEA240A321CE0C3A0026D013 /* redo_prebinding.3 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DEB23D8B21DEA11C007F9934 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DEB23D9921DEA214007F9934 /* vtool.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + DEC00B62220012660079FFD3 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "${CCTOOLS_USRLOCALMAN}/man1"; + dstSubfolderSpec = 0; + files = ( + DEC00B6D2200193E0079FFD3 /* mtor.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + DE000B3621CDB9DB000CEC53 /* libmacho.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libmacho.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DE000B3A21CDB9FE000CEC53 /* macho_static.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = macho_static.xcconfig; sourceTree = ""; }; + DE000B5E21CDBE77000CEC53 /* libmacho_static.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libmacho_static.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DE000B6521CDBEE8000CEC53 /* libredo_prebinding.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libredo_prebinding.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DE000B7421CDEFDF000CEC53 /* libsyminfo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsyminfo.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DE095EF721CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095EF821CC1ABB00C4ADA1 /* foo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = foo.c; sourceTree = ""; }; + DE095EF921CC1ABB00C4ADA1 /* expected.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = expected.txt; sourceTree = ""; }; + DE095EFA21CC1ABB00C4ADA1 /* bar.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = bar.c; sourceTree = ""; }; + DE095EFC21CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095EFD21CC1ABB00C4ADA1 /* foo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = foo.c; sourceTree = ""; }; + DE095EFE21CC1ABB00C4ADA1 /* expected.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = expected.txt; sourceTree = ""; }; + DE095EFF21CC1ABB00C4ADA1 /* bar.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = bar.c; sourceTree = ""; }; + DE095F0121CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F0221CC1ABB00C4ADA1 /* foo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = foo.c; sourceTree = ""; }; + DE095F0421CC1ABB00C4ADA1 /* hello.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hello.c; sourceTree = ""; }; + DE095F0521CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F0721CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F0821CC1ABB00C4ADA1 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + DE095F0921CC1ABB00C4ADA1 /* MementoMori1.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = MementoMori1.txt; sourceTree = ""; }; + DE095F0B21CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F0C21CC1ABB00C4ADA1 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + DE095F0D21CC1ABB00C4ADA1 /* MementoMori2.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = MementoMori2.txt; sourceTree = ""; }; + DE095F0E21CC1ABB00C4ADA1 /* MementoMori1.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = MementoMori1.txt; sourceTree = ""; }; + DE095F1021CC1ABB00C4ADA1 /* hello.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hello.c; sourceTree = ""; }; + DE095F1121CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F1321CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F1521CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F1621CC1ABB00C4ADA1 /* libfoo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = libfoo.c; sourceTree = ""; }; + DE095F1821CC1ABB00C4ADA1 /* hello.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hello.c; sourceTree = ""; }; + DE095F1921CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F1B21CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F1C21CC1ABB00C4ADA1 /* empty.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = empty.c; sourceTree = ""; }; + DE095F1E21CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F1F21CC1ABB00C4ADA1 /* empty.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = empty.c; sourceTree = ""; }; + DE095F2121CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F2221CC1ABB00C4ADA1 /* libfoo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = libfoo.c; sourceTree = ""; }; + DE095F2421CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F2521CC1ABB00C4ADA1 /* foo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = foo.c; sourceTree = ""; }; + DE095F2621CC1ABB00C4ADA1 /* expected.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = expected.txt; sourceTree = ""; }; + DE095F2721CC1ABB00C4ADA1 /* expected2.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = expected2.txt; sourceTree = ""; }; + DE095F2821CC1ABB00C4ADA1 /* bar.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = bar.c; sourceTree = ""; }; + DE095F2A21CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F2B21CC1ABB00C4ADA1 /* foo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = foo.c; sourceTree = ""; }; + DE095F2D21CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F2E21CC1ABB00C4ADA1 /* libfoo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = libfoo.c; sourceTree = ""; }; + DE095F3021CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F3121CC1ABB00C4ADA1 /* foo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = foo.c; sourceTree = ""; }; + DE095F3321CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F3421CC1ABB00C4ADA1 /* foo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = foo.c; sourceTree = ""; }; + DE095F3521CC1ABB00C4ADA1 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + DE095F3621CC1ABB00C4ADA1 /* bar.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = bar.c; sourceTree = ""; }; + DE095F3821CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F3A21CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F3C21CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F3D21CC1ABB00C4ADA1 /* foo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = foo.c; sourceTree = ""; }; + DE095F3F21CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F4021CC1ABB00C4ADA1 /* foo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = foo.c; sourceTree = ""; }; + DE095F4121CC1ABB00C4ADA1 /* expected.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = expected.txt; sourceTree = ""; }; + DE095F4221CC1ABB00C4ADA1 /* expected2.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = expected2.txt; sourceTree = ""; }; + DE095F4321CC1ABB00C4ADA1 /* bar.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = bar.c; sourceTree = ""; }; + DE095F4521CC1ABB00C4ADA1 /* hello.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hello.c; sourceTree = ""; }; + DE095F4621CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F4821CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F4921CC1ABB00C4ADA1 /* expected.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = expected.txt; sourceTree = ""; }; + DE095F4A21CC1ABB00C4ADA1 /* libfoo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = libfoo.c; sourceTree = ""; }; + DE095F4C21CC1ABB00C4ADA1 /* hello.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hello.c; sourceTree = ""; }; + DE095F4D21CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F4F21CC1ABB00C4ADA1 /* pass-iff-exit-zero.pl */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = "pass-iff-exit-zero.pl"; sourceTree = ""; }; + DE095F5021CC1ABB00C4ADA1 /* verify-align.pl */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = "verify-align.pl"; sourceTree = ""; }; + DE095F5121CC1ABB00C4ADA1 /* fail-iff-exit-zero.pl */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = "fail-iff-exit-zero.pl"; sourceTree = ""; }; + DE095F5221CC1ABB00C4ADA1 /* exit-non-zero-pass.pl */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = "exit-non-zero-pass.pl"; sourceTree = ""; }; + DE095F5321CC1ABB00C4ADA1 /* fail-if-exit-zero.pl */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = "fail-if-exit-zero.pl"; sourceTree = ""; }; + DE095F5421CC1ABB00C4ADA1 /* pass-iff-stdin.pl */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = "pass-iff-stdin.pl"; sourceTree = ""; }; + DE095F5521CC1ABB00C4ADA1 /* pass-iff-no-stdin.pl */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = "pass-iff-no-stdin.pl"; sourceTree = ""; }; + DE095F5621CC1ABB00C4ADA1 /* fail-if-no-stdin.pl */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = "fail-if-no-stdin.pl"; sourceTree = ""; }; + DE095F5721CC1ABB00C4ADA1 /* fail-if-stdin.pl */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = "fail-if-stdin.pl"; sourceTree = ""; }; + DE095F5821CC1ABB00C4ADA1 /* fail-if-exit-non-zero.pl */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = "fail-if-exit-non-zero.pl"; sourceTree = ""; }; + DE095F5921CC1ABB00C4ADA1 /* pass-iff-exit-non-zero.pl */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = "pass-iff-exit-non-zero.pl"; sourceTree = ""; }; + DE095F5A21CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F5C21CC1ABB00C4ADA1 /* verstool.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = verstool.c; sourceTree = ""; }; + DE095F5D21CC1ABB00C4ADA1 /* common.makefile */ = {isa = PBXFileReference; lastKnownFileType = text; path = common.makefile; sourceTree = ""; }; + DE095F5E21CC1ABB00C4ADA1 /* README.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.txt; sourceTree = ""; }; + DE095F5F21CC1ABB00C4ADA1 /* run-tests */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = "run-tests"; sourceTree = ""; }; + DE095F6121CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F6221CC1ABB00C4ADA1 /* notes */ = {isa = PBXFileReference; lastKnownFileType = text; path = notes; sourceTree = ""; }; + DE095F6321CC1ABB00C4ADA1 /* libsyminfo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = libsyminfo.c; sourceTree = ""; }; + DE095F6521CC1ABB00C4ADA1 /* shlib.ofileList */ = {isa = PBXFileReference; lastKnownFileType = text; path = shlib.ofileList; sourceTree = ""; }; + DE095F6621CC1ABB00C4ADA1 /* getsegbyname.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = getsegbyname.c; sourceTree = ""; }; + DE095F6721CC1ABB00C4ADA1 /* slot_name.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = slot_name.c; sourceTree = ""; }; + DE095F6821CC1ABB00C4ADA1 /* i386_swap.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = i386_swap.c; sourceTree = ""; }; + DE095F6921CC1ABB00C4ADA1 /* m88k_swap.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = m88k_swap.c; sourceTree = ""; }; + DE095F6A21CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F6B21CC1ABB00C4ADA1 /* arch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = arch.c; sourceTree = ""; }; + DE095F6C21CC1ABB00C4ADA1 /* get_end.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = get_end.c; sourceTree = ""; }; + DE095F6D21CC1ABB00C4ADA1 /* dylib.ofileList */ = {isa = PBXFileReference; lastKnownFileType = text; path = dylib.ofileList; sourceTree = ""; }; + DE095F6E21CC1ABB00C4ADA1 /* notes */ = {isa = PBXFileReference; lastKnownFileType = text; path = notes; sourceTree = ""; }; + DE095F6F21CC1ABB00C4ADA1 /* ppc_swap.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ppc_swap.c; sourceTree = ""; }; + DE095F7021CC1ABB00C4ADA1 /* sparc_swap.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sparc_swap.c; sourceTree = ""; }; + DE095F7121CC1ABB00C4ADA1 /* swap.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = swap.c; sourceTree = ""; }; + DE095F7221CC1ABB00C4ADA1 /* hppa_swap.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hppa_swap.c; sourceTree = ""; }; + DE095F7321CC1ABB00C4ADA1 /* getsecbyname.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = getsecbyname.c; sourceTree = ""; }; + DE095F7421CC1ABB00C4ADA1 /* m68k_swap.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = m68k_swap.c; sourceTree = ""; }; + DE095F7521CC1ABB00C4ADA1 /* i860_swap.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = i860_swap.c; sourceTree = ""; }; + DE095F7821CC1ABB00C4ADA1 /* checksyms.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = checksyms.c; sourceTree = ""; }; + DE095F7921CC1ABB00C4ADA1 /* redo_prebinding.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = redo_prebinding.c; sourceTree = ""; }; + DE095F7A21CC1ABB00C4ADA1 /* cmpdylib.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = cmpdylib.c; sourceTree = ""; }; + DE095F7B21CC1ABB00C4ADA1 /* seg_hack.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = seg_hack.c; sourceTree = ""; }; + DE095F7C21CC1ABB00C4ADA1 /* strings.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = strings.c; sourceTree = ""; }; + DE095F7D21CC1ABB00C4ADA1 /* strip.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = strip.c; sourceTree = ""; usesTabs = 1; }; + DE095F7E21CC1ABB00C4ADA1 /* inout.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = inout.c; sourceTree = ""; }; + DE095F7F21CC1ABB00C4ADA1 /* nm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = nm.c; sourceTree = ""; }; + DE095F8021CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F8121CC1ABB00C4ADA1 /* libtool.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = libtool.c; sourceTree = ""; usesTabs = 1; }; + DE095F8221CC1ABB00C4ADA1 /* check_dylib.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = check_dylib.c; sourceTree = ""; }; + DE095F8321CC1ABB00C4ADA1 /* indr.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = indr.c; sourceTree = ""; }; + DE095F8421CC1ABB00C4ADA1 /* ctf_insert.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ctf_insert.c; sourceTree = ""; }; + DE095F8521CC1ABB00C4ADA1 /* pagestuff.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pagestuff.c; sourceTree = ""; }; + DE095F8621CC1ABB00C4ADA1 /* install_name_tool.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = install_name_tool.c; sourceTree = ""; }; + DE095F8721CC1ABB00C4ADA1 /* lipo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = lipo.c; sourceTree = ""; usesTabs = 1; }; + DE095F8821CC1ABB00C4ADA1 /* notes */ = {isa = PBXFileReference; lastKnownFileType = text; path = notes; sourceTree = ""; }; + DE095F8921CC1ABB00C4ADA1 /* size.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = size.c; sourceTree = ""; usesTabs = 1; }; + DE095F8A21CC1ABB00C4ADA1 /* bitcode_strip.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = bitcode_strip.c; sourceTree = ""; }; + DE095F8B21CC1ABB00C4ADA1 /* codesign_allocate.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = codesign_allocate.c; sourceTree = ""; }; + DE095F8C21CC1ABB00C4ADA1 /* segedit.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = segedit.c; sourceTree = ""; }; + DE095F8D21CC1ABB00C4ADA1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DE095F8E21CC1ABB00C4ADA1 /* seg_addr_table.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = seg_addr_table.c; sourceTree = ""; }; + DE095F9021CC1ABB00C4ADA1 /* redo_prebinding.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = redo_prebinding.3; sourceTree = ""; }; + DE095F9121CC1ABB00C4ADA1 /* lipo.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = lipo.1; sourceTree = ""; }; + DE095F9221CC1ABB00C4ADA1 /* size.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = size.1; sourceTree = ""; }; + DE095F9321CC1ABB00C4ADA1 /* as.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = as.1; sourceTree = ""; }; + DE095F9421CC1ABB00C4ADA1 /* NSObjectFileImage_priv.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = NSObjectFileImage_priv.3; sourceTree = ""; }; + DE095F9521CC1ABB00C4ADA1 /* install_name_tool.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = install_name_tool.1; sourceTree = ""; }; + DE095F9621CC1ABB00C4ADA1 /* getsegbyname.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = getsegbyname.3; sourceTree = ""; }; + DE095F9721CC1ABB00C4ADA1 /* codesign_allocate.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = codesign_allocate.1; sourceTree = ""; }; + DE095F9821CC1ABB00C4ADA1 /* ranlib.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = ranlib.1; sourceTree = ""; }; + DE095F9921CC1ABB00C4ADA1 /* dyld_debug.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = dyld_debug.3; sourceTree = ""; }; + DE095F9A21CC1ABB00C4ADA1 /* nmedit.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = nmedit.1; sourceTree = ""; }; + DE095F9B21CC1ABB00C4ADA1 /* nm-classic.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = "nm-classic.1"; sourceTree = ""; }; + DE095F9C21CC1ABB00C4ADA1 /* bitcode_strip.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = bitcode_strip.1; sourceTree = ""; }; + DE095F9D21CC1ABB00C4ADA1 /* getsectdatafromheader.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = getsectdatafromheader.3; sourceTree = ""; }; + DE095F9E21CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095F9F21CC1ABB00C4ADA1 /* a.out.5 */ = {isa = PBXFileReference; lastKnownFileType = text; path = a.out.5; sourceTree = ""; }; + DE095FA021CC1ABB00C4ADA1 /* segedit.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = segedit.1; sourceTree = ""; }; + DE095FA121CC1ABB00C4ADA1 /* Mach-O.5 */ = {isa = PBXFileReference; lastKnownFileType = text; path = "Mach-O.5"; sourceTree = ""; }; + DE095FA221CC1ABB00C4ADA1 /* seg_addr_table.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = seg_addr_table.1; sourceTree = ""; }; + DE095FA321CC1ABB00C4ADA1 /* gprof.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = gprof.1; sourceTree = ""; }; + DE095FA421CC1ABB00C4ADA1 /* get_end.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = get_end.3; sourceTree = ""; }; + DE095FA521CC1ABB00C4ADA1 /* rld.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = rld.3; sourceTree = ""; }; + DE095FA621CC1ABB00C4ADA1 /* arch.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = arch.3; sourceTree = ""; }; + DE095FA721CC1ABB00C4ADA1 /* NSModule.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = NSModule.3; sourceTree = ""; }; + DE095FA821CC1ABB00C4ADA1 /* dyld.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = dyld.1; sourceTree = ""; }; + DE095FA921CC1ABB00C4ADA1 /* mtoc.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = mtoc.1; sourceTree = ""; }; + DE095FAA21CC1ABB00C4ADA1 /* cmpdylib.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = cmpdylib.1; sourceTree = ""; }; + DE095FAB21CC1ABB00C4ADA1 /* strings.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = strings.1; sourceTree = ""; }; + DE095FAC21CC1ABB00C4ADA1 /* kld.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = kld.3; sourceTree = ""; }; + DE095FAD21CC1ABB00C4ADA1 /* NSObjectFileImage.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = NSObjectFileImage.3; sourceTree = ""; }; + DE095FAE21CC1ABB00C4ADA1 /* checksyms.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = checksyms.1; sourceTree = ""; }; + DE095FAF21CC1ABB00C4ADA1 /* notes */ = {isa = PBXFileReference; lastKnownFileType = text; path = notes; sourceTree = ""; }; + DE095FB021CC1ABB00C4ADA1 /* getsectdata.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = getsectdata.3; sourceTree = ""; }; + DE095FB121CC1ABB00C4ADA1 /* redo_prebinding.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = redo_prebinding.1; sourceTree = ""; }; + DE095FB221CC1ABB00C4ADA1 /* ranlib.5 */ = {isa = PBXFileReference; lastKnownFileType = text; path = ranlib.5; sourceTree = ""; }; + DE095FB321CC1ABB00C4ADA1 /* end.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = end.3; sourceTree = ""; }; + DE095FB421CC1ABB00C4ADA1 /* strip.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = strip.1; sourceTree = ""; }; + DE095FB521CC1ABB00C4ADA1 /* check_dylib.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = check_dylib.1; sourceTree = ""; }; + DE095FB621CC1ABB00C4ADA1 /* getsectbyname.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = getsectbyname.3; sourceTree = ""; }; + DE095FB721CC1ABB00C4ADA1 /* nm.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = nm.1; sourceTree = ""; }; + DE095FB821CC1ABB00C4ADA1 /* libtool.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = libtool.1; sourceTree = ""; }; + DE095FB921CC1ABB00C4ADA1 /* size-classic.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = "size-classic.1"; sourceTree = ""; }; + DE095FBA21CC1ABB00C4ADA1 /* getsectbynamefromheader.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = getsectbynamefromheader.3; sourceTree = ""; }; + DE095FBB21CC1ABB00C4ADA1 /* llvm-otool.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = "llvm-otool.1"; sourceTree = ""; }; + DE095FBC21CC1ABB00C4ADA1 /* dyld.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = dyld.3; sourceTree = ""; }; + DE095FBD21CC1ABB00C4ADA1 /* stab.5 */ = {isa = PBXFileReference; lastKnownFileType = text; path = stab.5; sourceTree = ""; }; + DE095FBE21CC1ABB00C4ADA1 /* otool.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = otool.1; sourceTree = ""; }; + DE095FBF21CC1ABB00C4ADA1 /* ld_classic.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = ld_classic.1; sourceTree = ""; }; + DE095FC021CC1ABB00C4ADA1 /* pagestuff.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = pagestuff.1; sourceTree = ""; }; + DE095FC121CC1ABB00C4ADA1 /* otool-classic.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = "otool-classic.1"; sourceTree = ""; }; + DE095FC221CC1ABB00C4ADA1 /* ctf_insert.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = ctf_insert.1; sourceTree = ""; }; + DE095FC321CC1ABB00C4ADA1 /* indr.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = indr.1; sourceTree = ""; }; + DE095FC421CC1ABB00C4ADA1 /* libsyminfo.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = libsyminfo.3; sourceTree = ""; }; + DE095FC621CC1ABB00C4ADA1 /* reloc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = reloc.c; sourceTree = ""; }; + DE095FC721CC1ABB00C4ADA1 /* set_arch_flag_name.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = set_arch_flag_name.c; sourceTree = ""; }; + DE095FC821CC1ABB00C4ADA1 /* allocate.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = allocate.c; sourceTree = ""; usesTabs = 1; }; + DE095FC921CC1ABB00C4ADA1 /* ofile_error.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ofile_error.c; sourceTree = ""; }; + DE095FCA21CC1ABB00C4ADA1 /* vm_flush_cache.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = vm_flush_cache.c; sourceTree = ""; }; + DE095FCB21CC1ABB00C4ADA1 /* symbol_list.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = symbol_list.c; sourceTree = ""; }; + DE095FCC21CC1ABB00C4ADA1 /* print.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = print.c; sourceTree = ""; }; + DE095FCD21CC1ABB00C4ADA1 /* dylib_roots.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dylib_roots.c; sourceTree = ""; }; + DE095FCE21CC1ABB00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095FCF21CC1ABB00C4ADA1 /* execute.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = execute.c; sourceTree = ""; }; + DE095FD021CC1ABB00C4ADA1 /* checkout.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = checkout.c; sourceTree = ""; }; + DE095FD121CC1ABB00C4ADA1 /* fatal_arch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = fatal_arch.c; sourceTree = ""; }; + DE095FD221CC1ABB00C4ADA1 /* lto.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = lto.c; sourceTree = ""; }; + DE095FD321CC1ABB00C4ADA1 /* arch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = arch.c; sourceTree = ""; }; + DE095FD421CC1ABB00C4ADA1 /* get_toc_byte_sex.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = get_toc_byte_sex.c; sourceTree = ""; }; + DE095FD521CC1ABB00C4ADA1 /* guess_short_name.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = guess_short_name.c; sourceTree = ""; usesTabs = 1; }; + DE095FD621CC1ABB00C4ADA1 /* ofile_get_word.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ofile_get_word.c; sourceTree = ""; }; + DE095FD721CC1ABB00C4ADA1 /* dylib_table.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dylib_table.c; sourceTree = ""; }; + DE095FD821CC1ABB00C4ADA1 /* crc32.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = crc32.c; sourceTree = ""; }; + DE095FD921CC1ABB00C4ADA1 /* coff_bytesex.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = coff_bytesex.c; sourceTree = ""; }; + DE095FDA21CC1ABB00C4ADA1 /* hash_string.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hash_string.c; sourceTree = ""; }; + DE095FDB21CC1ABB00C4ADA1 /* ofile.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ofile.c; sourceTree = ""; }; + DE095FDC21CC1ABB00C4ADA1 /* notes */ = {isa = PBXFileReference; lastKnownFileType = text; path = notes; sourceTree = ""; }; + DE095FDD21CC1ABB00C4ADA1 /* SymLoc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SymLoc.c; sourceTree = ""; }; + DE095FDE21CC1ABB00C4ADA1 /* bytesex.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = bytesex.c; sourceTree = ""; }; + DE095FDF21CC1ABB00C4ADA1 /* rnd.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = rnd.c; sourceTree = ""; }; + DE095FE021CC1ABB00C4ADA1 /* version_number.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = version_number.c; sourceTree = ""; }; + DE095FE121CC1ABB00C4ADA1 /* get_arch_from_host.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = get_arch_from_host.c; sourceTree = ""; }; + DE095FE221CC1ABB00C4ADA1 /* write64.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = write64.c; sourceTree = ""; }; + DE095FE321CC1ABB00C4ADA1 /* unix_standard_mode.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = unix_standard_mode.c; sourceTree = ""; }; + DE095FE421CC1ABB00C4ADA1 /* fatals.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = fatals.c; sourceTree = ""; }; + DE095FE521CC1ABB00C4ADA1 /* best_arch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = best_arch.c; sourceTree = ""; }; + DE095FE621CC1ABB00C4ADA1 /* macosx_deployment_target.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = macosx_deployment_target.c; sourceTree = ""; }; + DE095FE721CC1ABB00C4ADA1 /* writeout.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = writeout.c; sourceTree = ""; usesTabs = 1; }; + DE095FE821CC1ABB00C4ADA1 /* arch_usage.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = arch_usage.c; sourceTree = ""; }; + DE095FE921CC1ABB00C4ADA1 /* llvm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = llvm.c; sourceTree = ""; }; + DE095FEA21CC1ABB00C4ADA1 /* swap_headers.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = swap_headers.c; sourceTree = ""; }; + DE095FEB21CC1ABB00C4ADA1 /* breakout.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = breakout.c; sourceTree = ""; }; + DE095FEC21CC1ABB00C4ADA1 /* seg_addr_table.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = seg_addr_table.c; sourceTree = ""; }; + DE095FED21CC1ABB00C4ADA1 /* errors.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = errors.c; sourceTree = ""; }; + DE095FEE21CC1ABB00C4ADA1 /* hppa.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hppa.c; sourceTree = ""; }; + DE095FF021CC1ABC00C4ADA1 /* ppc_disasm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ppc_disasm.c; sourceTree = ""; }; + DE095FF121CC1ABC00C4ADA1 /* dyld_bind_info.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = dyld_bind_info.c; sourceTree = ""; usesTabs = 0; }; + DE095FF221CC1ABC00C4ADA1 /* arm_disasm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = arm_disasm.c; sourceTree = ""; }; + DE095FF321CC1ABC00C4ADA1 /* m88k_disasm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = m88k_disasm.h; sourceTree = ""; }; + DE095FF421CC1ABC00C4ADA1 /* i860_disasm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = i860_disasm.c; sourceTree = ""; }; + DE095FF521CC1ABC00C4ADA1 /* ofile_print.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ofile_print.h; sourceTree = ""; }; + DE095FF621CC1ABC00C4ADA1 /* i386_disasm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = i386_disasm.c; sourceTree = ""; }; + DE095FF721CC1ABC00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE095FF821CC1ABC00C4ADA1 /* print_objc2_32bit.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = print_objc2_32bit.c; sourceTree = ""; }; + DE095FF921CC1ABC00C4ADA1 /* m68k_disasm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = m68k_disasm.c; sourceTree = ""; }; + DE095FFA21CC1ABC00C4ADA1 /* arm64_disasm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = arm64_disasm.c; sourceTree = ""; }; + DE095FFB21CC1ABC00C4ADA1 /* cxa_demangle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cxa_demangle.h; sourceTree = ""; }; + DE095FFC21CC1ABC00C4ADA1 /* coff_print.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = coff_print.c; sourceTree = ""; }; + DE095FFD21CC1ABC00C4ADA1 /* print_objc2_64bit.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = print_objc2_64bit.c; sourceTree = ""; }; + DE095FFE21CC1ABC00C4ADA1 /* sparc_disasm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sparc_disasm.h; sourceTree = ""; }; + DE095FFF21CC1ABC00C4ADA1 /* hppa_disasm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = hppa_disasm.h; sourceTree = ""; }; + DE09600021CC1ABC00C4ADA1 /* notify.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = notify.h; sourceTree = ""; }; + DE09600121CC1ABC00C4ADA1 /* arm_disasm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = arm_disasm.h; sourceTree = ""; }; + DE09600221CC1ABC00C4ADA1 /* print_bitcode.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = print_bitcode.c; sourceTree = ""; }; + DE09600321CC1ABC00C4ADA1 /* notes */ = {isa = PBXFileReference; lastKnownFileType = text; path = notes; sourceTree = ""; }; + DE09600421CC1ABC00C4ADA1 /* main.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; usesTabs = 1; }; + DE09600521CC1ABC00C4ADA1 /* dyld_bind_info.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = dyld_bind_info.h; sourceTree = ""; }; + DE09600621CC1ABC00C4ADA1 /* ppc_disasm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ppc_disasm.h; sourceTree = ""; }; + DE09600721CC1ABC00C4ADA1 /* ofile_print.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ofile_print.c; sourceTree = ""; }; + DE09600821CC1ABC00C4ADA1 /* m88k_disasm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = m88k_disasm.c; sourceTree = ""; }; + DE09600921CC1ABC00C4ADA1 /* i860_disasm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = i860_disasm.h; sourceTree = ""; }; + DE09600A21CC1ABC00C4ADA1 /* m68k_disasm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = m68k_disasm.h; sourceTree = ""; }; + DE09600B21CC1ABC00C4ADA1 /* arm64_disasm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = arm64_disasm.h; sourceTree = ""; }; + DE09600C21CC1ABC00C4ADA1 /* i386_disasm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = i386_disasm.h; sourceTree = ""; }; + DE09600D21CC1ABC00C4ADA1 /* hppa_disasm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hppa_disasm.c; sourceTree = ""; }; + DE09600E21CC1ABC00C4ADA1 /* otool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = otool.h; sourceTree = ""; }; + DE09600F21CC1ABC00C4ADA1 /* sparc_disasm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sparc_disasm.c; sourceTree = ""; }; + DE09601021CC1ABC00C4ADA1 /* notify.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = notify.c; sourceTree = ""; }; + DE09601121CC1ABC00C4ADA1 /* print_objc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = print_objc.c; sourceTree = ""; }; + DE09601321CC1ABC00C4ADA1 /* CompilerTools.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = CompilerTools.html; sourceTree = ""; }; + DE09601421CC1ABC00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE09601521CC1ABC00C4ADA1 /* FatFiles.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = FatFiles.rtf; sourceTree = ""; }; + DE09601621CC1ABC00C4ADA1 /* Private_CompilerTools.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = Private_CompilerTools.html; sourceTree = ""; }; + DE09601721CC1ABC00C4ADA1 /* Prebinding.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = Prebinding.html; sourceTree = ""; }; + DE09601921CC1ABC00C4ADA1 /* archive.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = archive.h; sourceTree = ""; }; + DE09601A21CC1ABC00C4ADA1 /* extract.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = extract.c; sourceTree = ""; }; + DE09601B21CC1ABC00C4ADA1 /* print.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = print.c; sourceTree = ""; }; + DE09601C21CC1ABC00C4ADA1 /* contents.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = contents.c; sourceTree = ""; }; + DE09601D21CC1ABC00C4ADA1 /* ar.5 */ = {isa = PBXFileReference; lastKnownFileType = text; path = ar.5; sourceTree = ""; }; + DE09601E21CC1ABC00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE09601F21CC1ABC00C4ADA1 /* move.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = move.c; sourceTree = ""; }; + DE09602021CC1ABC00C4ADA1 /* ar.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ar.c; sourceTree = ""; }; + DE09602121CC1ABC00C4ADA1 /* append.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = append.c; sourceTree = ""; }; + DE09602221CC1ABC00C4ADA1 /* archive.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = archive.c; sourceTree = ""; }; + DE09602321CC1ABC00C4ADA1 /* notes */ = {isa = PBXFileReference; lastKnownFileType = text; path = notes; sourceTree = ""; }; + DE09602421CC1ABC00C4ADA1 /* pathnames.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pathnames.h; sourceTree = ""; }; + DE09602521CC1ABC00C4ADA1 /* replace.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = replace.c; sourceTree = ""; }; + DE09602621CC1ABC00C4ADA1 /* delete.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = delete.c; sourceTree = ""; }; + DE09602721CC1ABC00C4ADA1 /* ar.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = ar.1; sourceTree = ""; }; + DE09602821CC1ABC00C4ADA1 /* extern.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = extern.h; sourceTree = ""; }; + DE09602921CC1ABC00C4ADA1 /* misc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = misc.c; sourceTree = ""; }; + DE09602C21CC1ABC00C4ADA1 /* filehdr.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = filehdr.h; sourceTree = ""; }; + DE09602D21CC1ABC00C4ADA1 /* syment.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = syment.h; sourceTree = ""; }; + DE09602E21CC1ABC00C4ADA1 /* base_relocs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = base_relocs.h; sourceTree = ""; }; + DE09602F21CC1ABC00C4ADA1 /* bytesex.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bytesex.h; sourceTree = ""; }; + DE09603021CC1ABC00C4ADA1 /* ms_dos_stub.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ms_dos_stub.h; sourceTree = ""; }; + DE09603121CC1ABC00C4ADA1 /* aouthdr.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = aouthdr.h; sourceTree = ""; }; + DE09603221CC1ABC00C4ADA1 /* debug_directory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = debug_directory.h; sourceTree = ""; }; + DE09603321CC1ABC00C4ADA1 /* scnhdr.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = scnhdr.h; sourceTree = ""; }; + DE09603521CC1ABC00C4ADA1 /* libsyminfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libsyminfo.h; sourceTree = ""; }; + DE09603721CC1ABC00C4ADA1 /* libsa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libsa.h; sourceTree = ""; }; + DE09603821CC1ABC00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE09603A21CC1ABC00C4ADA1 /* eflags.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = eflags.h; sourceTree = ""; }; + DE09603C21CC1ABC00C4ADA1 /* xar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = xar.h; sourceTree = ""; }; + DE09603E21CC1ABC00C4ADA1 /* SymLoc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SymLoc.h; sourceTree = ""; }; + DE09603F21CC1ABC00C4ADA1 /* ofile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ofile.h; sourceTree = ""; }; + DE09604021CC1ABC00C4ADA1 /* hash_string.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = hash_string.h; sourceTree = ""; }; + DE09604121CC1ABC00C4ADA1 /* bytesex.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bytesex.h; sourceTree = ""; }; + DE09604221CC1ABC00C4ADA1 /* rnd.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = rnd.h; sourceTree = ""; }; + DE09604321CC1ABC00C4ADA1 /* symbol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = symbol.h; sourceTree = ""; }; + DE09604421CC1ABC00C4ADA1 /* bool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bool.h; sourceTree = ""; }; + DE09604521CC1ABC00C4ADA1 /* unix_standard_mode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = unix_standard_mode.h; sourceTree = ""; }; + DE09604621CC1ABC00C4ADA1 /* write64.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = write64.h; sourceTree = ""; }; + DE09604721CC1ABC00C4ADA1 /* version_number.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = version_number.h; sourceTree = ""; }; + DE09604821CC1ABC00C4ADA1 /* hppa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = hppa.h; sourceTree = ""; }; + DE09604921CC1ABC00C4ADA1 /* errors.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = errors.h; sourceTree = ""; }; + DE09604A21CC1ABC00C4ADA1 /* breakout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = breakout.h; sourceTree = ""; }; + DE09604B21CC1ABC00C4ADA1 /* seg_addr_table.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = seg_addr_table.h; sourceTree = ""; }; + DE09604C21CC1ABC00C4ADA1 /* llvm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = llvm.h; sourceTree = ""; }; + DE09604D21CC1ABC00C4ADA1 /* macosx_deployment_target.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = macosx_deployment_target.h; sourceTree = ""; }; + DE09604E21CC1ABC00C4ADA1 /* best_arch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = best_arch.h; sourceTree = ""; }; + DE09604F21CC1ABC00C4ADA1 /* vm_flush_cache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = vm_flush_cache.h; sourceTree = ""; }; + DE09605021CC1ABC00C4ADA1 /* symbol_list.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = symbol_list.h; sourceTree = ""; }; + DE09605121CC1ABC00C4ADA1 /* openstep_mach.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = openstep_mach.h; sourceTree = ""; }; + DE09605221CC1ABC00C4ADA1 /* allocate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = allocate.h; sourceTree = ""; }; + DE09605321CC1ABC00C4ADA1 /* reloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; + DE09605421CC1ABC00C4ADA1 /* print.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = print.h; sourceTree = ""; }; + DE09605521CC1ABC00C4ADA1 /* execute.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = execute.h; sourceTree = ""; }; + DE09605621CC1ABC00C4ADA1 /* dylib_roots.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dylib_roots.h; sourceTree = ""; }; + DE09605721CC1ABC00C4ADA1 /* crc32.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = crc32.h; sourceTree = ""; }; + DE09605821CC1ABC00C4ADA1 /* dylib_table.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dylib_table.h; sourceTree = ""; }; + DE09605921CC1ABC00C4ADA1 /* guess_short_name.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = guess_short_name.h; sourceTree = ""; }; + DE09605A21CC1ABC00C4ADA1 /* arch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = arch.h; sourceTree = ""; }; + DE09605B21CC1ABC00C4ADA1 /* lto.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = lto.h; sourceTree = ""; }; + DE09605D21CC1ABC00C4ADA1 /* symseg.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = symseg.h; sourceTree = ""; }; + DE09605E21CC1ABC00C4ADA1 /* exec.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = exec.h; sourceTree = ""; }; + DE09605F21CC1ABC00C4ADA1 /* a.out.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = a.out.h; sourceTree = ""; }; + DE09606221CC1ABC00C4ADA1 /* macro_help.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = macro_help.h; sourceTree = ""; }; + DE09606321CC1ABC00C4ADA1 /* reg_help.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = reg_help.h; sourceTree = ""; }; + DE09606521CC1ABC00C4ADA1 /* fp_regs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fp_regs.h; sourceTree = ""; }; + DE09606621CC1ABC00C4ADA1 /* reg_help.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = reg_help.h; sourceTree = ""; }; + DE09606821CC1ABC00C4ADA1 /* frame.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = frame.h; sourceTree = ""; }; + DE09606921CC1ABC00C4ADA1 /* fpu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fpu.h; sourceTree = ""; }; + DE09606B21CC1ABC00C4ADA1 /* reg.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = reg.h; sourceTree = ""; }; + DE09606D21CC1ABC00C4ADA1 /* gmon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = gmon.h; sourceTree = ""; }; + DE09606E21CC1ABC00C4ADA1 /* notes */ = {isa = PBXFileReference; lastKnownFileType = text; path = notes; sourceTree = ""; }; + DE09607121CC1ABC00C4ADA1 /* thread_status.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = thread_status.h; sourceTree = ""; }; + DE09607321CC1ABC00C4ADA1 /* thread_status.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = thread_status.h; sourceTree = ""; }; + DE09607421CC1ABC00C4ADA1 /* machine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = machine.h; sourceTree = ""; }; + DE09607621CC1ABC00C4ADA1 /* fp_reg.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fp_reg.h; sourceTree = ""; }; + DE09607721CC1ABC00C4ADA1 /* thread_state.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = thread_state.h; sourceTree = ""; }; + DE09607821CC1ABC00C4ADA1 /* _structs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _structs.h; sourceTree = ""; }; + DE09607921CC1ABC00C4ADA1 /* thread_status.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = thread_status.h; sourceTree = ""; }; + DE09607B21CC1ABC00C4ADA1 /* thread_status.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = thread_status.h; sourceTree = ""; }; + DE09607D21CC1ABC00C4ADA1 /* _structs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _structs.h; sourceTree = ""; }; + DE09607E21CC1ABC00C4ADA1 /* thread_status.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = thread_status.h; sourceTree = ""; }; + DE09607F21CC1ABC00C4ADA1 /* slot_name.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = slot_name.h; sourceTree = ""; }; + DE09608121CC1ABC00C4ADA1 /* thread_state.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = thread_state.h; sourceTree = ""; }; + DE09608221CC1ABC00C4ADA1 /* _structs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _structs.h; sourceTree = ""; }; + DE09608321CC1ABC00C4ADA1 /* thread_status.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = thread_status.h; sourceTree = ""; }; + DE09608521CC1ABC00C4ADA1 /* thread_status.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = thread_status.h; sourceTree = ""; }; + DE09608721CC1ABC00C4ADA1 /* thread_status.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = thread_status.h; sourceTree = ""; }; + DE09608A21CC1ABC00C4ADA1 /* swap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = swap.h; sourceTree = ""; }; + DE09608B21CC1ABC00C4ADA1 /* rld_state.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = rld_state.h; sourceTree = ""; }; + DE09608D21CC1ABC00C4ADA1 /* swap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = swap.h; sourceTree = ""; }; + DE09608E21CC1ABC00C4ADA1 /* reloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; + DE09608F21CC1ABC00C4ADA1 /* kld.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = kld.h; sourceTree = ""; }; + DE09609021CC1ABC00C4ADA1 /* getsect.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = getsect.h; sourceTree = ""; }; + DE09609121CC1ABC00C4ADA1 /* ranlib.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ranlib.h; sourceTree = ""; }; + DE09609221CC1ABC00C4ADA1 /* sarld.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sarld.h; sourceTree = ""; }; + DE09609421CC1ABC00C4ADA1 /* swap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = swap.h; sourceTree = ""; }; + DE09609621CC1ABC00C4ADA1 /* swap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = swap.h; sourceTree = ""; }; + DE09609721CC1ABC00C4ADA1 /* reloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; + DE09609921CC1ABC00C4ADA1 /* swap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = swap.h; sourceTree = ""; }; + DE09609A21CC1ABC00C4ADA1 /* reloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; + DE09609B21CC1ABC00C4ADA1 /* swap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = swap.h; sourceTree = ""; }; + DE09609C21CC1ABC00C4ADA1 /* stab.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = stab.h; sourceTree = ""; }; + DE09609D21CC1ABC00C4ADA1 /* dyld_gdb.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dyld_gdb.h; sourceTree = ""; }; + DE09609E21CC1ABC00C4ADA1 /* gmon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = gmon.h; sourceTree = ""; }; + DE09609F21CC1ABC00C4ADA1 /* dyld.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dyld.h; sourceTree = ""; }; + DE0960A021CC1ABC00C4ADA1 /* nlist.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = nlist.h; sourceTree = ""; }; + DE0960A121CC1ABC00C4ADA1 /* redo_prebinding.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = redo_prebinding.h; sourceTree = ""; }; + DE0960A221CC1ABC00C4ADA1 /* dyld_priv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dyld_priv.h; sourceTree = ""; }; + DE0960A321CC1ABC00C4ADA1 /* loader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = loader.h; sourceTree = ""; }; + DE0960A421CC1ABC00C4ADA1 /* reloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; + DE0960A521CC1ABC00C4ADA1 /* dyld_debug.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dyld_debug.h; sourceTree = ""; }; + DE0960A721CC1ABC00C4ADA1 /* reloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; + DE0960A921CC1ABC00C4ADA1 /* swap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = swap.h; sourceTree = ""; }; + DE0960AA21CC1ABC00C4ADA1 /* reloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; + DE0960AC21CC1ABC00C4ADA1 /* swap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = swap.h; sourceTree = ""; }; + DE0960AD21CC1ABC00C4ADA1 /* reloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; + DE0960AF21CC1ABC00C4ADA1 /* reloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; + DE0960B021CC1ABC00C4ADA1 /* ldsyms.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ldsyms.h; sourceTree = ""; }; + DE0960B121CC1ABC00C4ADA1 /* fat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fat.h; sourceTree = ""; }; + DE0960B221CC1ABC00C4ADA1 /* rld.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = rld.h; sourceTree = ""; }; + DE0960B421CC1ABC00C4ADA1 /* reloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; + DE0960B521CC1ABC00C4ADA1 /* arch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = arch.h; sourceTree = ""; }; + DE0960B721CC1ABC00C4ADA1 /* arm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = arm.h; sourceTree = ""; }; + DE0960B921CC1ABC00C4ADA1 /* dwarf2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dwarf2.h; sourceTree = ""; }; + DE0960BB21CC1ABC00C4ADA1 /* Disassembler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Disassembler.h; sourceTree = ""; }; + DE0960BD21CC1ABC00C4ADA1 /* mtoc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mtoc.c; sourceTree = ""; }; + DE0960BE21CC1ABC00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE0960BF21CC1ABC00C4ADA1 /* notes */ = {isa = PBXFileReference; lastKnownFileType = text; path = notes; sourceTree = ""; }; + DE0960C021CC1ABC00C4ADA1 /* makerelocs.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = makerelocs.c; sourceTree = ""; }; + DE0960C221CC1ABC00C4ADA1 /* write_object.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = write_object.h; sourceTree = ""; }; + DE0960C321CC1ABC00C4ADA1 /* as.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = as.h; sourceTree = ""; }; + DE0960C421CC1ABC00C4ADA1 /* input-scrub.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "input-scrub.h"; sourceTree = ""; }; + DE0960C521CC1ABC00C4ADA1 /* i860-check.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "i860-check.c"; sourceTree = ""; }; + DE0960C621CC1ABC00C4ADA1 /* layout.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = layout.c; sourceTree = ""; }; + DE0960C721CC1ABC00C4ADA1 /* ppc-check.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "ppc-check.c"; sourceTree = ""; }; + DE0960C821CC1ABC00C4ADA1 /* m68k-opcode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "m68k-opcode.h"; sourceTree = ""; }; + DE0960C921CC1ABC00C4ADA1 /* frags.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = frags.h; sourceTree = ""; }; + DE0960CA21CC1ABC00C4ADA1 /* messages.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = messages.h; sourceTree = ""; }; + DE0960CB21CC1ABC00C4ADA1 /* symbols.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = symbols.h; sourceTree = ""; }; + DE0960CC21CC1ABC00C4ADA1 /* m88k-check.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "m88k-check.c"; sourceTree = ""; }; + DE0960CD21CC1ABC00C4ADA1 /* dwarf2dbg.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dwarf2dbg.c; sourceTree = ""; }; + DE0960CE21CC1ABC00C4ADA1 /* xmalloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = xmalloc.h; sourceTree = ""; }; + DE0960CF21CC1ABC00C4ADA1 /* i386-opcode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "i386-opcode.h"; sourceTree = ""; }; + DE0960D021CC1ABC00C4ADA1 /* obstack.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = obstack.c; sourceTree = ""; }; + DE0960D121CC1ABC00C4ADA1 /* sections.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sections.h; sourceTree = ""; }; + DE0960D221CC1ABC00C4ADA1 /* ppc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ppc.c; sourceTree = ""; }; + DE0960D321CC1ABC00C4ADA1 /* atof-ieee.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "atof-ieee.c"; sourceTree = ""; }; + DE0960D421CC1ABC00C4ADA1 /* i386.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = i386.c; sourceTree = ""; }; + DE0960D521CC1ABC00C4ADA1 /* i860-opcode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "i860-opcode.h"; sourceTree = ""; }; + DE0960D621CC1ABC00C4ADA1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + DE0960D721CC1ABC00C4ADA1 /* arm_reloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = arm_reloc.h; sourceTree = ""; }; + DE0960D821CC1ABC00C4ADA1 /* fixes.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = fixes.c; sourceTree = ""; }; + DE0960D921CC1ABC00C4ADA1 /* i860.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = i860.c; sourceTree = ""; }; + DE0960DA21CC1ABC00C4ADA1 /* i386-check.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "i386-check.c"; sourceTree = ""; }; + DE0960DB21CC1ABC00C4ADA1 /* flonum.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = flonum.h; sourceTree = ""; }; + DE0960DC21CC1ABC00C4ADA1 /* input-file.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "input-file.c"; sourceTree = ""; }; + DE0960DD21CC1ABC00C4ADA1 /* m88k.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = m88k.c; sourceTree = ""; }; + DE0960DE21CC1ABC00C4ADA1 /* app.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = app.h; sourceTree = ""; }; + DE0960DF21CC1ABC00C4ADA1 /* expr.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = expr.h; sourceTree = ""; }; + DE0960E021CC1ABC00C4ADA1 /* hppa-aux.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "hppa-aux.h"; sourceTree = ""; }; + DE0960E121CC1ABC00C4ADA1 /* md.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = md.h; sourceTree = ""; }; + DE0960E221CC1ABC00C4ADA1 /* ppc-opcode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ppc-opcode.h"; sourceTree = ""; }; + DE0960E321CC1ABC00C4ADA1 /* hex-value.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "hex-value.c"; sourceTree = ""; }; + DE0960E421CC1ABC00C4ADA1 /* hash.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hash.c; sourceTree = ""; }; + DE0960E521CC1ABC00C4ADA1 /* read.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = read.c; sourceTree = ""; }; + DE0960E621CC1ABC00C4ADA1 /* struc-symbol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "struc-symbol.h"; sourceTree = ""; }; + DE0960E721CC1ABC00C4ADA1 /* m68k.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = m68k.c; sourceTree = ""; }; + DE0960E821CC1ABC00C4ADA1 /* hex_value.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = hex_value.h; sourceTree = ""; }; + DE0960E921CC1ABC00C4ADA1 /* sparc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sparc.c; sourceTree = ""; }; + DE0960EA21CC1ABC00C4ADA1 /* arm-check.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "arm-check.c"; sourceTree = ""; }; + DE0960EB21CC1ABC00C4ADA1 /* layout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = layout.h; sourceTree = ""; }; + DE0960EC21CC1ABC00C4ADA1 /* flonum-const.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "flonum-const.c"; sourceTree = ""; }; + DE0960ED21CC1ABC00C4ADA1 /* hppa-opcode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "hppa-opcode.h"; sourceTree = ""; }; + DE0960EE21CC1ABC00C4ADA1 /* sparc-opcode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "sparc-opcode.h"; sourceTree = ""; }; + DE0960EF21CC1ABC00C4ADA1 /* hppa-check.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "hppa-check.c"; sourceTree = ""; }; + DE0960F021CC1ABC00C4ADA1 /* input-scrub.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "input-scrub.c"; sourceTree = ""; }; + DE0960F121CC1ABC00C4ADA1 /* COPYING */ = {isa = PBXFileReference; lastKnownFileType = text; path = COPYING; sourceTree = ""; }; + DE0960F221CC1ABC00C4ADA1 /* notes */ = {isa = PBXFileReference; lastKnownFileType = text; path = notes; sourceTree = ""; }; + DE0960F321CC1ABC00C4ADA1 /* atof-generic.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "atof-generic.c"; sourceTree = ""; }; + DE0960F421CC1ABC00C4ADA1 /* write_object.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = write_object.c; sourceTree = ""; }; + DE0960F521CC1ABC00C4ADA1 /* as.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = as.c; sourceTree = ""; }; + DE0960F621CC1ABC00C4ADA1 /* sections.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sections.c; sourceTree = ""; }; + DE0960F721CC1ABC00C4ADA1 /* flonum-copy.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "flonum-copy.c"; sourceTree = ""; }; + DE0960F821CC1ABC00C4ADA1 /* obstack.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = obstack.h; sourceTree = ""; }; + DE0960F921CC1ABC00C4ADA1 /* atof-ieee.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "atof-ieee.h"; sourceTree = ""; }; + DE0960FA21CC1ABC00C4ADA1 /* relax.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = relax.h; sourceTree = ""; }; + DE0960FB21CC1ABC00C4ADA1 /* xmalloc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = xmalloc.c; sourceTree = ""; }; + DE0960FC21CC1ABC00C4ADA1 /* dwarf2dbg.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dwarf2dbg.h; sourceTree = ""; }; + DE0960FD21CC1ABC00C4ADA1 /* messages.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = messages.c; sourceTree = ""; }; + DE0960FE21CC1ABC00C4ADA1 /* filenames.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = filenames.h; sourceTree = ""; }; + DE0960FF21CC1ABC00C4ADA1 /* frags.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = frags.c; sourceTree = ""; }; + DE09610021CC1ABC00C4ADA1 /* arch64_32.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = arch64_32.h; sourceTree = ""; }; + DE09610121CC1ABC00C4ADA1 /* symbols.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = symbols.c; sourceTree = ""; }; + DE09610221CC1ABC00C4ADA1 /* cctools.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = cctools.plist; sourceTree = ""; }; + DE09610321CC1ABC00C4ADA1 /* flonum-mult.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "flonum-mult.c"; sourceTree = ""; }; + DE09610421CC1ABC00C4ADA1 /* fixes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fixes.h; sourceTree = ""; }; + DE09610521CC1ABC00C4ADA1 /* arm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = arm.c; sourceTree = ""; }; + DE09610621CC1ABC00C4ADA1 /* i386.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = i386.h; sourceTree = ""; }; + DE09610721CC1ABC00C4ADA1 /* m88k-opcode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "m88k-opcode.h"; sourceTree = ""; }; + DE09610821CC1ABC00C4ADA1 /* read.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = read.h; sourceTree = ""; }; + DE09610921CC1ABC00C4ADA1 /* hppa-aux.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "hppa-aux.c"; sourceTree = ""; }; + DE09610A21CC1ABC00C4ADA1 /* hash.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = hash.h; sourceTree = ""; }; + DE09610B21CC1ABC00C4ADA1 /* sparc-check.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "sparc-check.c"; sourceTree = ""; }; + DE09610C21CC1ABC00C4ADA1 /* bignum.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bignum.h; sourceTree = ""; }; + DE09610D21CC1ABC00C4ADA1 /* driver.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = driver.c; sourceTree = ""; }; + DE09610E21CC1ABC00C4ADA1 /* expr.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = expr.c; sourceTree = ""; }; + DE09610F21CC1ABC00C4ADA1 /* app.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = app.c; sourceTree = ""; }; + DE09611021CC1ABC00C4ADA1 /* input-file.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "input-file.h"; sourceTree = ""; }; + DE09611121CC1ABC00C4ADA1 /* m68k-check.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "m68k-check.c"; sourceTree = ""; }; + DE09611221CC1ABC00C4ADA1 /* hppa.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hppa.c; sourceTree = ""; }; + DE09611321CC1C7900C4ADA1 /* cctools.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = cctools.xcconfig; sourceTree = ""; }; + DE09612C21CC218E00C4ADA1 /* libstuff.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libstuff.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DE09613221CC242900C4ADA1 /* libstuff.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = libstuff.xcconfig; sourceTree = ""; }; + DE09613321CC293000C4ADA1 /* apple_version.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = apple_version.c; sourceTree = ""; }; + DE09616321CC4A7C00C4ADA1 /* as */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = as; sourceTree = BUILT_PRODUCTS_DIR; }; + DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = public_tool.xcconfig; sourceTree = ""; }; + DE09617721CC4F1B00C4ADA1 /* as-arm */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "as-arm"; sourceTree = BUILT_PRODUCTS_DIR; }; + DE09617E21CC4F6500C4ADA1 /* public_assembler.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = public_assembler.xcconfig; sourceTree = ""; }; + DE0961BD21CC534200C4ADA1 /* as-i386 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "as-i386"; sourceTree = BUILT_PRODUCTS_DIR; }; + DE0961E121CC53E700C4ADA1 /* as-x86_64 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "as-x86_64"; sourceTree = BUILT_PRODUCTS_DIR; }; + DE0961EE21CC550500C4ADA1 /* public_assemblers.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = public_assemblers.sh; sourceTree = ""; }; + DE0961FD21CC77FC00C4ADA1 /* lipo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = lipo; sourceTree = BUILT_PRODUCTS_DIR; }; + DE09620E21CC78BD00C4ADA1 /* strings */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = strings; sourceTree = BUILT_PRODUCTS_DIR; }; + DE09621D21CC78F500C4ADA1 /* size-classic */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "size-classic"; sourceTree = BUILT_PRODUCTS_DIR; }; + DE09622221CC79A800C4ADA1 /* create_symlink.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = create_symlink.sh; sourceTree = ""; }; + DE09623521CC809300C4ADA1 /* nm-classic */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "nm-classic"; sourceTree = BUILT_PRODUCTS_DIR; }; + DE09624921CD4F8F00C4ADA1 /* libtool */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = libtool; sourceTree = BUILT_PRODUCTS_DIR; }; + DE09625D21CD500600C4ADA1 /* strip */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = strip; sourceTree = BUILT_PRODUCTS_DIR; }; + DE09625E21CD514000C4ADA1 /* strip.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = strip.xcconfig; sourceTree = ""; }; + DE09627321CD594000C4ADA1 /* nmedit */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = nmedit; sourceTree = BUILT_PRODUCTS_DIR; }; + DE09628521CD599B00C4ADA1 /* segedit */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = segedit; sourceTree = BUILT_PRODUCTS_DIR; }; + DE09629421CD59E800C4ADA1 /* cmpdylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cmpdylib; sourceTree = BUILT_PRODUCTS_DIR; }; + DE0962A321CD5A0400C4ADA1 /* pagestuff */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = pagestuff; sourceTree = BUILT_PRODUCTS_DIR; }; + DE0962B221CD5A2300C4ADA1 /* redo_prebinding */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = redo_prebinding; sourceTree = BUILT_PRODUCTS_DIR; }; + DE0962C121CD5A4900C4ADA1 /* install_name_tool */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = install_name_tool; sourceTree = BUILT_PRODUCTS_DIR; }; + DE0962D021CD5A6100C4ADA1 /* codesign_allocate */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = codesign_allocate; sourceTree = BUILT_PRODUCTS_DIR; }; + DE0962D421CD5AD600C4ADA1 /* copy_if.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = copy_if.sh; sourceTree = ""; }; + DE0962ED21CD618200C4ADA1 /* ctf_insert */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ctf_insert; sourceTree = BUILT_PRODUCTS_DIR; }; + DE0962FC21CD61A600C4ADA1 /* bitcode_strip */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = bitcode_strip; sourceTree = BUILT_PRODUCTS_DIR; }; + DE09630F21CD621600C4ADA1 /* otool-classic */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "otool-classic"; sourceTree = BUILT_PRODUCTS_DIR; }; + DE09632521CD638600C4ADA1 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; + DE09633321CD640900C4ADA1 /* llvm-otool */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "llvm-otool"; sourceTree = BUILT_PRODUCTS_DIR; }; + DE0E42D922065D1300DD227C /* fixup-chains.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "fixup-chains.h"; sourceTree = ""; }; + DE175CB022A2248D0001D8CC /* test_util.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = test_util.h; sourceTree = ""; }; + DE175CB122A2248D0001D8CC /* test_util.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = test_util.c; sourceTree = ""; }; + DE1F63F321CD6511004CA2BF /* ar */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ar; sourceTree = BUILT_PRODUCTS_DIR; }; + DE1F640121CD6576004CA2BF /* private_tool.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = private_tool.xcconfig; sourceTree = ""; }; + DE1F641721CD65BC004CA2BF /* checksyms */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = checksyms; sourceTree = BUILT_PRODUCTS_DIR; }; + DE1F642821CD66BA004CA2BF /* indr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = indr; sourceTree = BUILT_PRODUCTS_DIR; }; + DE1F643921CD66F5004CA2BF /* seg_addr_table */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = seg_addr_table; sourceTree = BUILT_PRODUCTS_DIR; }; + DE1F644821CD6715004CA2BF /* check_dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = check_dylib; sourceTree = BUILT_PRODUCTS_DIR; }; + DE1F645721CD6734004CA2BF /* seg_hack */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = seg_hack; sourceTree = BUILT_PRODUCTS_DIR; }; + DE1F645921CD6786004CA2BF /* private_efi.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = private_efi.xcconfig; sourceTree = ""; }; + DE1F646521CD67E8004CA2BF /* mtoc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mtoc; sourceTree = BUILT_PRODUCTS_DIR; }; + DE21482121F59BCE00FF8882 /* allocate_test.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = allocate_test.c; sourceTree = ""; }; + DE21482321F5AB0F00FF8882 /* arch_test.c */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = arch_test.c; sourceTree = ""; usesTabs = 0; }; + DE21482521F5B7D700FF8882 /* get_arch_from_host_test.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = get_arch_from_host_test.c; sourceTree = ""; }; + DE2439D221D158640080FC74 /* codesign_allocate.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = codesign_allocate.xcconfig; sourceTree = ""; }; + DE2439D321D158CA0080FC74 /* codesign_allocate-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "codesign_allocate-Info.plist"; sourceTree = ""; }; + DE38751A21F13DEA00704209 /* otool.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = otool.xcconfig; sourceTree = ""; }; + DE5DC67B21F7EA8000A7CA07 /* libmacho.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libmacho.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; + DE5DC68521F7ED5200A7CA07 /* getsect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = getsect.h; sourceTree = ""; usesTabs = 0; }; + DE5DC68721F7EEBB00A7CA07 /* macho_dynamic_driverkit.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = macho_dynamic_driverkit.xcconfig; sourceTree = ""; }; + DE5DC68821F7EFEE00A7CA07 /* macho_headers_driverkit.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = macho_headers_driverkit.sh; sourceTree = ""; }; + DE8229F921CD8DD6008CD150 /* libmacho.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libmacho.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; + DE8229FD21CD8DF7008CD150 /* macho_dynamic.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = macho_dynamic.xcconfig; sourceTree = ""; }; + DE822A0421CDA47C008CD150 /* macho_headers.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = macho_headers.sh; sourceTree = ""; }; + DE97E91321F3B67600C7947D /* private_test.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = private_test.xcconfig; sourceTree = ""; }; + DE97E91821F3B72700C7947D /* libstuff_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = libstuff_test; sourceTree = BUILT_PRODUCTS_DIR; }; + DE97E91A21F3B72700C7947D /* libstuff_test.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = libstuff_test.c; sourceTree = ""; }; + DE97E92521F3B8EC00C7947D /* guess_short_name_test.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = guess_short_name_test.c; sourceTree = ""; }; + DE97E92721F3B91800C7947D /* test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = test.c; sourceTree = ""; }; + DE97E92821F3B91900C7947D /* test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = test.h; sourceTree = ""; }; + DE97E92A21F3B97A00C7947D /* null_test.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = null_test.c; sourceTree = ""; }; + DEA2409421CE04460026D013 /* as_license.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = as_license.sh; sourceTree = ""; }; + DEB23D8D21DEA11C007F9934 /* vtool */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = vtool; sourceTree = BUILT_PRODUCTS_DIR; }; + DEB23D9421DEA192007F9934 /* vtool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vtool.c; sourceTree = ""; }; + DEB23D9521DEA192007F9934 /* vtool.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = vtool.1; sourceTree = ""; }; + DEB5E8D0228B04D000263617 /* version_number_test.c */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = version_number_test.c; sourceTree = ""; usesTabs = 0; }; + DEB7156022A194230031FD9F /* args.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = args.c; sourceTree = ""; }; + DEB7156222A194350031FD9F /* args.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = args.h; sourceTree = ""; }; + DEB7157622A1F27A0031FD9F /* args_test.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = args_test.c; sourceTree = ""; }; + DEC00B67220012660079FFD3 /* mtor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mtor; sourceTree = BUILT_PRODUCTS_DIR; }; + DEC00B6A220012C80079FFD3 /* mtor.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = mtor.c; sourceTree = ""; usesTabs = 0; }; + DEC00B6C220012DA0079FFD3 /* mtor.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = mtor.1; sourceTree = ""; }; + DEDFD7E22299C66D00230D7D /* test_main.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = test_main.h; sourceTree = ""; }; + DEDFD7E32299C7F100230D7D /* rnd_test.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = rnd_test.c; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + DE000B3421CDB9DB000CEC53 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE000B5A21CDBE77000CEC53 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE000B6321CDBEE8000CEC53 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE000B6B21CDBEFD000CEC53 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE000B7221CDEFDF000CEC53 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09612A21CC218E00C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09616021CC4A7C00C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09616F21CC4DD500C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09617421CC4F1B00C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09618121CC523600C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE0961B721CC534200C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE0961B821CC534200C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE0961DB21CC53E700C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE0961DC21CC53E700C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE0961F621CC77FC00C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE0961F721CC77FC00C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09620721CC78BD00C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09620821CC78BD00C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09621621CC78F500C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09621721CC78F500C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09622C21CC809300C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09622D21CC809300C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09624021CD4F8F00C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09624121CD4F8F00C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09625421CD500600C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09625521CD500600C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09626A21CD594000C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09626B21CD594000C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09627D21CD599B00C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09627E21CD599B00C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09628D21CD59E800C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09628E21CD59E800C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09629C21CD5A0400C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09629D21CD5A0400C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE0962AB21CD5A2300C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE0962AC21CD5A2300C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE0962BA21CD5A4900C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE0962BB21CD5A4900C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE0962C921CD5A6100C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE0962CA21CD5A6100C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE0962E621CD618200C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE0962E721CD618200C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE0962F521CD61A600C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE0962F621CD61A600C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09630821CD621600C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09632621CD638600C4ADA1 /* libc++.tbd in Frameworks */, + DE09630921CD621600C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09632C21CD640900C4ADA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE1F63E321CD6494004CA2BF /* libc++.tbd in Frameworks */, + DE09632D21CD640900C4ADA1 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE1F63EC21CD6511004CA2BF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE1F63ED21CD6511004CA2BF /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE1F641021CD65BC004CA2BF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE1F641121CD65BC004CA2BF /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE1F642121CD66BA004CA2BF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE1F642221CD66BA004CA2BF /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE1F643221CD66F5004CA2BF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE1F643321CD66F5004CA2BF /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE1F644121CD6715004CA2BF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE1F644221CD6715004CA2BF /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE1F645021CD6734004CA2BF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE1F645121CD6734004CA2BF /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE1F645F21CD67E8004CA2BF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE1F646021CD67E8004CA2BF /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE5DC67621F7EA8000A7CA07 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE8229F721CD8DD6008CD150 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE97E91521F3B72700C7947D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE97E92421F3B86100C7947D /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DEB23D8A21DEA11C007F9934 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DEC00B60220012660079FFD3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DEC00B61220012660079FFD3 /* libstuff.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + DE095EF421CC1ABB00C4ADA1 /* tests */ = { + isa = PBXGroup; + children = ( + DE095F4E21CC1ABB00C4ADA1 /* bin */, + DE095F5B21CC1ABB00C4ADA1 /* include */, + DE095F5A21CC1ABB00C4ADA1 /* Makefile */, + DE095F5E21CC1ABB00C4ADA1 /* README.txt */, + DE095F5F21CC1ABB00C4ADA1 /* run-tests */, + DE095EF521CC1ABB00C4ADA1 /* test-cases */, + ); + path = tests; + sourceTree = ""; + }; + DE095EF521CC1ABB00C4ADA1 /* test-cases */ = { + isa = PBXGroup; + children = ( + DE095F3721CC1ABB00C4ADA1 /* 1a_harness_test */, + DE095F1A21CC1ABB00C4ADA1 /* bitcode_strip_arm64_32 */, + DE095F4B21CC1ABB00C4ADA1 /* bitcode_strip_large */, + DE095F0321CC1ABB00C4ADA1 /* codesign_allocate_arm64_32 */, + DE095F1221CC1ABB00C4ADA1 /* codesign_allocate_debug */, + DE095F4421CC1ABB00C4ADA1 /* codesign_allocate_large */, + DE095F2021CC1ABB00C4ADA1 /* libtool-atomic */, + DE095F4721CC1ABB00C4ADA1 /* libtool-deterministic */, + DE095F2321CC1ABB00C4ADA1 /* libtool-ldtrace-file */, + DE095F3E21CC1ABB00C4ADA1 /* libtool-ldtrace-json-file */, + DE095EFB21CC1ABB00C4ADA1 /* libtool-ldtrace-json-stderr */, + DE095EF621CC1ABB00C4ADA1 /* libtool-ldtrace-stderr */, + DE095F2C21CC1ABB00C4ADA1 /* libtool-static */, + DE095F2921CC1ABB00C4ADA1 /* lipo-cpusubtype-order */, + DE095F1D21CC1ABB00C4ADA1 /* lipo-hidden */, + DE095F0F21CC1ABB00C4ADA1 /* lipo-info */, + DE095F1721CC1ABB00C4ADA1 /* lipo-large */, + DE095F1421CC1ABB00C4ADA1 /* ranlib-atomic */, + DE095F0621CC1ABB00C4ADA1 /* segedit-extract */, + DE095F0A21CC1ABB00C4ADA1 /* segedit-replace */, + DE095F3921CC1ABB00C4ADA1 /* strings-stdin */, + DE095F3221CC1ABB00C4ADA1 /* strip-uniq */, + DE095F0021CC1ABB00C4ADA1 /* verify-build-version */, + DE095F3B21CC1ABB00C4ADA1 /* verify-iosmac */, + DE095F2F21CC1ABB00C4ADA1 /* verify-iosmac-backdeploy */, + ); + path = "test-cases"; + sourceTree = ""; + }; + DE095EF621CC1ABB00C4ADA1 /* libtool-ldtrace-stderr */ = { + isa = PBXGroup; + children = ( + DE095EFA21CC1ABB00C4ADA1 /* bar.c */, + DE095EF921CC1ABB00C4ADA1 /* expected.txt */, + DE095EF821CC1ABB00C4ADA1 /* foo.c */, + DE095EF721CC1ABB00C4ADA1 /* Makefile */, + ); + path = "libtool-ldtrace-stderr"; + sourceTree = ""; + }; + DE095EFB21CC1ABB00C4ADA1 /* libtool-ldtrace-json-stderr */ = { + isa = PBXGroup; + children = ( + DE095EFF21CC1ABB00C4ADA1 /* bar.c */, + DE095EFE21CC1ABB00C4ADA1 /* expected.txt */, + DE095EFD21CC1ABB00C4ADA1 /* foo.c */, + DE095EFC21CC1ABB00C4ADA1 /* Makefile */, + ); + path = "libtool-ldtrace-json-stderr"; + sourceTree = ""; + }; + DE095F0021CC1ABB00C4ADA1 /* verify-build-version */ = { + isa = PBXGroup; + children = ( + DE095F0221CC1ABB00C4ADA1 /* foo.c */, + DE095F0121CC1ABB00C4ADA1 /* Makefile */, + ); + path = "verify-build-version"; + sourceTree = ""; + }; + DE095F0321CC1ABB00C4ADA1 /* codesign_allocate_arm64_32 */ = { + isa = PBXGroup; + children = ( + DE095F0421CC1ABB00C4ADA1 /* hello.c */, + DE095F0521CC1ABB00C4ADA1 /* Makefile */, + ); + path = codesign_allocate_arm64_32; + sourceTree = ""; + }; + DE095F0621CC1ABB00C4ADA1 /* segedit-extract */ = { + isa = PBXGroup; + children = ( + DE095F0821CC1ABB00C4ADA1 /* main.c */, + DE095F0721CC1ABB00C4ADA1 /* Makefile */, + DE095F0921CC1ABB00C4ADA1 /* MementoMori1.txt */, + ); + path = "segedit-extract"; + sourceTree = ""; + }; + DE095F0A21CC1ABB00C4ADA1 /* segedit-replace */ = { + isa = PBXGroup; + children = ( + DE095F0C21CC1ABB00C4ADA1 /* main.c */, + DE095F0B21CC1ABB00C4ADA1 /* Makefile */, + DE095F0E21CC1ABB00C4ADA1 /* MementoMori1.txt */, + DE095F0D21CC1ABB00C4ADA1 /* MementoMori2.txt */, + ); + path = "segedit-replace"; + sourceTree = ""; + }; + DE095F0F21CC1ABB00C4ADA1 /* lipo-info */ = { + isa = PBXGroup; + children = ( + DE095F1021CC1ABB00C4ADA1 /* hello.c */, + DE095F1121CC1ABB00C4ADA1 /* Makefile */, + ); + path = "lipo-info"; + sourceTree = ""; + }; + DE095F1221CC1ABB00C4ADA1 /* codesign_allocate_debug */ = { + isa = PBXGroup; + children = ( + DE095F1321CC1ABB00C4ADA1 /* Makefile */, + ); + path = codesign_allocate_debug; + sourceTree = ""; + }; + DE095F1421CC1ABB00C4ADA1 /* ranlib-atomic */ = { + isa = PBXGroup; + children = ( + DE095F1621CC1ABB00C4ADA1 /* libfoo.c */, + DE095F1521CC1ABB00C4ADA1 /* Makefile */, + ); + path = "ranlib-atomic"; + sourceTree = ""; + }; + DE095F1721CC1ABB00C4ADA1 /* lipo-large */ = { + isa = PBXGroup; + children = ( + DE095F1821CC1ABB00C4ADA1 /* hello.c */, + DE095F1921CC1ABB00C4ADA1 /* Makefile */, + ); + path = "lipo-large"; + sourceTree = ""; + }; + DE095F1A21CC1ABB00C4ADA1 /* bitcode_strip_arm64_32 */ = { + isa = PBXGroup; + children = ( + DE095F1C21CC1ABB00C4ADA1 /* empty.c */, + DE095F1B21CC1ABB00C4ADA1 /* Makefile */, + ); + path = bitcode_strip_arm64_32; + sourceTree = ""; + }; + DE095F1D21CC1ABB00C4ADA1 /* lipo-hidden */ = { + isa = PBXGroup; + children = ( + DE095F1F21CC1ABB00C4ADA1 /* empty.c */, + DE095F1E21CC1ABB00C4ADA1 /* Makefile */, + ); + path = "lipo-hidden"; + sourceTree = ""; + }; + DE095F2021CC1ABB00C4ADA1 /* libtool-atomic */ = { + isa = PBXGroup; + children = ( + DE095F2221CC1ABB00C4ADA1 /* libfoo.c */, + DE095F2121CC1ABB00C4ADA1 /* Makefile */, + ); + path = "libtool-atomic"; + sourceTree = ""; + }; + DE095F2321CC1ABB00C4ADA1 /* libtool-ldtrace-file */ = { + isa = PBXGroup; + children = ( + DE095F2821CC1ABB00C4ADA1 /* bar.c */, + DE095F2621CC1ABB00C4ADA1 /* expected.txt */, + DE095F2721CC1ABB00C4ADA1 /* expected2.txt */, + DE095F2521CC1ABB00C4ADA1 /* foo.c */, + DE095F2421CC1ABB00C4ADA1 /* Makefile */, + ); + path = "libtool-ldtrace-file"; + sourceTree = ""; + }; + DE095F2921CC1ABB00C4ADA1 /* lipo-cpusubtype-order */ = { + isa = PBXGroup; + children = ( + DE095F2B21CC1ABB00C4ADA1 /* foo.c */, + DE095F2A21CC1ABB00C4ADA1 /* Makefile */, + ); + path = "lipo-cpusubtype-order"; + sourceTree = ""; + }; + DE095F2C21CC1ABB00C4ADA1 /* libtool-static */ = { + isa = PBXGroup; + children = ( + DE095F2E21CC1ABB00C4ADA1 /* libfoo.c */, + DE095F2D21CC1ABB00C4ADA1 /* Makefile */, + ); + path = "libtool-static"; + sourceTree = ""; + }; + DE095F2F21CC1ABB00C4ADA1 /* verify-iosmac-backdeploy */ = { + isa = PBXGroup; + children = ( + DE095F3121CC1ABB00C4ADA1 /* foo.c */, + DE095F3021CC1ABB00C4ADA1 /* Makefile */, + ); + path = "verify-iosmac-backdeploy"; + sourceTree = ""; + }; + DE095F3221CC1ABB00C4ADA1 /* strip-uniq */ = { + isa = PBXGroup; + children = ( + DE095F3621CC1ABB00C4ADA1 /* bar.c */, + DE095F3421CC1ABB00C4ADA1 /* foo.c */, + DE095F3521CC1ABB00C4ADA1 /* main.c */, + DE095F3321CC1ABB00C4ADA1 /* Makefile */, + ); + path = "strip-uniq"; + sourceTree = ""; + }; + DE095F3721CC1ABB00C4ADA1 /* 1a_harness_test */ = { + isa = PBXGroup; + children = ( + DE095F3821CC1ABB00C4ADA1 /* Makefile */, + ); + path = 1a_harness_test; + sourceTree = ""; + }; + DE095F3921CC1ABB00C4ADA1 /* strings-stdin */ = { + isa = PBXGroup; + children = ( + DE095F3A21CC1ABB00C4ADA1 /* Makefile */, + ); + path = "strings-stdin"; + sourceTree = ""; + }; + DE095F3B21CC1ABB00C4ADA1 /* verify-iosmac */ = { + isa = PBXGroup; + children = ( + DE095F3D21CC1ABB00C4ADA1 /* foo.c */, + DE095F3C21CC1ABB00C4ADA1 /* Makefile */, + ); + path = "verify-iosmac"; + sourceTree = ""; + }; + DE095F3E21CC1ABB00C4ADA1 /* libtool-ldtrace-json-file */ = { + isa = PBXGroup; + children = ( + DE095F4321CC1ABB00C4ADA1 /* bar.c */, + DE095F4121CC1ABB00C4ADA1 /* expected.txt */, + DE095F4221CC1ABB00C4ADA1 /* expected2.txt */, + DE095F4021CC1ABB00C4ADA1 /* foo.c */, + DE095F3F21CC1ABB00C4ADA1 /* Makefile */, + ); + path = "libtool-ldtrace-json-file"; + sourceTree = ""; + }; + DE095F4421CC1ABB00C4ADA1 /* codesign_allocate_large */ = { + isa = PBXGroup; + children = ( + DE095F4521CC1ABB00C4ADA1 /* hello.c */, + DE095F4621CC1ABB00C4ADA1 /* Makefile */, + ); + path = codesign_allocate_large; + sourceTree = ""; + }; + DE095F4721CC1ABB00C4ADA1 /* libtool-deterministic */ = { + isa = PBXGroup; + children = ( + DE095F4921CC1ABB00C4ADA1 /* expected.txt */, + DE095F4A21CC1ABB00C4ADA1 /* libfoo.c */, + DE095F4821CC1ABB00C4ADA1 /* Makefile */, + ); + path = "libtool-deterministic"; + sourceTree = ""; + }; + DE095F4B21CC1ABB00C4ADA1 /* bitcode_strip_large */ = { + isa = PBXGroup; + children = ( + DE095F4C21CC1ABB00C4ADA1 /* hello.c */, + DE095F4D21CC1ABB00C4ADA1 /* Makefile */, + ); + path = bitcode_strip_large; + sourceTree = ""; + }; + DE095F4E21CC1ABB00C4ADA1 /* bin */ = { + isa = PBXGroup; + children = ( + DE095F5221CC1ABB00C4ADA1 /* exit-non-zero-pass.pl */, + DE095F5821CC1ABB00C4ADA1 /* fail-if-exit-non-zero.pl */, + DE095F5321CC1ABB00C4ADA1 /* fail-if-exit-zero.pl */, + DE095F5621CC1ABB00C4ADA1 /* fail-if-no-stdin.pl */, + DE095F5721CC1ABB00C4ADA1 /* fail-if-stdin.pl */, + DE095F5121CC1ABB00C4ADA1 /* fail-iff-exit-zero.pl */, + DE095F5921CC1ABB00C4ADA1 /* pass-iff-exit-non-zero.pl */, + DE095F4F21CC1ABB00C4ADA1 /* pass-iff-exit-zero.pl */, + DE095F5521CC1ABB00C4ADA1 /* pass-iff-no-stdin.pl */, + DE095F5421CC1ABB00C4ADA1 /* pass-iff-stdin.pl */, + DE095F5021CC1ABB00C4ADA1 /* verify-align.pl */, + ); + path = bin; + sourceTree = ""; + }; + DE095F5B21CC1ABB00C4ADA1 /* include */ = { + isa = PBXGroup; + children = ( + DE095F5D21CC1ABB00C4ADA1 /* common.makefile */, + DE095F5C21CC1ABB00C4ADA1 /* verstool.c */, + ); + path = include; + sourceTree = ""; + }; + DE095F6021CC1ABB00C4ADA1 /* cbtlibs */ = { + isa = PBXGroup; + children = ( + DE095F6321CC1ABB00C4ADA1 /* libsyminfo.c */, + DE095F6121CC1ABB00C4ADA1 /* Makefile */, + DE095F6221CC1ABB00C4ADA1 /* notes */, + ); + path = cbtlibs; + sourceTree = ""; + }; + DE095F6421CC1ABB00C4ADA1 /* libmacho */ = { + isa = PBXGroup; + children = ( + DE095F6B21CC1ABB00C4ADA1 /* arch.c */, + DE095F6D21CC1ABB00C4ADA1 /* dylib.ofileList */, + DE095F6C21CC1ABB00C4ADA1 /* get_end.c */, + DE095F7321CC1ABB00C4ADA1 /* getsecbyname.c */, + DE095F6621CC1ABB00C4ADA1 /* getsegbyname.c */, + DE095F7221CC1ABB00C4ADA1 /* hppa_swap.c */, + DE095F6821CC1ABB00C4ADA1 /* i386_swap.c */, + DE095F7521CC1ABB00C4ADA1 /* i860_swap.c */, + DE095F7421CC1ABB00C4ADA1 /* m68k_swap.c */, + DE095F6921CC1ABB00C4ADA1 /* m88k_swap.c */, + DE095F6A21CC1ABB00C4ADA1 /* Makefile */, + DE095F6E21CC1ABB00C4ADA1 /* notes */, + DE095F6F21CC1ABB00C4ADA1 /* ppc_swap.c */, + DE095F6521CC1ABB00C4ADA1 /* shlib.ofileList */, + DE095F6721CC1ABB00C4ADA1 /* slot_name.c */, + DE095F7021CC1ABB00C4ADA1 /* sparc_swap.c */, + DE095F7121CC1ABB00C4ADA1 /* swap.c */, + ); + path = libmacho; + sourceTree = ""; + }; + DE095F7621CC1ABB00C4ADA1 /* xcode */ = { + isa = PBXGroup; + children = ( + DE09611321CC1C7900C4ADA1 /* cctools.xcconfig */, + DE2439D221D158640080FC74 /* codesign_allocate.xcconfig */, + DE09613221CC242900C4ADA1 /* libstuff.xcconfig */, + DE8229FD21CD8DF7008CD150 /* macho_dynamic.xcconfig */, + DE5DC68721F7EEBB00A7CA07 /* macho_dynamic_driverkit.xcconfig */, + DE000B3A21CDB9FE000CEC53 /* macho_static.xcconfig */, + DE38751A21F13DEA00704209 /* otool.xcconfig */, + DE1F645921CD6786004CA2BF /* private_efi.xcconfig */, + DE97E91321F3B67600C7947D /* private_test.xcconfig */, + DE1F640121CD6576004CA2BF /* private_tool.xcconfig */, + DE09617E21CC4F6500C4ADA1 /* public_assembler.xcconfig */, + DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */, + DE09625E21CD514000C4ADA1 /* strip.xcconfig */, + DEA2409421CE04460026D013 /* as_license.sh */, + DE0962D421CD5AD600C4ADA1 /* copy_if.sh */, + DE09622221CC79A800C4ADA1 /* create_symlink.sh */, + DE822A0421CDA47C008CD150 /* macho_headers.sh */, + DE5DC68821F7EFEE00A7CA07 /* macho_headers_driverkit.sh */, + DE0961EE21CC550500C4ADA1 /* public_assemblers.sh */, + ); + path = xcode; + sourceTree = ""; + }; + DE095F7721CC1ABB00C4ADA1 /* misc */ = { + isa = PBXGroup; + children = ( + DE095F8A21CC1ABB00C4ADA1 /* bitcode_strip.c */, + DE095F8221CC1ABB00C4ADA1 /* check_dylib.c */, + DE095F7821CC1ABB00C4ADA1 /* checksyms.c */, + DE095F7A21CC1ABB00C4ADA1 /* cmpdylib.c */, + DE095F8B21CC1ABB00C4ADA1 /* codesign_allocate.c */, + DE2439D321D158CA0080FC74 /* codesign_allocate-Info.plist */, + DE095F8421CC1ABB00C4ADA1 /* ctf_insert.c */, + DE095F8321CC1ABB00C4ADA1 /* indr.c */, + DE095F8D21CC1ABB00C4ADA1 /* Info.plist */, + DE095F7E21CC1ABB00C4ADA1 /* inout.c */, + DE095F8621CC1ABB00C4ADA1 /* install_name_tool.c */, + DE095F8121CC1ABB00C4ADA1 /* libtool.c */, + DE095F8721CC1ABB00C4ADA1 /* lipo.c */, + DE095F8021CC1ABB00C4ADA1 /* Makefile */, + DE095F7F21CC1ABB00C4ADA1 /* nm.c */, + DE095F8821CC1ABB00C4ADA1 /* notes */, + DE095F8521CC1ABB00C4ADA1 /* pagestuff.c */, + DE095F7921CC1ABB00C4ADA1 /* redo_prebinding.c */, + DE095F8E21CC1ABB00C4ADA1 /* seg_addr_table.c */, + DE095F7B21CC1ABB00C4ADA1 /* seg_hack.c */, + DE095F8C21CC1ABB00C4ADA1 /* segedit.c */, + DE095F8921CC1ABB00C4ADA1 /* size.c */, + DE095F7C21CC1ABB00C4ADA1 /* strings.c */, + DE095F7D21CC1ABB00C4ADA1 /* strip.c */, + DEB23D9421DEA192007F9934 /* vtool.c */, + ); + path = misc; + sourceTree = ""; + }; + DE095F8F21CC1ABB00C4ADA1 /* man */ = { + isa = PBXGroup; + children = ( + DE095F9E21CC1ABB00C4ADA1 /* Makefile */, + DE095FAF21CC1ABB00C4ADA1 /* notes */, + DE095F9321CC1ABB00C4ADA1 /* as.1 */, + DE095F9C21CC1ABB00C4ADA1 /* bitcode_strip.1 */, + DE095FB521CC1ABB00C4ADA1 /* check_dylib.1 */, + DE095FAE21CC1ABB00C4ADA1 /* checksyms.1 */, + DE095FAA21CC1ABB00C4ADA1 /* cmpdylib.1 */, + DE095F9721CC1ABB00C4ADA1 /* codesign_allocate.1 */, + DE095FC221CC1ABB00C4ADA1 /* ctf_insert.1 */, + DE095FA821CC1ABB00C4ADA1 /* dyld.1 */, + DE095FA321CC1ABB00C4ADA1 /* gprof.1 */, + DE095FC321CC1ABB00C4ADA1 /* indr.1 */, + DE095F9521CC1ABB00C4ADA1 /* install_name_tool.1 */, + DE095FBF21CC1ABB00C4ADA1 /* ld_classic.1 */, + DE095FB821CC1ABB00C4ADA1 /* libtool.1 */, + DE095F9121CC1ABB00C4ADA1 /* lipo.1 */, + DE095FBB21CC1ABB00C4ADA1 /* llvm-otool.1 */, + DE095FA921CC1ABB00C4ADA1 /* mtoc.1 */, + DEC00B6C220012DA0079FFD3 /* mtor.1 */, + DE095F9B21CC1ABB00C4ADA1 /* nm-classic.1 */, + DE095FB721CC1ABB00C4ADA1 /* nm.1 */, + DE095F9A21CC1ABB00C4ADA1 /* nmedit.1 */, + DE095FC121CC1ABB00C4ADA1 /* otool-classic.1 */, + DE095FBE21CC1ABB00C4ADA1 /* otool.1 */, + DE095FC021CC1ABB00C4ADA1 /* pagestuff.1 */, + DE095F9821CC1ABB00C4ADA1 /* ranlib.1 */, + DE095FB121CC1ABB00C4ADA1 /* redo_prebinding.1 */, + DE095FA221CC1ABB00C4ADA1 /* seg_addr_table.1 */, + DE095FA021CC1ABB00C4ADA1 /* segedit.1 */, + DE095FB921CC1ABB00C4ADA1 /* size-classic.1 */, + DE095F9221CC1ABB00C4ADA1 /* size.1 */, + DE095FAB21CC1ABB00C4ADA1 /* strings.1 */, + DE095FB421CC1ABB00C4ADA1 /* strip.1 */, + DEB23D9521DEA192007F9934 /* vtool.1 */, + DE095FA621CC1ABB00C4ADA1 /* arch.3 */, + DE095F9921CC1ABB00C4ADA1 /* dyld_debug.3 */, + DE095FBC21CC1ABB00C4ADA1 /* dyld.3 */, + DE095FB321CC1ABB00C4ADA1 /* end.3 */, + DE095FA421CC1ABB00C4ADA1 /* get_end.3 */, + DE095FB621CC1ABB00C4ADA1 /* getsectbyname.3 */, + DE095FBA21CC1ABB00C4ADA1 /* getsectbynamefromheader.3 */, + DE095FB021CC1ABB00C4ADA1 /* getsectdata.3 */, + DE095F9D21CC1ABB00C4ADA1 /* getsectdatafromheader.3 */, + DE095F9621CC1ABB00C4ADA1 /* getsegbyname.3 */, + DE095FAC21CC1ABB00C4ADA1 /* kld.3 */, + DE095FC421CC1ABB00C4ADA1 /* libsyminfo.3 */, + DE095FA721CC1ABB00C4ADA1 /* NSModule.3 */, + DE095F9421CC1ABB00C4ADA1 /* NSObjectFileImage_priv.3 */, + DE095FAD21CC1ABB00C4ADA1 /* NSObjectFileImage.3 */, + DE095F9021CC1ABB00C4ADA1 /* redo_prebinding.3 */, + DE095FA521CC1ABB00C4ADA1 /* rld.3 */, + DE095F9F21CC1ABB00C4ADA1 /* a.out.5 */, + DE095FA121CC1ABB00C4ADA1 /* Mach-O.5 */, + DE095FB221CC1ABB00C4ADA1 /* ranlib.5 */, + DE095FBD21CC1ABB00C4ADA1 /* stab.5 */, + ); + path = man; + sourceTree = ""; + }; + DE095FC521CC1ABB00C4ADA1 /* libstuff */ = { + isa = PBXGroup; + children = ( + DE095FC821CC1ABB00C4ADA1 /* allocate.c */, + DE09613321CC293000C4ADA1 /* apple_version.c */, + DE095FE821CC1ABB00C4ADA1 /* arch_usage.c */, + DE095FD321CC1ABB00C4ADA1 /* arch.c */, + DEB7156022A194230031FD9F /* args.c */, + DE095FE521CC1ABB00C4ADA1 /* best_arch.c */, + DE095FEB21CC1ABB00C4ADA1 /* breakout.c */, + DE095FDE21CC1ABB00C4ADA1 /* bytesex.c */, + DE095FD021CC1ABB00C4ADA1 /* checkout.c */, + DE095FD921CC1ABB00C4ADA1 /* coff_bytesex.c */, + DE095FD821CC1ABB00C4ADA1 /* crc32.c */, + DE095FCD21CC1ABB00C4ADA1 /* dylib_roots.c */, + DE095FD721CC1ABB00C4ADA1 /* dylib_table.c */, + DE095FED21CC1ABB00C4ADA1 /* errors.c */, + DE095FCF21CC1ABB00C4ADA1 /* execute.c */, + DE095FD121CC1ABB00C4ADA1 /* fatal_arch.c */, + DE095FE421CC1ABB00C4ADA1 /* fatals.c */, + DE095FE121CC1ABB00C4ADA1 /* get_arch_from_host.c */, + DE095FD421CC1ABB00C4ADA1 /* get_toc_byte_sex.c */, + DE095FD521CC1ABB00C4ADA1 /* guess_short_name.c */, + DE095FDA21CC1ABB00C4ADA1 /* hash_string.c */, + DE095FEE21CC1ABB00C4ADA1 /* hppa.c */, + DE095FE921CC1ABB00C4ADA1 /* llvm.c */, + DE095FD221CC1ABB00C4ADA1 /* lto.c */, + DE095FE621CC1ABB00C4ADA1 /* macosx_deployment_target.c */, + DE095FCE21CC1ABB00C4ADA1 /* Makefile */, + DE095FDC21CC1ABB00C4ADA1 /* notes */, + DE095FC921CC1ABB00C4ADA1 /* ofile_error.c */, + DE095FD621CC1ABB00C4ADA1 /* ofile_get_word.c */, + DE095FDB21CC1ABB00C4ADA1 /* ofile.c */, + DE095FCC21CC1ABB00C4ADA1 /* print.c */, + DE095FC621CC1ABB00C4ADA1 /* reloc.c */, + DE095FDF21CC1ABB00C4ADA1 /* rnd.c */, + DE095FEC21CC1ABB00C4ADA1 /* seg_addr_table.c */, + DE095FC721CC1ABB00C4ADA1 /* set_arch_flag_name.c */, + DE095FEA21CC1ABB00C4ADA1 /* swap_headers.c */, + DE095FCB21CC1ABB00C4ADA1 /* symbol_list.c */, + DE095FDD21CC1ABB00C4ADA1 /* SymLoc.c */, + DE095FE321CC1ABB00C4ADA1 /* unix_standard_mode.c */, + DE095FE021CC1ABB00C4ADA1 /* version_number.c */, + DE095FCA21CC1ABB00C4ADA1 /* vm_flush_cache.c */, + DE095FE221CC1ABB00C4ADA1 /* write64.c */, + DE095FE721CC1ABB00C4ADA1 /* writeout.c */, + ); + path = libstuff; + sourceTree = ""; + }; + DE095FEF21CC1ABC00C4ADA1 /* otool */ = { + isa = PBXGroup; + children = ( + DE095FF221CC1ABC00C4ADA1 /* arm_disasm.c */, + DE09600121CC1ABC00C4ADA1 /* arm_disasm.h */, + DE095FFA21CC1ABC00C4ADA1 /* arm64_disasm.c */, + DE09600B21CC1ABC00C4ADA1 /* arm64_disasm.h */, + DE095FFC21CC1ABC00C4ADA1 /* coff_print.c */, + DE095FFB21CC1ABC00C4ADA1 /* cxa_demangle.h */, + DE095FF121CC1ABC00C4ADA1 /* dyld_bind_info.c */, + DE09600521CC1ABC00C4ADA1 /* dyld_bind_info.h */, + DE0E42D922065D1300DD227C /* fixup-chains.h */, + DE09600D21CC1ABC00C4ADA1 /* hppa_disasm.c */, + DE095FFF21CC1ABC00C4ADA1 /* hppa_disasm.h */, + DE095FF621CC1ABC00C4ADA1 /* i386_disasm.c */, + DE09600C21CC1ABC00C4ADA1 /* i386_disasm.h */, + DE095FF421CC1ABC00C4ADA1 /* i860_disasm.c */, + DE09600921CC1ABC00C4ADA1 /* i860_disasm.h */, + DE095FF921CC1ABC00C4ADA1 /* m68k_disasm.c */, + DE09600A21CC1ABC00C4ADA1 /* m68k_disasm.h */, + DE09600821CC1ABC00C4ADA1 /* m88k_disasm.c */, + DE095FF321CC1ABC00C4ADA1 /* m88k_disasm.h */, + DE09600421CC1ABC00C4ADA1 /* main.c */, + DE095FF721CC1ABC00C4ADA1 /* Makefile */, + DE09600321CC1ABC00C4ADA1 /* notes */, + DE09601021CC1ABC00C4ADA1 /* notify.c */, + DE09600021CC1ABC00C4ADA1 /* notify.h */, + DE09600721CC1ABC00C4ADA1 /* ofile_print.c */, + DE095FF521CC1ABC00C4ADA1 /* ofile_print.h */, + DE09600E21CC1ABC00C4ADA1 /* otool.h */, + DE095FF021CC1ABC00C4ADA1 /* ppc_disasm.c */, + DE09600621CC1ABC00C4ADA1 /* ppc_disasm.h */, + DE09600221CC1ABC00C4ADA1 /* print_bitcode.c */, + DE09601121CC1ABC00C4ADA1 /* print_objc.c */, + DE095FF821CC1ABC00C4ADA1 /* print_objc2_32bit.c */, + DE095FFD21CC1ABC00C4ADA1 /* print_objc2_64bit.c */, + DE09600F21CC1ABC00C4ADA1 /* sparc_disasm.c */, + DE095FFE21CC1ABC00C4ADA1 /* sparc_disasm.h */, + ); + path = otool; + sourceTree = ""; + }; + DE09601221CC1ABC00C4ADA1 /* RelNotes */ = { + isa = PBXGroup; + children = ( + DE09601321CC1ABC00C4ADA1 /* CompilerTools.html */, + DE09601521CC1ABC00C4ADA1 /* FatFiles.rtf */, + DE09601421CC1ABC00C4ADA1 /* Makefile */, + DE09601721CC1ABC00C4ADA1 /* Prebinding.html */, + DE09601621CC1ABC00C4ADA1 /* Private_CompilerTools.html */, + ); + path = RelNotes; + sourceTree = ""; + }; + DE09601821CC1ABC00C4ADA1 /* ar */ = { + isa = PBXGroup; + children = ( + DE09602121CC1ABC00C4ADA1 /* append.c */, + DE09602721CC1ABC00C4ADA1 /* ar.1 */, + DE09601D21CC1ABC00C4ADA1 /* ar.5 */, + DE09602021CC1ABC00C4ADA1 /* ar.c */, + DE09602221CC1ABC00C4ADA1 /* archive.c */, + DE09601921CC1ABC00C4ADA1 /* archive.h */, + DE09601C21CC1ABC00C4ADA1 /* contents.c */, + DE09602621CC1ABC00C4ADA1 /* delete.c */, + DE09602821CC1ABC00C4ADA1 /* extern.h */, + DE09601A21CC1ABC00C4ADA1 /* extract.c */, + DE09601E21CC1ABC00C4ADA1 /* Makefile */, + DE09602921CC1ABC00C4ADA1 /* misc.c */, + DE09601F21CC1ABC00C4ADA1 /* move.c */, + DE09602321CC1ABC00C4ADA1 /* notes */, + DE09602421CC1ABC00C4ADA1 /* pathnames.h */, + DE09601B21CC1ABC00C4ADA1 /* print.c */, + DE09602521CC1ABC00C4ADA1 /* replace.c */, + ); + path = ar; + sourceTree = ""; + }; + DE09602A21CC1ABC00C4ADA1 /* include */ = { + isa = PBXGroup; + children = ( + DE09606021CC1ABC00C4ADA1 /* architecture */, + DE09603421CC1ABC00C4ADA1 /* cbt */, + DE09602B21CC1ABC00C4ADA1 /* coff */, + DE5DC68421F7ED5200A7CA07 /* driverkit */, + DE0960B821CC1ABC00C4ADA1 /* elf */, + DE09605C21CC1ABC00C4ADA1 /* gnu */, + DE09603921CC1ABC00C4ADA1 /* i386 */, + DE0960BA21CC1ABC00C4ADA1 /* llvm-c */, + DE09606F21CC1ABC00C4ADA1 /* mach */, + DE09608821CC1ABC00C4ADA1 /* mach-o */, + DE09603821CC1ABC00C4ADA1 /* Makefile */, + DE09606E21CC1ABC00C4ADA1 /* notes */, + DE0960B621CC1ABC00C4ADA1 /* opcode */, + DE09603621CC1ABC00C4ADA1 /* standalone */, + DE09603D21CC1ABC00C4ADA1 /* stuff */, + DE09606C21CC1ABC00C4ADA1 /* sys */, + DE09603B21CC1ABC00C4ADA1 /* xar */, + ); + path = include; + sourceTree = ""; + }; + DE09602B21CC1ABC00C4ADA1 /* coff */ = { + isa = PBXGroup; + children = ( + DE09603121CC1ABC00C4ADA1 /* aouthdr.h */, + DE09602E21CC1ABC00C4ADA1 /* base_relocs.h */, + DE09602F21CC1ABC00C4ADA1 /* bytesex.h */, + DE09603221CC1ABC00C4ADA1 /* debug_directory.h */, + DE09602C21CC1ABC00C4ADA1 /* filehdr.h */, + DE09603021CC1ABC00C4ADA1 /* ms_dos_stub.h */, + DE09603321CC1ABC00C4ADA1 /* scnhdr.h */, + DE09602D21CC1ABC00C4ADA1 /* syment.h */, + ); + path = coff; + sourceTree = ""; + }; + DE09603421CC1ABC00C4ADA1 /* cbt */ = { + isa = PBXGroup; + children = ( + DE09603521CC1ABC00C4ADA1 /* libsyminfo.h */, + ); + path = cbt; + sourceTree = ""; + }; + DE09603621CC1ABC00C4ADA1 /* standalone */ = { + isa = PBXGroup; + children = ( + DE09603721CC1ABC00C4ADA1 /* libsa.h */, + ); + path = standalone; + sourceTree = ""; + }; + DE09603921CC1ABC00C4ADA1 /* i386 */ = { + isa = PBXGroup; + children = ( + DE09603A21CC1ABC00C4ADA1 /* eflags.h */, + ); + path = i386; + sourceTree = ""; + }; + DE09603B21CC1ABC00C4ADA1 /* xar */ = { + isa = PBXGroup; + children = ( + DE09603C21CC1ABC00C4ADA1 /* xar.h */, + ); + path = xar; + sourceTree = ""; + }; + DE09603D21CC1ABC00C4ADA1 /* stuff */ = { + isa = PBXGroup; + children = ( + DE09605221CC1ABC00C4ADA1 /* allocate.h */, + DE09605A21CC1ABC00C4ADA1 /* arch.h */, + DEB7156222A194350031FD9F /* args.h */, + DE09604E21CC1ABC00C4ADA1 /* best_arch.h */, + DE09604421CC1ABC00C4ADA1 /* bool.h */, + DE09604A21CC1ABC00C4ADA1 /* breakout.h */, + DE09604121CC1ABC00C4ADA1 /* bytesex.h */, + DE09605721CC1ABC00C4ADA1 /* crc32.h */, + DE09605621CC1ABC00C4ADA1 /* dylib_roots.h */, + DE09605821CC1ABC00C4ADA1 /* dylib_table.h */, + DE09604921CC1ABC00C4ADA1 /* errors.h */, + DE09605521CC1ABC00C4ADA1 /* execute.h */, + DE09605921CC1ABC00C4ADA1 /* guess_short_name.h */, + DE09604021CC1ABC00C4ADA1 /* hash_string.h */, + DE09604821CC1ABC00C4ADA1 /* hppa.h */, + DE09604C21CC1ABC00C4ADA1 /* llvm.h */, + DE09605B21CC1ABC00C4ADA1 /* lto.h */, + DE09604D21CC1ABC00C4ADA1 /* macosx_deployment_target.h */, + DE09603F21CC1ABC00C4ADA1 /* ofile.h */, + DE09605121CC1ABC00C4ADA1 /* openstep_mach.h */, + DE09605421CC1ABC00C4ADA1 /* print.h */, + DE09605321CC1ABC00C4ADA1 /* reloc.h */, + DE09604221CC1ABC00C4ADA1 /* rnd.h */, + DE09604B21CC1ABC00C4ADA1 /* seg_addr_table.h */, + DE09605021CC1ABC00C4ADA1 /* symbol_list.h */, + DE09604321CC1ABC00C4ADA1 /* symbol.h */, + DE09603E21CC1ABC00C4ADA1 /* SymLoc.h */, + DE09604521CC1ABC00C4ADA1 /* unix_standard_mode.h */, + DE09604721CC1ABC00C4ADA1 /* version_number.h */, + DE09604F21CC1ABC00C4ADA1 /* vm_flush_cache.h */, + DE09604621CC1ABC00C4ADA1 /* write64.h */, + ); + path = stuff; + sourceTree = ""; + }; + DE09605C21CC1ABC00C4ADA1 /* gnu */ = { + isa = PBXGroup; + children = ( + DE09605F21CC1ABC00C4ADA1 /* a.out.h */, + DE09605E21CC1ABC00C4ADA1 /* exec.h */, + DE09605D21CC1ABC00C4ADA1 /* symseg.h */, + ); + path = gnu; + sourceTree = ""; + }; + DE09606021CC1ABC00C4ADA1 /* architecture */ = { + isa = PBXGroup; + children = ( + DE09606721CC1ABC00C4ADA1 /* i386 */, + DE09606421CC1ABC00C4ADA1 /* m88k */, + DE09606121CC1ABC00C4ADA1 /* nrw */, + DE09606A21CC1ABC00C4ADA1 /* sparc */, + ); + path = architecture; + sourceTree = ""; + }; + DE09606121CC1ABC00C4ADA1 /* nrw */ = { + isa = PBXGroup; + children = ( + DE09606221CC1ABC00C4ADA1 /* macro_help.h */, + DE09606321CC1ABC00C4ADA1 /* reg_help.h */, + ); + path = nrw; + sourceTree = ""; + }; + DE09606421CC1ABC00C4ADA1 /* m88k */ = { + isa = PBXGroup; + children = ( + DE09606521CC1ABC00C4ADA1 /* fp_regs.h */, + DE09606621CC1ABC00C4ADA1 /* reg_help.h */, + ); + path = m88k; + sourceTree = ""; + }; + DE09606721CC1ABC00C4ADA1 /* i386 */ = { + isa = PBXGroup; + children = ( + DE09606921CC1ABC00C4ADA1 /* fpu.h */, + DE09606821CC1ABC00C4ADA1 /* frame.h */, + ); + path = i386; + sourceTree = ""; + }; + DE09606A21CC1ABC00C4ADA1 /* sparc */ = { + isa = PBXGroup; + children = ( + DE09606B21CC1ABC00C4ADA1 /* reg.h */, + ); + path = sparc; + sourceTree = ""; + }; + DE09606C21CC1ABC00C4ADA1 /* sys */ = { + isa = PBXGroup; + children = ( + DE09606D21CC1ABC00C4ADA1 /* gmon.h */, + ); + path = sys; + sourceTree = ""; + }; + DE09606F21CC1ABC00C4ADA1 /* mach */ = { + isa = PBXGroup; + children = ( + DE09608021CC1ABC00C4ADA1 /* arm */, + DE09607A21CC1ABC00C4ADA1 /* hppa */, + DE09607521CC1ABC00C4ADA1 /* i386 */, + DE09608421CC1ABC00C4ADA1 /* i860 */, + DE09607021CC1ABC00C4ADA1 /* m68k */, + DE09607221CC1ABC00C4ADA1 /* m88k */, + DE09607421CC1ABC00C4ADA1 /* machine.h */, + DE09607C21CC1ABC00C4ADA1 /* ppc */, + DE09607F21CC1ABC00C4ADA1 /* slot_name.h */, + DE09608621CC1ABC00C4ADA1 /* sparc */, + ); + path = mach; + sourceTree = ""; + }; + DE09607021CC1ABC00C4ADA1 /* m68k */ = { + isa = PBXGroup; + children = ( + DE09607121CC1ABC00C4ADA1 /* thread_status.h */, + ); + path = m68k; + sourceTree = ""; + }; + DE09607221CC1ABC00C4ADA1 /* m88k */ = { + isa = PBXGroup; + children = ( + DE09607321CC1ABC00C4ADA1 /* thread_status.h */, + ); + path = m88k; + sourceTree = ""; + }; + DE09607521CC1ABC00C4ADA1 /* i386 */ = { + isa = PBXGroup; + children = ( + DE09607821CC1ABC00C4ADA1 /* _structs.h */, + DE09607621CC1ABC00C4ADA1 /* fp_reg.h */, + DE09607721CC1ABC00C4ADA1 /* thread_state.h */, + DE09607921CC1ABC00C4ADA1 /* thread_status.h */, + ); + path = i386; + sourceTree = ""; + }; + DE09607A21CC1ABC00C4ADA1 /* hppa */ = { + isa = PBXGroup; + children = ( + DE09607B21CC1ABC00C4ADA1 /* thread_status.h */, + ); + path = hppa; + sourceTree = ""; + }; + DE09607C21CC1ABC00C4ADA1 /* ppc */ = { + isa = PBXGroup; + children = ( + DE09607D21CC1ABC00C4ADA1 /* _structs.h */, + DE09607E21CC1ABC00C4ADA1 /* thread_status.h */, + ); + path = ppc; + sourceTree = ""; + }; + DE09608021CC1ABC00C4ADA1 /* arm */ = { + isa = PBXGroup; + children = ( + DE09608221CC1ABC00C4ADA1 /* _structs.h */, + DE09608121CC1ABC00C4ADA1 /* thread_state.h */, + DE09608321CC1ABC00C4ADA1 /* thread_status.h */, + ); + path = arm; + sourceTree = ""; + }; + DE09608421CC1ABC00C4ADA1 /* i860 */ = { + isa = PBXGroup; + children = ( + DE09608521CC1ABC00C4ADA1 /* thread_status.h */, + ); + path = i860; + sourceTree = ""; + }; + DE09608621CC1ABC00C4ADA1 /* sparc */ = { + isa = PBXGroup; + children = ( + DE09608721CC1ABC00C4ADA1 /* thread_status.h */, + ); + path = sparc; + sourceTree = ""; + }; + DE09608821CC1ABC00C4ADA1 /* mach-o */ = { + isa = PBXGroup; + children = ( + DE0960B521CC1ABC00C4ADA1 /* arch.h */, + DE0960A621CC1ABC00C4ADA1 /* arm */, + DE0960AE21CC1ABC00C4ADA1 /* arm64 */, + DE0960A521CC1ABC00C4ADA1 /* dyld_debug.h */, + DE09609D21CC1ABC00C4ADA1 /* dyld_gdb.h */, + DE0960A221CC1ABC00C4ADA1 /* dyld_priv.h */, + DE09609F21CC1ABC00C4ADA1 /* dyld.h */, + DE0960B121CC1ABC00C4ADA1 /* fat.h */, + DE09609021CC1ABC00C4ADA1 /* getsect.h */, + DE09609E21CC1ABC00C4ADA1 /* gmon.h */, + DE09609521CC1ABC00C4ADA1 /* hppa */, + DE09609321CC1ABC00C4ADA1 /* i386 */, + DE0960A821CC1ABC00C4ADA1 /* i860 */, + DE09608F21CC1ABC00C4ADA1 /* kld.h */, + DE0960B021CC1ABC00C4ADA1 /* ldsyms.h */, + DE0960A321CC1ABC00C4ADA1 /* loader.h */, + DE09608921CC1ABC00C4ADA1 /* m68k */, + DE09608C21CC1ABC00C4ADA1 /* m88k */, + DE0960A021CC1ABC00C4ADA1 /* nlist.h */, + DE09609821CC1ABC00C4ADA1 /* ppc */, + DE09609121CC1ABC00C4ADA1 /* ranlib.h */, + DE0960A121CC1ABC00C4ADA1 /* redo_prebinding.h */, + DE0960A421CC1ABC00C4ADA1 /* reloc.h */, + DE09608B21CC1ABC00C4ADA1 /* rld_state.h */, + DE0960B221CC1ABC00C4ADA1 /* rld.h */, + DE09609221CC1ABC00C4ADA1 /* sarld.h */, + DE0960AB21CC1ABC00C4ADA1 /* sparc */, + DE09609C21CC1ABC00C4ADA1 /* stab.h */, + DE09609B21CC1ABC00C4ADA1 /* swap.h */, + DE0960B321CC1ABC00C4ADA1 /* x86_64 */, + ); + path = "mach-o"; + sourceTree = ""; + }; + DE09608921CC1ABC00C4ADA1 /* m68k */ = { + isa = PBXGroup; + children = ( + DE09608A21CC1ABC00C4ADA1 /* swap.h */, + ); + path = m68k; + sourceTree = ""; + }; + DE09608C21CC1ABC00C4ADA1 /* m88k */ = { + isa = PBXGroup; + children = ( + DE09608E21CC1ABC00C4ADA1 /* reloc.h */, + DE09608D21CC1ABC00C4ADA1 /* swap.h */, + ); + path = m88k; + sourceTree = ""; + }; + DE09609321CC1ABC00C4ADA1 /* i386 */ = { + isa = PBXGroup; + children = ( + DE09609421CC1ABC00C4ADA1 /* swap.h */, + ); + path = i386; + sourceTree = ""; + }; + DE09609521CC1ABC00C4ADA1 /* hppa */ = { + isa = PBXGroup; + children = ( + DE09609721CC1ABC00C4ADA1 /* reloc.h */, + DE09609621CC1ABC00C4ADA1 /* swap.h */, + ); + path = hppa; + sourceTree = ""; + }; + DE09609821CC1ABC00C4ADA1 /* ppc */ = { + isa = PBXGroup; + children = ( + DE09609A21CC1ABC00C4ADA1 /* reloc.h */, + DE09609921CC1ABC00C4ADA1 /* swap.h */, + ); + path = ppc; + sourceTree = ""; + }; + DE0960A621CC1ABC00C4ADA1 /* arm */ = { + isa = PBXGroup; + children = ( + DE0960A721CC1ABC00C4ADA1 /* reloc.h */, + ); + path = arm; + sourceTree = ""; + }; + DE0960A821CC1ABC00C4ADA1 /* i860 */ = { + isa = PBXGroup; + children = ( + DE0960AA21CC1ABC00C4ADA1 /* reloc.h */, + DE0960A921CC1ABC00C4ADA1 /* swap.h */, + ); + path = i860; + sourceTree = ""; + }; + DE0960AB21CC1ABC00C4ADA1 /* sparc */ = { + isa = PBXGroup; + children = ( + DE0960AD21CC1ABC00C4ADA1 /* reloc.h */, + DE0960AC21CC1ABC00C4ADA1 /* swap.h */, + ); + path = sparc; + sourceTree = ""; + }; + DE0960AE21CC1ABC00C4ADA1 /* arm64 */ = { + isa = PBXGroup; + children = ( + DE0960AF21CC1ABC00C4ADA1 /* reloc.h */, + ); + path = arm64; + sourceTree = ""; + }; + DE0960B321CC1ABC00C4ADA1 /* x86_64 */ = { + isa = PBXGroup; + children = ( + DE0960B421CC1ABC00C4ADA1 /* reloc.h */, + ); + path = x86_64; + sourceTree = ""; + }; + DE0960B621CC1ABC00C4ADA1 /* opcode */ = { + isa = PBXGroup; + children = ( + DE0960B721CC1ABC00C4ADA1 /* arm.h */, + ); + path = opcode; + sourceTree = ""; + }; + DE0960B821CC1ABC00C4ADA1 /* elf */ = { + isa = PBXGroup; + children = ( + DE0960B921CC1ABC00C4ADA1 /* dwarf2.h */, + ); + path = elf; + sourceTree = ""; + }; + DE0960BA21CC1ABC00C4ADA1 /* llvm-c */ = { + isa = PBXGroup; + children = ( + DE0960BB21CC1ABC00C4ADA1 /* Disassembler.h */, + ); + path = "llvm-c"; + sourceTree = ""; + }; + DE0960BC21CC1ABC00C4ADA1 /* efitools */ = { + isa = PBXGroup; + children = ( + DE0960BE21CC1ABC00C4ADA1 /* Makefile */, + DE0960C021CC1ABC00C4ADA1 /* makerelocs.c */, + DE0960BD21CC1ABC00C4ADA1 /* mtoc.c */, + DEC00B6A220012C80079FFD3 /* mtor.c */, + DE0960BF21CC1ABC00C4ADA1 /* notes */, + ); + path = efitools; + sourceTree = ""; + }; + DE0960C121CC1ABC00C4ADA1 /* as */ = { + isa = PBXGroup; + children = ( + DE09610F21CC1ABC00C4ADA1 /* app.c */, + DE0960DE21CC1ABC00C4ADA1 /* app.h */, + DE09610021CC1ABC00C4ADA1 /* arch64_32.h */, + DE0960D721CC1ABC00C4ADA1 /* arm_reloc.h */, + DE0960EA21CC1ABC00C4ADA1 /* arm-check.c */, + DE09610521CC1ABC00C4ADA1 /* arm.c */, + DE0960F521CC1ABC00C4ADA1 /* as.c */, + DE0960C321CC1ABC00C4ADA1 /* as.h */, + DE0960F321CC1ABC00C4ADA1 /* atof-generic.c */, + DE0960D321CC1ABC00C4ADA1 /* atof-ieee.c */, + DE0960F921CC1ABC00C4ADA1 /* atof-ieee.h */, + DE09610C21CC1ABC00C4ADA1 /* bignum.h */, + DE09610221CC1ABC00C4ADA1 /* cctools.plist */, + DE0960F121CC1ABC00C4ADA1 /* COPYING */, + DE09610D21CC1ABC00C4ADA1 /* driver.c */, + DE0960CD21CC1ABC00C4ADA1 /* dwarf2dbg.c */, + DE0960FC21CC1ABC00C4ADA1 /* dwarf2dbg.h */, + DE09610E21CC1ABC00C4ADA1 /* expr.c */, + DE0960DF21CC1ABC00C4ADA1 /* expr.h */, + DE0960FE21CC1ABC00C4ADA1 /* filenames.h */, + DE0960D821CC1ABC00C4ADA1 /* fixes.c */, + DE09610421CC1ABC00C4ADA1 /* fixes.h */, + DE0960EC21CC1ABC00C4ADA1 /* flonum-const.c */, + DE0960F721CC1ABC00C4ADA1 /* flonum-copy.c */, + DE09610321CC1ABC00C4ADA1 /* flonum-mult.c */, + DE0960DB21CC1ABC00C4ADA1 /* flonum.h */, + DE0960FF21CC1ABC00C4ADA1 /* frags.c */, + DE0960C921CC1ABC00C4ADA1 /* frags.h */, + DE0960E421CC1ABC00C4ADA1 /* hash.c */, + DE09610A21CC1ABC00C4ADA1 /* hash.h */, + DE0960E821CC1ABC00C4ADA1 /* hex_value.h */, + DE0960E321CC1ABC00C4ADA1 /* hex-value.c */, + DE09610921CC1ABC00C4ADA1 /* hppa-aux.c */, + DE0960E021CC1ABC00C4ADA1 /* hppa-aux.h */, + DE0960EF21CC1ABC00C4ADA1 /* hppa-check.c */, + DE0960ED21CC1ABC00C4ADA1 /* hppa-opcode.h */, + DE09611221CC1ABC00C4ADA1 /* hppa.c */, + DE0960DA21CC1ABC00C4ADA1 /* i386-check.c */, + DE0960CF21CC1ABC00C4ADA1 /* i386-opcode.h */, + DE0960D421CC1ABC00C4ADA1 /* i386.c */, + DE09610621CC1ABC00C4ADA1 /* i386.h */, + DE0960C521CC1ABC00C4ADA1 /* i860-check.c */, + DE0960D521CC1ABC00C4ADA1 /* i860-opcode.h */, + DE0960D921CC1ABC00C4ADA1 /* i860.c */, + DE0960DC21CC1ABC00C4ADA1 /* input-file.c */, + DE09611021CC1ABC00C4ADA1 /* input-file.h */, + DE0960F021CC1ABC00C4ADA1 /* input-scrub.c */, + DE0960C421CC1ABC00C4ADA1 /* input-scrub.h */, + DE0960C621CC1ABC00C4ADA1 /* layout.c */, + DE0960EB21CC1ABC00C4ADA1 /* layout.h */, + DE09611121CC1ABC00C4ADA1 /* m68k-check.c */, + DE0960C821CC1ABC00C4ADA1 /* m68k-opcode.h */, + DE0960E721CC1ABC00C4ADA1 /* m68k.c */, + DE0960CC21CC1ABC00C4ADA1 /* m88k-check.c */, + DE09610721CC1ABC00C4ADA1 /* m88k-opcode.h */, + DE0960DD21CC1ABC00C4ADA1 /* m88k.c */, + DE0960D621CC1ABC00C4ADA1 /* Makefile */, + DE0960E121CC1ABC00C4ADA1 /* md.h */, + DE0960FD21CC1ABC00C4ADA1 /* messages.c */, + DE0960CA21CC1ABC00C4ADA1 /* messages.h */, + DE0960F221CC1ABC00C4ADA1 /* notes */, + DE0960D021CC1ABC00C4ADA1 /* obstack.c */, + DE0960F821CC1ABC00C4ADA1 /* obstack.h */, + DE0960C721CC1ABC00C4ADA1 /* ppc-check.c */, + DE0960E221CC1ABC00C4ADA1 /* ppc-opcode.h */, + DE0960D221CC1ABC00C4ADA1 /* ppc.c */, + DE0960E521CC1ABC00C4ADA1 /* read.c */, + DE09610821CC1ABC00C4ADA1 /* read.h */, + DE0960FA21CC1ABC00C4ADA1 /* relax.h */, + DE0960F621CC1ABC00C4ADA1 /* sections.c */, + DE0960D121CC1ABC00C4ADA1 /* sections.h */, + DE09610B21CC1ABC00C4ADA1 /* sparc-check.c */, + DE0960EE21CC1ABC00C4ADA1 /* sparc-opcode.h */, + DE0960E921CC1ABC00C4ADA1 /* sparc.c */, + DE0960E621CC1ABC00C4ADA1 /* struc-symbol.h */, + DE09610121CC1ABC00C4ADA1 /* symbols.c */, + DE0960CB21CC1ABC00C4ADA1 /* symbols.h */, + DE0960F421CC1ABC00C4ADA1 /* write_object.c */, + DE0960C221CC1ABC00C4ADA1 /* write_object.h */, + DE0960FB21CC1ABC00C4ADA1 /* xmalloc.c */, + DE0960CE21CC1ABC00C4ADA1 /* xmalloc.h */, + ); + path = as; + sourceTree = ""; + }; + DE09612D21CC218E00C4ADA1 /* Products */ = { + isa = PBXGroup; + children = ( + DE09612C21CC218E00C4ADA1 /* libstuff.a */, + DE09616321CC4A7C00C4ADA1 /* as */, + DE09617721CC4F1B00C4ADA1 /* as-arm */, + DE0961BD21CC534200C4ADA1 /* as-i386 */, + DE0961E121CC53E700C4ADA1 /* as-x86_64 */, + DE0961FD21CC77FC00C4ADA1 /* lipo */, + DE09620E21CC78BD00C4ADA1 /* strings */, + DE09621D21CC78F500C4ADA1 /* size-classic */, + DE09623521CC809300C4ADA1 /* nm-classic */, + DE09624921CD4F8F00C4ADA1 /* libtool */, + DE09625D21CD500600C4ADA1 /* strip */, + DE09627321CD594000C4ADA1 /* nmedit */, + DE09628521CD599B00C4ADA1 /* segedit */, + DE09629421CD59E800C4ADA1 /* cmpdylib */, + DE0962A321CD5A0400C4ADA1 /* pagestuff */, + DE0962B221CD5A2300C4ADA1 /* redo_prebinding */, + DE0962C121CD5A4900C4ADA1 /* install_name_tool */, + DE0962D021CD5A6100C4ADA1 /* codesign_allocate */, + DE0962ED21CD618200C4ADA1 /* ctf_insert */, + DE0962FC21CD61A600C4ADA1 /* bitcode_strip */, + DE09630F21CD621600C4ADA1 /* otool-classic */, + DE09633321CD640900C4ADA1 /* llvm-otool */, + DE1F63F321CD6511004CA2BF /* ar */, + DE1F641721CD65BC004CA2BF /* checksyms */, + DE1F642821CD66BA004CA2BF /* indr */, + DE1F643921CD66F5004CA2BF /* seg_addr_table */, + DE1F644821CD6715004CA2BF /* check_dylib */, + DE1F645721CD6734004CA2BF /* seg_hack */, + DE1F646521CD67E8004CA2BF /* mtoc */, + DE8229F921CD8DD6008CD150 /* libmacho.dylib */, + DE000B3621CDB9DB000CEC53 /* libmacho.a */, + DE000B5E21CDBE77000CEC53 /* libmacho_static.a */, + DE000B6521CDBEE8000CEC53 /* libredo_prebinding.a */, + DE000B7421CDEFDF000CEC53 /* libsyminfo.a */, + DEB23D8D21DEA11C007F9934 /* vtool */, + DE97E91821F3B72700C7947D /* libstuff_test */, + DE5DC67B21F7EA8000A7CA07 /* libmacho.dylib */, + DEC00B67220012660079FFD3 /* mtor */, + ); + name = Products; + sourceTree = ""; + }; + DE09616E21CC4DD500C4ADA1 /* Frameworks */ = { + isa = PBXGroup; + children = ( + DE09632521CD638600C4ADA1 /* libc++.tbd */, + ); + name = Frameworks; + sourceTree = ""; + }; + DE5DC68421F7ED5200A7CA07 /* driverkit */ = { + isa = PBXGroup; + children = ( + DE5DC68521F7ED5200A7CA07 /* getsect.h */, + ); + path = driverkit; + sourceTree = ""; + }; + DE76108321CC103000736984 = { + isa = PBXGroup; + children = ( + DE09601821CC1ABC00C4ADA1 /* ar */, + DE0960C121CC1ABC00C4ADA1 /* as */, + DE095F6021CC1ABB00C4ADA1 /* cbtlibs */, + DE0960BC21CC1ABC00C4ADA1 /* efitools */, + DE09602A21CC1ABC00C4ADA1 /* include */, + DE095F6421CC1ABB00C4ADA1 /* libmacho */, + DE095FC521CC1ABB00C4ADA1 /* libstuff */, + DE97E91921F3B72700C7947D /* libstuff_test */, + DE095F8F21CC1ABB00C4ADA1 /* man */, + DE095F7721CC1ABB00C4ADA1 /* misc */, + DE095FEF21CC1ABC00C4ADA1 /* otool */, + DE09601221CC1ABC00C4ADA1 /* RelNotes */, + DE095EF421CC1ABB00C4ADA1 /* tests */, + DE095F7621CC1ABB00C4ADA1 /* xcode */, + DE09612D21CC218E00C4ADA1 /* Products */, + DE09616E21CC4DD500C4ADA1 /* Frameworks */, + ); + sourceTree = ""; + }; + DE97E91921F3B72700C7947D /* libstuff_test */ = { + isa = PBXGroup; + children = ( + DE97E91A21F3B72700C7947D /* libstuff_test.c */, + DEDFD7E22299C66D00230D7D /* test_main.h */, + DE97E92821F3B91900C7947D /* test.h */, + DE97E92721F3B91800C7947D /* test.c */, + DE175CB022A2248D0001D8CC /* test_util.h */, + DE175CB122A2248D0001D8CC /* test_util.c */, + DE97E92A21F3B97A00C7947D /* null_test.c */, + DE21482121F59BCE00FF8882 /* allocate_test.c */, + DE21482321F5AB0F00FF8882 /* arch_test.c */, + DEB7157622A1F27A0031FD9F /* args_test.c */, + DE21482521F5B7D700FF8882 /* get_arch_from_host_test.c */, + DE97E92521F3B8EC00C7947D /* guess_short_name_test.c */, + DEDFD7E32299C7F100230D7D /* rnd_test.c */, + DEB5E8D0228B04D000263617 /* version_number_test.c */, + ); + path = libstuff_test; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + DE000B3221CDB9DB000CEC53 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE000B4B21CDBE77000CEC53 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE000B6121CDBEE8000CEC53 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DE000B6C21CDBF1A000CEC53 /* redo_prebinding.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE000B7021CDEFDF000CEC53 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DE000B7821CDF007000CEC53 /* libsyminfo.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09612821CC218E00C4ADA1 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE5DC65F21F7EA8000A7CA07 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DEA1B37B221F52A4003A9149 /* reloc.h in Headers */, + DE5DC66221F7EA8000A7CA07 /* loader.h in Headers */, + DEA1B37C221F52C8003A9149 /* fat.h in Headers */, + DE5DC68621F7ED5200A7CA07 /* getsect.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE8229F521CD8DD6008CD150 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DE822A0D21CDAB13008CD150 /* reloc.h in Headers */, + DE822A0921CDAB13008CD150 /* fat.h in Headers */, + DE822A0B21CDAB13008CD150 /* loader.h in Headers */, + DE822A0A21CDAB13008CD150 /* getsect.h in Headers */, + DE822A0821CDAB13008CD150 /* arch.h in Headers */, + DE822A0C21CDAB13008CD150 /* ranlib.h in Headers */, + DE822A0E21CDAB13008CD150 /* stab.h in Headers */, + DE822A0F21CDAB13008CD150 /* swap.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + DE000B3521CDB9DB000CEC53 /* macho static */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE000B3721CDB9DB000CEC53 /* Build configuration list for PBXNativeTarget "macho static" */; + buildPhases = ( + DE000B3221CDB9DB000CEC53 /* Headers */, + DE000B3321CDB9DB000CEC53 /* Sources */, + DE000B3421CDB9DB000CEC53 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "macho static"; + productName = "macho static"; + productReference = DE000B3621CDB9DB000CEC53 /* libmacho.a */; + productType = "com.apple.product-type.library.static"; + }; + DE000B4A21CDBE77000CEC53 /* macho static 2 */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE000B5B21CDBE77000CEC53 /* Build configuration list for PBXNativeTarget "macho static 2" */; + buildPhases = ( + DE000B4B21CDBE77000CEC53 /* Headers */, + DE000B4C21CDBE77000CEC53 /* Sources */, + DE000B5A21CDBE77000CEC53 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "macho static 2"; + productName = "macho static"; + productReference = DE000B5E21CDBE77000CEC53 /* libmacho_static.a */; + productType = "com.apple.product-type.library.static"; + }; + DE000B6421CDBEE8000CEC53 /* libredo_prebinding */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE000B6621CDBEE8000CEC53 /* Build configuration list for PBXNativeTarget "libredo_prebinding" */; + buildPhases = ( + DE000B6121CDBEE8000CEC53 /* Headers */, + DE000B6221CDBEE8000CEC53 /* Sources */, + DE000B6321CDBEE8000CEC53 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + DE000B6A21CDBEF7000CEC53 /* PBXTargetDependency */, + ); + name = libredo_prebinding; + productName = libredo_prebinding; + productReference = DE000B6521CDBEE8000CEC53 /* libredo_prebinding.a */; + productType = "com.apple.product-type.library.static"; + }; + DE000B7321CDEFDF000CEC53 /* syminfo */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE000B7521CDEFDF000CEC53 /* Build configuration list for PBXNativeTarget "syminfo" */; + buildPhases = ( + DE000B7021CDEFDF000CEC53 /* Headers */, + DE000B7121CDEFDF000CEC53 /* Sources */, + DE000B7221CDEFDF000CEC53 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = syminfo; + productName = syminfo; + productReference = DE000B7421CDEFDF000CEC53 /* libsyminfo.a */; + productType = "com.apple.product-type.library.static"; + }; + DE09612B21CC218E00C4ADA1 /* stuff */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE09612E21CC218E00C4ADA1 /* Build configuration list for PBXNativeTarget "stuff" */; + buildPhases = ( + DE09612821CC218E00C4ADA1 /* Headers */, + DE09612921CC218E00C4ADA1 /* Sources */, + DE09612A21CC218E00C4ADA1 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = stuff; + productName = stuff; + productReference = DE09612C21CC218E00C4ADA1 /* libstuff.a */; + productType = "com.apple.product-type.library.static"; + }; + DE09616221CC4A7C00C4ADA1 /* as driver */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE09616721CC4A7D00C4ADA1 /* Build configuration list for PBXNativeTarget "as driver" */; + buildPhases = ( + DE09615F21CC4A7C00C4ADA1 /* Sources */, + DE09616021CC4A7C00C4ADA1 /* Frameworks */, + DE09616121CC4A7C00C4ADA1 /* CopyFiles */, + DEA2409521CE05E10026D013 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + DE09616C21CC4DB800C4ADA1 /* PBXTargetDependency */, + ); + name = "as driver"; + productName = "as driver"; + productReference = DE09616321CC4A7C00C4ADA1 /* as */; + productType = "com.apple.product-type.tool"; + }; + DE09617621CC4F1B00C4ADA1 /* as arm */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE09617D21CC4F1B00C4ADA1 /* Build configuration list for PBXNativeTarget "as arm" */; + buildPhases = ( + DE09617321CC4F1B00C4ADA1 /* Sources */, + DE09617421CC4F1B00C4ADA1 /* Frameworks */, + DE09617521CC4F1B00C4ADA1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE09618021CC523300C4ADA1 /* PBXTargetDependency */, + ); + name = "as arm"; + productName = "as arm"; + productReference = DE09617721CC4F1B00C4ADA1 /* as-arm */; + productType = "com.apple.product-type.tool"; + }; + DE09619B21CC534200C4ADA1 /* as i386 */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE0961BA21CC534200C4ADA1 /* Build configuration list for PBXNativeTarget "as i386" */; + buildPhases = ( + DE09619E21CC534200C4ADA1 /* Sources */, + DE0961B721CC534200C4ADA1 /* Frameworks */, + DE0961B921CC534200C4ADA1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE09619C21CC534200C4ADA1 /* PBXTargetDependency */, + ); + name = "as i386"; + productName = "as arm"; + productReference = DE0961BD21CC534200C4ADA1 /* as-i386 */; + productType = "com.apple.product-type.tool"; + }; + DE0961BF21CC53E700C4ADA1 /* as x86_64 */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE0961DE21CC53E700C4ADA1 /* Build configuration list for PBXNativeTarget "as x86_64" */; + buildPhases = ( + DE0961C221CC53E700C4ADA1 /* Sources */, + DE0961DB21CC53E700C4ADA1 /* Frameworks */, + DE0961DD21CC53E700C4ADA1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE0961C021CC53E700C4ADA1 /* PBXTargetDependency */, + ); + name = "as x86_64"; + productName = "as arm"; + productReference = DE0961E121CC53E700C4ADA1 /* as-x86_64 */; + productType = "com.apple.product-type.tool"; + }; + DE0961F121CC77FC00C4ADA1 /* lipo */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE0961FA21CC77FC00C4ADA1 /* Build configuration list for PBXNativeTarget "lipo" */; + buildPhases = ( + DE0961F421CC77FC00C4ADA1 /* Sources */, + DE0961F621CC77FC00C4ADA1 /* Frameworks */, + DE0961F821CC77FC00C4ADA1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE0961F221CC77FC00C4ADA1 /* PBXTargetDependency */, + ); + name = lipo; + productName = "as driver"; + productReference = DE0961FD21CC77FC00C4ADA1 /* lipo */; + productType = "com.apple.product-type.tool"; + }; + DE09620221CC78BD00C4ADA1 /* strings */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE09620B21CC78BD00C4ADA1 /* Build configuration list for PBXNativeTarget "strings" */; + buildPhases = ( + DE09620521CC78BD00C4ADA1 /* Sources */, + DE09620721CC78BD00C4ADA1 /* Frameworks */, + DE09620921CC78BD00C4ADA1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE09620321CC78BD00C4ADA1 /* PBXTargetDependency */, + ); + name = strings; + productName = "as driver"; + productReference = DE09620E21CC78BD00C4ADA1 /* strings */; + productType = "com.apple.product-type.tool"; + }; + DE09621121CC78F500C4ADA1 /* size-classic */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE09621A21CC78F500C4ADA1 /* Build configuration list for PBXNativeTarget "size-classic" */; + buildPhases = ( + DE09621421CC78F500C4ADA1 /* Sources */, + DE09621621CC78F500C4ADA1 /* Frameworks */, + DE09621821CC78F500C4ADA1 /* CopyFiles */, + DE09622121CC793C00C4ADA1 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + DE09621221CC78F500C4ADA1 /* PBXTargetDependency */, + ); + name = "size-classic"; + productName = "as driver"; + productReference = DE09621D21CC78F500C4ADA1 /* size-classic */; + productType = "com.apple.product-type.tool"; + }; + DE09622721CC809300C4ADA1 /* nm-classic */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE09623221CC809300C4ADA1 /* Build configuration list for PBXNativeTarget "nm-classic" */; + buildPhases = ( + DE09622A21CC809300C4ADA1 /* Sources */, + DE09622C21CC809300C4ADA1 /* Frameworks */, + DE09622E21CC809300C4ADA1 /* CopyFiles */, + DE09623121CC809300C4ADA1 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + DE09622821CC809300C4ADA1 /* PBXTargetDependency */, + ); + name = "nm-classic"; + productName = "as driver"; + productReference = DE09623521CC809300C4ADA1 /* nm-classic */; + productType = "com.apple.product-type.tool"; + }; + DE09623B21CD4F8F00C4ADA1 /* libtool */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE09624621CD4F8F00C4ADA1 /* Build configuration list for PBXNativeTarget "libtool" */; + buildPhases = ( + DE09623E21CD4F8F00C4ADA1 /* Sources */, + DE09624021CD4F8F00C4ADA1 /* Frameworks */, + DE09624221CD4F8F00C4ADA1 /* CopyFiles */, + DE09624521CD4F8F00C4ADA1 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + DE09623C21CD4F8F00C4ADA1 /* PBXTargetDependency */, + ); + name = libtool; + productName = "as driver"; + productReference = DE09624921CD4F8F00C4ADA1 /* libtool */; + productType = "com.apple.product-type.tool"; + }; + DE09624F21CD500600C4ADA1 /* strip */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE09625A21CD500600C4ADA1 /* Build configuration list for PBXNativeTarget "strip" */; + buildPhases = ( + DE09625221CD500600C4ADA1 /* Sources */, + DE09625421CD500600C4ADA1 /* Frameworks */, + DE09625621CD500600C4ADA1 /* CopyFiles */, + DE555B3D21E9119800F45496 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + DE09625021CD500600C4ADA1 /* PBXTargetDependency */, + ); + name = strip; + productName = "as driver"; + productReference = DE09625D21CD500600C4ADA1 /* strip */; + productType = "com.apple.product-type.tool"; + }; + DE09626521CD594000C4ADA1 /* nmedit */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE09627021CD594000C4ADA1 /* Build configuration list for PBXNativeTarget "nmedit" */; + buildPhases = ( + DE09626821CD594000C4ADA1 /* Sources */, + DE09626A21CD594000C4ADA1 /* Frameworks */, + DE09626C21CD594000C4ADA1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE09626621CD594000C4ADA1 /* PBXTargetDependency */, + ); + name = nmedit; + productName = "as driver"; + productReference = DE09627321CD594000C4ADA1 /* nmedit */; + productType = "com.apple.product-type.tool"; + }; + DE09627821CD599B00C4ADA1 /* segedit */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE09628221CD599B00C4ADA1 /* Build configuration list for PBXNativeTarget "segedit" */; + buildPhases = ( + DE09627B21CD599B00C4ADA1 /* Sources */, + DE09627D21CD599B00C4ADA1 /* Frameworks */, + DE09627F21CD599B00C4ADA1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE09627921CD599B00C4ADA1 /* PBXTargetDependency */, + ); + name = segedit; + productName = "as driver"; + productReference = DE09628521CD599B00C4ADA1 /* segedit */; + productType = "com.apple.product-type.tool"; + }; + DE09628821CD59E800C4ADA1 /* cmpdylib */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE09629121CD59E800C4ADA1 /* Build configuration list for PBXNativeTarget "cmpdylib" */; + buildPhases = ( + DE09628B21CD59E800C4ADA1 /* Sources */, + DE09628D21CD59E800C4ADA1 /* Frameworks */, + DE09628F21CD59E800C4ADA1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE09628921CD59E800C4ADA1 /* PBXTargetDependency */, + ); + name = cmpdylib; + productName = "as driver"; + productReference = DE09629421CD59E800C4ADA1 /* cmpdylib */; + productType = "com.apple.product-type.tool"; + }; + DE09629721CD5A0400C4ADA1 /* pagestuff */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE0962A021CD5A0400C4ADA1 /* Build configuration list for PBXNativeTarget "pagestuff" */; + buildPhases = ( + DE09629A21CD5A0400C4ADA1 /* Sources */, + DE09629C21CD5A0400C4ADA1 /* Frameworks */, + DE09629E21CD5A0400C4ADA1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE09629821CD5A0400C4ADA1 /* PBXTargetDependency */, + ); + name = pagestuff; + productName = "as driver"; + productReference = DE0962A321CD5A0400C4ADA1 /* pagestuff */; + productType = "com.apple.product-type.tool"; + }; + DE0962A621CD5A2300C4ADA1 /* redo_prebinding */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE0962AF21CD5A2300C4ADA1 /* Build configuration list for PBXNativeTarget "redo_prebinding" */; + buildPhases = ( + DE0962A921CD5A2300C4ADA1 /* Sources */, + DE0962AB21CD5A2300C4ADA1 /* Frameworks */, + DE0962AD21CD5A2300C4ADA1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE0962A721CD5A2300C4ADA1 /* PBXTargetDependency */, + ); + name = redo_prebinding; + productName = "as driver"; + productReference = DE0962B221CD5A2300C4ADA1 /* redo_prebinding */; + productType = "com.apple.product-type.tool"; + }; + DE0962B521CD5A4900C4ADA1 /* install_name_tool */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE0962BE21CD5A4900C4ADA1 /* Build configuration list for PBXNativeTarget "install_name_tool" */; + buildPhases = ( + DE0962B821CD5A4900C4ADA1 /* Sources */, + DE0962BA21CD5A4900C4ADA1 /* Frameworks */, + DE0962BC21CD5A4900C4ADA1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE0962B621CD5A4900C4ADA1 /* PBXTargetDependency */, + ); + name = install_name_tool; + productName = "as driver"; + productReference = DE0962C121CD5A4900C4ADA1 /* install_name_tool */; + productType = "com.apple.product-type.tool"; + }; + DE0962C421CD5A6100C4ADA1 /* codesign_allocate */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE0962CD21CD5A6100C4ADA1 /* Build configuration list for PBXNativeTarget "codesign_allocate" */; + buildPhases = ( + DE0962C721CD5A6100C4ADA1 /* Sources */, + DE0962C921CD5A6100C4ADA1 /* Frameworks */, + DE0962CB21CD5A6100C4ADA1 /* CopyFiles */, + DE0962D321CD5A9900C4ADA1 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + DE0962C521CD5A6100C4ADA1 /* PBXTargetDependency */, + ); + name = codesign_allocate; + productName = "as driver"; + productReference = DE0962D021CD5A6100C4ADA1 /* codesign_allocate */; + productType = "com.apple.product-type.tool"; + }; + DE0962E121CD618200C4ADA1 /* ctf_insert */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE0962EA21CD618200C4ADA1 /* Build configuration list for PBXNativeTarget "ctf_insert" */; + buildPhases = ( + DE0962E421CD618200C4ADA1 /* Sources */, + DE0962E621CD618200C4ADA1 /* Frameworks */, + DE0962E821CD618200C4ADA1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE0962E221CD618200C4ADA1 /* PBXTargetDependency */, + ); + name = ctf_insert; + productName = "as driver"; + productReference = DE0962ED21CD618200C4ADA1 /* ctf_insert */; + productType = "com.apple.product-type.tool"; + }; + DE0962F021CD61A600C4ADA1 /* bitcode_strip */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE0962F921CD61A600C4ADA1 /* Build configuration list for PBXNativeTarget "bitcode_strip" */; + buildPhases = ( + DE0962F321CD61A600C4ADA1 /* Sources */, + DE0962F521CD61A600C4ADA1 /* Frameworks */, + DE0962F721CD61A600C4ADA1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE0962F121CD61A600C4ADA1 /* PBXTargetDependency */, + ); + name = bitcode_strip; + productName = "as driver"; + productReference = DE0962FC21CD61A600C4ADA1 /* bitcode_strip */; + productType = "com.apple.product-type.tool"; + }; + DE09630321CD621600C4ADA1 /* otool-classic */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE09630C21CD621600C4ADA1 /* Build configuration list for PBXNativeTarget "otool-classic" */; + buildPhases = ( + DE09630621CD621600C4ADA1 /* Sources */, + DE09630821CD621600C4ADA1 /* Frameworks */, + DE09630A21CD621600C4ADA1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE09630421CD621600C4ADA1 /* PBXTargetDependency */, + ); + name = "otool-classic"; + productName = "as driver"; + productReference = DE09630F21CD621600C4ADA1 /* otool-classic */; + productType = "com.apple.product-type.tool"; + }; + DE09632721CD640900C4ADA1 /* llvm-otool */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE09633021CD640900C4ADA1 /* Build configuration list for PBXNativeTarget "llvm-otool" */; + buildPhases = ( + DE09632A21CD640900C4ADA1 /* Sources */, + DE09632C21CD640900C4ADA1 /* Frameworks */, + DE09632E21CD640900C4ADA1 /* CopyFiles */, + DE1F63E421CD64A9004CA2BF /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + DE09632821CD640900C4ADA1 /* PBXTargetDependency */, + ); + name = "llvm-otool"; + productName = "as driver"; + productReference = DE09633321CD640900C4ADA1 /* llvm-otool */; + productType = "com.apple.product-type.tool"; + }; + DE1F63E721CD6511004CA2BF /* ar */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE1F63F021CD6511004CA2BF /* Build configuration list for PBXNativeTarget "ar" */; + buildPhases = ( + DE1F63EA21CD6511004CA2BF /* Sources */, + DE1F63EC21CD6511004CA2BF /* Frameworks */, + DE1F63EE21CD6511004CA2BF /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE1F63E821CD6511004CA2BF /* PBXTargetDependency */, + ); + name = ar; + productName = "as driver"; + productReference = DE1F63F321CD6511004CA2BF /* ar */; + productType = "com.apple.product-type.tool"; + }; + DE1F640221CD65BC004CA2BF /* checksyms */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE1F641421CD65BC004CA2BF /* Build configuration list for PBXNativeTarget "checksyms" */; + buildPhases = ( + DE1F640521CD65BC004CA2BF /* Sources */, + DE1F641021CD65BC004CA2BF /* Frameworks */, + DE1F641221CD65BC004CA2BF /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE1F640321CD65BC004CA2BF /* PBXTargetDependency */, + ); + name = checksyms; + productName = "as driver"; + productReference = DE1F641721CD65BC004CA2BF /* checksyms */; + productType = "com.apple.product-type.tool"; + }; + DE1F641C21CD66BA004CA2BF /* indr */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE1F642521CD66BA004CA2BF /* Build configuration list for PBXNativeTarget "indr" */; + buildPhases = ( + DE1F641F21CD66BA004CA2BF /* Sources */, + DE1F642121CD66BA004CA2BF /* Frameworks */, + DE1F642321CD66BA004CA2BF /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE1F641D21CD66BA004CA2BF /* PBXTargetDependency */, + ); + name = indr; + productName = "as driver"; + productReference = DE1F642821CD66BA004CA2BF /* indr */; + productType = "com.apple.product-type.tool"; + }; + DE1F642D21CD66F5004CA2BF /* seg_addr_table */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE1F643621CD66F5004CA2BF /* Build configuration list for PBXNativeTarget "seg_addr_table" */; + buildPhases = ( + DE1F643021CD66F5004CA2BF /* Sources */, + DE1F643221CD66F5004CA2BF /* Frameworks */, + DE1F643421CD66F5004CA2BF /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE1F642E21CD66F5004CA2BF /* PBXTargetDependency */, + ); + name = seg_addr_table; + productName = "as driver"; + productReference = DE1F643921CD66F5004CA2BF /* seg_addr_table */; + productType = "com.apple.product-type.tool"; + }; + DE1F643C21CD6715004CA2BF /* check_dylib */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE1F644521CD6715004CA2BF /* Build configuration list for PBXNativeTarget "check_dylib" */; + buildPhases = ( + DE1F643F21CD6715004CA2BF /* Sources */, + DE1F644121CD6715004CA2BF /* Frameworks */, + DE1F644321CD6715004CA2BF /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE1F643D21CD6715004CA2BF /* PBXTargetDependency */, + ); + name = check_dylib; + productName = "as driver"; + productReference = DE1F644821CD6715004CA2BF /* check_dylib */; + productType = "com.apple.product-type.tool"; + }; + DE1F644B21CD6734004CA2BF /* seg_hack */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE1F645421CD6734004CA2BF /* Build configuration list for PBXNativeTarget "seg_hack" */; + buildPhases = ( + DE1F644E21CD6734004CA2BF /* Sources */, + DE1F645021CD6734004CA2BF /* Frameworks */, + DE1F645221CD6734004CA2BF /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE1F644C21CD6734004CA2BF /* PBXTargetDependency */, + ); + name = seg_hack; + productName = "as driver"; + productReference = DE1F645721CD6734004CA2BF /* seg_hack */; + productType = "com.apple.product-type.tool"; + }; + DE1F645A21CD67E8004CA2BF /* mtoc */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE1F646221CD67E8004CA2BF /* Build configuration list for PBXNativeTarget "mtoc" */; + buildPhases = ( + DE1F645D21CD67E8004CA2BF /* Sources */, + DE1F645F21CD67E8004CA2BF /* Frameworks */, + DE1F646121CD67E8004CA2BF /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE1F645B21CD67E8004CA2BF /* PBXTargetDependency */, + ); + name = mtoc; + productName = "as driver"; + productReference = DE1F646521CD67E8004CA2BF /* mtoc */; + productType = "com.apple.product-type.tool"; + }; + DE5DC65C21F7EA8000A7CA07 /* macho dynamic driverkit */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE5DC67821F7EA8000A7CA07 /* Build configuration list for PBXNativeTarget "macho dynamic driverkit" */; + buildPhases = ( + DE5DC65F21F7EA8000A7CA07 /* Headers */, + DE5DC66821F7EA8000A7CA07 /* Sources */, + DE5DC67621F7EA8000A7CA07 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + DE5DC68221F7EAA400A7CA07 /* PBXTargetDependency */, + ); + name = "macho dynamic driverkit"; + productName = "macho dynamic"; + productReference = DE5DC67B21F7EA8000A7CA07 /* libmacho.dylib */; + productType = "com.apple.product-type.library.dynamic"; + }; + DE8229F821CD8DD6008CD150 /* macho dynamic */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE8229FC21CD8DD6008CD150 /* Build configuration list for PBXNativeTarget "macho dynamic" */; + buildPhases = ( + DE8229F521CD8DD6008CD150 /* Headers */, + DE8229F621CD8DD6008CD150 /* Sources */, + DE8229F721CD8DD6008CD150 /* Frameworks */, + DE822A2121CDAB6A008CD150 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + DE822A0721CDAAAE008CD150 /* PBXTargetDependency */, + ); + name = "macho dynamic"; + productName = "macho dynamic"; + productReference = DE8229F921CD8DD6008CD150 /* libmacho.dylib */; + productType = "com.apple.product-type.library.dynamic"; + }; + DE97E91721F3B72700C7947D /* libstuff_test */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE97E91C21F3B72700C7947D /* Build configuration list for PBXNativeTarget "libstuff_test" */; + buildPhases = ( + DE97E91421F3B72700C7947D /* Sources */, + DE97E91521F3B72700C7947D /* Frameworks */, + DE97E91621F3B72700C7947D /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DE97E92321F3B85A00C7947D /* PBXTargetDependency */, + ); + name = libstuff_test; + productName = libstuff_test; + productReference = DE97E91821F3B72700C7947D /* libstuff_test */; + productType = "com.apple.product-type.tool"; + }; + DEB23D8C21DEA11C007F9934 /* vtool */ = { + isa = PBXNativeTarget; + buildConfigurationList = DEB23D9321DEA11D007F9934 /* Build configuration list for PBXNativeTarget "vtool" */; + buildPhases = ( + DEB23D8921DEA11C007F9934 /* Sources */, + DEB23D8A21DEA11C007F9934 /* Frameworks */, + DEB23D8B21DEA11C007F9934 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = vtool; + productName = vtool; + productReference = DEB23D8D21DEA11C007F9934 /* vtool */; + productType = "com.apple.product-type.tool"; + }; + DEC00B5B220012660079FFD3 /* mtor */ = { + isa = PBXNativeTarget; + buildConfigurationList = DEC00B64220012660079FFD3 /* Build configuration list for PBXNativeTarget "mtor" */; + buildPhases = ( + DEC00B5E220012660079FFD3 /* Sources */, + DEC00B60220012660079FFD3 /* Frameworks */, + DEC00B62220012660079FFD3 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + DEC00B5C220012660079FFD3 /* PBXTargetDependency */, + ); + name = mtor; + productName = "as driver"; + productReference = DEC00B67220012660079FFD3 /* mtor */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + DE76108421CC103000736984 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1100; + TargetAttributes = { + DE000B3521CDB9DB000CEC53 = { + CreatedOnToolsVersion = 11.0; + }; + DE000B6421CDBEE8000CEC53 = { + CreatedOnToolsVersion = 11.0; + }; + DE000B7321CDEFDF000CEC53 = { + CreatedOnToolsVersion = 11.0; + }; + DE09611421CC205D00C4ADA1 = { + CreatedOnToolsVersion = 11.0; + }; + DE09612B21CC218E00C4ADA1 = { + CreatedOnToolsVersion = 11.0; + }; + DE09616221CC4A7C00C4ADA1 = { + CreatedOnToolsVersion = 11.0; + }; + DE09617621CC4F1B00C4ADA1 = { + CreatedOnToolsVersion = 11.0; + }; + DE0961E321CC548B00C4ADA1 = { + CreatedOnToolsVersion = 11.0; + }; + DE1F647121CD71E0004CA2BF = { + CreatedOnToolsVersion = 11.0; + }; + DE1F647A21CD8443004CA2BF = { + CreatedOnToolsVersion = 11.0; + }; + DE1F648221CD84C7004CA2BF = { + CreatedOnToolsVersion = 11.0; + }; + DE1F649721CD855C004CA2BF = { + CreatedOnToolsVersion = 11.0; + }; + DE8229F821CD8DD6008CD150 = { + CreatedOnToolsVersion = 11.0; + }; + DE822A0021CDA455008CD150 = { + CreatedOnToolsVersion = 11.0; + }; + DE97E91721F3B72700C7947D = { + CreatedOnToolsVersion = 11.0; + }; + DEA2409721CE08830026D013 = { + CreatedOnToolsVersion = 11.0; + }; + DEB23D8C21DEA11C007F9934 = { + CreatedOnToolsVersion = 11.0; + }; + }; + }; + buildConfigurationList = DE76108721CC103000736984 /* Build configuration list for PBXProject "cctools" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = DE76108321CC103000736984; + productRefGroup = DE09612D21CC218E00C4ADA1 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + DE09611421CC205D00C4ADA1 /* cctools */, + DE09611821CC207000C4ADA1 /* cctools_ofiles */, + DE5DC64E21F7EA4B00A7CA07 /* cctools_ofiles_driverkit */, + DE09611C21CC208300C4ADA1 /* install */, + DE09612021CC209100C4ADA1 /* ofiles_install */, + DE0961E321CC548B00C4ADA1 /* assemblers install */, + DE1F647121CD71E0004CA2BF /* codesign_allocate install */, + DEA2409721CE08830026D013 /* efi install */, + DE1F648221CD84C7004CA2BF /* man3 */, + DE1F649721CD855C004CA2BF /* man5 */, + DE1F647A21CD8443004CA2BF /* RelNotes */, + DE09612B21CC218E00C4ADA1 /* stuff */, + DE97E91721F3B72700C7947D /* libstuff_test */, + DE1F63E721CD6511004CA2BF /* ar */, + DE09616221CC4A7C00C4ADA1 /* as driver */, + DE09617621CC4F1B00C4ADA1 /* as arm */, + DE09619B21CC534200C4ADA1 /* as i386 */, + DE0961BF21CC53E700C4ADA1 /* as x86_64 */, + DE0962F021CD61A600C4ADA1 /* bitcode_strip */, + DE1F643C21CD6715004CA2BF /* check_dylib */, + DE1F640221CD65BC004CA2BF /* checksyms */, + DE09628821CD59E800C4ADA1 /* cmpdylib */, + DE0962C421CD5A6100C4ADA1 /* codesign_allocate */, + DE0962E121CD618200C4ADA1 /* ctf_insert */, + DE1F641C21CD66BA004CA2BF /* indr */, + DE0962B521CD5A4900C4ADA1 /* install_name_tool */, + DE09623B21CD4F8F00C4ADA1 /* libtool */, + DE0961F121CC77FC00C4ADA1 /* lipo */, + DE09632721CD640900C4ADA1 /* llvm-otool */, + DE1F645A21CD67E8004CA2BF /* mtoc */, + DEC00B5B220012660079FFD3 /* mtor */, + DE09622721CC809300C4ADA1 /* nm-classic */, + DE09626521CD594000C4ADA1 /* nmedit */, + DE09630321CD621600C4ADA1 /* otool-classic */, + DE09629721CD5A0400C4ADA1 /* pagestuff */, + DE0962A621CD5A2300C4ADA1 /* redo_prebinding */, + DE1F642D21CD66F5004CA2BF /* seg_addr_table */, + DE1F644B21CD6734004CA2BF /* seg_hack */, + DE09627821CD599B00C4ADA1 /* segedit */, + DE09621121CC78F500C4ADA1 /* size-classic */, + DE09620221CC78BD00C4ADA1 /* strings */, + DE09624F21CD500600C4ADA1 /* strip */, + DEB23D8C21DEA11C007F9934 /* vtool */, + DE8229F821CD8DD6008CD150 /* macho dynamic */, + DE822A0021CDA455008CD150 /* macho headers */, + DE5DC65C21F7EA8000A7CA07 /* macho dynamic driverkit */, + DE5DC67C21F7EA8E00A7CA07 /* macho headers driverkit */, + DE000B3521CDB9DB000CEC53 /* macho static */, + DE000B4A21CDBE77000CEC53 /* macho static 2 */, + DE000B6421CDBEE8000CEC53 /* libredo_prebinding */, + DE000B7321CDEFDF000CEC53 /* syminfo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + DE0961ED21CC54B800C4ADA1 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n${SRCROOT}/xcode/public_assemblers.sh\n"; + }; + DE09622121CC793C00C4ADA1 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "${SRCROOT}/xcode/create_symlink.sh ${INSTALL_DIR} size-classic size\n"; + }; + DE09623121CC809300C4ADA1 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "${SRCROOT}/xcode/create_symlink.sh ${INSTALL_DIR} llvm-nm nm\n"; + }; + DE09624521CD4F8F00C4ADA1 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "${SRCROOT}/xcode/create_symlink.sh ${INSTALL_DIR} libtool ranlib\n"; + }; + DE0962D321CD5A9900C4ADA1 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "${SRCROOT}/xcode/copy_if.sh \"${INSTALL_DIR}/codesign_allocate\" \"${DSTROOT}/usr/libexec/DeveloperTools\" \"${CCTB_MACOS}${CCTB_XCODE}\"\n${SRCROOT}/xcode/create_symlink.sh ${INSTALL_DIR} codesign_allocate codesign_allocate-p\n\n"; + }; + DE1F63E421CD64A9004CA2BF /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "${SRCROOT}/xcode/create_symlink.sh ${INSTALL_DIR} llvm-otool otool\n${SRCROOT}/xcode/create_symlink.sh ${DSTROOT}/${CCTOOLS_USRMAN}/man1 llvm-objdump.1 objdump.1\n"; + }; + DE1F647921CD7237004CA2BF /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "${SRCROOT}/xcode/copy_if.sh \"${INSTALL_DIR}/codesign_allocate\" \"${DSTROOT}/usr/libexec/DeveloperTools\" \"${CCTB_MACOS}${CCTB_XCODE}\"\n${SRCROOT}/xcode/create_symlink.sh ${INSTALL_DIR} codesign_allocate codesign_allocate-p\n"; + }; + DE555B3D21E9119800F45496 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo %%%\necho %%%\necho %%% strip HEADER_SEARCH_PATHS=${HEADER_SEARCH_PATHS}\necho %%% strip OTHER_CFLAGS=${OTHER_CFLAGS}\necho %%% strip OTHER_LDFLAGS=${OTHER_LDFLAGS}\necho %%%\necho %%%\n"; + }; + DE5DC67D21F7EA8E00A7CA07 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "${SRCROOT}/xcode/macho_headers_driverkit.sh\n"; + }; + DE822A0521CDA49D008CD150 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "${SRCROOT}/xcode/macho_headers.sh\n"; + }; + DE822A2121CDAB6A008CD150 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "if [ `echo ${SDKROOT} | grep Simulator` != \"\" ]; then\n ${SRCROOT}/xcode/create_symlink.sh ${INSTALL_DIR} libmacho.dylib libmacho_sim.dylib\nfi\n"; + }; + DEA2409521CE05E10026D013 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "${SRCROOT}/xcode/as_license.sh\n"; + }; + DEA2409D21CE089B0026D013 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "${SRCROOT}/xcode/copy_if.sh \"${DSTROOT}/${CCTOOLS_EFI}/bin/mtoc\" \"${DSTROOT}/${CCTOOLS_USRLOCALBIN}\" \"YES\"\n${SRCROOT}/xcode/copy_if.sh \"${DSTROOT}/${CCTOOLS_EFI}/bin/mtor\" \"${DSTROOT}/${CCTOOLS_USRLOCALBIN}\" \"YES\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + DE000B3321CDB9DB000CEC53 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE000B3B21CDBA79000CEC53 /* arch.c in Sources */, + DE000B3C21CDBA79000CEC53 /* get_end.c in Sources */, + DE000B3D21CDBA79000CEC53 /* getsecbyname.c in Sources */, + DE000B3E21CDBA79000CEC53 /* getsegbyname.c in Sources */, + DE000B3F21CDBA79000CEC53 /* hppa_swap.c in Sources */, + DE000B4021CDBA79000CEC53 /* i386_swap.c in Sources */, + DE000B4121CDBA79000CEC53 /* i860_swap.c in Sources */, + DE000B4221CDBA79000CEC53 /* m68k_swap.c in Sources */, + DE000B4321CDBA79000CEC53 /* m88k_swap.c in Sources */, + DE000B4421CDBA79000CEC53 /* ppc_swap.c in Sources */, + DE000B4521CDBA79000CEC53 /* slot_name.c in Sources */, + DE000B4621CDBA79000CEC53 /* sparc_swap.c in Sources */, + DE000B4721CDBA79000CEC53 /* swap.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE000B4C21CDBE77000CEC53 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE000B4D21CDBE77000CEC53 /* arch.c in Sources */, + DE000B4E21CDBE77000CEC53 /* get_end.c in Sources */, + DE000B4F21CDBE77000CEC53 /* getsecbyname.c in Sources */, + DE000B5021CDBE77000CEC53 /* getsegbyname.c in Sources */, + DE000B5121CDBE77000CEC53 /* hppa_swap.c in Sources */, + DE000B5221CDBE77000CEC53 /* i386_swap.c in Sources */, + DE000B5321CDBE77000CEC53 /* i860_swap.c in Sources */, + DE000B5421CDBE77000CEC53 /* m68k_swap.c in Sources */, + DE000B5521CDBE77000CEC53 /* m88k_swap.c in Sources */, + DE000B5621CDBE77000CEC53 /* ppc_swap.c in Sources */, + DE000B5721CDBE77000CEC53 /* slot_name.c in Sources */, + DE000B5821CDBE77000CEC53 /* sparc_swap.c in Sources */, + DE000B5921CDBE77000CEC53 /* swap.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE000B6221CDBEE8000CEC53 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE000B6D21CDBF2B000CEC53 /* redo_prebinding.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE000B7121CDEFDF000CEC53 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DEA240A421CE12070026D013 /* libsyminfo.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09612921CC218E00C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09615721CC2BEC00C4ADA1 /* swap_headers.c in Sources */, + DE09615421CC2BEC00C4ADA1 /* rnd.c in Sources */, + DE09614A21CC2BEC00C4ADA1 /* hash_string.c in Sources */, + DE09613921CC2BEC00C4ADA1 /* arch_usage.c in Sources */, + DE09614B21CC2BEC00C4ADA1 /* hppa.c in Sources */, + DE09615821CC2BEC00C4ADA1 /* symbol_list.c in Sources */, + DE09613E21CC2BEC00C4ADA1 /* checkout.c in Sources */, + DE09613A21CC2BEC00C4ADA1 /* arch.c in Sources */, + DE09614021CC2BEC00C4ADA1 /* crc32.c in Sources */, + DE09615621CC2BEC00C4ADA1 /* set_arch_flag_name.c in Sources */, + DE09614621CC2BEC00C4ADA1 /* fatals.c in Sources */, + DE09613C21CC2BEC00C4ADA1 /* breakout.c in Sources */, + DE09614921CC2BEC00C4ADA1 /* guess_short_name.c in Sources */, + DE09615221CC2BEC00C4ADA1 /* print.c in Sources */, + DE09614321CC2BEC00C4ADA1 /* errors.c in Sources */, + DE09614521CC2BEC00C4ADA1 /* fatal_arch.c in Sources */, + DE09615C21CC2BEC00C4ADA1 /* vm_flush_cache.c in Sources */, + DE09615121CC2BEC00C4ADA1 /* ofile.c in Sources */, + DE09613721CC2BEC00C4ADA1 /* allocate.c in Sources */, + DE09614821CC2BEC00C4ADA1 /* get_toc_byte_sex.c in Sources */, + DE09613821CC2BEC00C4ADA1 /* apple_version.c in Sources */, + DE09614D21CC2BEC00C4ADA1 /* lto.c in Sources */, + DE09613F21CC2BEC00C4ADA1 /* coff_bytesex.c in Sources */, + DE09613B21CC2BEC00C4ADA1 /* best_arch.c in Sources */, + DE09615A21CC2BEC00C4ADA1 /* unix_standard_mode.c in Sources */, + DE09614121CC2BEC00C4ADA1 /* dylib_roots.c in Sources */, + DEB7156122A194230031FD9F /* args.c in Sources */, + DE09614C21CC2BEC00C4ADA1 /* llvm.c in Sources */, + DE09614E21CC2BEC00C4ADA1 /* macosx_deployment_target.c in Sources */, + DE09615E21CC2BEC00C4ADA1 /* writeout.c in Sources */, + DE09613D21CC2BEC00C4ADA1 /* bytesex.c in Sources */, + DE09615B21CC2BEC00C4ADA1 /* version_number.c in Sources */, + DE09615921CC2BEC00C4ADA1 /* SymLoc.c in Sources */, + DE09615021CC2BEC00C4ADA1 /* ofile_get_word.c in Sources */, + DE09614421CC2BEC00C4ADA1 /* execute.c in Sources */, + DE09614721CC2BEC00C4ADA1 /* get_arch_from_host.c in Sources */, + DE09614F21CC2BEC00C4ADA1 /* ofile_error.c in Sources */, + DE09615D21CC2BEC00C4ADA1 /* write64.c in Sources */, + DE09615321CC2BEC00C4ADA1 /* reloc.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09615F21CC4A7C00C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09616D21CC4DC900C4ADA1 /* driver.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09617321CC4F1B00C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09618E21CC52B100C4ADA1 /* hash.c in Sources */, + DE09619321CC52B100C4ADA1 /* messages.c in Sources */, + DE09619921CC52B100C4ADA1 /* xmalloc.c in Sources */, + DE09618221CC52B100C4ADA1 /* app.c in Sources */, + DE09618B21CC52B100C4ADA1 /* flonum-copy.c in Sources */, + DE09619221CC52B100C4ADA1 /* layout.c in Sources */, + DE09619A21CC531B00C4ADA1 /* arm.c in Sources */, + DE09618421CC52B100C4ADA1 /* as.c in Sources */, + DE09618D21CC52B100C4ADA1 /* frags.c in Sources */, + DE09618621CC52B100C4ADA1 /* atof-ieee.c in Sources */, + DE09618C21CC52B100C4ADA1 /* flonum-mult.c in Sources */, + DE09619721CC52B100C4ADA1 /* symbols.c in Sources */, + DE09618721CC52B100C4ADA1 /* dwarf2dbg.c in Sources */, + DE09618821CC52B100C4ADA1 /* expr.c in Sources */, + DE09619121CC52B100C4ADA1 /* input-scrub.c in Sources */, + DE09618521CC52B100C4ADA1 /* atof-generic.c in Sources */, + DE09618921CC52B100C4ADA1 /* fixes.c in Sources */, + DE09619521CC52B100C4ADA1 /* read.c in Sources */, + DE09619821CC52B100C4ADA1 /* write_object.c in Sources */, + DE09618A21CC52B100C4ADA1 /* flonum-const.c in Sources */, + DE09619421CC52B100C4ADA1 /* obstack.c in Sources */, + DE09619621CC52B100C4ADA1 /* sections.c in Sources */, + DE09618F21CC52B100C4ADA1 /* hex-value.c in Sources */, + DE09619021CC52B100C4ADA1 /* input-file.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09619E21CC534200C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09619F21CC534200C4ADA1 /* hash.c in Sources */, + DE0961A021CC534200C4ADA1 /* messages.c in Sources */, + DE0961A121CC534200C4ADA1 /* xmalloc.c in Sources */, + DE0961A221CC534200C4ADA1 /* app.c in Sources */, + DE0961A321CC534200C4ADA1 /* flonum-copy.c in Sources */, + DE0961A421CC534200C4ADA1 /* layout.c in Sources */, + DE0961A621CC534200C4ADA1 /* as.c in Sources */, + DE0961A721CC534200C4ADA1 /* frags.c in Sources */, + DE0961A821CC534200C4ADA1 /* atof-ieee.c in Sources */, + DE0961BE21CC536A00C4ADA1 /* i386.c in Sources */, + DE0961A921CC534200C4ADA1 /* flonum-mult.c in Sources */, + DE0961AA21CC534200C4ADA1 /* symbols.c in Sources */, + DE0961AB21CC534200C4ADA1 /* dwarf2dbg.c in Sources */, + DE0961AC21CC534200C4ADA1 /* expr.c in Sources */, + DE0961AD21CC534200C4ADA1 /* input-scrub.c in Sources */, + DE0961AE21CC534200C4ADA1 /* atof-generic.c in Sources */, + DE0961AF21CC534200C4ADA1 /* fixes.c in Sources */, + DE0961B021CC534200C4ADA1 /* read.c in Sources */, + DE0961B121CC534200C4ADA1 /* write_object.c in Sources */, + DE0961B221CC534200C4ADA1 /* flonum-const.c in Sources */, + DE0961B321CC534200C4ADA1 /* obstack.c in Sources */, + DE0961B421CC534200C4ADA1 /* sections.c in Sources */, + DE0961B521CC534200C4ADA1 /* hex-value.c in Sources */, + DE0961B621CC534200C4ADA1 /* input-file.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE0961C221CC53E700C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE0961C321CC53E700C4ADA1 /* hash.c in Sources */, + DE0961C421CC53E700C4ADA1 /* messages.c in Sources */, + DE0961C521CC53E700C4ADA1 /* xmalloc.c in Sources */, + DE0961C621CC53E700C4ADA1 /* app.c in Sources */, + DE0961C721CC53E700C4ADA1 /* flonum-copy.c in Sources */, + DE0961C821CC53E700C4ADA1 /* layout.c in Sources */, + DE0961C921CC53E700C4ADA1 /* as.c in Sources */, + DE0961CA21CC53E700C4ADA1 /* frags.c in Sources */, + DE0961CB21CC53E700C4ADA1 /* atof-ieee.c in Sources */, + DE0961E221CC540700C4ADA1 /* i386.c in Sources */, + DE0961CD21CC53E700C4ADA1 /* flonum-mult.c in Sources */, + DE0961CE21CC53E700C4ADA1 /* symbols.c in Sources */, + DE0961CF21CC53E700C4ADA1 /* dwarf2dbg.c in Sources */, + DE0961D021CC53E700C4ADA1 /* expr.c in Sources */, + DE0961D121CC53E700C4ADA1 /* input-scrub.c in Sources */, + DE0961D221CC53E700C4ADA1 /* atof-generic.c in Sources */, + DE0961D321CC53E700C4ADA1 /* fixes.c in Sources */, + DE0961D421CC53E700C4ADA1 /* read.c in Sources */, + DE0961D521CC53E700C4ADA1 /* write_object.c in Sources */, + DE0961D621CC53E700C4ADA1 /* flonum-const.c in Sources */, + DE0961D721CC53E700C4ADA1 /* obstack.c in Sources */, + DE0961D821CC53E700C4ADA1 /* sections.c in Sources */, + DE0961D921CC53E700C4ADA1 /* hex-value.c in Sources */, + DE0961DA21CC53E700C4ADA1 /* input-file.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE0961F421CC77FC00C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE0961FF21CC781C00C4ADA1 /* lipo.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09620521CC78BD00C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09620F21CC78DA00C4ADA1 /* strings.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09621421CC78F500C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09621E21CC790500C4ADA1 /* size.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09622A21CC809300C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09623621CC80A000C4ADA1 /* nm.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09623E21CD4F8F00C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09624D21CD4FC100C4ADA1 /* libtool.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09625221CD500600C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09625F21CD56FB00C4ADA1 /* strip.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09626821CD594000C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09627421CD596B00C4ADA1 /* strip.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09627B21CD599B00C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09628621CD59A400C4ADA1 /* segedit.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09628B21CD59E800C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09629521CD59F200C4ADA1 /* cmpdylib.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09629A21CD5A0400C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE0962A521CD5A1700C4ADA1 /* pagestuff.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE0962A921CD5A2300C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE0962B421CD5A3900C4ADA1 /* redo_prebinding.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE0962B821CD5A4900C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE0962C221CD5A5800C4ADA1 /* install_name_tool.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE0962C721CD5A6100C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE0962D121CD5A6C00C4ADA1 /* codesign_allocate.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE0962E421CD618200C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE0962EE21CD618D00C4ADA1 /* ctf_insert.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE0962F321CD61A600C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE0962FE21CD61BE00C4ADA1 /* bitcode_strip.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09630621CD621600C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE09631B21CD629A00C4ADA1 /* notify.c in Sources */, + DE38751B21F13F2C00704209 /* ofile.c in Sources */, + DE09631A21CD629A00C4ADA1 /* main.c in Sources */, + DE09631621CD629A00C4ADA1 /* i386_disasm.c in Sources */, + DE09632021CD629A00C4ADA1 /* print_objc2_32bit.c in Sources */, + DE09631121CD628900C4ADA1 /* arm_disasm.c in Sources */, + DE09631721CD629A00C4ADA1 /* i860_disasm.c in Sources */, + DE09631C21CD629A00C4ADA1 /* ofile_print.c in Sources */, + DE09632121CD629A00C4ADA1 /* print_objc2_64bit.c in Sources */, + DE09631921CD629A00C4ADA1 /* m88k_disasm.c in Sources */, + DE09631D21CD629A00C4ADA1 /* ppc_disasm.c in Sources */, + DE09631E21CD629A00C4ADA1 /* print_bitcode.c in Sources */, + DE09631421CD629A00C4ADA1 /* dyld_bind_info.c in Sources */, + DE09632221CD629A00C4ADA1 /* sparc_disasm.c in Sources */, + DE09631821CD629A00C4ADA1 /* m68k_disasm.c in Sources */, + DE09631221CD629A00C4ADA1 /* arm64_disasm.c in Sources */, + DE09631521CD629A00C4ADA1 /* hppa_disasm.c in Sources */, + DE09631321CD629A00C4ADA1 /* coff_print.c in Sources */, + DE09631F21CD629A00C4ADA1 /* print_objc.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE09632A21CD640900C4ADA1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE1F63E021CD6438004CA2BF /* main.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE1F63EA21CD6511004CA2BF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE1F63FD21CD653D004CA2BF /* print.c in Sources */, + DE1F63FB21CD653D004CA2BF /* misc.c in Sources */, + DE1F63F621CD653D004CA2BF /* ar.c in Sources */, + DE1F63FA21CD653D004CA2BF /* extract.c in Sources */, + DE1F63F821CD653D004CA2BF /* contents.c in Sources */, + DE1F63F721CD653D004CA2BF /* archive.c in Sources */, + DE1F63F521CD653D004CA2BF /* append.c in Sources */, + DE1F63FC21CD653D004CA2BF /* move.c in Sources */, + DE1F63FE21CD653D004CA2BF /* replace.c in Sources */, + DE1F63F921CD653D004CA2BF /* delete.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE1F640521CD65BC004CA2BF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE1F641821CD65E8004CA2BF /* checksyms.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE1F641F21CD66BA004CA2BF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE1F642A21CD66D5004CA2BF /* indr.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE1F643021CD66F5004CA2BF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE1F643B21CD670D004CA2BF /* seg_addr_table.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE1F643F21CD6715004CA2BF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE1F644A21CD6730004CA2BF /* check_dylib.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE1F644E21CD6734004CA2BF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE1F645821CD6757004CA2BF /* seg_hack.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE1F645D21CD67E8004CA2BF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE1F646721CD68C2004CA2BF /* mtoc.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE5DC66821F7EA8000A7CA07 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE5DC66B21F7EA8000A7CA07 /* getsecbyname.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE8229F621CD8DD6008CD150 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE822A1021CDAB2B008CD150 /* arch.c in Sources */, + DE822A1221CDAB2B008CD150 /* get_end.c in Sources */, + DE822A1321CDAB2B008CD150 /* getsecbyname.c in Sources */, + DE822A1421CDAB2B008CD150 /* getsegbyname.c in Sources */, + DE822A1521CDAB2B008CD150 /* hppa_swap.c in Sources */, + DE822A1621CDAB2B008CD150 /* i386_swap.c in Sources */, + DE822A1721CDAB2B008CD150 /* i860_swap.c in Sources */, + DE822A1821CDAB2B008CD150 /* m68k_swap.c in Sources */, + DE822A1921CDAB2B008CD150 /* m88k_swap.c in Sources */, + DE822A1C21CDAB2B008CD150 /* ppc_swap.c in Sources */, + DE822A1E21CDAB2B008CD150 /* slot_name.c in Sources */, + DE822A1F21CDAB2B008CD150 /* sparc_swap.c in Sources */, + DE822A2021CDAB2B008CD150 /* swap.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE97E91421F3B72700C7947D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE97E92B21F3B97A00C7947D /* null_test.c in Sources */, + DE97E91B21F3B72700C7947D /* libstuff_test.c in Sources */, + DE175CB222A2248D0001D8CC /* test_util.c in Sources */, + DE97E92621F3B8EC00C7947D /* guess_short_name_test.c in Sources */, + DEB5E8D1228B04D000263617 /* version_number_test.c in Sources */, + DEB7157722A1F27A0031FD9F /* args_test.c in Sources */, + DE21482221F59BCE00FF8882 /* allocate_test.c in Sources */, + DE97E92921F3B91900C7947D /* test.c in Sources */, + DEDFD7E42299C7F100230D7D /* rnd_test.c in Sources */, + DE21482621F5B7D700FF8882 /* get_arch_from_host_test.c in Sources */, + DE21482421F5AB0F00FF8882 /* arch_test.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DEB23D8921DEA11C007F9934 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DEB23D9621DEA192007F9934 /* vtool.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DEC00B5E220012660079FFD3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DEC00B6B220012C80079FFD3 /* mtor.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + DE000B4921CDBB29000CEC53 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE000B3521CDB9DB000CEC53 /* macho static */; + targetProxy = DE000B4821CDBB29000CEC53 /* PBXContainerItemProxy */; + }; + DE000B6021CDBEB4000CEC53 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE000B4A21CDBE77000CEC53 /* macho static 2 */; + targetProxy = DE000B5F21CDBEB4000CEC53 /* PBXContainerItemProxy */; + }; + DE000B6A21CDBEF7000CEC53 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE000B6921CDBEF7000CEC53 /* PBXContainerItemProxy */; + }; + DE000B6F21CDEF81000CEC53 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE000B6421CDBEE8000CEC53 /* libredo_prebinding */; + targetProxy = DE000B6E21CDEF81000CEC53 /* PBXContainerItemProxy */; + }; + DE09612521CC209A00C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09611421CC205D00C4ADA1 /* cctools */; + targetProxy = DE09612421CC209A00C4ADA1 /* PBXContainerItemProxy */; + }; + DE09612721CC20A000C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09611821CC207000C4ADA1 /* cctools_ofiles */; + targetProxy = DE09612621CC20A000C4ADA1 /* PBXContainerItemProxy */; + }; + DE09613621CC2BA200C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE09613521CC2BA200C4ADA1 /* PBXContainerItemProxy */; + }; + DE09616C21CC4DB800C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE09616B21CC4DB800C4ADA1 /* PBXContainerItemProxy */; + }; + DE09617221CC4E4C00C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09616221CC4A7C00C4ADA1 /* as driver */; + targetProxy = DE09617121CC4E4C00C4ADA1 /* PBXContainerItemProxy */; + }; + DE09618021CC523300C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE09617F21CC523300C4ADA1 /* PBXContainerItemProxy */; + }; + DE09619C21CC534200C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE09619D21CC534200C4ADA1 /* PBXContainerItemProxy */; + }; + DE0961C021CC53E700C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE0961C121CC53E700C4ADA1 /* PBXContainerItemProxy */; + }; + DE0961E821CC54AF00C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09617621CC4F1B00C4ADA1 /* as arm */; + targetProxy = DE0961E721CC54AF00C4ADA1 /* PBXContainerItemProxy */; + }; + DE0961EA21CC54AF00C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09619B21CC534200C4ADA1 /* as i386 */; + targetProxy = DE0961E921CC54AF00C4ADA1 /* PBXContainerItemProxy */; + }; + DE0961EC21CC54AF00C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE0961BF21CC53E700C4ADA1 /* as x86_64 */; + targetProxy = DE0961EB21CC54AF00C4ADA1 /* PBXContainerItemProxy */; + }; + DE0961F021CC560000C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE0961E321CC548B00C4ADA1 /* assemblers install */; + targetProxy = DE0961EF21CC560000C4ADA1 /* PBXContainerItemProxy */; + }; + DE0961F221CC77FC00C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE0961F321CC77FC00C4ADA1 /* PBXContainerItemProxy */; + }; + DE09620121CC784600C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE0961F121CC77FC00C4ADA1 /* lipo */; + targetProxy = DE09620021CC784600C4ADA1 /* PBXContainerItemProxy */; + }; + DE09620321CC78BD00C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE09620421CC78BD00C4ADA1 /* PBXContainerItemProxy */; + }; + DE09621221CC78F500C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE09621321CC78F500C4ADA1 /* PBXContainerItemProxy */; + }; + DE09622421CC7FCD00C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09620221CC78BD00C4ADA1 /* strings */; + targetProxy = DE09622321CC7FCD00C4ADA1 /* PBXContainerItemProxy */; + }; + DE09622621CC7FCF00C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09621121CC78F500C4ADA1 /* size-classic */; + targetProxy = DE09622521CC7FCF00C4ADA1 /* PBXContainerItemProxy */; + }; + DE09622821CC809300C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE09622921CC809300C4ADA1 /* PBXContainerItemProxy */; + }; + DE09623A21CC80C500C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09622721CC809300C4ADA1 /* nm-classic */; + targetProxy = DE09623921CC80C500C4ADA1 /* PBXContainerItemProxy */; + }; + DE09623C21CD4F8F00C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE09623D21CD4F8F00C4ADA1 /* PBXContainerItemProxy */; + }; + DE09625021CD500600C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE09625121CD500600C4ADA1 /* PBXContainerItemProxy */; + }; + DE09626221CD592E00C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09624F21CD500600C4ADA1 /* strip */; + targetProxy = DE09626121CD592E00C4ADA1 /* PBXContainerItemProxy */; + }; + DE09626421CD593000C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09623B21CD4F8F00C4ADA1 /* libtool */; + targetProxy = DE09626321CD593000C4ADA1 /* PBXContainerItemProxy */; + }; + DE09626621CD594000C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE09626721CD594000C4ADA1 /* PBXContainerItemProxy */; + }; + DE09627721CD598F00C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09626521CD594000C4ADA1 /* nmedit */; + targetProxy = DE09627621CD598F00C4ADA1 /* PBXContainerItemProxy */; + }; + DE09627921CD599B00C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE09627A21CD599B00C4ADA1 /* PBXContainerItemProxy */; + }; + DE09628921CD59E800C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE09628A21CD59E800C4ADA1 /* PBXContainerItemProxy */; + }; + DE09629821CD5A0400C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE09629921CD5A0400C4ADA1 /* PBXContainerItemProxy */; + }; + DE0962A721CD5A2300C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE0962A821CD5A2300C4ADA1 /* PBXContainerItemProxy */; + }; + DE0962B621CD5A4900C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE0962B721CD5A4900C4ADA1 /* PBXContainerItemProxy */; + }; + DE0962C521CD5A6100C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE0962C621CD5A6100C4ADA1 /* PBXContainerItemProxy */; + }; + DE0962D621CD616800C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09627821CD599B00C4ADA1 /* segedit */; + targetProxy = DE0962D521CD616800C4ADA1 /* PBXContainerItemProxy */; + }; + DE0962D821CD616800C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09628821CD59E800C4ADA1 /* cmpdylib */; + targetProxy = DE0962D721CD616800C4ADA1 /* PBXContainerItemProxy */; + }; + DE0962DA21CD616800C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09629721CD5A0400C4ADA1 /* pagestuff */; + targetProxy = DE0962D921CD616800C4ADA1 /* PBXContainerItemProxy */; + }; + DE0962DE21CD616800C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE0962B521CD5A4900C4ADA1 /* install_name_tool */; + targetProxy = DE0962DD21CD616800C4ADA1 /* PBXContainerItemProxy */; + }; + DE0962E221CD618200C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE0962E321CD618200C4ADA1 /* PBXContainerItemProxy */; + }; + DE0962F121CD61A600C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE0962F221CD61A600C4ADA1 /* PBXContainerItemProxy */; + }; + DE09630021CD61CA00C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE0962E121CD618200C4ADA1 /* ctf_insert */; + targetProxy = DE0962FF21CD61CA00C4ADA1 /* PBXContainerItemProxy */; + }; + DE09630221CD61CA00C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE0962F021CD61A600C4ADA1 /* bitcode_strip */; + targetProxy = DE09630121CD61CA00C4ADA1 /* PBXContainerItemProxy */; + }; + DE09630421CD621600C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE09630521CD621600C4ADA1 /* PBXContainerItemProxy */; + }; + DE09632421CD635900C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09630321CD621600C4ADA1 /* otool-classic */; + targetProxy = DE09632321CD635900C4ADA1 /* PBXContainerItemProxy */; + }; + DE09632821CD640900C4ADA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE09632921CD640900C4ADA1 /* PBXContainerItemProxy */; + }; + DE1F63E621CD64C0004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09632721CD640900C4ADA1 /* llvm-otool */; + targetProxy = DE1F63E521CD64C0004CA2BF /* PBXContainerItemProxy */; + }; + DE1F63E821CD6511004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE1F63E921CD6511004CA2BF /* PBXContainerItemProxy */; + }; + DE1F640021CD6555004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE1F63E721CD6511004CA2BF /* ar */; + targetProxy = DE1F63FF21CD6555004CA2BF /* PBXContainerItemProxy */; + }; + DE1F640321CD65BC004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE1F640421CD65BC004CA2BF /* PBXContainerItemProxy */; + }; + DE1F641B21CD6600004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE1F640221CD65BC004CA2BF /* checksyms */; + targetProxy = DE1F641A21CD6600004CA2BF /* PBXContainerItemProxy */; + }; + DE1F641D21CD66BA004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE1F641E21CD66BA004CA2BF /* PBXContainerItemProxy */; + }; + DE1F642C21CD66DF004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE1F641C21CD66BA004CA2BF /* indr */; + targetProxy = DE1F642B21CD66DF004CA2BF /* PBXContainerItemProxy */; + }; + DE1F642E21CD66F5004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE1F642F21CD66F5004CA2BF /* PBXContainerItemProxy */; + }; + DE1F643D21CD6715004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE1F643E21CD6715004CA2BF /* PBXContainerItemProxy */; + }; + DE1F644C21CD6734004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE1F644D21CD6734004CA2BF /* PBXContainerItemProxy */; + }; + DE1F645B21CD67E8004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE1F645C21CD67E8004CA2BF /* PBXContainerItemProxy */; + }; + DE1F646D21CD690B004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE1F644B21CD6734004CA2BF /* seg_hack */; + targetProxy = DE1F646C21CD690B004CA2BF /* PBXContainerItemProxy */; + }; + DE1F647621CD7219004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE1F647121CD71E0004CA2BF /* codesign_allocate install */; + targetProxy = DE1F647521CD7219004CA2BF /* PBXContainerItemProxy */; + }; + DE1F647821CD7222004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE0962C421CD5A6100C4ADA1 /* codesign_allocate */; + targetProxy = DE1F647721CD7222004CA2BF /* PBXContainerItemProxy */; + }; + DE1F64A221CD858A004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE1F647A21CD8443004CA2BF /* RelNotes */; + targetProxy = DE1F64A121CD858A004CA2BF /* PBXContainerItemProxy */; + }; + DE1F64A421CD858A004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE1F648221CD84C7004CA2BF /* man3 */; + targetProxy = DE1F64A321CD858A004CA2BF /* PBXContainerItemProxy */; + }; + DE1F64A621CD858A004CA2BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE1F649721CD855C004CA2BF /* man5 */; + targetProxy = DE1F64A521CD858A004CA2BF /* PBXContainerItemProxy */; + }; + DE5DC68221F7EAA400A7CA07 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE5DC67C21F7EA8E00A7CA07 /* macho headers driverkit */; + targetProxy = DE5DC68121F7EAA400A7CA07 /* PBXContainerItemProxy */; + }; + DE5DC68A21F7F44200A7CA07 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE5DC65C21F7EA8000A7CA07 /* macho dynamic driverkit */; + targetProxy = DE5DC68921F7F44200A7CA07 /* PBXContainerItemProxy */; + }; + DE8229FF21CDA419008CD150 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE8229F821CD8DD6008CD150 /* macho dynamic */; + targetProxy = DE8229FE21CDA419008CD150 /* PBXContainerItemProxy */; + }; + DE822A0721CDAAAE008CD150 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE822A0021CDA455008CD150 /* macho headers */; + targetProxy = DE822A0621CDAAAE008CD150 /* PBXContainerItemProxy */; + }; + DE97E92321F3B85A00C7947D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DE97E92221F3B85A00C7947D /* PBXContainerItemProxy */; + }; + DEA2409321CDF1240026D013 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE000B7321CDEFDF000CEC53 /* syminfo */; + targetProxy = DEA2409221CDF1240026D013 /* PBXContainerItemProxy */; + }; + DEA2409C21CE08940026D013 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE1F645A21CD67E8004CA2BF /* mtoc */; + targetProxy = DEA2409B21CE08940026D013 /* PBXContainerItemProxy */; + }; + DEA2409F21CE096A0026D013 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DEA2409721CE08830026D013 /* efi install */; + targetProxy = DEA2409E21CE096A0026D013 /* PBXContainerItemProxy */; + }; + DEB23D9821DEA1EE007F9934 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DEB23D8C21DEA11C007F9934 /* vtool */; + targetProxy = DEB23D9721DEA1EE007F9934 /* PBXContainerItemProxy */; + }; + DEC00B5C220012660079FFD3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE09612B21CC218E00C4ADA1 /* stuff */; + targetProxy = DEC00B5D220012660079FFD3 /* PBXContainerItemProxy */; + }; + DEC00B69220012B10079FFD3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DEC00B5B220012660079FFD3 /* mtor */; + targetProxy = DEC00B68220012B10079FFD3 /* PBXContainerItemProxy */; + }; + DEC31BCE21F652520006E1D8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE97E91721F3B72700C7947D /* libstuff_test */; + targetProxy = DEC31BCD21F652520006E1D8 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + DE000B3821CDB9DB000CEC53 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE000B3A21CDB9FE000CEC53 /* macho_static.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + BUILD_VARIANTS = ( + normal, + debug, + profile, + ); + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = macho; + SDKROOT = macosx; + }; + name = Debug; + }; + DE000B3921CDB9DB000CEC53 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE000B3A21CDB9FE000CEC53 /* macho_static.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + BUILD_VARIANTS = ( + normal, + debug, + profile, + ); + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = macho; + SDKROOT = macosx; + }; + name = Release; + }; + DE000B5C21CDBE77000CEC53 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE000B3A21CDB9FE000CEC53 /* macho_static.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + BUILD_VARIANTS = normal; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = macho_static; + SDKROOT = macosx; + }; + name = Debug; + }; + DE000B5D21CDBE77000CEC53 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE000B3A21CDB9FE000CEC53 /* macho_static.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + BUILD_VARIANTS = normal; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = macho_static; + SDKROOT = macosx; + }; + name = Release; + }; + DE000B6721CDBEE8000CEC53 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + EXECUTABLE_PREFIX = ""; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = ( + "${inherited}", + "-DLIBRARY_API", + ); + PRIVATE_HEADERS_FOLDER_PATH = "/usr/local/include/mach-o"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE000B6821CDBEE8000CEC53 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + EXECUTABLE_PREFIX = ""; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + OTHER_CFLAGS = ( + "${inherited}", + "-DLIBRARY_API", + ); + PRIVATE_HEADERS_FOLDER_PATH = "/usr/local/include/mach-o"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE000B7621CDEFDF000CEC53 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = ( + "${inherited}", + "-DLIBRARY_API", + ); + PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/cbt; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE000B7721CDEFDF000CEC53 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + OTHER_CFLAGS = ( + "${inherited}", + "-DLIBRARY_API", + ); + PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/cbt; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE09611621CC205D00C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + DE09611721CC205D00C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + DE09611A21CC207000C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + DE09611B21CC207000C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + DE09611E21CC208300C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + DE09611F21CC208300C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + DE09612221CC209100C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + DE09612321CC209100C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + DE09612F21CC218E00C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09613221CC242900C4ADA1 /* libstuff.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + DE09613021CC218E00C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09613221CC242900C4ADA1 /* libstuff.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Release; + }; + DE09616821CC4A7D00C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = as; + SDKROOT = macosx; + }; + name = Debug; + }; + DE09616921CC4A7D00C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = as; + SDKROOT = macosx; + }; + name = Release; + }; + DE09617B21CC4F1B00C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09617E21CC4F6500C4ADA1 /* public_assembler.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = "${inherited}/arm"; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = ( + "${inherited}", + "-DARM", + ); + PRODUCT_NAME = "as-arm"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE09617C21CC4F1B00C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09617E21CC4F6500C4ADA1 /* public_assembler.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = "${inherited}/arm"; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + OTHER_CFLAGS = ( + "${inherited}", + "-DARM", + ); + PRODUCT_NAME = "as-arm"; + SDKROOT = macosx; + }; + name = Release; + }; + DE0961BB21CC534200C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09617E21CC4F6500C4ADA1 /* public_assembler.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = "${inherited}/i386"; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = ( + "${inherited}", + "-DI386", + "-Di486", + "-Di586", + "-Di686", + ); + PRODUCT_NAME = "as-i386"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE0961BC21CC534200C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09617E21CC4F6500C4ADA1 /* public_assembler.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = "${inherited}/i386"; + MACOSX_DEPLOYMENT_TARGET = 10.14; + OTHER_CFLAGS = ( + "${inherited}", + "-DI386", + "-Di486", + "-Di586", + "-Di686", + ); + PRODUCT_NAME = "as-i386"; + SDKROOT = macosx; + }; + name = Release; + }; + DE0961DF21CC53E700C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09617E21CC4F6500C4ADA1 /* public_assembler.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = "${inherited}/x86_64"; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = ( + "${inherited}", + "-DI386", + "-Di486", + "-Di586", + "-Di686", + "-DARCH64", + ); + PRODUCT_NAME = "as-x86_64"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE0961E021CC53E700C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09617E21CC4F6500C4ADA1 /* public_assembler.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = "${inherited}/x86_64"; + MACOSX_DEPLOYMENT_TARGET = 10.14; + OTHER_CFLAGS = ( + "${inherited}", + "-DI386", + "-Di486", + "-Di586", + "-Di686", + "-DARCH64", + ); + PRODUCT_NAME = "as-x86_64"; + SDKROOT = macosx; + }; + name = Release; + }; + DE0961E521CC548B00C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + DE0961E621CC548B00C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + DE0961FB21CC77FC00C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE0961FC21CC77FC00C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE09620C21CC78BD00C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE09620D21CC78BD00C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE09621B21CC78F500C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE09621C21CC78F500C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE09623321CC809300C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE09623421CC809300C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE09624721CD4F8F00C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE09624821CD4F8F00C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE09625B21CD500600C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09625E21CD514000C4ADA1 /* strip.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE09625C21CD500600C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09625E21CD514000C4ADA1 /* strip.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE09627121CD594000C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = ( + "${inherited}", + "-DNMEDIT", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE09627221CD594000C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + OTHER_CFLAGS = ( + "${inherited}", + "-DNMEDIT", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE09628321CD599B00C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE09628421CD599B00C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE09629221CD59E800C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE09629321CD59E800C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE0962A121CD5A0400C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE0962A221CD5A0400C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE0962B021CD5A2300C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE0962B121CD5A2300C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE0962BF21CD5A4900C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE0962C021CD5A4900C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE0962CE21CD5A6100C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE2439D221D158640080FC74 /* codesign_allocate.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE0962CF21CD5A6100C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE2439D221D158640080FC74 /* codesign_allocate.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE0962EB21CD618200C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE0962EC21CD618200C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE0962FA21CD61A600C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE0962FB21CD61A600C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE09630D21CD621600C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE38751A21F13DEA00704209 /* otool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = ( + "${inherited}", + "-DEFI_SUPPORT", + "-DOTOOL", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE09630E21CD621600C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE38751A21F13DEA00704209 /* otool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + OTHER_CFLAGS = ( + "${inherited}", + "-DEFI_SUPPORT", + "-DOTOOL", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE09633121CD640900C4ADA1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = ( + "${inherited}", + "-DEFI_SUPPORT", + "-DLLVM_OTOOL", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE09633221CD640900C4ADA1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + OTHER_CFLAGS = ( + "${inherited}", + "-DEFI_SUPPORT", + "-DLLVM_OTOOL", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE1F63F121CD6511004CA2BF /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE1F63F221CD6511004CA2BF /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE1F641521CD65BC004CA2BF /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE1F640121CD6576004CA2BF /* private_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE1F641621CD65BC004CA2BF /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE1F640121CD6576004CA2BF /* private_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE1F642621CD66BA004CA2BF /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE1F640121CD6576004CA2BF /* private_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE1F642721CD66BA004CA2BF /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE1F640121CD6576004CA2BF /* private_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE1F643721CD66F5004CA2BF /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE1F640121CD6576004CA2BF /* private_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE1F643821CD66F5004CA2BF /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE1F640121CD6576004CA2BF /* private_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE1F644621CD6715004CA2BF /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE1F640121CD6576004CA2BF /* private_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE1F644721CD6715004CA2BF /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE1F640121CD6576004CA2BF /* private_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE1F645521CD6734004CA2BF /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE1F640121CD6576004CA2BF /* private_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE1F645621CD6734004CA2BF /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE1F640121CD6576004CA2BF /* private_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE1F646321CD67E8004CA2BF /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE1F645921CD6786004CA2BF /* private_efi.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE1F646421CD67E8004CA2BF /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE1F645921CD6786004CA2BF /* private_efi.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DE1F647321CD71E1004CA2BF /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + DE1F647421CD71E1004CA2BF /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + DE1F647C21CD8443004CA2BF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + DE1F647D21CD8443004CA2BF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + DE1F648421CD84C7004CA2BF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + DE1F648521CD84C7004CA2BF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + DE1F649921CD855C004CA2BF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + DE1F649A21CD855C004CA2BF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + DE5DC65A21F7EA4B00A7CA07 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + DE5DC65B21F7EA4B00A7CA07 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + DE5DC67921F7EA8000A7CA07 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE5DC68721F7EEBB00A7CA07 /* macho_dynamic_driverkit.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + }; + name = Debug; + }; + DE5DC67A21F7EA8000A7CA07 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE5DC68721F7EEBB00A7CA07 /* macho_dynamic_driverkit.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + }; + name = Release; + }; + DE5DC67F21F7EA8E00A7CA07 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + DE5DC68021F7EA8E00A7CA07 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + DE76108821CC103000736984 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09611321CC1C7900C4ADA1 /* cctools.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + DE76108921CC103000736984 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09611321CC1C7900C4ADA1 /* cctools.xcconfig */; + buildSettings = { + }; + name = Release; + }; + DE8229FA21CD8DD6008CD150 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE8229FD21CD8DF7008CD150 /* macho_dynamic.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = macho; + }; + name = Debug; + }; + DE8229FB21CD8DD6008CD150 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE8229FD21CD8DF7008CD150 /* macho_dynamic.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = macho; + }; + name = Release; + }; + DE822A0221CDA455008CD150 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + DE822A0321CDA455008CD150 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + DE97E91D21F3B72700C7947D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE97E91321F3B67600C7947D /* private_test.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = "compiler-default"; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DE97E91E21F3B72700C7947D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE97E91321F3B67600C7947D /* private_test.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = "compiler-default"; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DEA2409921CE08830026D013 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + DEA2409A21CE08830026D013 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + DEB23D9121DEA11D007F9934 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DEB23D9221DEA11D007F9934 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE09616A21CC4AB700C4ADA1 /* public_tool.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + DEC00B65220012660079FFD3 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE1F645921CD6786004CA2BF /* private_efi.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + DEC00B66220012660079FFD3 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE1F645921CD6786004CA2BF /* private_efi.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + DE000B3721CDB9DB000CEC53 /* Build configuration list for PBXNativeTarget "macho static" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE000B3821CDB9DB000CEC53 /* Debug */, + DE000B3921CDB9DB000CEC53 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE000B5B21CDBE77000CEC53 /* Build configuration list for PBXNativeTarget "macho static 2" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE000B5C21CDBE77000CEC53 /* Debug */, + DE000B5D21CDBE77000CEC53 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE000B6621CDBEE8000CEC53 /* Build configuration list for PBXNativeTarget "libredo_prebinding" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE000B6721CDBEE8000CEC53 /* Debug */, + DE000B6821CDBEE8000CEC53 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE000B7521CDEFDF000CEC53 /* Build configuration list for PBXNativeTarget "syminfo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE000B7621CDEFDF000CEC53 /* Debug */, + DE000B7721CDEFDF000CEC53 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09611521CC205D00C4ADA1 /* Build configuration list for PBXAggregateTarget "cctools" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09611621CC205D00C4ADA1 /* Debug */, + DE09611721CC205D00C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09611921CC207000C4ADA1 /* Build configuration list for PBXAggregateTarget "cctools_ofiles" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09611A21CC207000C4ADA1 /* Debug */, + DE09611B21CC207000C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09611D21CC208300C4ADA1 /* Build configuration list for PBXAggregateTarget "install" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09611E21CC208300C4ADA1 /* Debug */, + DE09611F21CC208300C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09612121CC209100C4ADA1 /* Build configuration list for PBXAggregateTarget "ofiles_install" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09612221CC209100C4ADA1 /* Debug */, + DE09612321CC209100C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09612E21CC218E00C4ADA1 /* Build configuration list for PBXNativeTarget "stuff" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09612F21CC218E00C4ADA1 /* Debug */, + DE09613021CC218E00C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09616721CC4A7D00C4ADA1 /* Build configuration list for PBXNativeTarget "as driver" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09616821CC4A7D00C4ADA1 /* Debug */, + DE09616921CC4A7D00C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09617D21CC4F1B00C4ADA1 /* Build configuration list for PBXNativeTarget "as arm" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09617B21CC4F1B00C4ADA1 /* Debug */, + DE09617C21CC4F1B00C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE0961BA21CC534200C4ADA1 /* Build configuration list for PBXNativeTarget "as i386" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE0961BB21CC534200C4ADA1 /* Debug */, + DE0961BC21CC534200C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE0961DE21CC53E700C4ADA1 /* Build configuration list for PBXNativeTarget "as x86_64" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE0961DF21CC53E700C4ADA1 /* Debug */, + DE0961E021CC53E700C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE0961E421CC548B00C4ADA1 /* Build configuration list for PBXAggregateTarget "assemblers install" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE0961E521CC548B00C4ADA1 /* Debug */, + DE0961E621CC548B00C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE0961FA21CC77FC00C4ADA1 /* Build configuration list for PBXNativeTarget "lipo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE0961FB21CC77FC00C4ADA1 /* Debug */, + DE0961FC21CC77FC00C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09620B21CC78BD00C4ADA1 /* Build configuration list for PBXNativeTarget "strings" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09620C21CC78BD00C4ADA1 /* Debug */, + DE09620D21CC78BD00C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09621A21CC78F500C4ADA1 /* Build configuration list for PBXNativeTarget "size-classic" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09621B21CC78F500C4ADA1 /* Debug */, + DE09621C21CC78F500C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09623221CC809300C4ADA1 /* Build configuration list for PBXNativeTarget "nm-classic" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09623321CC809300C4ADA1 /* Debug */, + DE09623421CC809300C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09624621CD4F8F00C4ADA1 /* Build configuration list for PBXNativeTarget "libtool" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09624721CD4F8F00C4ADA1 /* Debug */, + DE09624821CD4F8F00C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09625A21CD500600C4ADA1 /* Build configuration list for PBXNativeTarget "strip" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09625B21CD500600C4ADA1 /* Debug */, + DE09625C21CD500600C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09627021CD594000C4ADA1 /* Build configuration list for PBXNativeTarget "nmedit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09627121CD594000C4ADA1 /* Debug */, + DE09627221CD594000C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09628221CD599B00C4ADA1 /* Build configuration list for PBXNativeTarget "segedit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09628321CD599B00C4ADA1 /* Debug */, + DE09628421CD599B00C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09629121CD59E800C4ADA1 /* Build configuration list for PBXNativeTarget "cmpdylib" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09629221CD59E800C4ADA1 /* Debug */, + DE09629321CD59E800C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE0962A021CD5A0400C4ADA1 /* Build configuration list for PBXNativeTarget "pagestuff" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE0962A121CD5A0400C4ADA1 /* Debug */, + DE0962A221CD5A0400C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE0962AF21CD5A2300C4ADA1 /* Build configuration list for PBXNativeTarget "redo_prebinding" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE0962B021CD5A2300C4ADA1 /* Debug */, + DE0962B121CD5A2300C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE0962BE21CD5A4900C4ADA1 /* Build configuration list for PBXNativeTarget "install_name_tool" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE0962BF21CD5A4900C4ADA1 /* Debug */, + DE0962C021CD5A4900C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE0962CD21CD5A6100C4ADA1 /* Build configuration list for PBXNativeTarget "codesign_allocate" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE0962CE21CD5A6100C4ADA1 /* Debug */, + DE0962CF21CD5A6100C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE0962EA21CD618200C4ADA1 /* Build configuration list for PBXNativeTarget "ctf_insert" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE0962EB21CD618200C4ADA1 /* Debug */, + DE0962EC21CD618200C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE0962F921CD61A600C4ADA1 /* Build configuration list for PBXNativeTarget "bitcode_strip" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE0962FA21CD61A600C4ADA1 /* Debug */, + DE0962FB21CD61A600C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09630C21CD621600C4ADA1 /* Build configuration list for PBXNativeTarget "otool-classic" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09630D21CD621600C4ADA1 /* Debug */, + DE09630E21CD621600C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE09633021CD640900C4ADA1 /* Build configuration list for PBXNativeTarget "llvm-otool" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE09633121CD640900C4ADA1 /* Debug */, + DE09633221CD640900C4ADA1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE1F63F021CD6511004CA2BF /* Build configuration list for PBXNativeTarget "ar" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE1F63F121CD6511004CA2BF /* Debug */, + DE1F63F221CD6511004CA2BF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE1F641421CD65BC004CA2BF /* Build configuration list for PBXNativeTarget "checksyms" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE1F641521CD65BC004CA2BF /* Debug */, + DE1F641621CD65BC004CA2BF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE1F642521CD66BA004CA2BF /* Build configuration list for PBXNativeTarget "indr" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE1F642621CD66BA004CA2BF /* Debug */, + DE1F642721CD66BA004CA2BF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE1F643621CD66F5004CA2BF /* Build configuration list for PBXNativeTarget "seg_addr_table" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE1F643721CD66F5004CA2BF /* Debug */, + DE1F643821CD66F5004CA2BF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE1F644521CD6715004CA2BF /* Build configuration list for PBXNativeTarget "check_dylib" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE1F644621CD6715004CA2BF /* Debug */, + DE1F644721CD6715004CA2BF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE1F645421CD6734004CA2BF /* Build configuration list for PBXNativeTarget "seg_hack" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE1F645521CD6734004CA2BF /* Debug */, + DE1F645621CD6734004CA2BF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE1F646221CD67E8004CA2BF /* Build configuration list for PBXNativeTarget "mtoc" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE1F646321CD67E8004CA2BF /* Debug */, + DE1F646421CD67E8004CA2BF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE1F647221CD71E1004CA2BF /* Build configuration list for PBXAggregateTarget "codesign_allocate install" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE1F647321CD71E1004CA2BF /* Debug */, + DE1F647421CD71E1004CA2BF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE1F647B21CD8443004CA2BF /* Build configuration list for PBXAggregateTarget "RelNotes" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE1F647C21CD8443004CA2BF /* Debug */, + DE1F647D21CD8443004CA2BF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE1F648321CD84C7004CA2BF /* Build configuration list for PBXAggregateTarget "man3" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE1F648421CD84C7004CA2BF /* Debug */, + DE1F648521CD84C7004CA2BF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE1F649821CD855C004CA2BF /* Build configuration list for PBXAggregateTarget "man5" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE1F649921CD855C004CA2BF /* Debug */, + DE1F649A21CD855C004CA2BF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE5DC65921F7EA4B00A7CA07 /* Build configuration list for PBXAggregateTarget "cctools_ofiles_driverkit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE5DC65A21F7EA4B00A7CA07 /* Debug */, + DE5DC65B21F7EA4B00A7CA07 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE5DC67821F7EA8000A7CA07 /* Build configuration list for PBXNativeTarget "macho dynamic driverkit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE5DC67921F7EA8000A7CA07 /* Debug */, + DE5DC67A21F7EA8000A7CA07 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE5DC67E21F7EA8E00A7CA07 /* Build configuration list for PBXAggregateTarget "macho headers driverkit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE5DC67F21F7EA8E00A7CA07 /* Debug */, + DE5DC68021F7EA8E00A7CA07 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE76108721CC103000736984 /* Build configuration list for PBXProject "cctools" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE76108821CC103000736984 /* Debug */, + DE76108921CC103000736984 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE8229FC21CD8DD6008CD150 /* Build configuration list for PBXNativeTarget "macho dynamic" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE8229FA21CD8DD6008CD150 /* Debug */, + DE8229FB21CD8DD6008CD150 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE822A0121CDA455008CD150 /* Build configuration list for PBXAggregateTarget "macho headers" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE822A0221CDA455008CD150 /* Debug */, + DE822A0321CDA455008CD150 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE97E91C21F3B72700C7947D /* Build configuration list for PBXNativeTarget "libstuff_test" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE97E91D21F3B72700C7947D /* Debug */, + DE97E91E21F3B72700C7947D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DEA2409821CE08830026D013 /* Build configuration list for PBXAggregateTarget "efi install" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DEA2409921CE08830026D013 /* Debug */, + DEA2409A21CE08830026D013 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DEB23D9321DEA11D007F9934 /* Build configuration list for PBXNativeTarget "vtool" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DEB23D9121DEA11D007F9934 /* Debug */, + DEB23D9221DEA11D007F9934 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DEC00B64220012660079FFD3 /* Build configuration list for PBXNativeTarget "mtor" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DEC00B65220012660079FFD3 /* Debug */, + DEC00B66220012660079FFD3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = DE76108421CC103000736984 /* Project object */; +} diff --git a/cctools/cctools.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/cctools/cctools.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..230aacdf --- /dev/null +++ b/cctools/cctools.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/cctools/cctools.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/cctools/cctools.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/cctools/cctools.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/cctools/efitools/Makefile b/cctools/efitools/Makefile index ca7cfc5e..c2cf6af2 100644 --- a/cctools/efitools/Makefile +++ b/cctools/efitools/Makefile @@ -23,11 +23,11 @@ SYMROOT = . EFIBINDIR = /usr/local/efi/bin LOCBINDIR = /usr/local/bin -CFILES = makerelocs.c mtoc.c +CFILES = makerelocs.c mtoc.c mtor.c INSTALL_FILES = $(CFILES) Makefile notes -PROGS = makerelocs.NEW mtoc.NEW +PROGS = makerelocs.NEW mtoc.NEW mtor.NEW all: $(OFILE_DIR) $(SYMROOT) $(PROGS) @@ -50,10 +50,19 @@ mtoc.NEW: mtoc.o $(OFILE_DIR)/mtoc.private.o $(DSYMUTIL) $(SYMROOT)/mtoc.NEW +mtor.NEW: mtor.o + $(CC) $(RC_CFLAGS) -nostdlib -r \ + -o $(OBJROOT)/mtor.private.o \ + $(OFILE_DIR)/mtor.o $(LIBSTUFF) + $(CC) $(RC_CFLAGS) $(SDK) -o $(SYMROOT)/mtor.NEW \ + $(OFILE_DIR)/mtor.private.o + $(DSYMUTIL) $(SYMROOT)/mtor.NEW + clean: shlib_clean -rm -f \ $(SYMROOT)/makerelocs.NEW \ - $(SYMROOT)/mtoc.NEW + $(SYMROOT)/mtoc.NEW \ + $(SYMROOT)/mtor.NEW -rm -r -f *dSYM shlib_clean: @@ -61,7 +70,9 @@ shlib_clean: $(OFILE_DIR)/makerelocs.o \ $(OFILE_DIR)/makerelocs.private.o \ $(OFILE_DIR)/mtoc.o \ - $(OFILE_DIR)/mtoc.private.o + $(OFILE_DIR)/mtoc.private.o \ + $(OFILE_DIR)/mtor.o \ + $(OFILE_DIR)/mtor.private.o -rm -f make.out install: all install @@ -76,6 +87,10 @@ install: $(DSTROOT)$(EFIBINDIR)/mtoc install -c -s -m 555 $(SYMROOT)/mtoc.NEW \ $(DSTROOT)$(LOCBINDIR)/mtoc + install -c -s -m 555 $(SYMROOT)/mtor.NEW \ + $(DSTROOT)$(EFIBINDIR)/mtor + install -c -s -m 555 $(SYMROOT)/mtor.NEW \ + $(DSTROOT)$(LOCBINDIR)/mtor installsrc: $(MKDIRS) $(SRCROOT) diff --git a/cctools/efitools/makerelocs.c b/cctools/efitools/makerelocs.c index 09dc1874..f47c6b47 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" @@ -493,7 +494,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++; @@ -520,7 +522,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 befc2ba4..e4724d0b 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. */ @@ -356,7 +360,7 @@ char **envp) "option"); usage(EXIT_FAILURE); } - 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]); @@ -380,7 +384,7 @@ char **envp) warning("no argument specified for -align option"); usage(EXIT_FAILURE); } - 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]); @@ -400,6 +404,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) @@ -454,7 +470,8 @@ usage(int with_exit_value) { FILE *out = with_exit_value ? stderr : stdout; fprintf(out, "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); if (with_exit_value) exit(with_exit_value); @@ -686,7 +703,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: @@ -695,9 +711,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); @@ -706,11 +725,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); @@ -793,7 +814,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; @@ -811,7 +832,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; @@ -858,7 +879,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; @@ -899,9 +920,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; @@ -914,14 +935,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; @@ -1032,11 +1053,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); @@ -1047,11 +1074,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); @@ -1128,9 +1161,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; @@ -1142,9 +1176,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; @@ -1193,8 +1228,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; @@ -1215,8 +1250,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; @@ -1261,7 +1296,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) @@ -1322,7 +1357,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 @@ -1385,7 +1420,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; @@ -1412,9 +1447,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; @@ -1439,8 +1474,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; @@ -1479,7 +1514,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); } @@ -1488,7 +1523,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; @@ -1513,8 +1551,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; @@ -1671,7 +1709,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) @@ -2032,7 +2070,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; } } @@ -2180,11 +2218,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) == @@ -2205,21 +2243,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) @@ -2339,7 +2381,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; @@ -2383,7 +2425,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){ @@ -2391,7 +2433,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; @@ -2409,7 +2451,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; @@ -2422,7 +2464,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; @@ -2436,6 +2478,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); } @@ -2464,7 +2515,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; @@ -2476,9 +2527,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. */ @@ -2489,12 +2545,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 00000000..2a4d25cf --- /dev/null +++ b/cctools/efitools/mtor.c @@ -0,0 +1,809 @@ +/* + * 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 +#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 9da161c8..7965d29a 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 89f45c91..63d96fff 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/driverkit/getsect.h b/cctools/include/driverkit/getsect.h new file mode 100644 index 00000000..caf2acb0 --- /dev/null +++ b/cctools/include/driverkit/getsect.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019 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 _MACH_O_GETSECT_H_ +#define _MACH_O_GETSECT_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +extern uint8_t *getsectiondata(const struct mach_header_64 *mhp, + const char *segname, + const char *sectname, + unsigned long *size); + +extern uint8_t *getsegmentdata(const struct mach_header_64 *mhp, + const char *segname, + unsigned long *size); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _MACH_O_GETSECT_H_ */ diff --git a/cctools/include/mach-o/arch.h b/cctools/include/mach-o/arch.h index f2451816..94883161 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 diff --git a/cctools/include/mach-o/arm64/reloc.h b/cctools/include/mach-o/arm64/reloc.h new file mode 100644 index 00000000..6be5c8d8 --- /dev/null +++ b/cctools/include/mach-o/arm64/reloc.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2010 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 _MACHO_ARM64_RELOC_H_ +#define _MACHO_ARM64_RELOC_H_ + +/* + * Relocation types used in the arm64 implementation. + */ +enum reloc_type_arm64 +{ + ARM64_RELOC_UNSIGNED, // for pointers + ARM64_RELOC_SUBTRACTOR, // must be followed by a ARM64_RELOC_UNSIGNED + ARM64_RELOC_BRANCH26, // a B/BL instruction with 26-bit displacement + ARM64_RELOC_PAGE21, // pc-rel distance to page of target + ARM64_RELOC_PAGEOFF12, // offset within page, scaled by r_length + ARM64_RELOC_GOT_LOAD_PAGE21, // pc-rel distance to page of GOT slot + ARM64_RELOC_GOT_LOAD_PAGEOFF12, // offset within page of GOT slot, + // scaled by r_length + ARM64_RELOC_POINTER_TO_GOT, // for pointers to GOT slots + 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 + + // 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/loader.h b/cctools/include/mach-o/loader.h index 7458c2c0..193d4249 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 133e36b4..96b0cd5d 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/stab.h b/cctools/include/mach-o/stab.h index 0c89939e..8d456310 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 db3fe19b..5d1bd788 100644 --- a/cctools/include/mach-o/swap.h +++ b/cctools/include/mach-o/swap.h @@ -191,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); diff --git a/cctools/include/mach/i386/_structs.h b/cctools/include/mach/i386/_structs.h index 9dd3f441..c08fb9d0 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,31 @@ _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 +828,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 +1037,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 +1214,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 09ec31c9..6dbecce7 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 2d542d3d..4eeaba35 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 19451215..4c3b818b 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 28a5a1cf..85f578d0 100644 --- a/cctools/include/mach/machine.h +++ b/cctools/include/mach/machine.h @@ -157,9 +157,11 @@ 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_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)) /* @@ -320,6 +322,9 @@ 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) + /* * MC88000 subtypes */ diff --git a/cctools/include/mach/slot_name.h b/cctools/include/mach/slot_name.h new file mode 100644 index 00000000..1483edca --- /dev/null +++ b/cctools/include/mach/slot_name.h @@ -0,0 +1,5 @@ +#include +extern void slot_name(cpu_type_t, + cpu_subtype_t, + char **, + char **); diff --git a/cctools/include/stuff/arch.h b/cctools/include/stuff/arch.h index 7b4b8c51..51e444fb 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 00000000..24573066 --- /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/breakout.h b/cctools/include/stuff/breakout.h index 49f9248a..211d792c 100644 --- a/cctools/include/stuff/breakout.h +++ b/cctools/include/stuff/breakout.h @@ -94,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; @@ -104,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 */ @@ -123,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 @@ -176,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() @@ -210,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; @@ -222,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; diff --git a/cctools/include/stuff/bytesex.h b/cctools/include/stuff/bytesex.h index c8ea7cc6..c5d5ab1e 100644 --- a/cctools/include/stuff/bytesex.h +++ b/cctools/include/stuff/bytesex.h @@ -317,6 +317,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); @@ -377,6 +381,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, @@ -459,6 +476,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/rnd.h b/cctools/include/stuff/rnd.h index 1af3f975..b51fa7e5 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 26ab0ff2..2d28f814 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 00000000..95e8f80d --- /dev/null +++ b/cctools/include/stuff/write64.h @@ -0,0 +1,32 @@ +/* + * 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@ + */ + +#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); diff --git a/cctools/ld/layout.c b/cctools/ld/layout.c index e9e0c822..83f49625 100644 --- a/cctools/ld/layout.c +++ b/cctools/ld/layout.c @@ -178,6 +178,10 @@ static void check_for_overlapping_segments( static void check_for_lazy_pointer_relocs_too_far(void); static void print_load_map(void); static void print_load_map_for_objects(struct merged_section *ms); +static uint32_t get_stack_size_from_flag(const struct arch_flag *flag); +static vm_prot_t get_segprot_from_flag(const struct arch_flag *flag); +static int get_stack_direction_from_flag(const struct arch_flag *flag); + #endif /* !defined(RLD) */ /* @@ -2553,3 +2557,66 @@ print_thread_info(void) print("\n"); } #endif /* DEBUG */ + +#ifndef RLD + +/* + * 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. + */ +static +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); +} + +/* + * get_segprot_from_flag() returns the default segment protection. + */ +static +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); +} + +/* + * 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. + */ +static +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); +} + +#endif /* !defined(RLD) */ diff --git a/cctools/libmacho/Makefile b/cctools/libmacho/Makefile index cb852a16..fbbc1272 100644 --- a/cctools/libmacho/Makefile +++ b/cctools/libmacho/Makefile @@ -39,6 +39,10 @@ CFLAGS = $(OFLAG) -g -Wall $(LEGACY) \ -I$(SRCROOT) -I$(SRCROOT)/../include -I$(OFILE_DIR) $(SDK) PG = -pg +ifeq "$(RC_MACOS)" "YES" + DYNAMICLIB_FLAGS = -Wl,-iosmac_version_min,12.0 +endif + MKDIRS = /bin/mkdir -p SRCROOT = . SYMROOT = . @@ -296,7 +300,7 @@ libmacho.a libmacho_pg.a libmacho_static.a libmacho_kld.a: $(OBJS) $(LIBTOOL) -static -o $(SYMROOT)/$@ $(OBJS) libmacho.dylib libmacho_profile.dylib libmacho_debug.dylib: $(OBJS) - $(CC) $(CFLAGS) $(RC_CFLAGS) -dynamiclib \ + $(CC) $(CFLAGS) $(RC_CFLAGS) $(DYNAMICLIB_FLAGS) -dynamiclib \ -o $(SYMROOT)/$@ $(OBJS) \ -install_name $(INSTALL_NAME) \ -compatibility_version 1 \ diff --git a/cctools/libmacho/arch.c b/cctools/libmacho/arch.c index 7edf3622..a353c2cb 100644 --- a/cctools/libmacho/arch.c +++ b/cctools/libmacho/arch.c @@ -79,6 +79,10 @@ static const NXArchInfo ArchInfoTable[] = { "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, @@ -181,6 +185,74 @@ 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 @@ -190,29 +262,36 @@ const NXArchInfo * NXGetLocalArchInfo(void) { - struct host_basic_info hbi; - kern_return_t ret; - unsigned int count; - mach_port_t my_mach_host_self; + cpu_type_t cputype; + cpu_subtype_t cpusubtype; + int32_t ret; - 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)&hbi, - &count); - mach_port_deallocate(mach_task_self(), my_mach_host_self); - if(ret != KERN_SUCCESS) - return(NULL); + /* + * 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; - /* - * 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(hbi.cpu_type == CPU_TYPE_MC680x0 && - hbi.cpu_subtype == CPU_SUBTYPE_MC680x0_ALL) - hbi.cpu_subtype = CPU_SUBTYPE_MC68030_ONLY; +#ifdef HOST_PREFERRED_USER_ARCH + ret = internal_NXGetHostUserCPU(&cputype, &cpusubtype); +#endif + + if (ret != 0) + ret = internal_NXGetHostBasicCPU(&cputype, &cpusubtype); + + if(ret != 0) + return(NULL); - return(NXGetArchInfoFromCpuType(hbi.cpu_type, hbi.cpu_subtype)); + /* + * 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)); } /* @@ -296,6 +375,30 @@ cpu_subtype_t cpusubtype) 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 @@ -308,6 +411,7 @@ cpu_subtype_t cpusubtype) * 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, @@ -877,6 +981,9 @@ uint32_t nfat_archs) 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: { @@ -1048,6 +1155,11 @@ cpu_subtype_t cpusubtype2) 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); diff --git a/cctools/libmacho/getsecbyname.c b/cctools/libmacho/getsecbyname.c index a9642382..3de74de6 100644 --- a/cctools/libmacho/getsecbyname.c +++ b/cctools/libmacho/getsecbyname.c @@ -22,7 +22,9 @@ */ #ifndef RLD #include +#ifndef CCTB_DRIVERKIT_ENABLED #include +#endif /* !defined(CCTB_DRIVERKIT_ENABLED) */ #include #ifdef __DYNAMIC__ #include /* defines _dyld_lookup_and_bind() */ @@ -49,6 +51,8 @@ if ( var ## _pointer == NULL) { \ #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. @@ -315,6 +319,8 @@ unsigned long *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 @@ -466,6 +472,8 @@ unsigned long *size) #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 @@ -529,7 +537,8 @@ const char *segname, const char *sectname, unsigned long *size) { - uint32_t i, n; + uint32_t i; + unsigned long n; uintptr_t vmaddr_slide; #ifndef __LP64__ struct mach_header *mh; @@ -566,4 +575,5 @@ unsigned long *size) return(NULL); } #endif /* __DYNAMIC__ */ +#endif /* !defined(CCTB_DRIVERKIT_ENABLED) */ #endif /* !defined(RLD) */ diff --git a/cctools/libmacho/slot_name.c b/cctools/libmacho/slot_name.c index a7804306..1911166c 100644 --- a/cctools/libmacho/slot_name.c +++ b/cctools/libmacho/slot_name.c @@ -49,10 +49,8 @@ * Convert the specified cpu_type/cpu_subtype pair to their * human readable form. */ -void slot_name(cpu_type, cpu_subtype, cpu_name, cpu_subname) - cpu_type_t cpu_type; - cpu_subtype_t cpu_subtype; - char **cpu_name, **cpu_subname; +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 = ""; diff --git a/cctools/libmacho/swap.c b/cctools/libmacho/swap.c index 7b1eee7a..b7f8f1c3 100644 --- a/cctools/libmacho/swap.c +++ b/cctools/libmacho/swap.c @@ -407,6 +407,44 @@ enum NXByteOrder target_byte_sex) 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, @@ -447,6 +485,33 @@ enum NXByteOrder target_byte_sex) 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, @@ -532,6 +597,17 @@ enum NXByteOrder target_byte_sex) 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, diff --git a/cctools/libstuff/CMakeLists.txt b/cctools/libstuff/CMakeLists.txt index af6830d9..0cacd5cd 100644 --- a/cctools/libstuff/CMakeLists.txt +++ b/cctools/libstuff/CMakeLists.txt @@ -27,6 +27,7 @@ set(LIBSTUFF_SOURCES seg_addr_table.c dylib_table.c breakout.c + write64.c writeout.c checkout.c fatal_arch.c @@ -42,6 +43,7 @@ set(LIBSTUFF_SOURCES symbol_list.c unix_standard_mode.c lto.c llvm.c + args.c ${COFF_BYTESEX} ${CMAKE_BINARY_DIR}/cctools/cctools_version.c ) diff --git a/cctools/libstuff/Makefile b/cctools/libstuff/Makefile index 0704bbf2..1c844952 100644 --- a/cctools/libstuff/Makefile +++ b/cctools/libstuff/Makefile @@ -42,7 +42,7 @@ endif CFILES = allocate.c errors.c arch.c execute.c bytesex.c rnd.c hppa.c \ swap_headers.c reloc.c version_number.c get_toc_byte_sex.c \ best_arch.c fatals.c arch_usage.c ofile.c ofile_error.c print.c \ - set_arch_flag_name.c seg_addr_table.c dylib_table.c \ + set_arch_flag_name.c seg_addr_table.c dylib_table.c write64.c \ breakout.c writeout.c checkout.c fatal_arch.c ofile_get_word.c \ vm_flush_cache.c hash_string.c dylib_roots.c guess_short_name.c \ SymLoc.c get_arch_from_host.c crc32.c macosx_deployment_target.c \ diff --git a/cctools/libstuff/SymLoc.c b/cctools/libstuff/SymLoc.c index 08098e52..c2301f5c 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 318fba4a..fa8b44cb 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/apple_version.c b/cctools/libstuff/apple_version.c new file mode 100644 index 00000000..8db4ce8a --- /dev/null +++ b/cctools/libstuff/apple_version.c @@ -0,0 +1,12 @@ +// +// apple_version.c +// stuff +// +// Created by Michael Trent on 12/20/18. +// + +#ifndef CURRENT_PROJECT_VERSION +#define CURRENT_PROJECT_VERSION "cctools-localbuild" +#endif /* CURRENT_PROJECT_VERSION */ + +const char apple_version[] = "" CURRENT_PROJECT_VERSION; diff --git a/cctools/libstuff/arch.c b/cctools/libstuff/arch.c index e43c2401..6f2332f7 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 00000000..b3d07917 --- /dev/null +++ b/cctools/libstuff/args.c @@ -0,0 +1,421 @@ +// +// args.c +// stuff +// +// Created by Michael Trent on 5/31/19. +// + +#include "stuff/args.h" +#include "stuff/errors.h" + +#include +#include +#include +#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 e94ee40f..1d1eec83 100644 --- a/cctools/libstuff/best_arch.c +++ b/cctools/libstuff/best_arch.c @@ -49,8 +49,8 @@ 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; @@ -686,7 +686,7 @@ uint32_t nfat_archs) 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: @@ -878,6 +878,8 @@ uint32_t nfat_archs) } break; + /* For CPU_TYPE_ARM64_32 only an exact match is allowed. */ + default: return(-1); } @@ -971,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); @@ -1453,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 c182c2f4..18b3d0f2 100644 --- a/cctools/libstuff/breakout.c +++ b/cctools/libstuff/breakout.c @@ -267,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]; @@ -322,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 a4653aa9..9149dfda 100644 --- a/cctools/libstuff/bytesex.c +++ b/cctools/libstuff/bytesex.c @@ -2385,6 +2385,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( @@ -2562,6 +2572,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, @@ -2653,6 +2692,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( @@ -2922,7 +2973,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 827543ee..2212ac2f 100644 --- a/cctools/libstuff/checkout.c +++ b/cctools/libstuff/checkout.c @@ -171,6 +171,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){ @@ -268,7 +282,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 @@ -332,7 +347,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) @@ -391,6 +407,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){ @@ -427,6 +444,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 " @@ -535,7 +567,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; @@ -557,7 +590,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; @@ -574,7 +608,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; @@ -589,7 +624,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; } @@ -645,7 +681,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; } @@ -657,7 +693,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: "); @@ -690,7 +726,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_table.c b/cctools/libstuff/dylib_table.c index 9a258986..33d65e9a 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 085e3e7c..8526ab70 100644 --- a/cctools/libstuff/execute.c +++ b/cctools/libstuff/execute.c @@ -72,7 +72,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 +82,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 7454c2c7..d0f46d26 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 000870dc..c4847603 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 353eb571..8376c7e0 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 @@ char **return_suffix) /* 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 @@ char **return_suffix) 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/lto.c b/cctools/libstuff/lto.c index 9f8f292a..7157c34e 100644 --- a/cctools/libstuff/lto.c +++ b/cctools/libstuff/lto.c @@ -56,7 +56,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; @@ -282,6 +282,14 @@ const 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); } diff --git a/cctools/libstuff/macosx_deployment_target.c b/cctools/libstuff/macosx_deployment_target.c index 0fc27903..14eca829 100644 --- a/cctools/libstuff/macosx_deployment_target.c +++ b/cctools/libstuff/macosx_deployment_target.c @@ -81,20 +81,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; } @@ -124,14 +124,14 @@ struct macosx_deployment_target *value) * 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 8a3a0602..e79430e6 100644 --- a/cctools/libstuff/ofile.c +++ b/cctools/libstuff/ofile.c @@ -203,7 +203,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; @@ -919,6 +920,9 @@ enum bool archives_with_fat_objects) 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); if(ofile->file_name == NULL) @@ -972,8 +976,9 @@ enum bool archives_with_fat_objects) memcpy(ofile->fat_archs64, addr + sizeof(struct fat_header), size - sizeof(struct fat_header)); - small_nfat_arch = (size - sizeof(struct fat_header)) / - sizeof(struct fat_arch_64); + small_nfat_arch = (uint32_t) + ((size - sizeof(struct fat_header)) / + sizeof(struct fat_arch_64)); #ifdef __LITTLE_ENDIAN__ swap_fat_arch_64(ofile->fat_archs64, small_nfat_arch, host_byte_sex); @@ -987,8 +992,9 @@ enum bool archives_with_fat_objects) 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); + 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); @@ -1170,7 +1176,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 @@ -1215,7 +1221,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 @@ -1290,7 +1296,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 @@ -1324,10 +1330,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 } } } @@ -1337,7 +1341,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 @@ -1371,10 +1375,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 } } } @@ -1571,6 +1573,9 @@ uint32_t narch) ofile->mh64 = NULL; ofile->load_commands = NULL; + /* silence clang warning */ + magic = 0; + if(ofile->fat_header->magic == FAT_MAGIC_64){ ofile->arch_flag.cputype = ofile->fat_archs64[ofile->narch].cputype; @@ -1585,7 +1590,6 @@ uint32_t narch) } set_arch_flag_name(&(ofile->arch_flag)); - /* Now determine the file type for this specific architecture */ if(ofile->file_type == OFILE_FAT){ ofile->member_offset = 0; @@ -1661,7 +1665,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; @@ -1695,7 +1699,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; @@ -1733,7 +1737,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 */ @@ -1868,19 +1872,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"); @@ -2100,6 +2104,9 @@ struct ofile *ofile) uint32_t ar_name_size, member_name_offset, n; uint32_t sizeof_fat_archs; + /* silence clang warning */ + ar_name_size = 0; + /* * Get the address and size of the archive. */ @@ -2166,11 +2173,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; @@ -2181,7 +2188,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; @@ -2198,8 +2206,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"); @@ -2221,6 +2229,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 */ host_byte_sex = get_host_byte_sex(); @@ -2403,6 +2416,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. @@ -2459,12 +2477,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; @@ -2485,7 +2505,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; @@ -2494,7 +2514,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; } @@ -2510,8 +2531,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; @@ -2835,9 +2856,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); @@ -3320,9 +3343,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; @@ -3391,7 +3411,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); @@ -3403,8 +3423,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; @@ -3413,6 +3434,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){ @@ -3420,10 +3442,11 @@ 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 || (magic == FAT_MAGIC_64)) + if(magic == FAT_MAGIC || magic == FAT_MAGIC_64) #endif /* __BIG_ENDIAN__ */ #ifdef __LITTLE_ENDIAN__ if(magic == SWAP_INT(FAT_MAGIC) || @@ -3465,28 +3488,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; @@ -3495,7 +3531,6 @@ enum bool archives_with_fat_objects) ofile->member_name = NULL; ofile->member_name_size = 0; return(CHECK_GOOD); -#endif /* OTOOL */ } /* @@ -3523,7 +3558,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)", @@ -3569,6 +3604,14 @@ struct ofile *ofile) char *strings; enum bool toc_is_32bit; + /* 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; @@ -3626,7 +3669,8 @@ struct ofile *ofile) } } 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 @@ -3837,6 +3881,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; @@ -3859,9 +3904,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; @@ -3871,6 +3919,7 @@ 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; @@ -3902,13 +3951,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"; @@ -3925,13 +3975,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"; @@ -3968,12 +4019,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){ @@ -4235,7 +4291,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 " @@ -4579,7 +4635,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); @@ -4590,7 +4646,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); @@ -4610,6 +4666,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 " @@ -4654,8 +4732,9 @@ struct ofile *ofile) } 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; @@ -4666,6 +4745,15 @@ struct ofile *ofile) "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: @@ -4676,10 +4764,17 @@ struct ofile *ofile) } 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); @@ -4692,20 +4787,28 @@ struct ofile *ofile) 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; } @@ -4719,10 +4822,17 @@ struct ofile *ofile) } 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); @@ -4733,6 +4843,87 @@ struct ofile *ofile) } 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 " @@ -4828,7 +5019,7 @@ struct ofile *ofile) 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; } @@ -6362,7 +6553,7 @@ struct ofile *ofile) } break; } - if(cputype == CPU_TYPE_ARM64){ + if(cputype == CPU_TYPE_ARM64 || cputype == CPU_TYPE_ARM64_32){ arm_thread_state64_t *cpu; nflavor = 0; @@ -6505,6 +6696,31 @@ struct ofile *ofile) 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/reloc.c b/cctools/libstuff/reloc.c index 9d9c76c6..62ef47d2 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 95ba9944..597acae0 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 44afe512..594fece6 100644 --- a/cctools/libstuff/seg_addr_table.c +++ b/cctools/libstuff/seg_addr_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 @@ -96,20 +97,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 +152,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 +171,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 +247,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 +314,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 +332,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 0bfcdb72..0d4f153f 100644 --- a/cctools/libstuff/swap_headers.c +++ b/cctools/libstuff/swap_headers.c @@ -96,6 +96,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; @@ -1026,6 +1029,18 @@ struct load_command *load_commands) } 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 > @@ -1186,6 +1201,17 @@ struct load_command *load_commands) } 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)){ @@ -1695,6 +1721,11 @@ struct load_command *load_commands) 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); @@ -1731,6 +1762,8 @@ struct load_command *load_commands) 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; @@ -1768,6 +1801,13 @@ struct load_command *load_commands) 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 613bc1a0..d11b7c85 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 9a0384c6..baf018bf 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 00000000..0e19a517 --- /dev/null +++ b/cctools/libstuff/write64.c @@ -0,0 +1,66 @@ +/* + * 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@ + */ + +#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; +} diff --git a/cctools/libstuff/writeout.c b/cctools/libstuff/writeout.c index 8c1f42c2..71609777 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, @@ -105,7 +107,7 @@ static void warn_member( * 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 is is set to a value of bytes per second to limiting the writes to + * 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__ @@ -124,21 +126,47 @@ 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; uint64_t file_size; - time_t toc_time; enum bool seen_archive; kern_return_t r; - + int time_result; + seen_archive = FALSE; - toc_time = time(0); - writeout_to_mem(archs, narchs, output, (void **)&file, &file_size, +#ifndef __OPENSTEP__ +# ifdef XTOOLS_HAS_CLOCK_GETTIME + if (clock_gettime(CLOCK_REALTIME, &toc_timespec)) { + system_error("clock_gettime failed"); + return; + } +# else + if (gettimeofday(&toc_timeval, NULL)) { + system_error("gettimeofday failed"); + return; + } +# endif +#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); @@ -193,10 +221,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; } @@ -245,7 +274,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; } @@ -256,15 +285,29 @@ uint32_t *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. + */ +# ifdef XTOOLS_HAS_CLOCK_GETTIME + 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); +# else + 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 #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; @@ -339,7 +382,15 @@ 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; @@ -369,6 +420,10 @@ enum bool *seen_archive) 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; @@ -383,8 +438,16 @@ enum bool *seen_archive) file_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) - archs[i].fat_arch->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 @@ -409,8 +472,16 @@ enum bool *seen_archive) file_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) - archs[i].fat_arch->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; + } } } @@ -473,7 +544,7 @@ enum bool *seen_archive) } else{ offset = rnd(offset, 1 << archs[i].fat_arch->align); - fat_arch[i].offset = offset; + 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; @@ -569,20 +640,43 @@ enum bool *seen_archive) } if(archs[i].using_64toc == FALSE){ - i32 = archs[i].ntocs * sizeof(struct ranlib); + 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, + 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; + 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)); @@ -698,14 +792,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++) @@ -757,7 +852,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; @@ -857,6 +952,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 * @@ -940,8 +1047,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); @@ -982,8 +1091,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); @@ -1334,11 +1445,12 @@ 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) - @@ -1405,11 +1517,12 @@ enum bool library_warnings) * a uint64_t for the number of bytes of the strings * the strings */ - arch->toc_size = sizeof(struct ar_hdr) + - sizeof(uint64_t) + - arch->ntocs * sizeof(struct ranlib_64) + - sizeof(uint64_t) + - arch->toc_strsize; + 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) - @@ -1427,9 +1540,9 @@ enum bool library_warnings) arch->members[arch->toc_entries[i].member_index - 1].offset; } else{ - arch->toc_ranlibs[i].ran_un.ran_strx = - arch->toc_entries[i].symbol_name - arch->toc_strings; - arch->toc_ranlibs[i].ran_off = + 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; } } diff --git a/cctools/libstuff_test/allocate_test.c b/cctools/libstuff_test/allocate_test.c new file mode 100644 index 00000000..6806c108 --- /dev/null +++ b/cctools/libstuff_test/allocate_test.c @@ -0,0 +1,101 @@ +// +// allocate_test.c +// libstuff_test +// +// Created by Michael Trent on 1/20/19. +// + +#include "test_main.h" + +#include "stuff/allocate.h" + +static void test_allocate(void) +{ + // as an interesting quirk, allocate returns NULL when allocating a buffer + // of size 0. This is not what the actual malloc implementation does ... + void* p = allocate(0); + check_null("allocate(NULL)", p); + if (p) + free(p); + + p = allocate(1); + check_nonnull("allocate(1)", p); + if (p) + free(p); +} + +static void test_reallocate(void) +{ + void* p = reallocate(NULL, 0); + check_null("reallocate(NULL, 0)", p); + + p = reallocate(NULL, 1); + check_nonnull("reallocate(NULL, 1)", p); + + p = reallocate(p, 2); + check_nonnull("reallocate(p, 2)", p); + + p = reallocate(p, 0); + check_nonnull("reallocate(p, 0)", p); + + if (p) + free(p); +} + +static void test_savestr(void) +{ + // savestr is strdup with cctools error reporting. + char* s = savestr(""); + check_nonnull("savestr(\"\")", s); + if (s) { + check_string("savestr(\"\")", "", s); + free(s); + } + + const char* cs = "A brilliant red Barchetta"; + s = savestr(cs); + check_nonnull("savestr(cs)", s); + if (s) { + check_string("savestr(cs)", cs, s); + free(s); + } +} + +static void test_makestr(void) +{ + // makestr is a vararg wrapper to strcat. it is not possible to verify all + // the arguments to makestr are char*. + char* s = makestr(NULL); + + check_nonnull("makestr(NULL)", s); + if (s) { + check_string("makestr(NULL)", "", s); + free(s); + } + + s = makestr("", NULL); + check_nonnull("makestr(\"\", NULL)", s); + if (s) { + check_string("makestr(\"\", NULL)", "", s); + free(s); + } + + s = makestr("A", " brilliant", " red", " Barchetta", NULL); + check_nonnull("makestr(a, b, c, d)", s); + if (s) { + check_string("makestr(a, b, c, d)", "A brilliant red Barchetta", s); + free(s); + } +} + +static int test_main(void) +{ + int err = 0; + + if (!err) err = test_add("test allocate", test_allocate); + if (!err) err = test_add("test reallocate", test_reallocate); + if (!err) err = test_add("test savestr", test_savestr); + if (!err) err = test_add("test makestr", test_makestr); + + return err; +} diff --git a/cctools/libstuff_test/arch_test.c b/cctools/libstuff_test/arch_test.c new file mode 100644 index 00000000..78297f96 --- /dev/null +++ b/cctools/libstuff_test/arch_test.c @@ -0,0 +1,435 @@ +// +// arch_test.c +// libstuff_test +// +// Created by Michael Trent on 1/20/19. +// + +#include "test_main.h" + +#include +#include +#include +#include + +#include "stuff/bool.h" +#include "stuff/arch.h" + +static void check_arch_flag(const char* name, cpu_type_t cputype, + cpu_subtype_t cpusubtype) +{ + struct arch_flag af; + + get_arch_from_flag((char*)name, &af); + check_set_prefix("arch '%s'", name); + check_uint32("cputype", af.cputype, cputype); + check_uint32("cpusubtype", af.cpusubtype, cpusubtype); +} + +static void check_arch_name(const char* name, cpu_type_t cputype, + cpu_subtype_t cpusubtype) +{ + const char* nm = get_arch_name_from_types(cputype, cpusubtype); + check_set_prefix("arch (%u, %u)", cputype, cpusubtype); + check_string("name", name, nm); +} + +static void check_arch_if_known(const char* name, cpu_type_t cputype, + cpu_subtype_t cpusubtype) +{ + const char* nm = get_arch_name_if_known(cputype, cpusubtype); + check_set_prefix("arch (%u, %u)", cputype, cpusubtype); + check_string("name", name, nm); +} + +static void check_arch_family(const char* name, cpu_type_t cputype) +{ + const struct arch_flag *af; + + af = get_arch_family_from_cputype(cputype); + if (af) { + check_string("name", name, af->name); + } else if (name) { + test_printerr("arch family not found for cputype %u: %s", cputype); + } +} + +jmp_buf env; + +static void sig_handler(int signo) +{ + longjmp(env, 1); +} + +static void check_arch_values(const char* name, enum byte_sex byteorder, + uint64_t stack_addr, uint32_t seg_align, + int abort) +{ + // so ... silly me ... get_byte_sex_from_flag will abort on a bad cpu type + // so we know right away that code is doing something bad. So let's trap + // the abort. + // + // you need to hand this to lldb every. single. time. + // + // process handle SIGABRT -n true -p true -s false + + if (0 == setjmp(env)) { + + void (*ohandler)(int); + ohandler = signal(SIGABRT, sig_handler); + if (ohandler == SIG_ERR) { + test_printerr("internal error: cannot install SIGABRT handler"); + test_abort(); + return; + } + + struct arch_flag af; + enum byte_sex bo = UNKNOWN_BYTE_SEX; + uint64_t sad = 0; + uint32_t sal = 0; + + if (get_arch_from_flag((char*)name, &af)) { + bo = get_byte_sex_from_flag(&af); + sad = get_stack_addr_from_flag(&af); + sal = get_segalign_from_flag(&af); + } + + check_set_prefix("arch '%s'", name); + check_uint32("byte order", byteorder, bo); + check_uint64("stack addr", stack_addr, sad); + check_uint32("segalign", seg_align, sal); + + if (signal(SIGABRT, ohandler) == SIG_ERR) { + test_printerr("internal error: cannot restore SIGABRT handler"); + test_abort(); + return; + } + } + else { + if (0 == abort) + test_printerr("arch '%s' unexpectedly aborted", name); + } +} + +static void test_get_arch_from_flag(void) +{ + check_arch_flag("any", CPU_TYPE_ANY, CPU_SUBTYPE_MULTIPLE); + check_arch_flag("little", CPU_TYPE_ANY, CPU_SUBTYPE_LITTLE_ENDIAN); + check_arch_flag("big", CPU_TYPE_ANY, CPU_SUBTYPE_BIG_ENDIAN); + check_arch_flag("ppc64", CPU_TYPE_POWERPC64, CPU_SUBTYPE_POWERPC_ALL); + check_arch_flag("x86_64", CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL); + check_arch_flag("x86_64h", CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_H); + check_arch_flag("ppc970-64", CPU_TYPE_POWERPC64, CPU_SUBTYPE_POWERPC_970); + check_arch_flag("arm64_32", CPU_TYPE_ARM64_32, CPU_SUBTYPE_ARM64_32_V8); + check_arch_flag("arm64e", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64E); + check_arch_flag("ppc", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL); + check_arch_flag("i386", CPU_TYPE_I386, CPU_SUBTYPE_I386_ALL); + check_arch_flag("m68k", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC680x0_ALL); + check_arch_flag("hppa", CPU_TYPE_HPPA, CPU_SUBTYPE_HPPA_ALL); + check_arch_flag("sparc", CPU_TYPE_SPARC, CPU_SUBTYPE_SPARC_ALL); + check_arch_flag("m88k", CPU_TYPE_MC88000, CPU_SUBTYPE_MC88000_ALL); + check_arch_flag("i860", CPU_TYPE_I860, CPU_SUBTYPE_I860_ALL); + check_arch_flag("veo", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_ALL); + check_arch_flag("arm", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_ALL); + check_arch_flag("ppc601", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_601); + check_arch_flag("ppc603", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_603); + check_arch_flag("ppc603e",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_603e); + check_arch_flag("ppc603ev",CPU_TYPE_POWERPC,CPU_SUBTYPE_POWERPC_603ev); + check_arch_flag("ppc604", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_604); + check_arch_flag("ppc604e",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_604e); + check_arch_flag("ppc750", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_750); + check_arch_flag("ppc7400",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_7400); + check_arch_flag("ppc7450",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_7450); + check_arch_flag("ppc970", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_970); + check_arch_flag("i486", CPU_TYPE_I386, CPU_SUBTYPE_486); + check_arch_flag("i486SX", CPU_TYPE_I386, CPU_SUBTYPE_486SX); + check_arch_flag("pentium",CPU_TYPE_I386, CPU_SUBTYPE_PENT); + check_arch_flag("i586", CPU_TYPE_I386, CPU_SUBTYPE_586); + check_arch_flag("pentpro", CPU_TYPE_I386, CPU_SUBTYPE_PENTPRO); + check_arch_flag("i686", CPU_TYPE_I386, CPU_SUBTYPE_PENTPRO); + check_arch_flag("pentIIm3",CPU_TYPE_I386, CPU_SUBTYPE_PENTII_M3); + check_arch_flag("pentIIm5",CPU_TYPE_I386, CPU_SUBTYPE_PENTII_M5); + check_arch_flag("pentium4",CPU_TYPE_I386, CPU_SUBTYPE_PENTIUM_4); + check_arch_flag("m68030", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC68030_ONLY); + check_arch_flag("m68040", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC68040); + check_arch_flag("hppa7100LC", CPU_TYPE_HPPA, CPU_SUBTYPE_HPPA_7100LC); + check_arch_flag("veo1", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_1); + check_arch_flag("veo2", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_2); + check_arch_flag("veo3", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_3); + check_arch_flag("veo4", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_4); + check_arch_flag("armv4t", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V4T); + check_arch_flag("armv5", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V5TEJ); + check_arch_flag("xscale", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_XSCALE); + check_arch_flag("armv6", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6); + check_arch_flag("armv6m", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6M); + check_arch_flag("armv7", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7); + check_arch_flag("armv7f", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7F); + check_arch_flag("armv7s", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7S); + check_arch_flag("armv7k", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7K); + check_arch_flag("armv7m", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7M); + check_arch_flag("armv7em", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7EM); + check_arch_flag("arm64v8", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_V8); + check_arch_flag("unknown", 0, 0); +} + +static void test_get_arch_name_from_types(void) +{ + check_arch_name("any", CPU_TYPE_ANY, CPU_SUBTYPE_MULTIPLE); + check_arch_name("little", CPU_TYPE_ANY, CPU_SUBTYPE_LITTLE_ENDIAN); + check_arch_name("big", CPU_TYPE_ANY, CPU_SUBTYPE_BIG_ENDIAN); + check_arch_name("ppc64", CPU_TYPE_POWERPC64, CPU_SUBTYPE_POWERPC_ALL); + check_arch_name("x86_64", CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL); + check_arch_name("x86_64h", CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_H); + check_arch_name("ppc970-64", CPU_TYPE_POWERPC64, CPU_SUBTYPE_POWERPC_970); + check_arch_name("arm64_32", CPU_TYPE_ARM64_32, CPU_SUBTYPE_ARM64_32_V8); + check_arch_name("arm64e", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64E); + check_arch_name("ppc", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL); + check_arch_name("i386", CPU_TYPE_I386, CPU_SUBTYPE_I386_ALL); + check_arch_name("m68k", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC680x0_ALL); + check_arch_name("hppa", CPU_TYPE_HPPA, CPU_SUBTYPE_HPPA_ALL); + check_arch_name("sparc", CPU_TYPE_SPARC, CPU_SUBTYPE_SPARC_ALL); + check_arch_name("m88k", CPU_TYPE_MC88000, CPU_SUBTYPE_MC88000_ALL); + check_arch_name("i860", CPU_TYPE_I860, CPU_SUBTYPE_I860_ALL); + check_arch_name("veo", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_ALL); + check_arch_name("arm", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_ALL); + check_arch_name("ppc601", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_601); + check_arch_name("ppc603", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_603); + check_arch_name("ppc603e",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_603e); + check_arch_name("ppc603ev",CPU_TYPE_POWERPC,CPU_SUBTYPE_POWERPC_603ev); + check_arch_name("ppc604", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_604); + check_arch_name("ppc604e",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_604e); + check_arch_name("ppc750", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_750); + check_arch_name("ppc7400",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_7400); + check_arch_name("ppc7450",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_7450); + check_arch_name("ppc970", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_970); + check_arch_name("i486", CPU_TYPE_I386, CPU_SUBTYPE_486); + check_arch_name("i486SX", CPU_TYPE_I386, CPU_SUBTYPE_486SX); + check_arch_name("pentium",CPU_TYPE_I386, CPU_SUBTYPE_PENT); + // no reverse lookup for i586, looks like pentium. + //check_arch_name("i586", CPU_TYPE_I386, CPU_SUBTYPE_586); + check_arch_name("pentpro", CPU_TYPE_I386, CPU_SUBTYPE_PENTPRO); + // no reverse lookup for i686, looks like pentpro. + //check_arch_name("i686", CPU_TYPE_I386, CPU_SUBTYPE_PENTPRO); + check_arch_name("pentIIm3",CPU_TYPE_I386, CPU_SUBTYPE_PENTII_M3); + check_arch_name("pentIIm5",CPU_TYPE_I386, CPU_SUBTYPE_PENTII_M5); + check_arch_name("pentium4",CPU_TYPE_I386, CPU_SUBTYPE_PENTIUM_4); + check_arch_name("m68030", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC68030_ONLY); + check_arch_name("m68040", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC68040); + check_arch_name("hppa7100LC", CPU_TYPE_HPPA, CPU_SUBTYPE_HPPA_7100LC); + check_arch_name("veo1", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_1); + // no reverse lookup for veo2, looks like veo. + //check_arch_name("veo2", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_2); + check_arch_name("veo3", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_3); + check_arch_name("veo4", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_4); + check_arch_name("armv4t", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V4T); + check_arch_name("armv5", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V5TEJ); + check_arch_name("xscale", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_XSCALE); + check_arch_name("armv6", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6); + check_arch_name("armv6m", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6M); + check_arch_name("armv7", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7); + check_arch_name("armv7f", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7F); + check_arch_name("armv7s", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7S); + check_arch_name("armv7k", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7K); + check_arch_name("armv7m", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7M); + check_arch_name("armv7em", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7EM); + check_arch_name("arm64v8", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_V8); + check_arch_name("cputype 0 cpusubtype 0", 0, 0); +} + +static void test_get_arch_name_if_known(void) +{ + check_arch_if_known("any", CPU_TYPE_ANY, CPU_SUBTYPE_MULTIPLE); + check_arch_if_known("little", CPU_TYPE_ANY, CPU_SUBTYPE_LITTLE_ENDIAN); + check_arch_if_known("big", CPU_TYPE_ANY, CPU_SUBTYPE_BIG_ENDIAN); + check_arch_if_known("ppc64", CPU_TYPE_POWERPC64, CPU_SUBTYPE_POWERPC_ALL); + check_arch_if_known("x86_64", CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL); + check_arch_if_known("x86_64h", CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_H); + check_arch_if_known("ppc970-64", CPU_TYPE_POWERPC64, CPU_SUBTYPE_POWERPC_970); + check_arch_if_known("arm64_32", CPU_TYPE_ARM64_32, CPU_SUBTYPE_ARM64_32_V8); + check_arch_if_known("arm64e", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64E); + check_arch_if_known("ppc", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL); + check_arch_if_known("i386", CPU_TYPE_I386, CPU_SUBTYPE_I386_ALL); + check_arch_if_known("m68k", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC680x0_ALL); + check_arch_if_known("hppa", CPU_TYPE_HPPA, CPU_SUBTYPE_HPPA_ALL); + check_arch_if_known("sparc", CPU_TYPE_SPARC, CPU_SUBTYPE_SPARC_ALL); + check_arch_if_known("m88k", CPU_TYPE_MC88000, CPU_SUBTYPE_MC88000_ALL); + check_arch_if_known("i860", CPU_TYPE_I860, CPU_SUBTYPE_I860_ALL); + check_arch_if_known("veo", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_ALL); + check_arch_if_known("arm", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_ALL); + check_arch_if_known("ppc601", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_601); + check_arch_if_known("ppc603", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_603); + check_arch_if_known("ppc603e",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_603e); + check_arch_if_known("ppc603ev",CPU_TYPE_POWERPC,CPU_SUBTYPE_POWERPC_603ev); + check_arch_if_known("ppc604", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_604); + check_arch_if_known("ppc604e",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_604e); + check_arch_if_known("ppc750", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_750); + check_arch_if_known("ppc7400",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_7400); + check_arch_if_known("ppc7450",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_7450); + check_arch_if_known("ppc970", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_970); + check_arch_if_known("i486", CPU_TYPE_I386, CPU_SUBTYPE_486); + check_arch_if_known("i486SX", CPU_TYPE_I386, CPU_SUBTYPE_486SX); + check_arch_if_known("pentium",CPU_TYPE_I386, CPU_SUBTYPE_PENT); + // no reverse lookup for i586, looks like pentium. + //check_arch_name_known("i586", CPU_TYPE_I386, CPU_SUBTYPE_586); + check_arch_if_known("pentpro", CPU_TYPE_I386, CPU_SUBTYPE_PENTPRO); + // no reverse lookup for i686, looks like pentpro. + //check_arch_name_known("i686", CPU_TYPE_I386, CPU_SUBTYPE_PENTPRO); + check_arch_if_known("pentIIm3",CPU_TYPE_I386, CPU_SUBTYPE_PENTII_M3); + check_arch_if_known("pentIIm5",CPU_TYPE_I386, CPU_SUBTYPE_PENTII_M5); + check_arch_if_known("pentium4",CPU_TYPE_I386, CPU_SUBTYPE_PENTIUM_4); + check_arch_if_known("m68030", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC68030_ONLY); + check_arch_if_known("m68040", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC68040); + check_arch_if_known("hppa7100LC", CPU_TYPE_HPPA, CPU_SUBTYPE_HPPA_7100LC); + check_arch_if_known("veo1", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_1); + // no reverse lookup for veo2, looks like veo. + //check_arch_name_known("veo2", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_2); + check_arch_if_known("veo3", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_3); + check_arch_if_known("veo4", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_4); + check_arch_if_known("armv4t", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V4T); + check_arch_if_known("armv5", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V5TEJ); + check_arch_if_known("xscale", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_XSCALE); + check_arch_if_known("armv6", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6); + check_arch_if_known("armv6m", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6M); + check_arch_if_known("armv7", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7); + check_arch_if_known("armv7f", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7F); + check_arch_if_known("armv7s", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7S); + check_arch_if_known("armv7k", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7K); + check_arch_if_known("armv7m", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7M); + check_arch_if_known("armv7em", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7EM); + check_arch_if_known("arm64v8", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_V8); + check_arch_if_known(NULL, 0, 0); +} + +static void test_get_arch_family_from_cputype(void) +{ + check_arch_family("any", CPU_TYPE_ANY); + check_arch_family("ppc64", CPU_TYPE_POWERPC64); + check_arch_family("x86_64", CPU_TYPE_X86_64); + check_arch_family("arm64_32", CPU_TYPE_ARM64_32); + check_arch_family("ppc", CPU_TYPE_POWERPC); + check_arch_family("i386", CPU_TYPE_I386); + check_arch_family("m68k", CPU_TYPE_MC680x0); + check_arch_family("hppa", CPU_TYPE_HPPA); + check_arch_family("sparc", CPU_TYPE_SPARC); + check_arch_family("m88k", CPU_TYPE_MC88000); + check_arch_family("i860", CPU_TYPE_I860); + check_arch_family("veo", CPU_TYPE_VEO); + check_arch_family("arm", CPU_TYPE_ARM); + check_arch_family(NULL, 0); + check_arch_family(NULL, 2112); + + // there is no family name for ARM64 + check_arch_family(NULL, CPU_TYPE_ARM64); +} + +static void test_arch_flag_values(void) +{ + // set a breakpoint at the next line of code. at that break point, type this: + // process handle SIGABRT -n true -p true -s false + // see above. + check_arch_values("any", UNKNOWN_BYTE_SEX, 0, 0, 1); + check_arch_values("little", UNKNOWN_BYTE_SEX, 0, 0, 1); + check_arch_values("big", UNKNOWN_BYTE_SEX, 0, 0, 1); + check_arch_values("ppc64", BIG_ENDIAN_BYTE_SEX, 0x7ffff00000000, 0x1000, 0); + check_arch_values("x86_64", LITTLE_ENDIAN_BYTE_SEX, 0x7fff5fc00000, 0x1000,0); + check_arch_values("x86_64h", LITTLE_ENDIAN_BYTE_SEX, 0x7fff5fc00000,0x1000,0); + check_arch_values("ppc970-64", BIG_ENDIAN_BYTE_SEX, 0x7ffff00000000,0x1000,0); + check_arch_values("arm64_32", LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000, 0); + check_arch_values("arm64e", LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000, 0); + check_arch_values("ppc", BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("i386", LITTLE_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("m68k", BIG_ENDIAN_BYTE_SEX, 0x04000000, 0x2000, 0); + check_arch_values("hppa", BIG_ENDIAN_BYTE_SEX, 0, 0x2000, 0); + check_arch_values("sparc", BIG_ENDIAN_BYTE_SEX, 0xf0000000, 0x2000, 0); + check_arch_values("m88k", BIG_ENDIAN_BYTE_SEX, 0xffffe000, 0x2000, 0); + check_arch_values("i860", BIG_ENDIAN_BYTE_SEX, 0, 0x2000, 0); + check_arch_values("veo", BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("arm", LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000, 0); + check_arch_values("ppc601", BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("ppc603", BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("ppc603e",BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("ppc603ev",BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("ppc604", BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("ppc604e",BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("ppc750", BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("ppc7400",BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("ppc7450",BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("ppc970", BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("i486", LITTLE_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("i486SX", LITTLE_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("pentium",LITTLE_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("i586", LITTLE_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("pentpro", LITTLE_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("i686", LITTLE_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("pentIIm3",LITTLE_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("pentIIm5",LITTLE_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("pentium4",LITTLE_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("m68030", BIG_ENDIAN_BYTE_SEX, 0x04000000, 0x2000, 0); + check_arch_values("m68040", BIG_ENDIAN_BYTE_SEX, 0x04000000, 0x2000, 0); + check_arch_values("hppa7100LC", BIG_ENDIAN_BYTE_SEX, 0, 0x2000, 0); + check_arch_values("veo1", BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("veo2", BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("veo3", BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("veo4", BIG_ENDIAN_BYTE_SEX, 0xc0000000, 0x1000, 0); + check_arch_values("armv4t", LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000, 0); + check_arch_values("armv5", LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000, 0); + check_arch_values("xscale", LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000, 0); + check_arch_values("armv6", LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000, 0); + check_arch_values("armv6m", LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000, 0); + check_arch_values("armv7", LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000, 0); + check_arch_values("armv7f", LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000, 0); + check_arch_values("armv7s", LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000, 0); + check_arch_values("armv7k", LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000, 0); + check_arch_values("armv7m", LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000, 0); + check_arch_values("armv7em", LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000, 0); + check_arch_values("arm64v8", LITTLE_ENDIAN_BYTE_SEX, 0, 0x4000, 0); + check_arch_values("unknown", UNKNOWN_BYTE_SEX, 0, 0, 0); + // check_byte_order(NULL, UNKNOWN_BYTE_SEX, YYY, YYY, 0); .. will crash +} + +static void test_shared_region_size(void) +{ + const struct arch_flag* flag = get_arch_flags(); + while (flag->name) { + uint32_t size = flag->cputype == CPU_TYPE_ARM ? 0x08000000 : 0x10000000; + uint32_t sz = get_shared_region_size_from_flag(flag); + check_set_prefix("arch '%s'", flag->name); + check_uint32("shared region size", size, sz); + flag++; + } +} + +static void test_force_cpusubtypes(void) +{ + const struct arch_flag* flag = get_arch_flags(); + while (flag->name) { + enum bool force = flag->cputype == CPU_TYPE_I386 ? TRUE : FALSE; + enum bool frc = force_cpusubtype_ALL_for_cputype(flag->cputype); + check_set_prefix("arch '%s'", flag->name); + check_uint32("shared region size", force, frc); + flag++; + } +} + +static int test_main(void) +{ + // set a breakpoint at the next line of code. at that break point, type this: + // process handle SIGABRT -n true -p true -s false + // see above. + int err = 0; + + if (!err) err = test_add("test get_arch_from_flag", test_get_arch_from_flag); + if (!err) err = test_add("test get_arch_name_from_types", + test_get_arch_name_from_types); + if (!err) err = test_add("test get_arch_name_if_known", + test_get_arch_name_if_known); + if (!err) err = test_add("test get_arch_family_from_cputype", + test_get_arch_family_from_cputype); + if (!err) err = test_add("test arch_flag values", + test_arch_flag_values); + if (!err) err = test_add("test shared region size", test_shared_region_size); + if (!err) err = test_add("test force cpusubtypes", test_force_cpusubtypes); + + + return err; +} diff --git a/cctools/libstuff_test/args_test.c b/cctools/libstuff_test/args_test.c new file mode 100644 index 00000000..c68b7c67 --- /dev/null +++ b/cctools/libstuff_test/args_test.c @@ -0,0 +1,270 @@ +// +// args_test.c +// libstuff_test +// +// Created by Michael Trent on 5/31/19. +// + +#include "test_main.h" +#include "test_util.h" + +#include "stuff/args.h" + +#include +#include +#include +#include +#include +#include +#include + +#define countof(X) (sizeof(X) / sizeof(*X)) + +static char* masprintf(const char * __restrict format, ...) +{ + assert(format); + + va_list args; + va_start(args, format); + + char* s; + vasprintf(&s, format, args); + + va_end(args); + + return s; +} + +static void test_args_expand_at_1(void) +{ + char* strs[2] = {0}; + strs[0] = strdup("/bin/ls"); + + int argc = 1; + char** argv = strs; + int err = args_expand_at(&argc, &argv); + + check_uint32("args_expand_at result", 0, err); + check_uint32("argc", 1, argc); + check_string("argv[0]", "/bin/ls", argv[0]); + check_null("argv[1]", argv[1]); + + for (int i = 0; i < countof(strs); ++i) + if (strs[i]) + free(strs[i]); +} + +static void test_args_expand_at_2(void) +{ + char* strs[4] = {0}; + strs[0] = strdup("/bin/ls"); + strs[1] = strdup("-ls"); + strs[2] = strdup("/"); + + int argc = 3; + char** argv = strs; + int err = args_expand_at(&argc, &argv); + + check_uint32("args_expand_at result", 0, err); + check_uint32("argc", 3, argc); + check_string("argv[0]", "/bin/ls", argv[0]); + check_string("argv[1]", "-ls", argv[1]); + check_string("argv[2]", "/", argv[2]); + check_null("argv[3]", argv[3]); + + for (int i = 0; i < countof(strs); ++i) + if (strs[i]) + free(strs[i]); +} + +static void test_args_expand_at_3(void) +{ + char* strs[5] = {0}; + strs[0] = strdup("/bin/ls"); + strs[1] = strdup("@/tmp/missing-ls-args"); + strs[2] = strdup("@/tmp/missing-ls-args"); + strs[3] = strdup("/"); + + int argc = 4; + char** argv = strs; + int err = args_expand_at(&argc, &argv); + + check_uint32("args_expand_at result", 0, err); + check_uint32("argc", 4, argc); + check_string("argv[0]", "/bin/ls", argv[0]); + check_string("argv[1]", "@/tmp/missing-ls-args", argv[1]); + check_string("argv[2]", "@/tmp/missing-ls-args", argv[2]); + check_string("argv[3]", "/", argv[3]); + check_null("argv[4]", argv[4]); + + for (int i = 0; i < countof(strs); ++i) + if (strs[i]) + free(strs[i]); +} + +static void test_args_expand_at_4(void) +{ + const char* data = "-ls apple\tbanana\ncarrot durian\\ fruit 'el burro'\n"; + char* tempfile = NULL; + + if (test_write_tmp_data(data, strlen(data), &tempfile)) { + test_printerr("failed to write temp data: %s", strerror(errno)); + return; + } + + char* strs[3] = {0}; + strs[0] = strdup("/bin/ls"); + strs[1] = masprintf("@%s", tempfile); + + int argc = 2; + char** argv = strs; + int err = args_expand_at(&argc, &argv); + + check_uint32("args_expand_at result", 0, err); + check_uint32("argc", 7, argc); + check_string("argv[0]", "/bin/ls", argv[0]); + check_string("argv[1]", "-ls", argv[1]); + check_string("argv[2]", "apple", argv[2]); + check_string("argv[3]", "banana", argv[3]); + check_string("argv[4]", "carrot", argv[4]); + check_string("argv[5]", "durian fruit", argv[5]); + check_string("argv[6]", "el burro", argv[6]); + check_null("argv[7]", argv[7]); + + for (int i = 0; i < countof(strs); ++i) + if (strs[i]) + free(strs[i]); + + unlink(tempfile); + free(tempfile); +} + +static void test_args_expand_at_5(void) +{ + const char* data1 = " -ls apple\tbanana\ncarrot \n"; + const char* data2 = "\n\n\tdurian\\ fruit 'el burro' \n"; + char* tempname1 = NULL; + char* tempname2 = NULL; + + if (test_write_tmp_data(data1, strlen(data1), &tempname1)) { + test_printerr("failed to write temp data: %s", strerror(errno)); + return; + } + if (test_write_tmp_data(data2, strlen(data2), &tempname2)) { + unlink(tempname1); + free(tempname1); + test_printerr("failed to write temp data: %s", strerror(errno)); + return; + } + + char* strs[4] = {0}; + strs[0] = strdup("/bin/ls"); + strs[1] = masprintf("@%s", tempname1); + strs[2] = masprintf("@%s", tempname2); + + int argc = 3; + char** argv = strs; + int err = args_expand_at(&argc, &argv); + + check_uint32("args_expand_at result", 0, err); + check_uint32("argc", 7, argc); + check_string("argv[0]", "/bin/ls", argv[0]); + check_string("argv[1]", "-ls", argv[1]); + check_string("argv[2]", "apple", argv[2]); + check_string("argv[3]", "banana", argv[3]); + check_string("argv[4]", "carrot", argv[4]); + check_string("argv[5]", "durian fruit", argv[5]); + check_string("argv[6]", "el burro", argv[6]); + check_null("argv[7]", argv[7]); + + for (int i = 0; i < countof(strs); ++i) + if (strs[i]) + free(strs[i]); + + unlink(tempname1); + free(tempname1); + unlink(tempname2); + free(tempname2); +} + +static void test_args_expand_at_6(void) +{ + const char* data1 = " -ls apple\tbanana\ncarrot \n"; + const char* data2 = "\n\n\tdurian\\ fruit 'el burro' \n"; + char* tempname1 = NULL; + char* tempname2 = NULL; + char* tempname3 = NULL; + + if (test_write_tmp_data(data1, strlen(data1), &tempname1)) { + test_printerr("failed to write temp data: %s", strerror(errno)); + return; + } + if (test_write_tmp_data(data2, strlen(data2), &tempname2)) { + unlink(tempname1); + free(tempname1); + test_printerr("failed to write temp data: %s", strerror(errno)); + return; + } + + char* data3 = masprintf("@%s @%s\n", tempname1, tempname2); + if (test_write_tmp_data(data3, strlen(data3), &tempname3)) { + unlink(tempname1); + free(tempname1); + unlink(tempname2); + free(tempname2); + free(data3); + test_printerr("failed to write temp data: %s", strerror(errno)); + return; + } + free(data3); + + char* strs[3] = {0}; + strs[0] = strdup("/bin/ls"); + strs[1] = masprintf("@%s", tempname3); + + int argc = 2; + char** argv = strs; + int err = args_expand_at(&argc, &argv); + + check_uint32("args_expand_at result", 0, err); + check_uint32("argc", 7, argc); + check_string("argv[0]", "/bin/ls", argv[0]); + check_string("argv[1]", "-ls", argv[1]); + check_string("argv[2]", "apple", argv[2]); + check_string("argv[3]", "banana", argv[3]); + check_string("argv[4]", "carrot", argv[4]); + check_string("argv[5]", "durian fruit", argv[5]); + check_string("argv[6]", "el burro", argv[6]); + check_null("argv[7]", argv[7]); + + for (int i = 0; i < countof(strs); ++i) + if (strs[i]) + free(strs[i]); + + unlink(tempname1); + free(tempname1); + unlink(tempname2); + free(tempname2); + unlink(tempname3); + free(tempname3); +} + +static int test_main(void) +{ + int err = 0; + + if (!err) err = test_add("test args_expand_at with one argument", + test_args_expand_at_1); + if (!err) err = test_add("test args_expand_at with many arguments", + test_args_expand_at_2); + if (!err) err = test_add("test args_expand_at with missing @ file", + test_args_expand_at_3); + if (!err) err = test_add("test args_expand_at with one @ file", + test_args_expand_at_4); + if (!err) err = test_add("test args_expand_at with two @ files", + test_args_expand_at_5); + if (!err) err = test_add("test args_expand_at with nested @ files", + test_args_expand_at_6); + + return err; +} diff --git a/cctools/libstuff_test/get_arch_from_host_test.c b/cctools/libstuff_test/get_arch_from_host_test.c new file mode 100644 index 00000000..0d549fd1 --- /dev/null +++ b/cctools/libstuff_test/get_arch_from_host_test.c @@ -0,0 +1,31 @@ +// +// get_arch_from_host_test.c +// libstuff_test +// +// Created by Michael Trent on 1/21/19. +// + +#include "test_main.h" + +#include "stuff/arch.h" + +static void test_get_arch_from_host(void) +{ + struct arch_flag family; + struct arch_flag specific; + + // it's difficult to test the active host without knowing what it is. + int res = get_arch_from_host(&family, &specific); + check_nonzero("get_arch_from_host result", res); + check_nonzero("family cputype", family.cputype); + check_nonzero("specific cputype", specific.cputype); +} + +static int test_main(void) +{ + int err = 0; + + if (!err) err = test_add("test get_arch_from_host", test_get_arch_from_host); + + return err; +} diff --git a/cctools/libstuff_test/guess_short_name_test.c b/cctools/libstuff_test/guess_short_name_test.c new file mode 100644 index 00000000..0b9c30b3 --- /dev/null +++ b/cctools/libstuff_test/guess_short_name_test.c @@ -0,0 +1,190 @@ +// +// guess_short_name_test.c +// libstuff_test +// +// Created by Michael Trent on 1/19/19. +// + +#include "test_main.h" + +#include +#include + +#include "stuff/bool.h" +#include "stuff/guess_short_name.h" + +static int check_name(const char* install_name, const char* desc, const char* a, + const char* b) +{ + int res = 0; + + if (a && b && 0 != strcmp(a, b)) { + test_printerr("%s %s should be %s: %s", install_name, desc, a, b); + res = 1; + } else if (a && !b) { + test_printerr("%s %s should be %s: %s", install_name, desc, a, "NULL"); + res = 1; + } else if (!a && b) { + test_printerr("%s %s should be %s: %s", install_name, desc, "NULL", b); + res = 1; + } + + return res; +} + +static int check_ebool(const char* install_name, const char* desc, enum bool a, + enum bool b) +{ + int res = 0; + + if (a != b) { + test_printerr("%s %s should be %s: %s", install_name, desc, + a == TRUE ? "TRUE" : "FALSE", + b == TRUE ? "TRUE" : "FALSE"); + res = 1; + } + + return res; +} + +static int check(const char* install_name, const char* short_name, + const char* suffix, enum bool isFramework) +{ + int res = 0; + + char iname[MAXPATHLEN]; + + strncpy(iname, install_name, MAXPATHLEN); + + enum bool isFwk; + char* suf; + char* shname = guess_short_name(iname, &isFwk, &suf); + + res |= check_name(install_name, "short name", short_name, shname); + res |= check_name(install_name, "suffix", suffix, suf); + res |= check_ebool(install_name, "is framework", isFramework, isFwk); + + if (shname) + free(shname); + if (suf) + free(suf); + + return res; +} + +static void test_guess_short_name(void) +{ + // library, no suffix, no version + check("/usr/lib/libFoo.dylib", "libFoo", NULL, FALSE); + check("libFoo.dylib", "libFoo", NULL, FALSE); + + // library, no suffix, version + check("/usr/lib/libFoo.A.dylib", "libFoo", NULL, FALSE); + check("libFoo.A.dylib", "libFoo", NULL, FALSE); + + // library, suffix, no version + check("/usr/lib/libFoo_profile.dylib", "libFoo", "_profile", FALSE); + check("/usr/lib/libFoo_debug.dylib", "libFoo", "_debug", FALSE); + check("libFoo_profile.dylib", "libFoo", "_profile", FALSE); + check("libFoo_debug.dylib", "libFoo", "_debug", FALSE); + + // library, suffix, version + check("/usr/lib/libFoo_profile.A.dylib", "libFoo", "_profile", FALSE); + check("/usr/lib/libFoo_debug.A.dylib", "libFoo", "_debug", FALSE); + check("/usr/lib/libATS.A_profile.dylib", "libATS", "_profile", FALSE); + check("libFoo_profile.A.dylib", "libFoo", "_profile", FALSE); + check("libFoo_debug.A.dylib", "libFoo", "_debug", FALSE); + check("libATS.A_profile.dylib", "libATS", "_profile", FALSE); + + // framework, no suffix, no version + check("Frameworks/Foo.framework/Foo", "Foo", NULL, TRUE); + check("Foo.framework/Foo", "Foo", NULL, TRUE); + + // framework, no suffix, versions + check("Frameworks/Foo.framework/Versions/A/Foo", "Foo", NULL, TRUE); + check("Foo.framework/Versions/A/Foo", "Foo", NULL, TRUE); + + // framework, suffix, no version + check("Frameworks/Foo.framework/Foo_profile", "Foo", "_profile", TRUE); + check("Foo.framework/Foo_profile", "Foo", "_profile", TRUE); + check("Frameworks/Foo.framework/Foo_debug", "Foo", "_debug", TRUE); + check("Foo.framework/Foo_debug", "Foo", "_debug", TRUE); + + // framework, suffix, version + check("Frameworks/Foo.framework/Versions/A/Foo_profile", + "Foo", "_profile", TRUE); + check("Foo.framework/Versions/A/Foo_profile", "Foo", "_profile", TRUE); + check("Frameworks/Versions/A/Foo.framework/Foo_debug", + "Foo", "_debug", TRUE); + check("Foo.framework/Versions/A/Foo_debug", "Foo", "_debug", TRUE); + + // qtx, no suffix, no version + check("/usr/lib/libFoo.qtx", "libFoo", NULL, FALSE); + check("libFoo.qtx", "libFoo", NULL, FALSE); + + // qtx, no suffix, version + check("/usr/lib/libFoo.A.qtx", "libFoo", NULL, FALSE); + check("libFoo.A.qtx", "libFoo", NULL, FALSE); + + // qtx files do not support suffixes + + // non-standard suffixes +// check("/usr/lib/libFoo_mdt.dylib", "libFoo", "_mdt", FALSE); +// check("libFoo_network.dylib", "libFoo", "_network", FALSE); +// check("/usr/lib/libFoo_network.A.dylib", "libFoo", "_network", FALSE); +// check("libFoo_network.A.dylib", "libFoo", "_network", FALSE); +// check("Frameworks/Foo.framework/Foo_network", "Foo", "_network", TRUE); +// check("Foo.framework/Foo_network", "Foo", "_network", TRUE); +// check("Frameworks/Versions/A/Foo.framework/Foo_network", +// "Foo", "_network", TRUE); +// check("Foo.framework/Versions/A/Foo_network", "Foo", "_network", TRUE); + check("/usr/lib/libFoo_mdt.dylib", "libFoo_mdt", NULL, FALSE); + check("libFoo_network.dylib", "libFoo_network", NULL, FALSE); + check("/usr/lib/libFoo_network.A.dylib", "libFoo_network", NULL, FALSE); + check("libFoo_network.A.dylib", "libFoo_network", NULL, FALSE); + check("Frameworks/Foo_network.framework/Foo_network", + "Foo_network", NULL, TRUE); + check("Foo_network.framework/Foo_network", "Foo_network", NULL, TRUE); + check("Frameworks/Versions/A/Foo_network.framework/Foo_network", + "Foo_network", NULL, TRUE); + check("Foo_network.framework/Versions/A/Foo_network", + "Foo_network", NULL, TRUE); + + // questionable actors + // configd_libSystem + check("/lib/system/libsystem_configuration.dylib", + "libsystem_configuration", NULL, FALSE); + check("/lib/system/libsystem_configuration_debug.dylib", + "libsystem_configuration", "_debug", FALSE); + check("/lib/system/libsystem_configuration_profile.dylib", + "libsystem_configuration", "_profile", FALSE); + // Sandbox_libs + check("/usr/lib/system/libsystem_sandbox.dylib", + "libsystem_sandbox", NULL, FALSE); + check("/usr/lib/system/libsystem_sandbox_debug.dylib", + "libsystem_sandbox", "_debug", FALSE); + check("/usr/lib/system/libsystem_sandbox_profile.dylib", + "libsystem_sandbox", "_profile", FALSE); + + // bad actors + // nanocom + check("/usr/local/lib/nanocom/libnanocom_bell.dylib", + "libnanocom_bell", NULL, FALSE); + check("/usr/local/lib/nanocom/libnanocom_fastsim.dylib", + "libnanocom_fastsim", NULL, FALSE); + check("/usr/local/lib/nanocom/libnanocom_login.dylib", + "libnanocom_login", NULL, FALSE); + + // mDNSResponder + check("/usr/lib/libdns_services.dylib", + "libdns_services", NULL, FALSE); + + // ngttp2 + check("/usr/lib/libapple_nghttp2.dylib", + "libapple_nghttp2", NULL, FALSE); +} + +static int test_main(void) +{ + return test_add("test guess_short_name", test_guess_short_name); +} diff --git a/cctools/libstuff_test/libstuff_test.c b/cctools/libstuff_test/libstuff_test.c new file mode 100644 index 00000000..bf8cd622 --- /dev/null +++ b/cctools/libstuff_test/libstuff_test.c @@ -0,0 +1,22 @@ +// +// main.cpp +// libstuff_test +// +// Created by Michael Trent on 1/19/19. +// + +#include "test.h" + +#include "stuff/errors.h" + +/* used by error routines as the name of this program */ +char *progname = NULL; + +int main(int argc, const char * argv[]) +{ + progname = (char*)argv[0]; + + // run the tests + return test_run(); +} + diff --git a/cctools/libstuff_test/null_test.c b/cctools/libstuff_test/null_test.c new file mode 100644 index 00000000..1631bdb6 --- /dev/null +++ b/cctools/libstuff_test/null_test.c @@ -0,0 +1,18 @@ +// +// null_test.cpp +// libstuff_test +// +// Created by Michael Trent on 1/19/19. +// + +#include "test_main.h" + +static void test_null(void) +{ + ; +} + +int test_main(void) +{ + return test_add("test harness initialization", test_null); +} diff --git a/cctools/libstuff_test/rnd_test.c b/cctools/libstuff_test/rnd_test.c new file mode 100644 index 00000000..b8a983cd --- /dev/null +++ b/cctools/libstuff_test/rnd_test.c @@ -0,0 +1,110 @@ +// +// rnd_test.c +// libstuff_test +// +// Created by Michael Trent on 5/25/19. +// + +#include "test_main.h" + +#include "stuff/rnd.h" + +static void test_rnd64(void) +{ + // weird illegal values + check_uint64("rnd(0, 0)", 0, rnd64(0,0)); + check_uint64("rnd(1, 0)", 0, rnd64(1,0)); + check_uint64("rnd(1, 1)", 1, rnd64(1,1)); + check_uint64("rnd(2, 1)", 2, rnd64(2,1)); + check_uint64("rnd(1, 3)", 1, rnd64(1,3)); + + // 4-byte alignment + check_uint64("rnd(0, 4)", 0, rnd64(0, 4)); + check_uint64("rnd(1, 4)", 4, rnd64(1, 4)); + check_uint64("rnd(2, 4)", 4, rnd64(2, 4)); + check_uint64("rnd(3, 4)", 4, rnd64(3, 4)); + check_uint64("rnd(4, 4)", 4, rnd64(4, 4)); + check_uint64("rnd(5, 4)", 8, rnd64(5, 4)); + + // 16-byte alignment + check_uint64("rnd(0, 16)", 0, rnd64(0, 16)); + check_uint64("rnd(1, 16)", 16, rnd64(1, 16)); + check_uint64("rnd(2, 16)", 16, rnd64(2, 16)); + check_uint64("rnd(3, 16)", 16, rnd64(3, 16)); + check_uint64("rnd(4, 16)", 16, rnd64(4, 16)); + check_uint64("rnd(5, 16)", 16, rnd64(5, 16)); + check_uint64("rnd(6, 16)", 16, rnd64(6, 16)); + check_uint64("rnd(7, 16)", 16, rnd64(7, 16)); + check_uint64("rnd(8, 16)", 16, rnd64(8, 16)); + check_uint64("rnd(9, 16)", 16, rnd64(9, 16)); + check_uint64("rnd(10, 16)", 16, rnd64(10, 16)); + check_uint64("rnd(11, 16)", 16, rnd64(11, 16)); + check_uint64("rnd(12, 16)", 16, rnd64(12, 16)); + check_uint64("rnd(13, 16)", 16, rnd64(13, 16)); + check_uint64("rnd(14, 16)", 16, rnd64(14, 16)); + check_uint64("rnd(15, 16)", 16, rnd64(15, 16)); + check_uint64("rnd(16, 16)", 16, rnd64(16, 16)); + check_uint64("rnd(17, 16)", 32, rnd64(17, 16)); + + // large values around 32-bits + check_uint64("rnd(0xFFFFFFFF, 16)", 0x100000000, rnd64(0xFFFFFFFF, 16)); + check_uint64("rnd(0x100000000, 16)", 0x100000000, rnd64(0x100000000, 16)); + check_uint64("rnd(0x100000001, 16)", 0x100000010, rnd64(0x100000001, 16)); + check_uint64("rnd(0x1000000F1, 16)", 0x100000100, rnd64(0x1000000F1, 16)); + + // the bit-buster + check_uint64("rnd(0xFFFFFFFFFFFFFFF1, 16)", 0, rnd64(0xFFFFFFFFFFFFFFF1, 16)); + check_uint64("rnd(0xFFFFFFFFFFFFFFFF, 16)", 0, rnd64(0xFFFFFFFFFFFFFFFF, 16)); +} + +static void test_rnd32(void) +{ + // weird illegal values + check_uint32("rnd(0, 0)", 0, rnd32(0,0)); + check_uint32("rnd(1, 0)", 0, rnd32(1,0)); + check_uint32("rnd(1, 1)", 1, rnd32(1,1)); + check_uint32("rnd(2, 1)", 2, rnd32(2,1)); + check_uint32("rnd(1, 3)", 1, rnd32(1,3)); + + // 4-byte alignment + check_uint32("rnd(0, 4)", 0, rnd32(0, 4)); + check_uint32("rnd(1, 4)", 4, rnd32(1, 4)); + check_uint32("rnd(2, 4)", 4, rnd32(2, 4)); + check_uint32("rnd(3, 4)", 4, rnd32(3, 4)); + check_uint32("rnd(4, 4)", 4, rnd32(4, 4)); + check_uint32("rnd(5, 4)", 8, rnd32(5, 4)); + + // 16-byte alignment + check_uint32("rnd(0, 16)", 0, rnd32(0, 16)); + check_uint32("rnd(1, 16)", 16, rnd32(1, 16)); + check_uint32("rnd(2, 16)", 16, rnd32(2, 16)); + check_uint32("rnd(3, 16)", 16, rnd32(3, 16)); + check_uint32("rnd(4, 16)", 16, rnd32(4, 16)); + check_uint32("rnd(5, 16)", 16, rnd32(5, 16)); + check_uint32("rnd(6, 16)", 16, rnd32(6, 16)); + check_uint32("rnd(7, 16)", 16, rnd32(7, 16)); + check_uint32("rnd(8, 16)", 16, rnd32(8, 16)); + check_uint32("rnd(9, 16)", 16, rnd32(9, 16)); + check_uint32("rnd(10, 16)", 16, rnd32(10, 16)); + check_uint32("rnd(11, 16)", 16, rnd32(11, 16)); + check_uint32("rnd(12, 16)", 16, rnd32(12, 16)); + check_uint32("rnd(13, 16)", 16, rnd32(13, 16)); + check_uint32("rnd(14, 16)", 16, rnd32(14, 16)); + check_uint32("rnd(15, 16)", 16, rnd32(15, 16)); + check_uint32("rnd(16, 16)", 16, rnd32(16, 16)); + check_uint32("rnd(17, 16)", 32, rnd32(17, 16)); + + // large values around 32-bits + check_uint32("rnd(0xFFFFFFF1, 16)", 0, rnd32(0xFFFFFFF1, 16)); + check_uint32("rnd(0xFFFFFFFF, 16)", 0, rnd32(0xFFFFFFFF, 16)); +} + +static int test_main(void) +{ + int err = 0; + + if (!err) err = test_add("test rnd64", test_rnd64); + if (!err) err = test_add("test rnd32", test_rnd32); + + return err; +} diff --git a/cctools/libstuff_test/test.c b/cctools/libstuff_test/test.c new file mode 100644 index 00000000..474fd975 --- /dev/null +++ b/cctools/libstuff_test/test.c @@ -0,0 +1,462 @@ +// +// test.cpp +// libstuff_test +// +// Created by Michael Trent on 1/19/19. +// + +#include "test.h" + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +#include +#endif + +void test_breakpoint(void) +{ + +} + +typedef enum { + TEST_PASSED = 0, + TEST_FAILED, + TEST_ABORT, +} test_result_t; + +static int s_print_called = 0; +static test_result_t s_test_result = TEST_PASSED; + +static struct test *s_tests = NULL; +static uint32_t s_ntests = 0; + +struct test_init { + int order; + test_initializer_func initializer; +}; + +static struct test_init* s_inits; +static uint32_t s_ninits; + +static char* s_prefix; + +int test_register_initializer(int order, test_initializer_func initializer) +{ + if (s_ntests < 0xFFFFFFFF) + { + s_inits = (struct test_init*)reallocf(s_inits, sizeof(*s_inits) * + (s_ninits + 1)); + if (s_inits) + { + s_inits[s_ninits].order = order; + s_inits[s_ninits].initializer = initializer; + s_ninits++; + } + else + { + fprintf(stderr, "error: reallocf %s\n", strerror(errno)); + assert(s_inits); + } + } + else + { + fprintf(stderr, "error: maximum number of test initializers reached\n"); + assert(0); + } + + return 0; +} + +static int test_init_sort(const void* a, const void* b) +{ + struct test_init* aa = (struct test_init*)a; + struct test_init* bb = (struct test_init*)b; + return aa->order - bb->order; +} + +int test_add(const char* name, test_func test) +{ + int result = TEST_PASSED; + + if (s_ntests < 0xFFFFFFFF) + { + s_tests = (struct test *)reallocf(s_tests, sizeof(*s_tests) * + (s_ntests + 1)); + if (s_tests) + { + s_tests[s_ntests].name = name; + s_tests[s_ntests].testfunc = test; + s_ntests += 1; + } + else + { + fprintf(stderr, "error: reallocf %s\n", strerror(errno)); + result = TEST_ABORT; + } + } + else + { + fprintf(stderr, "error: maximum number of tests reached\n"); + result = TEST_ABORT; + } + + return result; +} + +int test_run(void) +{ + // if we've registered c++ initializers, sort them and run them. + if (s_ninits) { + qsort(s_inits, s_ninits, sizeof(*s_inits), test_init_sort); + for (uint32_t i = 0; i < s_ninits; ++i) + { + int err = s_inits[i].initializer(); + if (err) return err; + } + } + return test_run_tests(s_tests, s_ntests); +} + +int test_run_tests(struct test tests[], uint32_t ntests) +{ + test_result_t run_result = TEST_PASSED; + int passing = 0; + + printf("testing:\n"); + + for (uint32_t i = 0; i < ntests; ++i) + { + s_test_result = TEST_PASSED; + s_print_called = 0; + + check_set_prefix(NULL); + + printf("\t%s ... ", tests[i].name); + +#ifdef __cplusplus + try { + tests[i].testfunc(); + } + catch (int err) { + test_printerr("uncaught exception: int %d (might be %s)", err, + strerror(err)); + } + catch (const char* s) { + test_printerr("uncaught exception: %s", s); + } + catch (std::string s) { + test_printerr("uncaught exception: %s", s.c_str()); + } + catch (...) { + test_printerr("uncaught exception!"); + } +#else + tests[i].testfunc(); +#endif + if (s_print_called) + printf("\n\t... "); + + if (s_test_result == TEST_PASSED) + { + printf("passed\n"); + passing += 1; + } + else if (s_test_result == TEST_ABORT) + { + run_result = TEST_ABORT; + printf("aborted!\n"); + break; + } + else + { + run_result = TEST_FAILED; + printf("failed!\n"); + } + } + + printf("tests completed (%d/%d passing)\n", passing, ntests); + + check_set_prefix(NULL); + + return run_result; +} + +void test_abort(void) +{ + s_test_result = TEST_ABORT; +} + +static void test_vprint(const char * __restrict fmt, va_list args) +{ + assert(fmt); + + s_print_called = 1; + + size_t len = strlen(fmt); + char* format = (char*)calloc(1, len+4); + if (format) + { + sprintf(format, "\n\t\t%s", fmt); + vprintf(format, args); + free(format); + } +} + +void test_printinfo(const char * __restrict format, ...) +{ + assert(format); + + va_list args; + va_start(args, format); + + test_vprint(format, args); + + va_end(args); +} + +void test_printerr(const char * __restrict format, ...) +{ + assert(format); + + test_breakpoint(); + + if (s_test_result != TEST_ABORT) + s_test_result = TEST_FAILED; + + va_list args; + va_start(args, format); + + test_vprint(format, args); + + va_end(args); +} + +void test_vprintinfo(const char * __restrict fmt, va_list args) +{ + test_vprint(fmt, args); +} + +void test_vprinterr(const char * __restrict fmt, va_list args) +{ + if (s_test_result != TEST_ABORT) + s_test_result = TEST_FAILED; + + test_vprint(fmt, args); +} + +void check_set_prefix(const char* fmt, ...) +{ + va_list ap; + size_t len; + + if (s_prefix) { + free(s_prefix); + s_prefix = NULL; + } + + if (fmt) { + va_start(ap, fmt); + len = vsnprintf(NULL, 0, fmt, ap); + va_end(ap); + + // reserve space for an extra ' ' between the prefix and the check name + s_prefix = malloc(len + 2); + if (s_prefix) { + va_start(ap, fmt); + len = vsnprintf(s_prefix, len + 1, fmt, ap); + va_end(ap); + + // add the space + s_prefix[len++] = ' '; + s_prefix[len++] = 0; + } + } +} + +int check_bool (const char* name, bool orig, bool copy) +{ + int result = 0; + if (orig != copy) + { + test_printerr("%s%s should be %d: %d", s_prefix ? s_prefix : "", + name, orig, copy); + result = 1; + } + return result; +} + +int check_uint32(const char* name, uint32_t orig, uint32_t copy) +{ + int result = 0; + if (orig != copy) + { + test_printerr("%s%s should be %u: %u", s_prefix ? s_prefix : "", + name, orig, copy); + result = 1; + } + return result; +} + +int check_uint64(const char* name, uint64_t orig, uint64_t copy) +{ + int result = 0; + if (orig != copy) + { + test_printerr("%s%s should be %llu: %llu", s_prefix ? s_prefix : "", + name, orig, copy); + result = 1; + } + return result; +} + +int check_pointer(const char* name, const void* orig, const void* copy) +{ + int result = 0; + if (orig != copy) + { + test_printerr("%s%s should be 0x%p: 0x%p", s_prefix ? s_prefix : "", + name, orig, copy); + result = 1; + } + return result; +} + +int check_string(const char* name, const char* orig, const char* copy) +{ + int result = 0; + if (NULL != orig && NULL == copy) + { + test_printerr("missing %s%s should be '%s'", s_prefix ? s_prefix : "", + name, orig); + result = 1; + } + else if (NULL == orig && NULL != copy) + { + test_printerr("%s%s should be unset: '%s'", s_prefix ? s_prefix : "", + name, copy); + result = 1; + } + else if (NULL != orig && NULL != copy && strcmp(copy, orig)) + { + test_printerr("%s%s should be '%s': '%s'", s_prefix ? s_prefix : "", + name, orig, copy); + result = 1; + } + return result; +} + +int check_memory(const char* name, const void* vorig, const void* vcopy, + uint64_t size) +{ + const uint8_t* orig = (const uint8_t*)vorig; + const uint8_t* copy = (const uint8_t*)vcopy; + + int result = 0; + if (NULL == orig) + { + test_printerr("%s%s is missing input buffer: orig", + s_prefix ? s_prefix : "", name); + result = 1; + } + else if (NULL == copy) + { + test_printerr("%s%s is missing input buffer: copy", + s_prefix ? s_prefix : "", name); + result = 1; + } + else + { + for (uint64_t i = 0; i < size; ++i) + { + if (orig[i] != copy[i]) + { + test_printerr("%s%s differ at offset %llu[0x%llx]: 0x%x != 0x%x", + s_prefix ? s_prefix : "", name, i, i, orig[i], copy[i]); + result = 1; + break; + } + } + } + return result; +} + +int check_zerofill(const char* name, const unsigned char* buf, size_t size) +{ + int result = 0; + + for (int i = 0; i < size; ++i) + { + if (buf[i]) + { + test_printerr("%s%s is not zero filled", s_prefix ? s_prefix : "", name); + result = 1; + break; + } + } + + return result; +} + +int check_null(const char* name, void* copy) +{ + int result = 0; + if (copy) + { + test_printerr("%s%s should be NULL: 0x%p", s_prefix ? s_prefix : "", + name, copy); + result = 1; + } + return result; +} + +int check_nonnull(const char* name, void* copy) +{ + int result = 0; + if (!copy) + { + test_printerr("%s%s is NULL", s_prefix ? s_prefix : "", name); + result = 1; + } + return result; +} + +int check_count(const char* name, uint32_t orig, uint32_t copy) +{ + int result = 0; + if (orig != copy) + { + test_printerr("number of %s%s should be %d: %d", s_prefix ? s_prefix : "", + name, orig, copy); + result = 1; + } + return result; +} +/* +int check_zero(const char* name, uint32_t copy) +{ + int result = 0; + if (copy) + { + test_printerr("%s should be 0: %d", name, copy); + result = 1; + } + return result; +} + */ + +int check_nonzero(const char* name, uint32_t copy) +{ + int result = 0; + if (!copy) + { + test_printerr("%s%s is 0", s_prefix ? s_prefix : "", name); + result = 1; + } + return result; +} + diff --git a/cctools/libstuff_test/test.h b/cctools/libstuff_test/test.h new file mode 100644 index 00000000..291a6b16 --- /dev/null +++ b/cctools/libstuff_test/test.h @@ -0,0 +1,87 @@ +// +// test.h +// libstuff_test +// +// Created by Michael Trent on 1/19/19. +// +// test.h defines two name spaces: +// +// test_* +// functions beginning with test_* are expected to match the test_func +// type declaration. tests are assumed to pass unless they call one of: +// test_printerr +// test_vprinterr +// test_abort +// specific test implementations will provide their own test_* functions. +// +// check_* +// check functions are convenience front ends to test_printerr that unify +// common patterns, such as checking array counts, strings, and other data +// types. specific tests may provide public check_* functions. generally, +// these will implement a type similar to: +// int check_type(const char* label, int orig, int copy); +// where label is a human-readable label describing the comparison (e.g., +// "item name"), orig is the expected value, and copy is the actual value. +// check functions return 0 on success and non-zero on failure so that +// callers can customize their logic, such as bailing early. +// + +#ifndef test_h +#define test_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +typedef int (*test_initializer_func)(void); +int test_register_initializer(int order, test_initializer_func initializer); + +typedef void (*test_func)(void); + +struct test { + const char* name; + test_func testfunc; +}; + +#define TEST_ENTRY(NAME, FUNC) { NAME, FUNC } + +int test_add(const char* name, test_func test); + +int test_run(void); +int test_run_tests(struct test tests[], uint32_t ntests); + +void test_abort(void); +void test_printinfo(const char * __restrict format, ...); +void test_printerr(const char * __restrict format, ...); + +void test_vprintinfo(const char * __restrict format, va_list ap); +void test_vprinterr(const char * __restrict format, va_list ap); + +void check_set_prefix(const char* fmt, ...); + +int check_bool (const char* name, bool orig, bool copy); +int check_uint32(const char* name, uint32_t orig, uint32_t copy); +int check_uint64(const char* name, uint64_t orig, uint64_t copy); +int check_pointer(const char* name, const void* orig, const void* copy); + +int check_string(const char* name, const char* orig, const char* copy); +int check_memory(const char* name, const void* orig, const void* copy, + uint64_t size); +int check_zerofill(const char* name, const unsigned char* buf, size_t size); + +int check_null(const char* name, void* copy); +int check_nonnull(const char* name, void* copy); +int check_count(const char* name, uint32_t orig, uint32_t copy); +//int check_zero(const char* name, uint32_t copy); +int check_nonzero(const char* name, uint32_t copy); + +#ifdef __cplusplus +} +#endif + +#endif /* test_h */ diff --git a/cctools/libstuff_test/test_main.h b/cctools/libstuff_test/test_main.h new file mode 100644 index 00000000..07bad91e --- /dev/null +++ b/cctools/libstuff_test/test_main.h @@ -0,0 +1,42 @@ +// +// test_main.h +// cctools +// +// Created by Michael Trent on 5/25/19. +// +// When creating a new test, include this header, call the TEST_INTIALIZE +// macro, then define a function test_main() like so: +// +// static int test_main(void) +// { +// int err = 0; +// if (!err) err = test_add("some test", test_some_test); +// return err; +// } +// +// individal tests take and return void, and call check_* or test_* functions +// to report failure status. + +#ifndef test_case_h +#define test_case_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include "test.h" + +#define TEST_INITIALIZE \ +static int test_main(void);\ +__attribute__((constructor)) static void init(void)\ +{\ +test_register_initializer(0, test_main);\ +}\ + +TEST_INITIALIZE + +#ifdef __cplusplus +} +#endif + +#endif /* test_case_h */ diff --git a/cctools/libstuff_test/test_util.c b/cctools/libstuff_test/test_util.c new file mode 100644 index 00000000..088fbf3b --- /dev/null +++ b/cctools/libstuff_test/test_util.c @@ -0,0 +1,54 @@ +// +// test_util.c +// libstuff_test +// +// Created by Michael Trent on 5/31/19. +// + +#include "test_util.h" + +#include +#include +#include +#include +#include + +int test_write_tmp_data(const void* data, size_t size, char** name_p) +{ + if (!data || !name_p) { + errno = EINVAL; + return -1; + } + + char* name = strdup("/tmp/libstuff_test.XXXXXX"); + int fd = mkstemp(name); + if (-1 == fd) { + fprintf(stderr, "error: cannot make temporary file: %s\n", + strerror(errno)); + free(name); + return -1; + } + + const unsigned char* uchars = (const unsigned char*)data; + while (size) { + const size_t limit = 0x7FFFFFFF; + size_t towrite = size < limit ? size : limit; + ssize_t wrote = write(fd, uchars, towrite); + if (-1 == wrote) { + fprintf(stderr, "error: cannot write to file %s: %s\n", name, + strerror(errno)); + free(name); + return -1; + } + else if (0 == wrote) { + break; + } + else { + size -= wrote; + uchars += wrote; + } + } + + *name_p = name; + return 0; +} diff --git a/cctools/libstuff_test/test_util.h b/cctools/libstuff_test/test_util.h new file mode 100644 index 00000000..cc910a01 --- /dev/null +++ b/cctools/libstuff_test/test_util.h @@ -0,0 +1,19 @@ +// +// test_util.h +// libstuff_test +// +// Created by Michael Trent on 5/31/19. +// + +#ifndef test_util_h +#define test_util_h + +#include + +// test_write_tmp_data +// write data of size to a file in /tmp. The path to the file will be returned +// in *name, which will need to be deallocated via free(). Returns 0 on success +// or -1 on error. +int test_write_tmp_data(const void* data, size_t size, char** name); + +#endif /* test_util_h */ diff --git a/cctools/libstuff_test/version_number_test.c b/cctools/libstuff_test/version_number_test.c new file mode 100644 index 00000000..273edb01 --- /dev/null +++ b/cctools/libstuff_test/version_number_test.c @@ -0,0 +1,82 @@ +// +// version_number_test.c +// libstuff_test +// +// Created by Michael Trent on 5/14/19. +// + +#include "test_main.h" + +#include "stuff/bool.h" +#include "stuff/version_number.h" + +#include +#include +#include +#include + +static void check_version(const char* version, enum bool success, +uint32_t expected) +{ + check_set_prefix("get_version_number %s", version); + + uint32_t value; + enum bool result = get_version_number("", version, &value); + + check_bool("result", success, result); + check_uint32("version", expected, value); +} + +static void test_get_version_number(void) +{ + // silence stderr, because it will cause the test to fail upstream. + // this code needs to be refactored. And this test will help us do that = + // some day. + FILE* errcpy = stderr; + stderr = fopen("/dev/null", "w"); + + // You'd think passing a empty string to get_version_number would be an + // error condition, but it is not. It means: 0. + check_version("", TRUE, 0x0); + check_version("0", TRUE, 0x0); + check_version("0.", FALSE, 0x0); + check_version("0.0", TRUE, 0x0); + check_version("0.0.", FALSE, 0x0); + check_version("0.0.0", TRUE, 0x0); + // You'd think if passing "0." was an error that passing "0.0.0." would also + // be an error, but it is not. Everything past the 3rd number is ignored. + check_version("0.0.0.", TRUE, 0x0); + check_version("0.0.0.0", TRUE, 0x0); + // This probably qualifies as undefined behavior + check_version("0.0.0.9999999happybirthday", TRUE, 0x0); + + check_version("1", TRUE, 0x00010000); + check_version("1.2", TRUE, 0x00010200); + check_version("1.2.4", TRUE, 0x00010204); + + check_version("65535.255.255", TRUE, 0xFFFFFFFF); + check_version("65536.255.255", FALSE, 0); + check_version("65535.256.255", FALSE, 0); + check_version("65535.255.256", FALSE, 0); + check_version("-1", FALSE, 0); + check_version("0.-1", FALSE, 0); + check_version("0.0.-1", FALSE, 0); + check_version("0.-1000", FALSE, 0); + + check_version("a", FALSE, 0); + check_version("0.a", FALSE, 0); + check_version("0.0.a", FALSE, 0); + + // restore stderr + fclose(stderr); + stderr = errcpy; +} + +static int test_main(void) +{ + int err = 0; + + if (!err) err = test_add("test get_version_number", test_get_version_number); + + return err; +} diff --git a/cctools/man/Mach-O.5 b/cctools/man/Mach-O.5 index 78089841..149c6c33 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 index 1f754968..e6a44322 100644 --- a/cctools/man/Makefile +++ b/cctools/man/Makefile @@ -20,7 +20,7 @@ MAN3 = kld.3 arch.3 get_end.3 end.3 getsectbyname.3 \ MAN5 = Mach-O.5 a.out.5 ranlib.5 stab.5 -MANL = indr.1 checksyms.1 seg_addr_table.1 check_dylib.1 +MANL = indr.1 checksyms.1 seg_addr_table.1 check_dylib.1 mtor.1 EFI1 = mtoc.1 @@ -31,7 +31,7 @@ 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 +LOCMANDIR = /usr/local/share/man EFIMANDIR = /usr/local/efi/share/man DSTDIRS_MAN1 = $(DSTROOT)$(MANDIR)/man1 DSTDIRS = $(DSTROOT)$(MANDIR)/man3 \ diff --git a/cctools/man/NSModule.3 b/cctools/man/NSModule.3 index ab5a5bc7..50884550 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 c2359609..65a6b272 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 aeddd1c3..749e424b 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 4c230fbc..74a2496b 100644 --- a/cctools/man/arch.3 +++ b/cctools/man/arch.3 @@ -1,10 +1,11 @@ -.Dd March 11, 2016 +.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,6 +19,8 @@ .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 * @@ -56,6 +59,8 @@ The currently known architectures are: .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 @@ -107,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 @@ -118,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 diff --git a/cctools/man/as.1 b/cctools/man/as.1 index d3eb31f9..d595e7b2 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 f50c8004..f11ea2eb 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 95acd509..bd62a19b 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 78bdea08..6a335f32 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 881f4bab..fcfca23c 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 7e978bd2..2a016a61 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 8af3ae25..6eb10d6d 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 76ff27dc..1a26e7e1 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 d5bc8367..e2a06563 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 8e183019..be10c126 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/gprof.1 b/cctools/man/gprof.1 new file mode 100644 index 00000000..01ca8d45 --- /dev/null +++ b/cctools/man/gprof.1 @@ -0,0 +1,284 @@ +.\" $OpenBSD: gprof.1,v 1.4 1996/10/15 23:55:56 deraadt Exp $ +.\" $NetBSD: gprof.1,v 1.6 1995/11/21 22:24:55 jtc Exp $ +.\" +.\" Copyright (c) 1983, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" 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. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. +.\" +.\" @(#)gprof.1 8.1 (Berkeley) 6/6/93 +.\" +.TH GPROF 1 "July 28, 2005" "Apple Computer, Inc." +.SH NAME +gprof \- display call graph profile data +.SH SYNOPSIS +.B gprof +[ \fIoptions\fR ] [ a.out [ gmon.out ... ] ] +.SH DESCRIPTION +.I gprof +produces an execution profile of a C, Pascal, or Fortran77 program. +The effect of called routines is incorporated in the profile of each caller. +The profile data is taken from the call graph profile file +.RI ( gmon.out +by default), which is created by programs +compiled with the +.B \-pg +option of +.IR cc , +.IR pc , +and +.IR f77 . +The symbol table in the +named object file +.RI ( a.out +by default) +is read and correlated with the +call graph profile file. +If more than one profile file is specified, +the +.I gprof +output shows the sum of the profile information in the given profile files. +.PP +First, a flat profile is given. +This listing gives the total execution times +and call counts for each of the functions +in the program, sorted by decreasing time. +.PP +Next, these times are propagated along the edges of the call graph. +Cycles are discovered, and calls into a cycle are made to share the time +of the cycle. +A second listing shows the functions +sorted according to the time they represent +including the time of their call graph descendents. +Below each function entry is shown its (direct) call graph children, +and how their times are propagated to this function. +A similar display above the function shows how this function's time and the +time of its descendents is propagated to its (direct) call graph parents. +.PP +Cycles are also shown, with an entry for the cycle as a whole as well as a +listing of the members of the cycle and their contributions to the +time and call counts of the cycle. +.SH "UNIVERSAL FILE SUPPORT" +.I gprof +accepts a ``universal'' file for the +.I a.out +file, using the host architecture from the file. (It is an error if the +``universal'' file does not contain the host architecture.) +.SH OPTIONS +.TP +The following options are available: +.TP +.B \-a +suppresses the displaying of statically declared functions. +If this option is given, all relevant information about the static function +(such as time samples, calls to other functions, calls from other functions) +belongs to the function loaded just before the static function in the +.I a.out +file. +.TP +.B \-b +suppresses the displaying of a description of each field in the profile. +.TP +.B \-c +the static call graph of the program is discovered by a heuristic +which examines the text space of the object file. +Static-only parents or children are indicated +with call counts of 0. (The +.B \-c +option is currently not supported.) +.TP +.BI \-e " name" +suppresses the displaying of the graph profile entry for routine +.I name +and all its descendants +(unless they have other ancestors that aren't suppressed). +More than one +.B \-e +option may be given. +Only one +.I name +may be given with each +.B \-e +option. +.TP +.BI \-E " name" +suppresses the displaying of the graph profile entry for routine +.I name +(and its descendants) as +.BR \-e , +above, and also excludes the time spent in +.I name +(and its descendants) from the total and percentage time computations. +(For example, +.B \-E +.I mcount +and all of the other +.IR monitor (3) +routines are excluded by default.) +.TP +.BI \-f " name" +displays the graph profile entry of only the specified routine +.I name +and its descendants. +More than one +.B \-f +option may be given. +Only one +.I name +may be given with each +.B \-f +option. +.TP +.BI \-F " name" +displays the graph profile entry of only the routine +.I name +and its descendants (as +.BR \-f, +above) and also uses only the times of the displayed routines +in total time and percentage computations. +More than one +.B \-F +option may be given. +Only one +.I name +may be given with each +.B \-F +option. +The +.B \-F +option +overrides +the +.B \-E +option. +.TP +.B \-s +a profile file +.I gmon.sum +is produced which represents +the sum of the profile information in all the specified profile files. +This summary profile file may be given to subsequent +executions of gprof (probably also with a +.BR \-s ) +to accumulate profile data across several runs of an +.I a.out +file. +.TP +.B \-S +produces four order files suitable as input to +.IR ld (1): +.I gmon.order +is an ordering based on a closest is best algorithm, +.I callf.order +is based on call frequency, +.I callo.order +is based on call order and +.I time.order +is based on time. +The order files contain only those functions which were called or +sampled (including spontaneous functions). For library functions to +appear correctly in the order file, a +.I whatsloaded +file produced by +.IR ld (1) +should exist in the working directory. Filenames in the order file +will be missing for: files compiled without the +.BR \-g +option, assembly files, and stripped executables. +This option does not work with executables that have already been scattered. +The +.I gmon.order +file can take a long time to produce and can be suppressed with the +.B \-x +option. +.TP +.B \-z +displays routines which have zero usage (as indicated by call counts +and accumulated time). +This is useful in conjunction with the +.B \-c +option for discovering which routines were never called. +.SH FILES +.ta 1.5i +a.out +the namelist and text space. +.br +gmon.out +dynamic call graph and profile. +.br +gmon.sum +summarized dynamic call graph and profile. +.br +gmon.order +ordering based on closest is best algorithm. +.br +callf.order +ordering based on call frequency. +.br +callo.order +ordering based on call order. +.br +time.order +ordering based on time. +.SH "SEE ALSO" +monitor(3), profil(2), cc(1) +.br +dyld(1) and the DYLD_IMAGE_SUFFIX environment variable +.br +``gprof: A Call Graph Execution Profiler'', by +Graham, S.L., Kessler, P.B., McKusick, M.K.; +.IR "Proceedings of the SIGPLAN '82 Symposium on Compiler Construction" , +SIGPLAN Notices, Vol. 17, No. 6, pp. 120-126, June 1982. +.SH BUGS +Beware of quantization errors. +The granularity of the sampling is shown, but remains +statistical at best. +We assume that the time for each execution of a function +can be expressed by the total time for the function divided +by the number of times the function is called. +Thus the time propagated along the call graph arcs to parents of that +function is directly proportional to the number of times that +arc is traversed. +.PP +Parents which are not themselves profiled will have the time of +their profiled children propagated to them, but they will appear +to be spontaneously invoked in the call graph listing, and will +not have their time propagated further. +Similarly, signal catchers, even though profiled, will appear +to be spontaneous (although for more obscure reasons). +Any profiled children of signal catchers should have their times +propagated properly, unless the signal catcher was invoked during +the execution of the profiling routine, in which case all is lost. +.PP +The profiled program must call +.IR exit (2) +or return normally for the profiling information to be saved +in the +.B gmon.out +file. diff --git a/cctools/man/kld.3 b/cctools/man/kld.3 index bc3fd872..8d2300a7 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/ld_classic.1 b/cctools/man/ld_classic.1 new file mode 100644 index 00000000..6a223f72 --- /dev/null +++ b/cctools/man/ld_classic.1 @@ -0,0 +1,1823 @@ +.TH LD_CLASSIC 1 "August 4, 2006" "Apple Computer, Inc." +.SH NAME +ld_classic \- The old Mach object file link editor +.SH SYNOPSIS +.B ld_classic +[ +.I "option \&..." +] [ +.I "file \&..." +] +.SH DESCRIPTION +The +.I ld_classic +command combines several Mach-O (Mach object) files into one by combining like sections +in like segments from all the object files, resolving external references, and +searching libraries. In the simplest case several object +.I files +are given, and +.I ld_classic +combines them, producing an object file which can either be executed or +become the input for a further +.I ld_classic +run. (In the latter case, the +.B \-r +option must be given to preserve the relocation information.) Unless an output +file is specified, +.I ld_classic +produces a file named +.BR a.out . +This file is made executable only if no errors occurred during the link editing +and there are no undefined symbols. +.SH "UNIVERSAL FILE SUPPORT" +The link editor accepts ``universal'' (multiple-architecture) input files, but +always creates a ``thin'' (single-architecture), standard Mach-O output file. +The architecture is specified using the +.B \-arch +.I " arch_type" +option. If this option is not used, +.IR ld_classic (1) +attempts to determine the output architecture by examining the first object +file encountered on the command line. If it is a ``thin'' +file, its architecture determines that of the output file. If the first input +file is a ``universal'' file, the ``best'' architecture for the host is used. +(See the explanation of the +.B \-arch +option, below.) +.PP +The compiler driver +.IR cc (1) +handles creating universal executables by calling +.IR ld_classic (1) +multiple times and using +.IR lipo (1) +to create a ``universal'' file from the results of the +.IR ld_classic (1) +executions. +.SH "OUTPUT FILE LAYOUT" +.PP +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. All zero fill sections will appear +after all non-zero fill sections in their segments. +.PP +Sections created from files with the +.B \-sectcreate +option will appear in the output file last. Section names for sections created +from files are not allowed to overlap with a section name in the same segment +as a section coming from an object file. Sections created from files may be in +a segment which has sections from object files and if so will be loaded at the +end of the non-zero fill sections for that segment. +.PP +If the option +.B \-seglinkedit +is specified, the segment it creates is the last segment in the output file. +.PP +The address of each segment can be specified with +.B \-segaddr, +which takes the segment's name as an argument. +The address of the first segment can alternatively be specified using +.B \-seg1addr, +in which case a segment name is not used. +Segments that do not have a specified +address will be assigned addresses in the order in which they appear +in the output file. A segment's address will be assigned +based on the ending address of the previous segment. +If the address of the +first segment has not been specified by name, +its assigned address will be +the specified (via +.BR \-seg1addr ) +or default first segment address. +If neither flag is used to specify the first segment's address, its +default address is zero +for all formats except the demand-paged executable format +.SM (MH_EXECUTE), +in which case the default first address is the value of the segment alignment. +.PP +For demand-paged executable format +.SM (MH_EXECUTE) +output files, +if none of the segments' addresses covers address zero through +the value of the segment alignment, a segment with no access protection +will be created to cover those addresses. This segment, named +.SM "``_\|_PAGEZERO''," +is created so that any attempt to dereference a NULL pointer will cause a +memory exception. +.PP +The entry point of the output file is the beginning of +the first section in the first segment (unless the +.B \-e +option is specified). +.SH STATIC ARCHIVE LIBRARIES +.PP +.I ld_classic +supports two types of libraries: static archive libraries and dynamic shared +libraries. Searching for undefined symbols is performed differently for dynamic +shared libraries than it is for static archive libraries. The searching of +dynamic shared libraries is described later. +.PP +When a static archive library is specified as an argument to +.IR ld_classic , +it is searched exactly once, at the +point it is encountered in the argument list. Only those members defining an unresolved external +reference, as defined by the static archive library's table of contents, +are loaded. To produce the table of contents, all static archive libraries must be processed by +.IR ranlib (1). +.PP +Generally, a static archive library does not have multiple members that define +the same symbol. For these types of libraries, the order of the members is not important, so +the table of contents can be sorted for faster link editing using the +.B \-s +option to +.IR ranlib (1). +The first member +of the static archive library is named +.SM "``\_\^\_.SYMDEF SORTED''," +which is understood to be a sorted table of contents. +.PP +If the static archive library does have multiple members that define +the same symbol, the table of contents that +.IR ranlib (1) +produces can't be sorted. Instead, it follows the order in which the members +appear in the static archive library. The link editor searches the table of +contents iteratively, loading members until no further references are +satisfied. In the unsorted case, the first member of the static archive +library is named +.SM "``\_\^\_.SYMDEF''," +which is understood to be a table of contents in +the order of the archive members. +.PP +Static archive library members can also be loaded in response to +the +.B \-ObjC +and +.B \-all_load +flags. See their descriptions below. + +.SH DYNAMIC SHARED LIBRARIES +.PP +When a dynamic shared library or an object file that was linked against a +dynamic shared library is specified as an argument to +.IR ld_classic , +that library is placed in the dynamic shared library search list. The order of +the search list is always the same order the libraries were encountered on the +command line. When linking -flat_namespace, all dynamic libraries that the +dynamic libraries are dependent upon are added to the end of the search list. +.PP +Once the search list is constructed, the static link editor checks for undefined +symbols by simulating the way the dynamic linker will search for undefined +symbols at runtime. For each undefined symbol, the static link editor searches +each library in the search list until it finds a module that defines the symbol. +With each undefined symbol, the search starts with the first library in the +list. This is different than for static archive libraries, where each library +is searched exactly once for all undefined symbols. +.PP +The static link editor simulates dynamic linking as if all the undefined +symbols are to be bound at program launch time. The dynamic linker actually +binds undefined symbols as they are encountered during execution instead of at +program launch. However, the static link editor always produces the same linking +as the dynamic linker as long as none of the dynamic shared libraries define the +same symbol. Different linking can occur only when there is more than one +definition of a symbol and the library modules that contain the definitions for +that symbol do not define and reference exactly the same symbols. In this case, +even different executions of the same program can produce different linking +because the dynamic linker binds undefined functions as they are called, and +this affects the order in which undefined symbols are bound. Because it can +produce different dynamic linking, using dynamic shared libraries that define +the same symbols in the same program is strongly discouraged. +.PP +If a static archive library appears after a dynamic shared library on the +command line, the static library is placed in the dynamic library search list +and is searched as a dynamic library. In this way, when a dynamic library has +undefined symbols, it will cause the appropriate members of the static libraries +to be loaded into the output. Searching static libraries as dynamic libraries +can cause problems if the dynamic library later changes to reference symbols +from the static library that it did not previously reference. In this case when +the program runs, the dynamic linker will report these symbols as undefined +because the members for these symbols were not loaded into the output. + +.SH TWO-LEVEL AND FLAT NAMESPACES +.PP +Two-level and flat namespaces refer to how references to symbols in dynamic +libraries are resolved to a definition in specific dynamic library. For +two-level namespace that resolution is done at static link time when each +image (program, bundle and shared library) is built. When a program is using +images built with two-level namespace there may be different global symbols +with the same name being used by different images in the program (this is now +the default). When a program is using all flat namespace images then only one +global symbol for each global symbol name is used by all images of the program +(this was the default in MacOS X 10.0). +.PP +When creating an output file with the static link editor that links against +dynamic libraries, the references to symbols in those libraries can be recorded +at static link time to bind to a specific library definition (two-level +namespace) or left to be bound at execution time to the first library in the +search order of the program (flat namespace). A program, its dynamic libraries +and its bundles may each be either two-level or flat namespace images. The +dynamic linker will bind each image according to how it was built. +.PP +When creating an output file with the static link editor when +.B \-twolevel_namespace +is in effect (now the default) all undefined references must be satisfied at +static link time. The flags to allow undefined references, +.BI \-U symbol_name, +.BI \-undefined " warning" +and +.BI \-undefined " suppress" +can't be used. +When the environment variable +.B MACOSX_DEPLOYMENT_TARGET +is set to +.B 10.3 +or higher then +.BI \-undefined " dynamic_lookup" +can also be used. The specific library definition recorded +for each reference is the first library that has a definition as listed on the +link line. Listing an umbrella framework implies all of its sub-frameworks, +sub-umbrellas and sub-libraries. For any reference to a definition found in +an umbrella framework's sub-framework, sub-umbrella or sub-library will be +recorded as coming from the umbrella framework. Then at execution time the +dynamic linker will search that umbrella framework's sub-frameworks, +sub-umbrellas and sub-libraries for those references. +Also when two-level namespace is in effect only those frameworks listed on the +link line (and sub-frameworks, sub-umbrellas and sub-libraries of umbrella +frameworks) are searched. Other dependent libraries which are not +sub-frameworks, sub-umbrellas or sub-libraries of umbrella frameworks are not +searched. +.RS +.PP +When creating bundles (MH_BUNDLE outputs) with the static link editor when +two-level namespace is in effect (now the default) and the bundle has +references to symbols +expected to be defined in the program loading the bundle, then the +.BI \-bundle_loader " executable" +must be used. +.PP +When creating an output file with the static link editor when +.B \-flat_namespace +is in effect (the MacOS X 10.0 default) all undefined references must be +satisfied at static link time when +.BI \-undefined " error" +(the default) is used. The static +link editor checks the undefined references by searching all the libraries +listed on the link line then all dependent libraries. The undefined symbols +in the created output file are left to be resolved at execution time by the +dynamic link editor in the dynamic libraries in the search order of the program. + +.SH MULTIPLY DEFINED SYMBOLS +.PP +If there are multiply defined symbols in the object files being linked into +the output file being created this always results in a multiply defined +symbol error. +.PP +When the static link editor links symbols in from a dynamic library that result +in multiply defined symbols the handling depends on the type of name space of +output file being created and possibly the type of name space of the dynamic +library. +.PP +When the static link editor is creating a two-level namespace image and a +there is a multiply defined symbol from dynamic library then that generates a +multiply defined symbol warning (by default), where the treatment of this +warning can be changed with the +.B \-multiply_defined +flag. +.PP +When the static link editor is creating a flat namespace image and a there is +a multiply defined symbol from dynamic library, if the library is a flat +namespace image then that generates a multiply defined symbol error. If the +library is a two-level namespace image then that generates a multiply defined +symbol warning (by default), where the treatment of this warning can be changed +with the +.B \-multiply_defined +flag. + +.SH "USING THE DYNAMIC LINK EDITOR AND DYNAMIC SHARED LIBRARIES" +.PP +The option +.B \-dynamic +must be specified in order to use dynamic shared libraries (and any of the features used to implement them) and/or the dynamic link editor. +To make sure that the output is not using any features that would +require the dynamic link editor, the flag +.B \-static +can be specified. +Only one of these flags can be specified. + +.SH "LINK EDITOR DEFINED SYMBOLS" +.PP +There is a group of link editor defined symbols for the +.SM MH_EXECUTE, +.SM MH_DYLIB +and +.SM MH_PRELOAD +file types (see the header file ). Link editor symbols are +reserved; it is an error if an input object file defines such a symbol. +Only those link editor symbols that are referenced by the object file +appear in the output file's symbol table. +.PP +The link editor defined symbol `\_\^\_mh_execute_header' +(`\_mh_execute_header' in C) is reserved when the output file format is +.SM MH_EXECUTE. +This symbol is the address of the Mach header in a Mach-O executable (a +file of type +.SM MH_EXECUTE). +It does not appear in +any other Mach-O file type. It can be used to get to the addresses and +sizes of all the segments and sections in the executable. This can be done by parsing the headers +and load commands (see +.IR Mach-O (5)). +.PP +The link editor defined symbol `\_\^\_mh_dylib_header' +(`\_mh_dylib_header' in C) is reserved when the output file format is +.SM MH_DYLIB. +This symbol is the address of the Mach header in a Mach-O dynamic shared library +(a file of type +.SM MH_DYLIB) +and is a private external symbol. +It does not appear in +any other Mach-O file type. It can be used to get to the addresses and +sizes of all the segments and sections in a dynamic shared library. The +addresses, however, must have the value +.IR _dyld_get_image_vmaddr_slide (3) +added to them. +.PP +The +.SM MH_PRELOAD +file type has link editor defined symbols for the +beginning and ending of each segment, and for the +beginning and ending of each section within a segment. +These names are provided for use in a Mach-O preloaded file, +since it does not have its headers loaded as part of the first segment. +The names of the symbols for a segment's beginning and end +have the form: \_\^\_SEGNAME\_\^\_begin and \_\^\_SEGNAME\_\^\_end, +where \_\^\_SEGNAME is the name of the segment. Similarly, the symbols for +a section have the form: +\_\^\_SEGNAME\_\^\_sectname\_\^\_begin and \_\^\_SEGNAME\_\^\_sectname\_\^\_end, +where \_\^\_sectname is the name of the section in the segment \_\^\_SEGNAME. +These symbols' types are those of the section that the names refer to. +(A symbol that refers to the end of a section actually has, as its value, the beginning address of the next section, but the symbol's type is still that of the section mentioned in the symbol's name.) +.SH OPTIONS +.PP +.I Ld +understands several options. Filenames and +options that refer to libraries (such as +.B \-l +and +.BR \-framework ), +as well as options that create symbols (such as +.B \-u +and +.BR \-i ), +are position-dependent: They define the load order and affect what gets +loaded from libraries. +Some +.I ld_classic +options overlap with compiler options. If the compiler driver +.IR cc (1) +is used to invoke +.I ld_classic , +it maybe necessary to pass the +.IR ld_classic (1) +options to +.IR cc (1) +using +.BR \-Wl,\-option,argument1,argument2 . + +In this release of the static link editor, 64-bit code is processed by a the new +link editor /usr/bin/ld. And it is an error to pass -arch ppc64 or -arch x86_64 +to +.IR ld_classic (1). + +The most common option is: +.TP +.BI \-o " name" +The output file is named +.IR name , +instead of +.BR a.out . + +.PP +The following flags are related to architectures: +.TP +.BI \-arch " arch_type" +Specifies the architecture, +.I arch_type, +for the output file. ``Universal'' input files that do not contain this +specified architecture are ignored. Only one +.BI \-arch " arch_type" +can be specified. See +.IR arch (3) +for the currently known +.IR arch_type s. +If +.I " arch_type" +specifies a certain implementation of an architecture (such as +.BI \-arch " m68040" +or +.BI \-arch " i486" +), the resulting object file has that specific CPU subtype, and it is an +error if any input file has a CPU subtype that will not combine to the CPU subtype +for +.IR " arch_type" . +.IP +The default output file architecture is determined by the first object file to +be linked. If it is a ``thin'' (standard Mach-O) file, or a ``universal'' file +that contains only one architecture, the output file will have the same +architecture. Otherwise, if it is a ``universal'' file +containing an architecture that would execute on the host, then the ``best'' +architecture is used, as defined by what the kernel exec(2) would select. +Otherwise, it is an error, and a +.BI \-arch " arch_type" +must be specified. +For family architectures (like ppc and i386) the CPU subtype of the linked +output is the ALL cpusubtype. For specific CPU subtypes (ppc7400 vs. ppc970), +the resulting CPU subtype of the linked output is to 'combine' the CPU subtypes. +The combining is CPU specific and generally results in the minimum CPU subtype +needed to support all the combined CPU subtypes. +.TP +.B \-arch_multiple +This flag is used by the +.IR cc (1) +driver program when it is run with multiple +.BI \-arch " arch_type" +flags. It instructs programs like +.IR ld_classic (1) +to precede any displayed message with a line stating +the program name, in this case +.IR ld_classic , +and the architecture (from the +.BI \-arch " arch_type" +flag). This helps distinguish which architecture the error messages refer to. +.TP +.B \-force_cpusubtype_ALL +The +.B \-force_cpusubtype_ALL +flag causes the CPU subtype to remain the +.SM ALL +CPU subtype and not to be combined or +changed. This flag has precedence over any +.BI \-arch " arch_type" +flag for a specific implementation. +This is the default for all x86 architectures. +.PP +The following flags are related to using the dynamic link editor and/or +dynamic shared libraries (and any of the features used to implement them): +.TP +.B \-dynamic +Allows use of the features associated with dynamic link editor. The default is +.B \-dynamic. +.TP +.B \-static +Causes those features associated with dynamic link editor to be treated as +an error. (The description for the options that will cause an error if you use them in conjunction with +.B \-static +are marked with the statement "when +.B \-dynamic + is used"). +.TP +.BI \-read_only_relocs " treatment" +Specifies how relocation entries in read-only sections are to be treated when +.B \-dynamic +is used. +To get the best possible sharing, the read-only sections should not have any +relocation entries. +If they do, the dynamic linker will write on the section. +Having relocation entries appear in read-only sections is normally avoided by compiling with the option +.B \-dynamic. +But in such cases non-converted assembly code +or objects not compiled with +.B \-dynamic +relocation entries will appear in read-only sections. +The +.I treatment +can be: +.I error, +.I warning, +or +.I suppress. +Which cause the treatment of relocation entries in read-only sections as either, +errors, warnings, or suppressed messages. +The default is to treat these as errors. +.TP +.BI \-sect_diff_relocs " treatment" +Specifies how section difference relocation enries are to be treated when +.B \-dynamic +and +.B \-execute +are used. +To get the best possible code generation the compiler should not generate code +for executables (MH_EXECUTE format outputs) that have any section difference +relocation entries. The +.IR gcc (1) +compiler has the +.B \-mdynamic-no-pic +flag for generating code for executables. The default treatment is +.I suppress, +where no message is printed. The other treatments are +.I error +or +.I warning. +This option can also be specified by setting the environment variable +.SM LD_SECT_DIFF_RELOCS +to the treatment values. +.TP +.BI \-weak_reference_mismatches " treatment" +Specifies how to treat mismatches of symbol references in the the object files +being linked. Normally the all the undefined symbol references of the object +files being linked should be consistent for each undefined symbol. That is all +undefined symbols should either be weak or non-weak references. The default +treatment is +.I error, +where the link fails with an error message. The other treatments are +.I weak +or +.I non-weak, +which makes mismatched undefined symbol references either weak or non-weak +in the output, respectively. Care must be taken when using the treatment +.I weak +as the use of the non-weak symbol references in an object file may cause the +program to crash when the symbol is not present at execution time. +.TP +.B \-prebind +Have the static linker, +.IR ld_classic (1), +prebind an executable's or dynamic shared library's undefined symbols to the +addresses of the dynamic libraries it is being linked with. +This optimization can only be done if the libraries don't overlap and +no symbols are overridden. +When the resulting program is run and the same libraries are used to run the +program as when the program was linked, the dynamic linker can use the prebound +addresses. +If not, the dynamic linker undoes the prebinding and binds normally. +This option can also be specified by setting the environment variable +.SM LD_PREBIND. +If the environment variable +.SM LD_FORCE_NO_PREBIND +is set both the option +.B \-prebind +.SM LD_PREBIND +environment variable are ignore and the output is not prebound. +Or if the environment variable +.B MACOSX_DEPLOYMENT_TARGET +is set to 10.4 or greater and the output is not a split a dynamic library the +output is not prebound. +.TP +.B \-noprebind +Do not have the static linker, +.IR ld_classic (1), +prebind the output. If this is specified the environment variable +.SM LD_PREBIND +is ignored. +.TP +.B \-prebind_allow_overlap +Have the static linker, +.IR ld_classic (1), +prebind the output even if the addresses of the dynamic libraries it uses +overlap. The resulting output can then have +.IR redo_prebinding (1) +run on it to fix up the prebinding after the overlapping dynamic libraries +have been rebuilt. This option can also be specified by setting the +environment variable +.SM LD_PREBIND_ALLOW_OVERLAP. +.TP +.B \-prebind_all_twolevel_modules +Have the static linker, +.IR ld_classic (1), +mark all modules from prebound two-level namespace dynamic libraries as used +by the program even if they are not statically referenced. This can provide +improved launch time for programs like Objective-C programs that use symbols +indirectly through NIB files. This option can also be specified by setting the +environment variable +.SM LD_PREBIND_ALL_TWOLEVEL_MODULES. +.TP +.B \-noprebind_all_twolevel_modules +Don't have the static linker, +.IR ld_classic (1), +mark all modules from prebound two-level namespace dynamic libraries as used +by the program. This flag overrides the setting of the +environment variable +.SM LD_PREBIND_ALL_TWOLEVEL_MODULES. +.TP +.B \-nofixprebinding +Have the static linker, +.IR ld_classic (1), +mark the executable so that the dynamic linker will never notify the prebinding +agent if this launched and its prebinding is out of date. This is used when +building the prebinding agent itself. +.PP +The following flags are related to libraries: +.TP +.BI \-l x +This +option is an abbreviation for the library name +.RI `lib x .a', +where +.I x +is a string. +If +.B \-dynamic +is specified the abbreviation for the library name is first search as +.RI `lib x .dylib' +and then +.RI `lib x .a' +is searched for. +.I ld_classic +searches for libraries first in any directories +specified with +.B \-L +options, then in any directories specified in the colon separated set of paths +in the environment variable LD_LIBRARY_PATH, then the standard directories +.BR /lib , +.BR /usr/lib , +and +.BR "/usr/local/lib" . +A library is searched when its name is encountered, +so the placement of the +.B \-l +flag is significant. If string +.I x +is of the form +.IR x .o, +then that file is searched for in the same places, but without prepending +`lib' or appending `.a' or `.dylib' to the filename. +.TP +.BI \-weak-l x +This is the same as the +.BI \-l x +but forces the library and all references to it to be marked as weak imports. +Care must be taken when using this as the use of the non-weak symbol references +in an object file may cause the program to crash when the symbol or library is +not present at execution time. +.TP +.BI \-weak_library " file_name_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. +Care must be taken when using this as the use of the non-weak symbol references +in an object file may cause the program to crash when the symbol or library is +not present at execution time. +.TP +.BI \-L dir +Add +.I dir +to the list of directories in which to search for libraries. +Directories specified with +.B \-L +are searched before the standard directories. +.TP +.B \-Z +Do not search the standard directories when searching for libraries. +.TP +.BI "\-syslibroot " rootdir +Prepend +.I rootdir +to the standard directories when searching for libraries or frameworks. +.TP +.B \-search_paths_first +By default when the +.B \-dynamic +flag is in effect, the +.BI \-l x +and +.BI \-weak-l x +options first search for a file of the form +.RI `lib x .dylib' +in each directory in the library search path, then a file of the form +.RI `lib x .a' +is searched for in the library search paths. +This option changes it so that in each path +.RI `lib x .dylib' +is searched for then +.RI `lib x .a' +before the next path in the library search path is searched. +.TP +.BI "\-framework " name[,suffix] +Specifies a framework to link against. Frameworks are dynamic shared libraries, +but they are stored in different locations, and therefore must be searched for +differently. When this option is specified, +.I ld_classic +searches for framework `\fIname\fR.framework/\fIname\fR' +first in any directories +specified with the +.B \-F +option, then in the standard framework directories +.BR /Library/Frameworks , +.BR /Network/Library/Frameworks , +and +.BR "/System/Library/Frameworks" . +The placement of the +.B \-framework +option is significant, as it determines when and how the framework is searched. +If the optional suffix is specified the framework is first searched for the +name with the suffix and then without. +.TP +.BI "\-weak_framework " name[,suffix] +This is the same as the +.BI "\-framework " name[,suffix] +but forces the framework and all references to it to be marked as weak imports. +Care must be taken when using this as the use of the non-weak symbol references +in an object file may cause the program to crash when the symbol or framework is +not present at execution time. +.TP +.BI \-F dir +Add +.I dir +to the list of directories in which to search for frameworks. +Directories specified with +.B \-F +are searched before the standard framework directories. +.TP +.B \-ObjC +Loads all members of static archive libraries that define an Objective C class or a category. This option does not apply to dynamic shared libraries. +.TP +.B \-all_load +Loads all members of static archive libraries. +This option does not apply to dynamic shared +libraries. +.TP +.BI \-dylib_file " 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. +.I install_name +specifies the path where the library normally resides. +.I 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: +\fB\-dylib_file /lib/libsys_s.A.dylib:/me/lib/libsys_s.A.dylib\fR. +.TP +.BI \-executable_path " path_name" +Specifies that +.I path_name +is used to replace +.I @executable_path +for dependent libraries. + +.PP +The following options specify the output file format (the file type): +.TP +.B "\-execute" +Produce a Mach-O demand-paged executable format file. The headers are placed +in the first segment, and all segments are padded to the segment alignment. +This has a file type of +.SM MH_EXECUTE. +This is the default. If no segment address is specified at address zero, a +segment with no protection (no read, write, or execute permission) is created +at address zero. +This segment, whose size is that of the segment +alignment, is named +.SM ``_\|_PAGEZERO''. +This option was previously named +.BR "\-Mach" , +which will continue to be recognized. +.TP +.B \-object +Produce a Mach-O file in the relocatable object file format that is +intended for execution. This differs from using the +.B \-r +option in that it defines common symbols, does not allow undefined symbols and +does not preserve relocation entries. This has a file type of +.SM MH_OBJECT. +In this format all sections are placed in one unnamed segment with all +protections (read, write, execute) allowed on that segment. This is intended +for extremely small programs that would otherwise be large due to segment +padding. In this format, and all +.SM non-MH_EXECUTE +formats, the link editor +defined symbol ``\_\^\_mh_execute_header'' is not defined since the headers are +not part of the segment. This format file can't be used with the dynamic +linker. +.TP +.B \-preload +Produce a Mach-O preloaded executable format file. The headers are not placed +in any segment. All sections are placed in their proper segments and they are +padded to the segment alignment. This has a file type of +.SM MH_PRELOAD. +This option was previously +.BR "\-p" , +which will continue to be recognized. +.TP +.B "\-dylib" +Produce a Mach-O dynamically linked shared library format file. The headers are +placed in the first segment. All sections are placed in their proper segments +and they are padded to the segment alignment. This has a file type of +.SM MH_DYLIB. +This option is used by +.IR libtool (1) +when its +.B \-dynamic +option is specified. +.TP +.B "\-bundle" +Produce a Mach-O bundle format file. The headers are placed in the first +segment. All sections are placed in their proper segments +and they are padded to the segment alignment. This has a file type of +.SM MH_BUNDLE. +.TP +.B "\-dylinker" +Produces a Mach-O dynamic link editor format file. The headers are placed in the +first segment. All sections are placed in their proper segments, and they are +padded to the segment alignment. This has a file type of +.SM MH_DYLINKER. +.TP +.B \-fvmlib +Produce a Mach-O fixed VM shared library format file. The headers are placed +in the first segment but the first section in that segment will be placed on +the next segment alignment boundary in that segment. All sections are placed +in their proper segments and they are padded to the segment alignment. +This has a file type of +.SM MH_FVMLIB. + +.PP +The following flags affect the contents of the output file: +.TP +.B \-r +Save the relocation information in the output file +so that it can be the subject of another +.I ld_classic +run. The resulting file type is a Mach-O relocatable file +.SM (MH_OBJECT) +if not otherwise specified. +This flag also prevents final definitions from being +given to common symbols, +and suppresses the `undefined symbol' diagnostics. +.TP +.B \-d +Force definition of common storage even if the +.B \-r +option is present. This option also forces link editor defined symbols to be defined. +This option is assumed when there is a dynamic link editor load command in the input +and +.B \-r +is not specified. + +.PP +The following flags support segment specifications: +.TP +.BI "\-segalign" " value" +Specifies the segment alignment. +.I value +is a hexadecimal number that must be an integral power of 2. +The default is the target pagesize (currently 1000 hex for the PowerPC and +i386). +.TP +.BI "\-seg1addr" " addr" +Specifies the starting address of the first segment in the output file. +.I addr +is a hexadecimal number and must be a multiple of the segment alignment. +This option can also be specified as +.B "\-image_base." +.TP +.BI "\-segaddr" " name addr" +Specifies the starting address of the segment named +.I name +to be +.I addr. +The address must be a hexadecimal number that is a multiple of the segment alignment. +.TP +.BI "\-segs_read_only_addr" " addr" +Specifies the starting address of the read-only segments in a dynamic shared +library. When this option is used the dynamic shared library is built such +that the read-only and read-write segments are split into separate address +ranges. By default the read-write segments are 256meg (0x10000000) after +the read-only segments. +.I addr +is a hexadecimal number and must be a multiple of the segment alignment. +.TP +.BI "\-segs_read_write_addr" " addr" +Specifies the starting address of the read-write segments in a dynamic shared +library. When this option is used the +.B \-segs_read_only_addr +must also be used (see above). +.I addr +is a hexadecimal number and must be a multiple of the segment alignment. +.TP +.BI "\-seg_addr_table" " filename" +For dynamic shared libraries the +.B "\-seg1addr" +or the pair of +.B "\-segs_read_only_addr" +and +.B "\-segs_read_write_addr" +are specified by an entry in the segment address table in +.I filename +that matches the install name of the library. +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 as the +.B "\-seg1addr". +In the second form the first address is used as the +.B "\-segs_read_only_addr" +address and the second address is used as the +.B "\-segs_read_write_addr" +address. +This option can also be specified by setting the environment variable +.SM LD_SEG_ADDR_TABLE. +If the environment variable is set then any +.BR "\-seg1addr" , +.BR "\-segs_read_only_addr" , +.B "\-segs_read_write_addr" +and +.B "\-seg_addr_table" +options are ignored and a warning is printed. +.TP +.BI "\-seg_addr_table_filename" " pathname" +Use +.B pathname +instead of the install name of the library for matching an entry in the segment +address table. +.TP +.BI "\-segprot" " name max init" +Specifies the maximum and initial virtual memory protection of the named +segment, +.I name, +to be +.I max +and +.I init +,respectively. The values for +.I max +and +.I init +are any combination of the characters `r' (for read), `w' (for write), +`x' (for execute) and '\-' (no access). The default is `rwx' for the maximum +protection for all segments for PowerPC architecures and `rw` for the all Intel +architecures. +The default for the initial protection for all segments is `rw' unless the +segment contains a section which contains some machine instructions, in which +case the default for the initial protection is `rwx' (and for Intel +architecures it also sets the maximum protection to `rwx' in this case). +The default for the initial protection for the +.SM "``_\|_TEXT''" +segment is `rx' (not writable). +.TP +.B \-seglinkedit +Create the link edit segment, named +.SM "``_\|_LINKEDIT''" +(this is the default). +This segment contains all the link edit information (relocation information, +symbol table, string table, etc.) in the object file. If the segment protection +for this segment is not specified, the initial protection is not writable. +This can only be specified when the output file type is not +.SM MH_OBJECT +and +.SM MH_PRELOAD +output file types. To get at the contents of this section, the Mach header +and load commands must be parsed from the link editor defined symbols like +`\_\^\_mh_execute_header' (see +.IR Mach-O (5)). +.TP +.B \-noseglinkedit +Do not create the link edit segment (see +.B \-seglinkedit +above). +.TP +.BI "\-pagezero_size" " value" +Specifies the segment size of _\|_PAGEZERO to be of size +.IR value , +where +.I value +is a hexadecimal number rounded to the segment alignment. +The default is the target pagesize (currently, 1000 hexadecimal for the PowerPC +and for i386). +.TP +.BI "\-stack_addr" " value" +Specifies the initial address of the stack pointer +.IR value , +where +.I value +is a hexadecimal number rounded to the segment alignment. +The default segment alignment is the target pagesize (currently, 1000 +hexadecimal for the PowerPC and for i386). +If +.B \-stack_size +is specified and +.B \-stack_addr +is not, a default stack address specific for the architecture being linked will +be used and its value printed as a warning message. +This creates a segment named _\|_UNIXSTACK. Note that the initial stack address +will be either at the high address of the segment or the low address of the +segment depending on which direction the stack grows for the architecture being +linked. +.TP +.BI "\-stack_size" " value" +Specifies the size of the stack segment +.IR value , +where +.I value +is a hexadecimal number rounded to the segment alignment. +The default segment alignment is the target pagesize (currently, 1000 +hexadecimal for the PowerPC and for i386). +If +.B \-stack_addr +is specified and +.B \-stack_size +is not, a default stack size specific for the architecture being linked will be +used and its value printed as a warning message. +This creates a segment named _\|_UNIXSTACK . +.TP +.B \-allow_stack_execute +Marks executable so that all stacks in the task will be given stack execution +privilege. This includes pthread stacks. + +.PP +The following flags support section specifications: +.TP +.BI "\-sectcreate" " segname sectname file" +The section +.I sectname +in the segment +.I segname +is created from the contents of +.I file. +The combination of +.I segname +and +.I sectname +must be unique; there cannot already be a section +.I (segname,sectname) +in any input object file. +This option was previously called +.BR "\-segcreate" , +which will continue to be recognized. +.TP +.BI "\-sectalign" " segname sectname value" +The section named +.I sectname +in the segment +.I segname +will have its alignment set to +.IR value , +where +.I value +is a hexadecimal number that must be an integral power of 2. +This can be used to set the alignment of a section created from a file, or to +increase the alignment of a section from an object file, or to set the maximum +alignment of the +.SM (_\|_DATA,_\|_common) +section, where common symbols are defined +by the link editor. Setting the alignment of a literal section causes the +individual literals to be aligned on that boundary. If the section +alignment is not specified by a section header in an object file or on the +command line, it defaults to 10 (hex), indicating 16-byte alignment. +.TP +.BI "\-sectorder" " segname sectname orderfile" +The section +.I sectname +in the segment +.I segname +of the input files will be broken up into blocks associated with +symbols in the section. The output section will be created by ordering +the blocks as specified by the lines in the +.I orderfile. +These blocks are aligned to the output file's section alignment for this +section. Any section can be ordered in the output file except symbol pointer and symbol stub sections. +.IP +For non-literal sections, each line of the +.I orderfile +contains an object name and a symbol name, separated by a single colon (':'). +Lines that start with # are ignored and treated as comments. +If the object file is +in an archive, the archive name, followed by a single colon, must precede the +object file name. The object file names and archive names should be exactly the +names as seen by the link editor, but if not, the link editor attempts to match +up the names the best it can. +For non-literal sections, the easiest way to generate an order file is +with the ``\f3\-jonls +\f2segname sectname\f1'' options to +.IR nm (1). +.IP +The format of the +.I orderfile +for literal sections is specific to each type of literal section. For C +string literal sections, each line of the order file contains one literal C +string, which may include ANSI C escape sequences. For four-byte literal +sections, the order file format is one 32-bit hex number with a leading 0x +per +line, with the rest of the line treated as a comment. For eight-byte literal +sections, the order file has two 32-bit hex numbers per line; each number +has a leading 0x, the two numbers are separated by white +space, and the rest of the line is treated as a comment. +For literal pointer sections, the lines in the order file represent +pointers, one per line. A literal pointer is represented by the name of +the segment that contains the literal being pointed to, followed by the +section name, followed by the literal. These three strings are separated +by colons with no extra white space. +For all the literal sections, each line in the the order file is simply entered +into the literal section and will appear in the output file in the same order +as in the +order file. There is no check to see whether the literal is present +in the loaded objects. +For literal sections, the easiest way to generate an order file is with +the ``\f3\-X \-v \-s \f2segname sectname\f1'' options to +.IR otool (1). +.TP +.B \-sectorder_detail +When using the +.B \-sectorder +option, any pairs of object file names and symbol names that are found in +the loaded objects, but not specified in the +.IR orderfile , +are placed last in the output file's section. These pairs are ordered by +object file (as the filenames appear +on the command line), with the different symbols from a given object +file being ordered by +increasing symbol address (that is, the order +in which the symbols occurred in the object file, +not their order in the symbol table). By default, the link editor displays a summary +that simply shows the number +of symbol names found in the loaded objects but not in the +.IR orderfile , +as well as the number of symbol names listed in the +.I orderfile +but not found in the loaded objects. (The summary is omitted if both values +are zero.) To instead produce a detailed list of these symbols, use the +.B \-sectorder_detail +flag. If an object file-symbol name pair is listed multiple times, a +warning is generated, and the first occurrence is used. +.TP +.BI "\-sectobjectsymbols" " segname sectname" +This causes the link editor to generate local symbols in the section +.I sectname +in the segment +.IR segname . +Each object file that has one of these sections will have a local +symbol created +whose name is that of the object file, or of the member of the archive. +The symbol's value will be the first address where that object file's section +was loaded. The symbol has the type N_SECT and its section number is the +the same as that of the section +.I (segname,sectname) +in the output file. +This symbol will be placed in the symbol table just before all other local +symbols +for the object file. This feature is typically used where the section is +.SM (\_\^\_TEXT,\_\^\_text), +in order to help the debugger debug object files produced by old versions of +the compiler or by non-Apple compilers. + +.PP +The following flags are related to name spaces: +.TP +.B \-twolevel_namespace +Specifies the output to be built as a two-level namespace image. +This option can also be specified by setting the environment variable +.SM LD_TWOLEVEL_NAMESPACE. +This is the default. +.TP +.B \-flat_namespace +Specifies the output to be built as a flat namespace image. +This is not the default (but was the default in MacOS X 10.0). +.TP +.B \-force_flat_namespace +Specifies the executable output to be built and executed treating all its +dynamic libraries as flat namespace images. This marks the executable so that +the dynamic link editor treats all dynamic libraries as flat namespace +images when the program is executed. +.TP +.BI \-bundle_loader " executable" +This specifies the +.I executable +that will be loading the bundle output file being linked. Undefined symbols +from the bundle are checked against the specified executable like it was one of +the dynamic libraries the bundle was linked with. If the bundle being created +with +.B \-twolevel_namespace +in effect then the searching of the executable for +symbols is based on the placement of the +.B \-bundle_loader +flag relative to the dynamic libraries. If the the bundle being created with +.B \-flat_namespace +then the searching of the executable is done before all dynamic libraries. +.TP +.B \-private_bundle +This allows symbols defined in the output to also be defined in executable in +the +.B \-bundle_loader +argument +when +.B \-flat_namespace +is in effect. +This implies that the bundle output file being created is going to be loaded by +the executable with the +.B NSLINKMODULE_OPTION_PRIVATE +option to +.IR NSLinkModule (3). +.TP +.B \-twolevel_namespace_hints +Specifies to create the output with the two-level namespace hints table to be +used by the dynamic linker. This is the default except when the +.B \-bundle +flag is specified. If this is used when the +.B \-bundle +flag is specified the bundle will fail to load on a MacOS X 10.0 system with a +malformed object error. +.TP +.BI \-multiply_defined " treatment" +Specifies how multiply defined symbols in dynamic libraries when +.B \-twolevel_namespace +is in effect are to be treated. +.I treatment +can be: +.I error, +.I warning, +or +.I suppress. +Which cause the treatment of multiply defined symbols in dynamic libraries +as either, errors, warnings, or suppresses the checking of multiply symbols +from dynamic libraries when +.B \-twolevel_namespace +is in effect. +The default is to treat multiply defined symbols in dynamic libraries as +warnings when +.B \-twolevel_namespace +is in effect. +.TP +.BI \-multiply_defined_unused " treatment" +Specifies how unused multiply defined symbols in dynamic libraries when +.B \-twolevel_namespace +is in effect are to be treated. +An unused multiply defined symbol is one in which there is a symbol defined in +the output that is also defined in the dynamic libraries the output is linked +with but the symbol in the dynamic library is not used by any reference in the +output. +.I treatment +can be: +.I error, +.I warning, +or +.I suppress. +The default for unused multiply defined symbols is to suppress these messages. +.TP +.B -nomultidefs +specifying this flag marks the umbrella being created such that the dynamic +linker is guaranteed that no multiple definitions of symbols in the umbrella's +sub-images will ever exist. This allows the dynamic linker to always use the +two-level namespace lookup hints even if the timestamps of the sub-images +do not match. This flag implies +.BI \-multiply_defined " error". + +.PP +The following flags are related to symbols. These flags' arguments +are external symbols whose names have `_' prepended to the C, +.SM FORTRAN, +or Pascal variable name. +.TP +.BI \-y sym +Display each file in which +.I sym +appears, its type, and whether the file defines or references it. Any +multiply defined symbols are automatically +traced. Like most of the other symbol-related flags, +.B \-y +takes only one argument; the flag may be specified more than once in the +command line to trace more than one symbol. +.TP +.BI \-Y " number" +For the first +.I number +undefined symbols, displays each file in which the symbol appears, its type and whether the file defines or references it (that is, the same style of output produced by the +.B \-y +option). To keep the output manageable, this option displays at most +.I number +references. +.TP +.B \-keep_private_externs +Don't turn private external symbols into static symbols, but rather leave them +as private external in the resulting output file. +.TP +.B \-m +Don't treat multiply defined symbols from the linked objects as a hard error; +instead, simply print a warning. The first linked object defining such a symbol +is used for linking; its value is used for the symbol in the symbol table. The +code and data for all such symbols are copied into the output. The duplicate +symbols other than the first symbol may still end up being used in the resulting +output file through local references. This can still produce a resulting output +file that is in error. This flag's use is strongly discouraged! +.TP +.B \-whyload +Indicate why each member of a library is loaded. In other words, indicate +which currently undefined symbol is being resolved, causing that +member to be loaded. This in combination with the above +.BI \-y sym +flag can help determine exactly why a link edit is failing due to multiply +defined symbols. +.B +.TP +.BI \-u " sym" +Enter the argument +.I sym +into the symbol table as an undefined symbol. This is useful +for loading wholly from a library, since initially the symbol +table is empty and an unresolved reference is needed +to force the loading of the first object file. +.TP +.BI \-e " sym" +The argument +.I sym +is taken to be the symbol name of the entry point of +the resulting file. By default, the entry point is the address of the +first section in the first segment. +.TP +.BI \-i definition:indirect +Create an indirect symbol for the symbol name +.I definition +which is defined to be the same as the symbol name +.I indirect +(which is taken to be undefined). When a definition of the symbol named +.I indirect +is linked, both symbols will take on the defined type and value. +.IP +This option overlaps with a compiler option. +If you use the compiler driver +.IR cc (1) +to invoke \fIld_classic\fR, +invoke this option in this way: +.BI \-Wl,\-i definition:indirect. + +.TP +.BI \-undefined " treatment" +Specifies how undefined symbols are to be treated. +.I treatment +can be: +.I error, +.I warning, +or +.I suppress. +Which cause the treatment of undefined symbols as either, errors, warnings, or +suppresses the checking of undefined symbols. +The default is to treat undefined symbols as errors. +When the environment variable +.B MACOSX_DEPLOYMENT_TARGET +is set to +.B 10.3 +or higher then +.BI \-undefined " dynamic_lookup" +can also be used to allow any undefined symbols to be looked up dynamically at +runtime. Use of a binary built with this flag requires a system with a dynamic +linker from Mac OS X 10.3 or later. +The flag +.BI \-undefined " define_a_way" +can also be used to cause the static linker to create a private definition for +all undefined symbols. This flag should only be used if it is known that the +undefined symbols are not referenced as any use of them may cause a crash. +.TP +.BI \-U " sym" +Allow the symbol +.I sym +to be undefined, even if the +.B \-r +flag is not given. Produce an executable file if the only undefined +symbols are those specified with +.BR \-U. +.IP +This option overlaps with a compiler option. +If you use the compiler driver +.IR cc (1) +to invoke \fIld_classic\fR, +invoke this option in this way: +.BI \-Wl,\-U, sym. +.TP +.B \-bind_at_load +Causes the output file to be marked such that the dynamic linker will bind all +undefined references when the file is loaded or launched. + +.PP +The following flags are related to stripping link edit information. +This information can also be removed by +.IR strip (1), +which uses the same options. (The +exception is the +.B \-s +flag below, but this is the same as +.IR strip (1) +with no arguments.) +The following flags are listed in decreasing level of stripping. +.TP +.B \-s +Completely strip the output; that is, remove the symbol table +and relocation information. +.TP +.B \-x +Strips the non-global symbols; only saves external symbols. +.IP +This option overlaps with a compiler option. +If you use the compiler driver +.IR cc (1) +to invoke \fIld_classic\fR, +invoke this option in this way: +.B \-Wl,\-x. +.TP +.B \-S +Strip debugging symbols; only save local and global symbols. +.TP +.B \-X +Strip local symbols whose names begin with `L'; save all other symbols. +(The compiler and assembler currently strip these internally-generated +labels by default, so they generally do not appear in object files +seen by the link editor.) +.TP +.B \-Sp +Strip, edit and add debugging symbols so the debugger can used most of the +debugging symbols from the object files. +.TP +.B \-Si +Strip duplicate debugging symbols from include files. This is +the default. +.TP +.B \-b +Strip the base file's symbols from the output file. (The base file +is given as the argument to the +.B \-A +option.) +.IP +This option overlaps with a compiler option. +If you use the compiler driver +.IR cc (1) +to invoke \fIld_classic\fR, +invoke this option in this way: +.B \-Wl,\-b. +.TP +.B \-Sn +Don't strip any symbols. +.TP +.BI \-exported_symbols_list " filename" +The specified +.I filename +contains lists 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 +.I __private_extern__ +and will not be global in the output file. The symbol names listed in +.I 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. +.TP +.BI \-unexported_symbols_list " filename" +The specified +.I filename +contains lists 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 +.I __private_extern__ +and will not be global in the output file. The symbol names listed in +.I 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. +.TP +.BI \-no_uuid +Do not emit an LC_UUID load command in the linked output file. + +.TP +.B -dead_strip +Remove blocks of code and data that are unreachable by the entry point or +exported symbols. +.TP +.B -no_dead_strip_inits_and_terms +When specified along with +.B -dead_strip +cause all constructors and destructors to never be dead stripped. + +.PP +The remaining options are infrequently used: +.TP +.B \-v +Print the version of the linker. +.TP +.B \-w +Suppresses all warning messages. +.TP +.B \-no_arch_warnings +Suppresses warning messages about files that have the wrong architecture for the +.B \-arch +flag. +.TP +.B \-arch_errors_fatal +Cause the errors having to do with files that have the wrong architecture to be +fatal and stop the link editor. +.TP +.B \-M +Produce a load map, listing all the segments and sections. The list +includes the address where each input file's section appears in the +output file, as well as the section's size. +.IP +This option overlaps with a compiler option. +If you use the compiler driver +.IR cc (1) +to invoke \fIld_classic\fR, +invoke this option in this way: +.B \-Wl,\-M. +.TP +.B \-whatsloaded +Display a single line listing each object file that is +loaded. Names of objects in archives have the form libfoo.a(bar.o). +.TP +.BI \-filelist " listfile[,dirname]" +Specifies that the linker should link the files listed in +.I listfile . +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, +.I dirname +is specified, it is prepended to each name in the list file. +.TP +.BI "\-headerpad" " value" +Specifies the minimum amount of space ("padding") following +the headers for the +.SM MH_EXECUTE +format and all output file types with the dynamic linker. +.I value +is a hexadecimal number. +When a segment's size is rounded up to the segment alignment, there +is extra space left over, which is placed between the headers and the sections, rather than at the end of the segment. The +.B headerpad +option specifies the minimum size of this padding, +which can be useful if the headers will be altered later. +The default value is the larger of 2 * sizeof(struct section) so the program +/usr/bin/objcunique can always add two section headers, or if the output is an +MH_EXECUTE filetype and +.B \-prebind +is specified 3 times the size of the LC_PREBOUND_DYLIB load commands. +The actual amount of pad will be as large as the amount of the first +segment's round-off. +(That is, take the total size of the first segments' +headers and non-zerofill sections, round this size +up to the segment alignment, +and use the difference between the rounded +and unrounded sizes as the minimum amount of padding.) +.TP +.B \-headerpad_max_install_names +Add to the header padding enough space to allow changing all dynamic shared +library paths recorded in the output file to be changed to MAXPATHLEN in length. +.TP +.B \-t +Trace the progress of the link editor; display the name of each file +that is +loaded as it is processed in the first and second pass of the link +editor. +.TP +.BI \-A " basefile" +Incremental loading: linking is to be done in a manner +that lets the resulting object be read into an already executing +program, the +.IR basefile . +.I basefile +is the name of a file whose symbol table will be taken as a basis +on which to define additional symbols. +Only newly linked material will be entered into the +.BR a.out +file, but the new symbol table will reflect +every symbol defined in the base file and the newly linked files. +Option(s) to specify the addresses of the segments are typically +needed, since +the default addresses tend to overlap with the +.I basefile. +The default format of the object file is +.SM MH_OBJECT. +Note: It is strongly recommended that this option NOT be used, +because the dyld package described in +.IR dyld (3) +is a much easier alternative. +.TP +.BI \-dylib_install_name " name" +For dynamic shared library files, specifies the name of the file +the library will be installed in for programs that use it. If this is not +specified, the name specified in the +.BI \-o " name" +option will be used. +This option is used as the +.IR libtool (1) +.BI \-install_name " name" +option when its +.B \-dynamic +option is specified. +.TP +.BI \-umbrella " framework_name" +Specifies this is a subframework where +.I framework_name +is the name of the umbrella framework this subframework is a part of. Where +.I framework_name +is the same as the argument to the +.BI \-framework " framework_name" +option. This subframework can then only be linked into the umbrella framework +with the same +.I framework_name +or another subframework with the same umbrella framework name. Any other +attempt to statically link this subframework directly will result in an error +stating to link with the umbrella framework instead. When building the umbrella +framework that uses this subframework no additional options are required. +However the install name of the umbrella framework, required to be specified +with +.BR \-dylib_install_name , +must have the proper format for an install name of a framework for the +.I framework_name +of the umbrella framework to be determined. +.TP +.BI \-allowable_client " client_name" +Specifies that for this subframework the +.I client_name +can link with this subframework without error even though it is not part of +the umbrella framework that this subframework is part of. The +.I client_name +can be another framework name or a name used by bundles (see the +.BI \-client_name " client_name" +option below). +.TP +.BI \-client_name " client_name" +Specifies the +.I client_name +of a bundle for checking of allowable clients of subframeworks (see the +.BI \-allowable_client " client_name" +option above). +.TP +.BI \-sub_umbrella " framework_name" +Specifies that the +.I framework_name +being linked by a dynamic library is to be treated as one of the +subframeworks with respect to twolevel namespace. +.TP +.BI \-sub_library " library_name" +Specifies that the +.I library_name +being linked by a dynamic library is to be treated as one of the +sublibraries with respect to twolevel namespace. For example the +.I library_name +for +.I /usr/lib/libobjc_profile.A.dylib +would be +.I libobjc. +.TP +.BI \-init " sym" +The argument +.I sym +is taken to be the symbol name of the dynamic shared library initialization +routine. If any module is used from the dynamic library the library +initialization routine is called before any symbol is used from the library +including C++ static initializers (and #pragma CALL_ON_LOAD routines). +.TP +.B \-run_init_lazily +This option is obsolete. +.TP +.BI \-dylib_compatibility_version " number" +For dynamic shared library files, this specifies the compatibility version number +of the library. When a library is used by a program, 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 +.I number +is +.I X[.Y[.Z]] +where +.I X +must be a positive non-zero number less than or equal to 65535, and +.I .Y +and +.I .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 used as the +.IR libtool (1) +.BI \-compatibility_version " number" +option +when its +.B \-dynamic +option is set. +.TP +.BI \-dylib_current_version " number" +For dynamic shared library files, 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 +.I number +is +.I X[.Y[.Z]] +where +.I X +must be a positive non-zero number less than or equal to 65535, and +.I .Y +and +.I .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 used as the +.IR libtool (1) +.BI \-current_version " number" +option when its +.B \-dynamic +option is set. +.TP +.BI \-single_module +When building a dynamic library build the library so that it contains only +one module. +.TP +.BI \-multi_module +When building a dynamic library build the library so that it contains one +module for each object file linked in. This is the default. +.TP +.BI \-dylinker_install_name " name" +For dynamic link editor files, specifies the name of the file +the dynamic link editor will be installed in for programs that use it. +.TP +.BI \-macosx_version_min " version" +This overrides the +.B MACOSX_DEPLOYMENT_TARGET +environment variable (see below). Unlike other linker options, this one may +be specified multiple times; only the last occurrence is effective. +.PP +The following environment variable is used to control the use of incompatible +features in the output with respect to Mac OS X releases. +.TP +.B MACOSX_DEPLOYMENT_TARGET +This is set to indicate the oldest Mac OS X version that that the output is to +be used on. When this is set to a release that is older than the current +release features that are incompatible with that release will be disabled. If +a feature is seen in the input that can't be in the output due to this setting +a warning is issued. The current allowable values for this are +.B 10.1, +.B 10.2 +.B 10.3, +and +.B 10.4 +with the default being +.B 10.4 +for the i386 architecture and +.B 10.1 +for all other architectures. +.PP +The following environment variables are used by Apple's Build and Integration +team: +.TP +.B LD_TRACE_ARCHIVES +When this is set it causes a message of the form ``[Logging for XBS] +Used static archive: +.I filename'' +for each static archive that has members linked into the output. +.TP +.B LD_TRACE_DYLIBS +When this is set it causes a message of the form ``[Logging for XBS] +Used dynamic library: +.I filename'' +for each dynamic library linked into the output. +.TP +.B RC_TRACE_PREBINDING_DISABLED +When this is set it causes a message of the form ``[Logging for XBS +prebinding disabled for +.I filename +because +.I reason''. +Where +.I filename +is the value of the +.B \-final_output +argument if specified or the value of the +.B \-o +argument. +.TP +.BI \-final_output " filename" +The argument +.I filename +is used in the above message when RC_TRACE_PREBINDING_DISABLED is set. +.TP +.B LD_TRACE_FILE +When this is set, messages displayed due to the +.B LD_TRACE_ARCHIVES +, +.B LD_TRACE_DYLIBS +, and +.B LD_TRACE_PREBINDING_DISABLED +environment variables are printed to the file whose path is specified +by this variable instead of stdout. +.TP +.B LD_SPLITSEGS_NEW_LIBRARIES +When set and +.B MACOSX_DEPLOYMENT_TARGET +is set to 10.4 or greater and the output is a dynamic library, and if the +install name of the library is not listed the segment address table, and if the +environment variable +.B LD_UNPREBOUND_LIBRARIES +is set with a file name with a list of library install names and the install +name is not listed, then this is built as a split shared library. + +.PP +Options available in early versions of the Mach-O link editor +may no longer be supported. + +.SH FILES +.ta \w'/Network/Library/Frameworks/*.framework/*\ \ 'u +/lib/lib*.{a,dylib} libraries +.br +/usr/lib/lib*.{a,dylib} +.br +/usr/local/lib/lib*.{a,dylib} +.br +/Library/Frameworks/*.framework/* framework libraries +.br +/Network/Library/Frameworks/*.framework/* framework libraries +.br +/System/Library/Frameworks/*.framework/* framework libraries +.br +a.out output file +.SH "SEE ALSO" +as(1), ar(1), cc(1), libtool(1), ranlib(1), nm(1), otool(1) lipo(1), ld(1), +arch(3), dyld(3), Mach-O(5), strip(1), redo_prebinding(1) diff --git a/cctools/man/libsyminfo.3 b/cctools/man/libsyminfo.3 index 5d793a1a..ca693859 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 2aa4860f..526f5f4c 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 b7ee4634..84411e29 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 -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. +.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 -The -.I arch_type +The +.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 -.BI \-detailed_info -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). +.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 \-arch " arch_type input_file" -Tells -.I lipo -that -.I input_file -contains the specified architecture type. +.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 -.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 +.B \-arch_blank +option specifies that the output for the specified .I arch_type -contents of the input file with the contents of the specified -.IR file_name . +will be an MH_DYLIB_STUB file. This command requires the +.B \-output +option. .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. +.BI \-detailed_info +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 \-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 ae2ca46c..9885e8e0 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 3e5c3b22..54c0ef16 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/mtor.1 b/cctools/man/mtor.1 new file mode 100644 index 00000000..b34f3a5a --- /dev/null +++ b/cctools/man/mtor.1 @@ -0,0 +1,146 @@ +.\" Copyright (c) 2019 Apple, Inc. +.\" MDT +.Dd January 31, 2019 +.Os "Darwin" +.Dt MTOR 1 +.Sh NAME +.Nm mtor +.Nd convert Mach-O to raw binary files +.\" SYNOPSIS +.Sh SYNOPSIS +.Nm +.Op Fl nv +.Op Fl start Aq start_address +.Op Fl no_bss +.Op Fl version +.Op Fl output Ar out_file +.Ar file +.Nm +.Fl help +.Op Fl version +.Nm +.Fl version +.\" DESCRIPTION +.Sh DESCRIPTION +.Nm +converts a Mach-O preload +.Ar file +into a raw binary +.Ar out_file . +These output files represent in-core images in a ready-to-run layout that +can be flashed to firmware, burned into ROM, or otherwise run on "bare metal". This raw binary includes only the __TEXT and __DATA segments of the Mach-O file; +the Mach-O header, load commands, and other segments are ignored. By default +.Nm +positions each segment at the address stored in the segment's +.Em vmaddr +field, as displayed by +.Xr otool 1 +using the +.Fl l +(ell) command. Empty space, such as that between the start of the file and the __TEXT +segment, will be zero-filled. +.Pp +The following options are available: +.Pp +.\" OPTIONS +.Bl -tag -width "XXkeepParent" +.It Fl h , help +Print usage. +.It Fl n +Don't actually write the output file. Implies the +.Fl v +flag. +.It Fl no_bss +Omit all zero-filled sections from the __DATA segment, including those sections +marked with the S_ZEROFILL flag in +.Xr otool 1 . +In practice, the __DATA segment is truncated at the first zero-filled section. +.It Fl o , output Ar out_file +Commands that create new files write to the +.Ar out_file +file specified by the +.Fl output +flag. This option is required. +.It Fl packdata Ar data_address_symbol_name Ar data_size_symbol_name +Position the __DATA segment immediately after __TEXT regardless of __DATA's +vm address. The preload program is expeceted to manually move the __DATA +segment into it's final vm location at runtime, before referencing any data. +In order to do that, +.Nm +will write the offset to __DATA (i.e., load memory address) and its size +directly into the __TEXT segment, using two symbols supplied on the command +line. These symbols must point to 32-bit values within the program's __TEXT +segment. +.Nm +will error if the symbols do not exist in the nlist, or if they do not refer +to storage within the __TEXT segment. Because the Mach-O nlist does not contain +symbol sizes, the 32-bit storage requirement cannot be verified, although +.Nm +will warn if +.Ar data_address_symbol_name +or +.Ar data_size_symbol_name +have not been pre-initialized to 0. +.It Fl start Ar start_address +Position the __TEXT segment at the specified address instead of honoring the +__TEXT segment's vmaddr location. The __DATA segment will also be adjusted by +a similar amount so that the relative distance between __TEXT and __DATA is +preserved. +.Nm +will warn and return a non-zero exit code if one or more sections is no longer +aligned to their section alignment. The +.Xr ld 1 +flags +.Fl image_base +and +.Fl seg1addr +are also synonyms for this option. +.It Fl v +Print verbose information about the segments being extracted into the output +file. +.It Fl version +Print version information. +.El +.\" CAVEAT MTOR +.Sh CAVEAT MTOR +Only Mach-O preload files can be processed by +.Nm . +Use the +.Fl preload +option to +.Xr ld 1 +to generate preload files. A Mach-O file's type can be viewed by passing the +.Fl hv +flags to +.Xr otool 1 . +.Pp +While +.Nm +can change the __TEXT section's starting address via the +.Fl start +option, the file contents cannot be relinked. Segments and sections cannot be +realigned or moved independently from each other. If segments or sections need +to be at specific addresses or be positioned within specific alignment +constraints, use +.Xr ld 1 's +.Fl seg1addr , +.Fl segalign , +and similar options to produce a Mach-O binary within those constraints. +.\" SEE ALSO +.Sh SEE ALSO +.Xr ld 1 , +.Xr lipo 1 , +.Xr otool 1 , +.Xr otool-classic 1 , +.Xr Mach-O 5 . +.\" HISTORY +.\" .Sh HISTORY +.\" BUGS +.Sh BUGS +The +.Nm +tool only works on Mach-O binaries. It current does not support universal +(multi-architectural) files. Use +.Xr lipo 1 +to extract stand-alone Mach-O files from universal files before running +.Nm . diff --git a/cctools/man/nm.1 b/cctools/man/nm.1 index f459b102..20531672 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 4ebff3e0..2c10141a 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 e1b3b23a..158afd01 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 b659573a..7809c7e3 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 bc70974f..b8d67436 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 47df8027..1b16dff7 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 256f2039..0f411909 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/rld.3 b/cctools/man/rld.3 new file mode 100644 index 00000000..5183218b --- /dev/null +++ b/cctools/man/rld.3 @@ -0,0 +1,333 @@ +.TH RLD 3 "July 28, 2005" "Apple Computer, Inc." +.SH NAME +rld_load, rld_load_from_memory, rld_unload, rld_lookup, rld_forget_symbol, rld_unload_all, rld_load_basefile, rld_address_func, rld_write_symfile \- programmatically link edit and load object files +.SH SYNOPSIS +.nf +.PP +#include +extern long rld_load( + NXStream *stream, + struct mach_header **header_addr, + const char * const *object_filenames, + const char *output_filename); +.sp .5 +extern long rld_load_from_memory( + NXStream *stream, + struct mach_header **header_addr, + const char *object_name, + char *object_addr, + long *object_size, + const char *output_filename); +.sp .5 +extern long rld_unload( + NXStream *stream); +.sp .5 +extern long rld_lookup( + NXStream *stream, + const char *symbol_name, + unsigned long *value); +.sp .5 +extern long rld_forget_symbol( + NXStream *stream, + const char *symbol_name); +.sp .5 +extern long rld_unload_all( + NXStream *stream, + long deallocate_sets); +.sp .5 +extern long rld_load_basefile( + NXStream *stream, + const char *base_filename); +.sp.5 +extern void rld_address_func( + unsigned long (*func)(unsigned long size, unsigned long headers_size)); +.sp .5 +extern long rld_write_symfile( + NXStream *stream, + const char *output_filename); +.fi +.SH DESCRIPTION +.I rld_load +link edits and loads the files specified by the NULL-terminated array +.I object_filenames +into the program that called it. Alternatively, it can be used to load into another program. +An object name can be an archive, in which case only those members defining +undefined symbols will be loaded. +.PP +If the program is to allow the loaded +object files to use symbols from itself, it must be built with the +.B \-seglinkedit +option of the link editor, +.IR ld (1), +in order to have its symbol table mapped into memory. +.PP +The symbol table may be trimmed to limit which symbols are allowed to be +referenced by loaded objects. This can be accomplished with the +.B "\-s filename" +option to +.IR strip (1). +For the routines described here, only global symbols are used, so local +symbols can be removed with the +.B \-x +option to +.IR ld (1) +or +.IR strip (1). +Doing so saves space in the final program and vastly decreases the time +spent by the first call to +.IR rld_load . +(This is true of the first call in the program, as well as the first call after an invocation of +.IR rld_unload_all). +The first call to +.I rld_load +must go through all the symbols of the program, so if the program has been +compiled for debugging (for example), it can take orders of magnitude longer. +.PP +Since the objects loaded with +.I rld_load +can only use symbols that appear in the executable program, +if the program uses a library and wants to make all the symbols in that +library available to the loaded objects, it must force all of the library +symbols into the executable. +This can be done for all libraries with the +.B \-all_load +option to +.IR ld (1) +when building the executable. For libraries that aren't shared, however, +this will copy all the library code into the executable. +Thus this approach may be desirable only for the shared libraries, where the library code isn't copied into the executable. +This can be done easily for shared libraries by having the +executable program reference the shared library reference symbol for each of +the shared libraries it uses. The shared library reference symbol is named +after the base name of the target library (its name up to the first '.'). +For example, the target +shared library +.I /usr/shlib/libsys_s.B.shlib +has the shared library reference symbol +.I libsys_s. +This name intentionally doesn't start with an underscore, '_', +in order to be out of the normal name space for C external symbols. +So to reference the symbol in this example, +.IR ld (1) +would be invoked with the flag +.BI \-u " libsys_s" +when linking the program, and this flag would come before the library on +the link edit command line. +If new routines and data are added to the target shared library, +they will be unavailable to objects loaded with +.I rld_load +until the program is relinked against the host shared library that matches the +target shared library. This approach is necessary to avoid link editing and +loading errors that would otherwise be very hard to detect. +.PP +The set of object files being +loaded will only be successful if there are no link edit errors (undefined +symbols, etc.). If an error occurs, the set of object files is unloaded +automatically. If errors occur, and the value specified for +.I stream +isn't NULL, error messages are printed on that stream. +If the link editing and loading is successful, +the address of the header of what was loaded is returned +through the pointer +.I header_addr +(if it isn't NULL). +If +.I rld_load +is successful and the parameter +.I output_filename +isn't NULL, an object file is written to that filename. +This file can be used with the +.IR gdb (1) +.I add-file +command to debug the code in the dynamically loaded set of objects. +When the program being debugged is using rld to load into itself, +the debugger +knows how to get the symbols automatically in most cases, and the +.I output_filename +parameter isn't needed. However, if some other program is +using rld to load into the program being +debugged, or if the specified objects +don't contain full paths, the debugger can't do this automatically. +The +.I rld_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 rld_load +and the other routines described here will fail. +.PP +.I rld_load_from_memory() +is similar to +.IR rld_load() , +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. +.I rld_load_from_memory() +only allows one thin object file (not an archive or ``universal'' file) to be +loaded. +.PP +.I rld_unload() +unlinks and unloads the last set of objects that were loaded. +It returns 1 if it is successful and 0 otherwise. If any errors occur +and +.I stream +isn't zero, the error messages are printed +on that stream. It's the caller's responsibility not to have any pointers +into the data areas of the object set, as well as to deallocate +any memory which that set of objects may have allocated. +.PP +.I rld_lookup() +looks up the specified symbol name and returns its value indirectly through the pointer +.I value. +It returns 1 if it finds the symbol, and 0 otherwise. If any errors occur and +.I stream +isn't zero, the error messages are printed on +that stream. (For this routine, only internal errors can result.) +.PP +.I rld_forget_symbol() +causes this package to forget the existence of the specified symbol name. +This allows a new object to be loaded that defines this symbol. All objects +loaded before this call will continue to use the value of the symbol in effect +at the time the object was loaded. +It returns 1 if it finds the symbol and 0 otherwise. If any errors occur and +.I stream +isn't zero, the error messages are printed on +that stream. (For this routine, only internal errors can result.) +.PP +.I rld_unload_all() +clears out all allocated data structures used by these routines. If the +parameter +.I deallocate_sets +is non-zero, the function also unloads all object sets 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 +described here will no longer know +about the symbols in those sets. If object sets aren't to be allowed access +to each other's symbols, an +.I rld_unload_all +call between calls to +.I rld_load +allows the objects sets to be loaded without fear of global symbol +names' clashing. +.I rld_unload_all +returns 1 if it is successful and 0 otherwise. If any errors occur +and +.I stream +isn't zero, the error messages are printed on that stream. +.PP +The second argument to +.IR rld_load_basefile +specifies a base file, whose symbol table is taken as the +basis for subsequent +.I rld_load's. +The base file may be a ``universal'' file, and +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) +would select) is used as the base file. +.I rld_load_basefile +must be invoked before any call to +.I rld_load. +Alternatively, it can be called after +.IR rld_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 +.I base_filename +contains the symbol table of the target program. The routine +.IR rld_address_func , +described next, would also be used. +.PP +.I rld_address_func +is passed a pointer to a function, +.IR func , +that will be called from +.IR rld_load . +The parameter values that +.I rld_load +will supply to +.I func +are the size of the memory required for the object set being loaded, +and the size of the headers (which are also included in the +calculation of +.IR size ). +The function +specified by +.I func +should return the address where the output is to be link edited. +.I rld_address_func +is +intended to be used when a program is dynamically loading object sets into a +program other than itself; the function allows it to pick the place in the +address space of the target program. +.PP +.I rld_write_symfile() +writes an object file containing only absolute symbols that mirrors that last +object set loaded. This file can later be used to recreate the loaded state +after the sets have been unloaded. It returns 1 for success and 0 for failure. + +.SH "UNIVERSAL FILE SUPPORT" +All functions that accept object files or archives also accept ``universal'' +files, except for the restrictions noted above for +.I rld_load_from_memory +and +.IR rld_load_basefile . + +.SH "CPU SUBTYPE HANDLING" +For compatibility (and due to existing bugs in the the CPU subtype handling), +the +.IR rld (3) +package will function as if the +.IR ld (1) +.B \-force_cpusubtype_ALL +option were specified. +As of the NEXTSTEP 3.0 release, the +.IR rld (3) +package doesn't do the same checking as +.IR exec (2) +does with regard to the handling of the CPU subtype. In the case of the +m68k architecture, +if an object file with the 68040 CPU subtype +is used with the +.IR rld (3) +package on a 68030 machine, no error is generated. This ``bug'' has the same effect as the +.IR ld (1) +.B \-force_cpusubtype_ALL +option, but it lacks the error detection supported by +.IR exec (2). +Since adding the error detection could break existing uses of +.IR rld (3), +the +.IR rld (3) +package functions as though the +.B \-force_cpusubtype_ALL +option to +.IR ld (1) +were specified. + +.SH "SEE ALSO" +ld(1), strip(1), gdb(1) + +.SH BUGS +There exists one semantic link edit problem with respect to common symbols. +If a set of object files are loaded that have common symbols left after the +symbols have been merged, +.I rld_load +has to allocate storage for these symbols +for the code to run without error. The problem occurs if, on a later call to +.IR rld_load , +one of the common symbols that +.I rld_load +allocated appears in an object +file as a defining symbol (not a common or undefined symbol). In this case, +.I rld_load +will report the symbol as being multiply defined. However, if this combination +of object files were statically linked, no error would occur. diff --git a/cctools/man/seg_addr_table.1 b/cctools/man/seg_addr_table.1 index 3e7ebb65..c73c1d0f 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 72570381..ad8dc84d 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 8a997c39..e5c70b7e 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 2f7ff3e7..a2884e20 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 08c9f1b3..4924745b 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 b0ac933e..8c25ba0d 100644 --- a/cctools/man/strip.1 +++ b/cctools/man/strip.1 @@ -1,4 +1,4 @@ -.TH STRIP 1 "February 25, 2016" "Apple, 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,7 +209,7 @@ 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 @@ -215,8 +217,15 @@ and other compilers). Remove the local symbols whose names begin with `L'. .TP .B \-T -Remove the symbols whose names begin with `\_\^\_T'. -.TP +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 @@ -260,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/man/vtool.1 b/cctools/man/vtool.1 new file mode 100644 index 00000000..ebc7cedf --- /dev/null +++ b/cctools/man/vtool.1 @@ -0,0 +1,340 @@ +.ig + + Copyright (c) 2019 Apple Inc. All Rights Reserved. + +.. +.Dd December 31, 2018 +.Os "Darwin" +.Dt VTOOL 1 +.Sh NAME +.Nm vtool +.Nd Mach-O version number utility +.\" SYNOPSIS +.Sh SYNOPSIS +.Nm +.Op Fl arch Aq arch +.Ar ... +.Aq Ar show\ command +.Ar ... +.Ar file +.Nm +.Op Fl arch Aq arch +.Ar ... +.Aq Ar set\ command +.Ar ... +.Op Fl replace +.Fl output Ar out_file +.Ar file +.Nm +.Op Fl arch Aq arch +.Ar ... +.Aq Ar remove\ command +.Ar ... +.Fl output Ar out_file +.Ar file +.Nm +.Fl help +.\" DESCRIPTION +.Sh DESCRIPTION +The +.Nm +utility displays and edits build and source version numbers embedded in the +.Xr Mach-O 5 +file format. These version numbers are stored within the Mach-O load +commands, as described in the +.Aq Pa mach-o/loader.h +header file and in the +.Sx VERSION LOAD COMMANDS +section below. When editing files, a new +.Ar out_file +must be specified using the +.Fl output +flag; +.Nm +will only ever write to a single output file, and input files are never modified +in place. +.Pp +.Nm +operates in one of three functional modes (in addition to a +.Em help +mode) depending on the type of arguments specified on the command line: +.Em show , +.Em set , +and +.Em remove . +All of these modes operate on +.Dq universal +(multi-architecture) files as well as +ordinary Mach-O files. The +.Fl arch +flag limits operation to one or more architectures within a universal file. +.Pp +.Bl -tag -width "XXkeepParent" +.It Em Show +Show options include +.Fl show , +.Fl show-build , +.Fl show-source , +and +.Fl show-space . +Only one of these commands may be specified. The version information will be +printed in a manner similar to +.Xr otool 1 +or +.Xr otool-classic 1 . +.It Em Set +Set options include +.Fl set-build-tool , +.Fl set-build-version , +.Fl set-source-version , +and +.Fl set-version-min . +Any number of these commands can be combined in a single +.Nm +invocation. You can use these set commands to add a new build version to a +Mach-O or to replace an existing version for a specific platform. When used +with the +.Fl replace +option, all existing build versions will be entirely replaced by the new +build versions specified on the command line. +.It Em Remove +Remove options include +.Fl remove-build-tool , +.Fl remove-build-version , +and +.Fl remove-source-version . +Any number of these commands can be combined in a single +.Nm +invocation. +.El +.Pp +Currently +.Nm +only operates on final linked binaries, such as executable files, dynamic +libraries, and bundles. Because the executable code in Mach-O final linked +binaries cannot be moved or resized, and because the load commands reside +between the mach header and the executable code, there is only a limited amount +of space available for +.Nm +to save changes. Set operations that add or resize load commands may fail if +there isn't enough space in the Mach-O file availble to hold the new load +commands. +.\" OPTIONS +.Sh OPTIONS +.Bl -tag -width "XXkeepParent" +.It Fl arch Aq arch +Specifies the architecture, +.Aq arch , +for +.Nm +to operate on when the file is a universal (multi-architecture) file. See +.Xr arch 3 +for the current list of architectures. More than one architecture can be +specified, and by default +.Nm +will operate on all architectures in a universal file. +.It Fl h , help +Print full usage. +.It Fl o , output Ar out_file +Commands that create new files write to the +.Ar out_file +file specified by the +.Fl output +flag. This option is required for all set and remove commands. +.It Fl r , replace +When used with +.Fl set-build-version +or +.Fl set-version-min +the +.Fl replace +option instructs +.Nm +to discard all of the existing build versions from the input file. Use this to +change a file's platform in a single call to +.Nm . +When used with the +.Fl set-build-tool +command, +.Nm +will discard all of the existing tool versions from the specified platform's +build version. This option has no effect on source versions. +.It Fl remove-build-tool Ar platform tool +Removes +.Ar tool +from the +.Ar platform +build version. A build version for the specified platform must exist in the +input file and that build version must be an +.Dv LC_BUILD_VERSION . +Must be used with +.Fl output . +See +.Sx VERSION LOAD COMMANDS +for more information on platform and tool values. +.It Fl remove-build-version Ar platform +Removes the build version for the specified +.Ar platform . +Must be used with +.Fl output . +See +.Sx VERSION LOAD COMMANDS +for more information on platform values. +.It Fl remove-source-version +Removes the source version from the Mach-O file. Must be used with +.Fl output . +.It Fl set-build-tool Ar platform tool version +Updates the build version load command for +.Ar platform +to include the specified +.Ar tool , +adding a new tool entry if necessary. The build version must be an +.Em LC_BUILD_VERSION +load command which either already existss within the input file or is newly +specified on the command line. The +.Ar version +field takes the format X.Y.Z. Must be used with +.Fl output . +See +.Sx VERSION LOAD COMMANDS +for more information on platform and tool values. +.It Fl set-build-version Ar platform minos sdk Op Fl tool Ar tool version +Create or update the +.Em LC_BUILD_VERSION +load command for +.Ar platform +to include the specified +.Ar minos +and +.Ar sdk +version numbers, and zero or more optional tools. The +.Ar minos , sdk , +and tool +.Ar version +all take the format X.Y.Z. Must be used with +.Fl output . +See +.Sx VERSION LOAD COMMANDS +for more information on platform and tool values. +.It Fl set-source-version Ar version +Create or update the source version load command. +.Ar version +takes the format A.B.C.D.E. Must be used with +.Fl output . +.It Fl set-version-min Ar platform minos sdk +Create or update an +.Em LC_VERSION_MIN_* +load command for +.Ar platform . +This option is included to support older operating systems, and generally one +should favor +.Fl set-build-version +instead. Note that version min load commands do not support tool versions, and +not all platforms can be expressed using version min load commands. Must be used +with +.Fl output . +.It Fl show , show-all +Display the build and source versions within the specified file. This option +cannot be combined with other commands. +.It Fl show-build +Display the build versions within the specified file. This option cannot be +combined with other commands. +.It Fl show-source +Display the source version within the specified file. This option cannot be +combined with other commands. +.It Fl show-space +Show the space in the file consumed by the mach header and the existing load +commands, and measure the amount of additional space available for adding new +load commands. +.It Fl +A single dash instructs +.Nm +to stop parsing arguments. This is useful for operating on files whose names +would otherwise be interpreted as an option or flag. +.El +.\" VERSION LOAD COMMANDS +.Sh VERSION LOAD COMMANDS +Modern Mach-O files can contain multiple build versions, one for each unqiue +.Em platform +represented in the file. A platform is a loosely-defined concept within +Mach-O, most often used to identify different Darwin operating systems, such +as +.Em macOS +and +.Em iOS . +Platforms and tools can be specified either by name (e.g., +.Qq macos +or +.Qq clang ) +or by number (e.g., +.Qq 1 ) . +Common platform and tool constants are defined in +.Aq Pa mach-o/loader.h +and +.Nm +will display platform and tool names when invoked with +.Fl help . +.Pp +Modern Mach-O files store build information in one or more +.Dv LC_BUILD_VERSION +load commands. +.Dv LC_BUILD_VERSION +supports arbitrary platforms and can include version information about the +tools used to build the Mach-O file. Older +Mach-O files use a +.Dq version min +load command, such as +.Dv LC_VERSION_MIN_MACOSX . +While version min commands are appropriate when deploying Mach-O files on older +operating systems, be aware that they do not support tool versions, and +version min load commands do not exist for all possible platforms. In some cases +.Dv LC_BUILD_VERSION +and +.Dv LC_VERSION_MIN_* +load commands can appear in a single Mach-O file, but many restrictions apply, +and +.Nm +may not enforce these restrictions. +.Nm +will prevent you from writing more than one build version load command for the +same platform. +.Pp +Source versions are stored in a single +.Dv LC_SOURCE_VERSION +load command. +.Pp +When writing new load commands, +.Nm +will attempt to preserve the order of the load commands as they appear on the +command line. No attempt is made to preserve positions relative to other +existing load commands. Editing an existing load command may have the side +effect of moving the load command to the end of the load command list. +.\" SEE ALSO +.Sh SEE ALSO +.Xr ld 1 , +.Xr lipo 1 , +.Xr otool-classic 1 , +.Xr arch 3 , +.Xr Mach-O 5 . +.\" HISTORY +.Sh HISTORY +.Em LC_BUILD_VERSION +first appeared in macOS 10.13 in 2017 for use with the bridgeOS platform. +.Pp +.Em LC_BUILD_VERSION +became the default build version load command for the macOS, iOS, tvOS, and +watchOS platforms in 2018 with macOS 10.14, iOS 12.0, and friends. The list of +platforms also grew to include iOSSimulator, tvOSSimulator, and +watchOSSimulator. +.Pp +.Nm +first appeared in macOS 10.15 and iOS 13.0 in 2019. +.\" BUGS +.Sh BUGS +.Nm +will write load commands in a different order than +.Xr ld 1 . +.Pp +Currently +.Nm +does not work with object files or archives. diff --git a/cctools/misc/Makefile b/cctools/misc/Makefile index 6f48e62a..11323784 100644 --- a/cctools/misc/Makefile +++ b/cctools/misc/Makefile @@ -33,6 +33,7 @@ OBJROOT = . OFILE_DIR = $(OBJROOT) VPATH = $(OFILE_DIR) SYMROOT = . +RAW_DSTROOT ?= $(DSTROOT) BINDIR = /bin USRBINDIR = /usr/bin @@ -356,9 +357,17 @@ dt_install: $(DSTROOT)$(USRBINDIR)/install_name_tool install -c -s -m 555 $(SYMROOT)/codesign_allocate.NEW \ $(DSTROOT)$(USRBINDIR)/codesign_allocate - $(MKDIRS) $(RAW_DSTROOT)/usr/libexec/DeveloperTools - cp $(DSTROOT)$(USRBINDIR)/codesign_allocate \ - $(RAW_DSTROOT)/usr/libexec/DeveloperTools + (cd $(DSTROOT)$(USRBINDIR); rm -f codesign_allocate-p; \ + ln -s codesign_allocate codesign_allocate-p) + rcName=`echo $(RC_ProjectName)`; \ + if [ "$(RC_MACOS)" != "" -o "$(RC_XCODE)" != "" ] && \ + [ "$$rcName" != "cctools_Fall2018" ]; \ + then \ + $(MKDIRS) $(RAW_DSTROOT)/usr/libexec/DeveloperTools; \ + rm -f $(RAW_DSTROOT)/usr/libexec/DeveloperTools/codesign_allocate;\ + cp $(DSTROOT)$(USRBINDIR)/codesign_allocate \ + $(RAW_DSTROOT)/usr/libexec/DeveloperTools; \ + fi install -c -s -m 555 $(SYMROOT)/ctf_insert.NEW \ $(DSTROOT)$(USRBINDIR)/ctf_insert install -c -s -m 555 $(SYMROOT)/bitcode_strip.NEW \ diff --git a/cctools/misc/bitcode_strip.c b/cctools/misc/bitcode_strip.c index bfecf768..b68566a0 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, @@ -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; } @@ -371,7 +373,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){ @@ -511,13 +513,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 */ } /* @@ -597,8 +601,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 @@ -610,7 +615,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; @@ -619,7 +625,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){ @@ -719,6 +725,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){ @@ -954,7 +978,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; } @@ -976,7 +1000,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 @@ -985,12 +1011,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 @@ -1012,7 +1038,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 @@ -1020,8 +1047,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; @@ -1031,8 +1063,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); @@ -1044,9 +1086,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; @@ -1071,8 +1133,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); @@ -1084,12 +1156,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++){ @@ -1099,7 +1192,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; } @@ -1129,6 +1223,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){ @@ -1244,7 +1352,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); } /* @@ -1359,13 +1468,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; @@ -1374,6 +1487,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 @@ -1404,19 +1519,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++; } } @@ -1429,19 +1551,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++; } } @@ -1456,6 +1585,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; @@ -1567,6 +1706,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); } @@ -1647,8 +1793,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) @@ -1819,6 +1965,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 cf59ff17..72b4fe94 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; /* @@ -115,7 +111,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; @@ -189,8 +185,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){ @@ -204,8 +199,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){ @@ -218,6 +212,8 @@ char **envp) usage(); } seg_addr_table_filename = argv[i+1]; + printf("warning: -seg_addr_table_filename is no longer " + "used.\n"); i++; } else{ @@ -313,8 +309,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-Info.plist b/cctools/misc/codesign_allocate-Info.plist new file mode 100644 index 00000000..22a87eb5 --- /dev/null +++ b/cctools/misc/codesign_allocate-Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleIdentifier + com.apple.tool.codesign_allocate.standard + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + codesign_allocate + CFBundleVersion + 0.3 + Application-Group + com.apple.tool.codesign_allocate + + diff --git a/cctools/misc/codesign_allocate.c b/cctools/misc/codesign_allocate.c index 6cbeb8e0..7c99e7a7 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,6 +65,11 @@ 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; @@ -70,10 +78,12 @@ extern char xtools_version[]; extern char package_version[]; extern char support_url[]; +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 @@ -89,6 +99,18 @@ 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]; pnam = strrchr(progname, '/'); pnam = (pnam)?pnam+1:progname; @@ -96,6 +118,14 @@ char **envp) 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], "--version") == 0){ /* Implement a gnu-style --version. */ @@ -149,7 +179,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]); @@ -171,13 +201,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]); @@ -188,7 +218,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]); @@ -201,13 +231,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) @@ -240,8 +281,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); } @@ -283,7 +324,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; } @@ -315,9 +356,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 @@ -326,15 +368,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. */ @@ -453,6 +509,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 = @@ -508,6 +576,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 * @@ -530,30 +604,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. @@ -584,20 +706,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 = @@ -609,9 +766,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. @@ -628,8 +784,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 @@ -638,10 +794,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; @@ -654,7 +825,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){ @@ -709,7 +880,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; @@ -726,11 +900,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; } } @@ -750,8 +925,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); @@ -794,3 +970,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 ad754fb0..7d2cb1cd 100644 --- a/cctools/misc/ctf_insert.c +++ b/cctools/misc/ctf_insert.c @@ -163,7 +163,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; @@ -265,7 +265,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; } @@ -432,11 +432,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){ @@ -563,7 +563,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); @@ -589,7 +589,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; @@ -602,7 +602,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 d03e5202..8772f71d 100644 --- a/cctools/misc/indr.c +++ b/cctools/misc/indr.c @@ -410,7 +410,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; /* @@ -569,7 +570,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; } @@ -833,8 +834,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; @@ -1039,7 +1041,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'; @@ -1067,7 +1069,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; @@ -1086,13 +1089,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; } } @@ -1103,7 +1108,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; @@ -1111,7 +1116,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++; } @@ -1127,7 +1132,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; @@ -1149,7 +1154,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; @@ -1183,14 +1188,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; @@ -1348,11 +1353,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; } @@ -1508,7 +1513,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; } @@ -1603,7 +1608,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); @@ -1815,7 +1820,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){ @@ -1839,7 +1845,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/install_name_tool.c b/cctools/misc/install_name_tool.c index 8aca5028..4d5f4d97 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; @@ -164,28 +155,11 @@ char **envp) fprintf(stdout, "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", pnam); fprintf(stdout, "Please report bugs to %s\n", support_url); exit(0); } -#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]); @@ -383,9 +357,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); } @@ -405,7 +376,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{ @@ -427,7 +397,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; @@ -448,7 +419,7 @@ char *input) 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 @@ -493,7 +464,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); @@ -502,165 +473,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 @@ -726,7 +538,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; @@ -741,7 +553,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; @@ -756,9 +568,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); @@ -825,8 +637,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; @@ -866,8 +678,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; } @@ -902,7 +714,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); @@ -924,7 +736,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); @@ -948,10 +760,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 = @@ -962,7 +774,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 + @@ -1000,8 +812,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; @@ -1028,8 +840,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; @@ -1122,6 +934,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 eef41751..1981db87 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,8 @@ #include #include #include +#include +#include "stuff/args.h" #include "stuff/bool.h" #include "stuff/ofile.h" #include "stuff/rnd.h" @@ -48,6 +51,7 @@ #include "stuff/execute.h" #include "stuff/version_number.h" #include "stuff/unix_standard_mode.h" +#include "stuff/write64.h" #ifdef LTO_SUPPORT #include "stuff/lto.h" #endif /* LTO_SUPPORT */ @@ -82,10 +86,32 @@ char *pnam = 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 @@ -94,11 +120,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 */ @@ -114,6 +135,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 */ @@ -146,9 +168,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; @@ -241,6 +270,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( int); static void process( @@ -314,8 +352,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 @@ -345,9 +385,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[]; @@ -371,33 +411,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 */ pnam = strrchr(argv[0], '/'); if(pnam != NULL) @@ -414,6 +434,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); @@ -644,7 +669,7 @@ char **envp) error("more than one: %s option specified", argv[i]); usage(EXIT_FAILURE); } - 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]); @@ -666,7 +691,7 @@ char **envp) error("more than one: %s option specified", argv[i]); usage(EXIT_FAILURE); } - 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]); @@ -688,7 +713,7 @@ char **envp) error("more than one: %s option specified", argv[i]); usage(EXIT_FAILURE); } - 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]); @@ -942,7 +967,6 @@ char **envp) usage(EXIT_FAILURE); } 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){ @@ -954,7 +978,6 @@ char **envp) usage(EXIT_FAILURE); } cmd_flags.files[cmd_flags.nfiles++] = argv[i]; - lflags_seen = TRUE; } else if(strcmp(argv[i], "-framework") == 0 || strcmp(argv[i], "-weak_framework") == 0 || @@ -969,7 +992,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){ @@ -1107,6 +1129,9 @@ char **envp) argv[i][j], argv[i]); usage(EXIT_FAILURE); } + case 'D': + cmd_flags.D = TRUE; + break; default: error("unknown option character `%c' in: %s", argv[i][j], argv[i]); @@ -1118,14 +1143,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("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("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("ZERO_AR_DATE") == NULL) + zero_ar_date = FALSE; + else + zero_ar_date = TRUE; /* * If either -syslibroot or the environment variable NEXT_ROOT is set @@ -1304,6 +1352,36 @@ 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__ +# if XTOOLS_HAS_CLOCK_GETTIME + if (clock_gettime(CLOCK_REALTIME, &toc_timespec)) { + system_fatal("clock_gettime failed"); + return(EXIT_FAILURE); + } + toc_time = toc_timespec.tv_sec; +# else + if (gettimeofday(&toc_timeval, NULL)) { + system_fatal("gettimeofday failed"); + return(EXIT_FAILURE); + } + toc_time = toc_timeval.tv_sec; +# endif +#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) @@ -1352,7 +1430,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 @@ -1390,20 +1468,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){ @@ -1463,18 +1534,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 && @@ -1555,7 +1621,7 @@ void) "library)", cmd_flags.files[i]); } } - + if(cmd_flags.ranlib == TRUE){ /* * In the case where ranlib is being used on an archive that @@ -1596,6 +1662,10 @@ void) 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. @@ -1787,21 +1857,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; @@ -1854,6 +1924,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) @@ -1875,6 +1946,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; @@ -1903,6 +1976,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) @@ -1924,6 +1998,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; @@ -1952,6 +2028,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( @@ -1970,6 +2047,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( @@ -2054,7 +2132,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 @@ -2070,9 +2148,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)), @@ -2097,8 +2175,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. */ @@ -2158,9 +2246,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)), @@ -2175,9 +2263,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) - @@ -2233,7 +2321,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); @@ -2322,7 +2410,6 @@ 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; @@ -2330,13 +2417,25 @@ struct ofile *ofile) struct fat_arch_64 *fat_arch64; int fd; #ifndef __OPENSTEP__ - struct utimbuf timep; + struct timeval timep[2]; #else time_t timep[2]; #endif 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){ @@ -2437,6 +2536,7 @@ 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 && @@ -2444,6 +2544,8 @@ struct ofile *ofile) 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 @@ -2451,12 +2553,19 @@ struct ofile *ofile) */ if(strncmp(ofile->toc_ar_hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){ - if(archs[0].toc_long_name != TRUE) - goto fail_to_update_toc_in_place; + /* + * 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; } /* @@ -2465,7 +2574,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){ @@ -2475,10 +2583,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 @@ -2504,7 +2620,7 @@ struct ofile *ofile) 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].toc_ranlibs[i].ran_off = (uint32_t) archs[0].members[j].input_member_offset; break; } @@ -2569,7 +2685,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); @@ -2580,300 +2695,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: - - /* - * 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); + } /* write_in_place == TRUE */ + else { /* if (write_in_place != TRUE) */ + char *library, *p, *flush_start; + + /* 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 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_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 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_header->magic = FAT_MAGIC; + fat_header->nfat_arch = narchs; + offset = sizeof(struct fat_header); if(cmd_flags.fat64 == TRUE){ - fat_arch64[i].cputype = archs[i].arch_flag.cputype; - fat_arch64[i].cpusubtype = archs[i].arch_flag.cpusubtype; + offset += sizeof(struct fat_arch_64) * narchs; + fat_arch64 = (struct fat_arch_64 *) + (library + sizeof(struct fat_header)); + fat_arch = NULL; } else{ - fat_arch[i].cputype = archs[i].arch_flag.cputype; - fat_arch[i].cpusubtype = archs[i].arch_flag.cpusubtype; + offset += sizeof(struct fat_arch) * narchs; + fat_arch = (struct fat_arch *) + (library + sizeof(struct fat_header)); + fat_arch64 = NULL; } - 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){ + 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) - fat_arch64[i].align = 3; + offset = rnd(offset, 1 << fat_arch64[i].align); else - fat_arch[i].align = 3; - } - 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].align = 2; + fat_arch64[i].size = archs[i].size; else - fat_arch[i].align = 2; + 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); 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; + swap_fat_arch_64(fat_arch64, narchs, BIG_ENDIAN_BYTE_SEX); else - fat_arch[i].offset = 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); + swap_fat_arch(fat_arch, narchs, BIG_ENDIAN_BYTE_SEX); +#endif /* __LITTLE_ENDIAN__ */ + offset = sizeof(struct fat_header); if(cmd_flags.fat64 == TRUE) - fat_arch64[i].size = archs[i].size; + offset += sizeof(struct fat_arch_64) * narchs; else - fat_arch[i].size = archs[i].size; - offset += archs[i].size; - } - if(errors != 0){ - (void)unlink(output); - return; + offset += sizeof(struct fat_arch) * narchs; } -#ifdef __LITTLE_ENDIAN__ - 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 - 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); - - /* - * 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; + offset = 0; + + /* flush out the fat headers if any */ + output_flush(library, library_size, fd, 0, offset); /* - * 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); - else - warning("warning for library: %s the table of contents is " - "empty (no object file members in the library " - "define global symbols)", output); - } - - /* - * 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. + * The time_offsets array records the offsets to the table of + * contents archive header's ar_date fields. */ - p = put_toc_member(p, arch, host_byte_sex, target_byte_sex); - - output_flush(library, library_size, fd, flush_start - library, - p - flush_start); - + time_offsets = allocate(narchs * sizeof(uint64_t)); + /* - * Put in the archive header and member contents for each member. + * Now put each arch in the buffer. */ - 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"); - } - 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"); + 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); } - 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(write(fd, library, library_size) != (int)library_size){ - system_error("can't write output file: %s", output); - return; + /* + * 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(close(fd) == -1){ - system_fatal("can't close output file: %s", output); - return; - } + else{ + final_output_flush(library, fd); + } + } /* if write_in_place != TRUE */ -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. + * 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(stat(output, &stat_buf) == -1){ - system_fatal("can't stat file output file: %s", output); + if (fstat(fd, &stat_buf) == -1) { + system_fatal("can't stat output file: %s", + tempfile ? tempfile : 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 @@ -2883,20 +3030,24 @@ struct ofile *ofile) (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; } /* @@ -2904,24 +3055,48 @@ struct ofile *ofile) * when we first closed it. */ #ifndef __OPENSTEP__ - timep.actime = stat_buf.st_mtime; - timep.modtime = stat_buf.st_mtime; - if(utime(output, &timep) == -1) +# ifdef XTOOLS_HAS_CLOCK_GETTIME + 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); +# endif #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"); + + /* + * 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; + } + } } /* @@ -2988,20 +3163,20 @@ enum byte_sex target_byte_sex) } if(arch->using_64toc == FALSE){ - l = arch->toc_nranlibs * sizeof(struct ranlib); + 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, + 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; + l = (uint32_t)arch->toc_strsize; if(target_byte_sex != host_byte_sex) l = SWAP_INT(l); memcpy(p, (char *)&l, sizeof(uint32_t)); @@ -3059,7 +3234,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; @@ -3162,11 +3338,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; } @@ -3186,7 +3362,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; @@ -3205,11 +3381,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; @@ -3227,8 +3403,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; @@ -3257,8 +3433,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) @@ -3286,10 +3462,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(); @@ -3321,8 +3496,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) @@ -3385,18 +3560,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)); } /* @@ -3505,31 +3681,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++){ @@ -3953,11 +4128,11 @@ 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 + @@ -4030,11 +4205,11 @@ char *output) * a uint64_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(uint64_t) + arch->toc_nranlibs * sizeof(struct ranlib_64) + sizeof(uint64_t) + - arch->toc_strsize; + 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) - @@ -4053,9 +4228,9 @@ char *output) } else{ arch->toc_ranlibs[i].ran_un.ran_strx = - arch->tocs[i].name - arch->toc_strings; + (uint32_t)(arch->tocs[i].name - arch->toc_strings); arch->toc_ranlibs[i].ran_off = - arch->members[arch->tocs[i].index1 - 1].offset; + (uint32_t)(arch->members[arch->tocs[i].index1 - 1].offset); } } @@ -4065,9 +4240,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), @@ -4401,42 +4576,92 @@ 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"); + } + + 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; - - 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; - } + int length; + + 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 b99761aa..0f10681a 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,9 @@ #include "stuff/errors.h" #include "stuff/allocate.h" #include "stuff/lto.h" +#include "stuff/write64.h" +#include "stuff/rnd.h" +#include /* The maximum section alignment allowed to be specified, as a power of two */ #define MAXSECTALIGN 15 /* 2**15 or 0x8000 */ @@ -81,6 +85,7 @@ struct input_file { 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; @@ -106,7 +111,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 @@ -116,6 +122,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 }; @@ -148,20 +155,14 @@ static enum bool arch_blank_flag = FALSE; static struct fat_header fat_header = { 0 }; -static struct thin_file *arm64_arch = NULL; -static struct thin_file *get_arm64_arch( - void); - -static struct thin_file *x86_64h_arch = NULL; -static struct thin_file *get_x86_64h_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( @@ -179,6 +180,9 @@ static void check_extend_format_1( struct ar_hdr *ar_hdr, 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, @@ -215,9 +219,6 @@ static struct segalign *new_segalign( static int cmp_qsort( const struct thin_file *thin1, const struct thin_file *thin2); -static uint64_t rnd( - uint64_t v, - uint64_t r); static enum bool ispoweroftwo( uint32_t x); static void check_arch( @@ -255,7 +256,7 @@ char *envp[]) const struct arch_flag *arch_flags; enum bool found; struct arch_flag blank_arch; - uint64_t nbytes_to_write, nbytes_written; + int time_result; char *pnam; input = NULL; @@ -320,6 +321,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; @@ -362,6 +366,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; @@ -437,7 +448,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]); @@ -525,13 +536,14 @@ char *envp[]) * 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 || @@ -548,18 +560,28 @@ char *envp[]) 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. @@ -619,28 +641,23 @@ char *envp[]) system_fatal("can't create output file: %s", output_file); - nbytes_written = 0; - do{ -#define MAX_WRITE 0x10000000 - if(thin_files[i].size - nbytes_written > MAX_WRITE) - nbytes_to_write = MAX_WRITE; - else - nbytes_to_write = thin_files[i].size - - nbytes_written; - if(write(fd, thin_files[i].addr + nbytes_written, - nbytes_to_write) != nbytes_to_write) - system_fatal("can't write thin file to output " - "file: %s", output_file); - nbytes_written += nbytes_to_write; - }while(nbytes_written != thin_files[i].size); + 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) +# if XTOOLS_HAS_UTIMENSAT + time_result = utimensat(AT_FDCWD, output_file, + output_times, 0); +# else + time_result = utimes(output_file, output_timev); +# endif #else - output_timep) == -1) + 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; @@ -795,6 +812,25 @@ char *envp[]) 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){ @@ -840,13 +876,23 @@ char *envp[]) 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 "); 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 & @@ -862,6 +908,9 @@ char *envp[]) 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, @@ -925,7 +974,6 @@ create_fat(void) int fd; struct fat_arch fat_arch; struct fat_arch_64 fat_arch64; - uint64_t nbytes_to_write, nbytes_written; /* fold in specified segment alignments */ for(i = 0; i < nsegaligns; i++){ @@ -969,19 +1017,44 @@ 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_arch = get_arm64_arch(); - - /* We will order the x86_64h slice last too. */ - x86_64h_arch = get_x86_64h_arch(); - + /* Fill in the fat header and the fat_arch's offsets. */ if(fat64_flag == TRUE) fat_header.magic = FAT_MAGIC_64; else fat_header.magic = FAT_MAGIC; fat_header.nfat_arch = nthin_files; + /* 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); @@ -1013,7 +1086,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); @@ -1021,18 +1094,6 @@ 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_arch == thin_files + i) - 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_arch == thin_files + i) - continue; if(fat64_flag == TRUE){ fat_arch64.cputype = thin_files[i].cputype; fat_arch64.cpusubtype = thin_files[i].cpusubtype; @@ -1043,15 +1104,15 @@ create_fat(void) else{ fat_arch.cputype = thin_files[i].cputype; fat_arch.cpusubtype = thin_files[i].cpusubtype; - fat_arch.offset = thin_files[i].offset; - fat_arch.size = thin_files[i].size; + 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_64(&fat_arch64, 1, BIG_ENDIAN_BYTE_SEX); #endif /* __LITTLE_ENDIAN__ */ - if(write(fd, &fat_arch64, sizeof(struct fat_arch_64)) != + 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); @@ -1060,96 +1121,21 @@ create_fat(void) #ifdef __LITTLE_ENDIAN__ swap_fat_arch(&fat_arch, 1, BIG_ENDIAN_BYTE_SEX); #endif /* __LITTLE_ENDIAN__ */ - if(write(fd, &fat_arch, sizeof(struct fat_arch)) != + 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_arch){ - if(fat64_flag == TRUE){ - fat_arch64.cputype = arm64_arch->cputype; - fat_arch64.cpusubtype = arm64_arch->cpusubtype; - fat_arch64.offset = arm64_arch->offset; - fat_arch64.size = arm64_arch->size; - fat_arch64.align = arm64_arch->align; -#ifdef __LITTLE_ENDIAN__ - swap_fat_arch_64(&fat_arch64, 1, BIG_ENDIAN_BYTE_SEX); -#endif /* __LITTLE_ENDIAN__ */ - if(write(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{ - fat_arch.cputype = arm64_arch->cputype; - fat_arch.cpusubtype = arm64_arch->cpusubtype; - fat_arch.offset = arm64_arch->offset; - fat_arch.size = arm64_arch->size; - fat_arch.align = arm64_arch->align; -#ifdef __LITTLE_ENDIAN__ - swap_fat_arch(&fat_arch, 1, BIG_ENDIAN_BYTE_SEX); -#endif /* __LITTLE_ENDIAN__ */ - if(write(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 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_arch){ - if(fat64_flag == TRUE){ - fat_arch64.cputype = x86_64h_arch->cputype; - fat_arch64.cpusubtype = x86_64h_arch->cpusubtype; - fat_arch64.offset = x86_64h_arch->offset; - fat_arch64.size = x86_64h_arch->size; - fat_arch64.align = x86_64h_arch->align; -#ifdef __LITTLE_ENDIAN__ - swap_fat_arch_64(&fat_arch64, 1, BIG_ENDIAN_BYTE_SEX); -#endif /* __LITTLE_ENDIAN__ */ - if(write(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{ - fat_arch.cputype = x86_64h_arch->cputype; - fat_arch.cpusubtype = x86_64h_arch->cpusubtype; - fat_arch.offset = x86_64h_arch->offset; - fat_arch.size = x86_64h_arch->size; - fat_arch.align = x86_64h_arch->align; -#ifdef __LITTLE_ENDIAN__ - swap_fat_arch(&fat_arch, 1, BIG_ENDIAN_BYTE_SEX); -#endif /* __LITTLE_ENDIAN__ */ - if(write(fd, &fat_arch, sizeof(struct fat_arch)) != - sizeof(struct fat_arch)) - system_fatal("can't write fat arch to output file: %s", - rename_file); - } - } + for(i = 0; i < nthin_files; i++){ if(extract_family_flag == FALSE || nthin_files > 1) if(lseek(fd, thin_files[i].offset, L_SET) == -1) system_fatal("can't lseek in output file: %s", rename_file); - nbytes_written = 0; - do{ - if(thin_files[i].size - nbytes_written > MAX_WRITE) - nbytes_to_write = MAX_WRITE; - else - nbytes_to_write = thin_files[i].size - nbytes_written; - if(write(fd, thin_files[i].addr + nbytes_written, - nbytes_to_write) != nbytes_to_write) - system_fatal("can't write to output file: %s", rename_file); - nbytes_written += nbytes_to_write; - }while(nbytes_written != thin_files[i].size); + 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); @@ -1181,6 +1167,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) @@ -1190,6 +1177,24 @@ 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 + */ +# ifdef XTOOLS_HAS_UTIMENSAT + 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 +#else /* * Select the eariliest modify time so that if the output file * contains archives with table of contents lipo will not make them @@ -1197,13 +1202,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; @@ -1262,6 +1260,34 @@ struct input_file *input) "extend past the end of the file) %s", input->name); 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); @@ -1484,6 +1510,7 @@ 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; if(fat64_flag == FALSE && size > UINT32_MAX) @@ -1534,8 +1561,8 @@ struct input_file *input) } 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; @@ -1801,6 +1828,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) && @@ -1822,11 +1860,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){ @@ -1849,7 +1899,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)); } } @@ -1876,7 +1926,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, @@ -1895,60 +1945,93 @@ uint32_t *member_name_size) } /* - * get_arm64_arch() will return a pointer to the thin_file 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 thin_file * -get_arm64_arch( -void) +uint32_t +get_default_align( +cpu_type_t cputype, +cpu_subtype_t cpusubtype) { - uint32_t i; - - /* - * Look for a 64-bit arm slice. - */ - for(i = 0; i < nthin_files; i++){ - if(thin_files[i].cputype == CPU_TYPE_ARM64){ - return(thin_files + i); - } + 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_arch() will return a pointer to the thin_file 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 thin_file * -get_x86_64h_arch( -void) +static uint32_t get_mh_filetype( + char* addr, + uint64_t size) { - uint32_t i; - - /* - * Look for a x86_64h slice. - */ - for(i = 0; i < nthin_files; i++){ - if(thin_files[i].cputype == CPU_TYPE_X86_64 && - (thin_files[i].cpusubtype & ~CPU_SUBTYPE_MASK) == - CPU_SUBTYPE_X86_64_H){ - return(thin_files + i); - } - } - 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 @@ -1964,20 +2047,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. - */ - if(mhp->cputype == CPU_TYPE_POWERPC || - mhp->cputype == CPU_TYPE_I386) - return(12); + /* - * Special case ARM and return 14. As it has 16k pages. + * 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_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(); @@ -2035,12 +2117,13 @@ 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 @@ -2058,19 +2141,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 */ @@ -2381,6 +2463,18 @@ cpu_subtype_t cpusubtype) 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; } @@ -2688,6 +2782,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; } @@ -2834,22 +2942,18 @@ cmp_qsort( const struct thin_file *thin1, const struct thin_file *thin2) { - return(thin1->align - thin2->align); -} - -/* - * rnd() rounds v to a multiple of r. - */ -static -uint64_t -rnd( -uint64_t v, -uint64_t r) -{ - r--; - v += r; - v &= ~(int64_t)r; - return(v); + /* if cpu types match, sort by cpu subtype */ + if (thin1->cputype == thin2->cputype) + return thin1->cpusubtype - thin2->cpusubtype; + + /* 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; } /* @@ -2947,17 +3051,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 e2862a9c..fe2d42c4 100644 --- a/cctools/misc/nm.c +++ b/cctools/misc/nm.c @@ -96,6 +96,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 @@ -527,7 +528,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; @@ -547,8 +548,8 @@ void *cookie) char *short_name, *has_suffix; enum bool is_framework; #ifdef LTO_SUPPORT - char *llvm_bundle_pointer; - uint64_t llvm_bundle_size; + char *llvm_bundle_pointer = NULL; + uint64_t llvm_bundle_size = 0; enum bool llvm_bundle_found; llvm_bundle_found = FALSE; #endif /* LTO_SUPPORT */ @@ -580,10 +581,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){ @@ -688,6 +691,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; @@ -1093,7 +1100,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 " @@ -1788,6 +1795,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] "); @@ -1893,7 +1905,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 52c9f488..e1a070e1 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( @@ -213,7 +217,7 @@ int argc, char *argv[]) { int i, start; - uint32_t j, page_number; + uint64_t j, page_number; char *endp, *pnam; struct arch_flag a; @@ -547,6 +551,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(); @@ -588,6 +593,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++){ @@ -622,6 +629,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 *) @@ -1070,6 +1085,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 @@ -1161,7 +1190,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) @@ -1196,7 +1225,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; @@ -1212,7 +1241,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)); @@ -1221,7 +1250,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) / @@ -1242,7 +1271,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; @@ -1256,13 +1285,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); @@ -1290,7 +1319,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); @@ -1319,165 +1348,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; @@ -1487,7 +1528,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); @@ -1524,7 +1565,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"); @@ -1544,7 +1585,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"); @@ -1694,6 +1735,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 ed412f99..e3465786 100644 --- a/cctools/misc/redo_prebinding.c +++ b/cctools/misc/redo_prebinding.c @@ -1729,6 +1729,11 @@ uint32_t *throttle) * 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, @@ -1849,7 +1854,7 @@ uint32_t *outlen) writeout_to_mem(archs, narchs, (char *)output_file, outbuf, &outlen64, TRUE, FALSE, FALSE, FALSE, &seen_archive); - *outlen = outlen64; + *outlen = (uint32_t)outlen64; }else writeout(archs, narchs, (char *)output_file, mode, TRUE, FALSE, FALSE, FALSE, NULL); @@ -1865,7 +1870,13 @@ uint32_t *outlen) writeout_to_mem(archs, narchs, (char *)output_file, outbuf, &outlen64, TRUE, FALSE, FALSE, FALSE, &seen_archive); - *outlen = outlen64; + /* 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, FALSE, NULL); @@ -2994,13 +3005,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) @@ -3892,13 +3905,15 @@ uint32_t *image_pointer) &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) @@ -4628,7 +4643,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 @@ -4801,9 +4816,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; @@ -5144,9 +5159,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); } @@ -5313,7 +5329,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); } } @@ -5393,7 +5409,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; @@ -5448,6 +5464,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) + @@ -5500,9 +5520,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; } @@ -5572,6 +5602,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; @@ -9066,7 +9110,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 @@ -9090,9 +9134,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; } } @@ -9140,8 +9184,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++; @@ -9230,11 +9275,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; @@ -9277,11 +9322,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; @@ -9362,6 +9407,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); } @@ -9779,7 +9832,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 a8d9a9e4..1bf8ac14 100644 --- a/cctools/misc/seg_hack.c +++ b/cctools/misc/seg_hack.c @@ -213,7 +213,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 a8978d07..3f1b41e0 100644 --- a/cctools/misc/segedit.c +++ b/cctools/misc/segedit.c @@ -48,6 +48,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 +110,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; @@ -179,8 +180,8 @@ char *envp[]) fprintf(stdout, "Please report bugs to %s\n", support_url); exit(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(); @@ -193,8 +194,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(); @@ -206,14 +208,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(); } @@ -278,7 +281,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); @@ -437,7 +440,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++; } } @@ -487,8 +491,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); @@ -513,6 +517,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; @@ -520,7 +525,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; @@ -537,6 +544,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 @@ -593,16 +603,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{ @@ -615,7 +626,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; @@ -629,8 +641,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) @@ -639,6 +667,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: @@ -654,6 +726,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); @@ -675,7 +770,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; } @@ -694,6 +789,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. @@ -701,6 +824,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; @@ -708,146 +835,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; @@ -857,46 +1104,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 @@ -930,8 +1179,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); @@ -952,9 +1201,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); @@ -962,7 +1211,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, @@ -985,8 +1234,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); @@ -1007,9 +1256,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); @@ -1017,7 +1266,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, @@ -1033,8 +1282,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); @@ -1048,8 +1298,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); @@ -1063,7 +1314,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); @@ -1109,7 +1360,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) @@ -1191,8 +1442,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 452245b2..c356c6d2 100644 --- a/cctools/misc/size.c +++ b/cctools/misc/size.c @@ -99,12 +99,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; char *pnam; progname = argv[0]; @@ -119,6 +120,7 @@ char **envp) flag.l = FALSE; flag.x = FALSE; + files = allocate(sizeof(char *) * argc); for(i = 1; i < argc; i++){ if(argv[i][0] == '-'){ if(strcmp(argv[i], "--version") == 0){ @@ -133,25 +135,11 @@ char **envp) fprintf(stdout, "Please report bugs to %s\n", support_url); exit(0); } - if(argv[i][1] == '\0'){ - flag.nfiles += argc - i - 1; - break; - } - if(strcmp(argv[i], "-m") == 0){ - flag.m = TRUE; - 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; + if(argv[i][1] == '\0' || + 0 == strcmp("--", argv[i])){ 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(); @@ -174,37 +162,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 e8d62a74..486f84ed 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, @@ -193,7 +194,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]); @@ -247,7 +249,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]); @@ -354,7 +357,11 @@ void *cookie) * If the ofile is not an object file then process it without reguard * to sections. */ - if(ofile->object_addr == NULL || ofile->member_type == OFILE_LLVM_BITCODE){ + if(ofile->object_addr == NULL +#ifdef LTO_SUPPORT + || ofile->member_type == OFILE_LLVM_BITCODE +#endif + ){ if(ofile->file_type == OFILE_FAT && ofile->arch_flag.cputype != 0){ if(ofile->fat_header->magic == FAT_MAGIC_64){ addr = ofile->file_addr + @@ -485,11 +492,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; @@ -528,24 +535,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 9704db08..bbb284e2 100644 --- a/cctools/misc/strip.c +++ b/cctools/misc/strip.c @@ -46,6 +46,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,7 +70,9 @@ 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 symbols that start with '__T' 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 */ @@ -88,6 +91,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 */ /* @@ -176,6 +186,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) */ @@ -234,6 +249,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 @@ -247,7 +263,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( @@ -286,6 +304,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); @@ -513,6 +539,9 @@ char *envp[]) Tflag = 1; strip_all = 0; break; + case 'N': + Nflag = 1; + break; case 'x': xflag = 1; strip_all = 0; @@ -561,6 +590,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); @@ -826,6 +862,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 @@ -951,8 +991,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; } @@ -978,6 +1018,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); @@ -1035,8 +1090,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){ @@ -1295,6 +1360,14 @@ 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 @@ -1311,7 +1384,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); @@ -1413,6 +1487,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 /* @@ -1630,7 +1732,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 @@ -1641,7 +1743,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; } @@ -1744,6 +1846,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); @@ -1845,7 +1966,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){ @@ -1968,10 +2093,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; } @@ -2237,8 +2367,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){ @@ -2313,7 +2444,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++; } } @@ -2334,12 +2465,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++; } } @@ -2362,6 +2493,13 @@ struct object *object) ) 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; + } } /* @@ -2380,7 +2518,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; @@ -2481,7 +2619,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; } @@ -2610,6 +2748,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; @@ -2617,12 +2756,15 @@ enum byte_sex host_byte_sex) uint32_t n_strx, value; uint64_t value64; enum bool made_local; - uint32_t mh_flags; + uint32_t mh_flags, mh_filetype; - if(object->mh != NULL) + if(object->mh != NULL) { mh_flags = object->mh->flags; - else + 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; @@ -2632,7 +2774,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 @@ -2689,16 +2832,19 @@ enum byte_sex host_byte_sex) saves[index] - 1; } #else /* !defined(NMEDIT) */ - else if(Tflag && (mh_flags & MH_DYLDLINK) == MH_DYLDLINK && + else if(strip_all_nlists || + (Tflag && swift_version != 0 && + (mh_flags & MH_DYLDLINK) == MH_DYLDLINK && n_strx != 0 && - strncmp(strings + n_strx, "__T", 3) == 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; @@ -2731,7 +2877,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; @@ -2777,6 +2924,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 @@ -2796,20 +2963,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; @@ -2819,7 +2989,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); @@ -2841,7 +3018,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 @@ -2916,6 +3096,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 @@ -2968,10 +3154,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; @@ -2987,7 +3233,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; @@ -3018,13 +3263,27 @@ 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 "__T". + * binary never save symbols that start with "_$S" if the + * swift version is non-zero. */ - if(Tflag && (mh_flags & MH_DYLDLINK) == MH_DYLDLINK && - n_strx != 0 && strncmp(strings + n_strx, "__T", 3) == 0){ + 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 */ @@ -3035,10 +3294,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; @@ -3079,8 +3339,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; @@ -3094,7 +3354,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; @@ -3115,7 +3375,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; @@ -3132,7 +3392,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; @@ -3144,10 +3405,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; @@ -3175,7 +3434,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; @@ -3185,7 +3444,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; @@ -3197,10 +3456,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; @@ -3262,7 +3519,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++; @@ -3274,7 +3530,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++; @@ -3285,7 +3540,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++; @@ -3312,7 +3566,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) @@ -3338,7 +3591,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++; @@ -3350,7 +3602,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++; @@ -3361,11 +3612,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 || @@ -3388,11 +3637,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 || @@ -3420,7 +3667,6 @@ uint32_t nextrefsyms) return(FALSE); } len = strlen(strings + module_name) + 1; - new_strsize += len; new_ext_strsize += len; } @@ -3461,7 +3707,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++; @@ -3527,6 +3772,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 @@ -3548,7 +3828,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++; @@ -3558,7 +3839,7 @@ uint32_t nextrefsyms) else{ hack_5614542 = FALSE; } - + if(object->mh != NULL){ new_symbols = (struct nlist *) allocate(new_nsyms * sizeof(struct nlist)); @@ -3570,9 +3851,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'; @@ -3589,6 +3870,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; @@ -3644,15 +3930,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){ @@ -3669,14 +3963,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; @@ -3709,10 +4018,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){ @@ -3720,10 +4029,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; } } @@ -3767,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) @@ -3791,10 +4100,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){ @@ -3845,7 +4154,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; @@ -3855,7 +4164,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; @@ -4037,9 +4346,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; @@ -4067,6 +4377,8 @@ uint32_t nextrefsyms) free(sections); if(sections64 != NULL) free(sections64); + if (strx_map != NULL) + free(strx_map); if(errors == 0) return(TRUE); @@ -4128,9 +4440,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. @@ -4162,7 +4477,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); @@ -4179,7 +4494,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) @@ -4316,14 +4634,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){ @@ -4346,7 +4664,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++){ @@ -4362,41 +4680,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; @@ -4455,13 +4773,13 @@ struct object *object) * Allocate space for the new load commands as 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); @@ -4470,7 +4788,7 @@ struct object *object) * Copy all the load commands except the LC_SEGMENT_SPLIT_INFO load * command 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++){ @@ -4486,42 +4804,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->split_info_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_FUNCTION_STARTS: object->func_starts_info_cmd = @@ -4577,13 +4895,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); @@ -4592,7 +4910,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++){ @@ -4608,42 +4926,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; @@ -4743,6 +5061,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. */ @@ -5020,9 +5358,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 && @@ -5031,7 +5369,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 && @@ -5233,7 +5571,7 @@ uint32_t nextrefsyms) "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; } @@ -5448,7 +5786,7 @@ uint32_t nextrefsyms) 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'; @@ -5518,10 +5856,10 @@ uint32_t nextrefsyms) 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++; @@ -5574,10 +5912,10 @@ uint32_t nextrefsyms) 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++; @@ -5626,10 +5964,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; } inew_syms++; @@ -5665,10 +6003,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; } inew_syms++; @@ -5684,7 +6022,7 @@ uint32_t nextrefsyms) 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; @@ -5700,7 +6038,7 @@ uint32_t nextrefsyms) } 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; @@ -5795,10 +6133,10 @@ uint32_t nextrefsyms) 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++; @@ -5839,10 +6177,10 @@ uint32_t nextrefsyms) 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++; @@ -5884,10 +6222,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; } inew_syms++; diff --git a/cctools/misc/vtool.c b/cctools/misc/vtool.c new file mode 100644 index 00000000..c37b509a --- /dev/null +++ b/cctools/misc/vtool.c @@ -0,0 +1,2838 @@ +// +// 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 + +#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/otool/arm64_disasm.c b/cctools/otool/arm64_disasm.c index 8009063a..7a1b839d 100644 --- a/cctools/otool/arm64_disasm.c +++ b/cctools/otool/arm64_disasm.c @@ -15,7 +15,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 +28,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 +44,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 +52,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 +84,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 +168,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 +236,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 +287,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 +303,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 +502,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 +519,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 +580,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 +686,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 +721,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 +739,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 +772,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 +833,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 +877,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 +887,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 +904,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 +934,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 +944,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 4665cf9a..affe6b50 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 8a2ea5d9..e68d22ef 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 1b4407c1..659b033b 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 b495cf47..63e7f115 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 de32b789..6a562c5a 100644 --- a/cctools/otool/dyld_bind_info.c +++ b/cctools/otool/dyld_bind_info.c @@ -1,43 +1,150 @@ #include +#include +#include #include #include #include +#include #include "dyld_bind_info.h" +#include "fixup-chains.h" + +/***************************************************************************** + * + * 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 +155,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 +176,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 +201,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("??"); +} + +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); +} - 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 * +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; + + *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); +} - 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); +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 +510,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 +538,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 +1728,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("%*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("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("%*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){ + 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; +} - for(n = 0; n < ndbi; n++){ - if(dbi[n].address == address) - return(dbi[n].symbolname); - } - return(NULL); +/* + * 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 6a609476..6390205b 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 00000000..907a0e7d --- /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 0b60eb81..177d53f3 100644 --- a/cctools/otool/i386_disasm.c +++ b/cctools/otool/i386_disasm.c @@ -134,10 +134,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 +157,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 +204,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 +1617,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 +1647,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 +1699,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 +1778,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 +3903,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 +3927,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 +3959,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 +4090,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 +4110,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 +4160,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 +4222,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 +4502,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 +4708,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 +5020,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 +5079,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 83d1be6f..48503649 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 6c75bde9..da084cf2 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 eeea33cc..7579594d 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) */ @@ -476,11 +489,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'){ @@ -651,6 +670,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(EXIT_FAILURE); @@ -663,9 +686,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(EXIT_FAILURE); } @@ -741,6 +765,7 @@ usage(int exit_with_code) fprintf(out, "\t-L print shared libraries used\n"); fprintf(out, "\t-D print shared library id name\n"); fprintf(out, "\t-t print the text section (disassemble with -v)\n"); + fprintf(out, "\t-x print all text sections (disassemble with -v)\n"); fprintf(out, "\t-p start dissassemble from routine " "name\n"); fprintf(out, "\t-s print contents of " @@ -748,15 +773,35 @@ usage(int exit_with_code) fprintf(out, "\t-d print the data section\n"); fprintf(out, "\t-o print the Objective-C segment\n"); fprintf(out, "\t-r print the relocation entries\n"); - fprintf(out, "\t-S print the table of contents of a library\n"); + fprintf(out, "\t-S print the table of contents of a library"); +#ifdef LLVM_OTOOL + fprintf(out, " (obsolete)"); +#endif /* LLVM_OTOOL */ + fprintf(out, "\n"); fprintf(out, "\t-T print the table of contents of a dynamic " - "shared library\n"); + "shared library"); +#ifdef LLVM_OTOOL + fprintf(out, " (obsolete)"); +#endif /* LLVM_OTOOL */ + fprintf(out, "\n"); fprintf(out, "\t-M print the module table of a dynamic shared " - "library\n"); + "library"); +#ifdef LLVM_OTOOL + fprintf(out, " (obsolete)"); +#endif /* LLVM_OTOOL */ + fprintf(out, "\n"); fprintf(out, "\t-R print the reference table of a dynamic shared " - "library\n"); + "library"); +#ifdef LLVM_OTOOL + fprintf(out, " (obsolete)"); +#endif /* LLVM_OTOOL */ + fprintf(out, "\n"); fprintf(out, "\t-I print the indirect symbol table\n"); - fprintf(out, "\t-H print the two-level hints table\n"); + fprintf(out, "\t-H print the two-level hints table"); +#ifdef LLVM_OTOOL + fprintf(out, " (obsolete)"); +#endif /* LLVM_OTOOL */ + fprintf(out, "\n"); fprintf(out, "\t-G print the data in code table\n"); fprintf(out, "\t-v print verbosely (symbolically) when possible\n"); fprintf(out, "\t-V print disassembled operands symbolically\n"); @@ -808,7 +853,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{ @@ -816,7 +869,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"); } @@ -859,12 +912,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"); @@ -901,7 +956,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) */ @@ -922,7 +978,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; @@ -950,7 +1007,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; @@ -967,6 +1027,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. @@ -982,7 +1050,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 @@ -1269,8 +1339,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); @@ -1306,7 +1381,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 || @@ -1317,8 +1392,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 || @@ -1326,7 +1401,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); @@ -1359,7 +1435,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) || @@ -1412,6 +1488,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, @@ -1486,7 +1571,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); @@ -1524,7 +1609,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) || @@ -1550,113 +1636,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 || - 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; + /* 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)loc_relocs % sizeof(int32_t) != 0 || + if((intptr_t)sect_relocs % sizeof(int32_t) != 0 || ofile->object_byte_sex != get_host_byte_sex()){ - relocs = allocate(nloc_relocs * + nrelocs = sect_nrelocs; + relocs = allocate(nrelocs * sizeof(struct relocation_info)); - memcpy(relocs, loc_relocs, nloc_relocs * + memcpy(relocs, sect_relocs, nrelocs * 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()); + else{ + nrelocs = sect_nrelocs; + relocs = sect_relocs; } - relocs = NULL; - } - 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)); + 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); } - else{ - nrelocs = sect_nrelocs; - relocs = sect_relocs; + 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); + } + else + printf("Contents of (%.16s,%.16s) section\n", segname, + sectname); } - 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){ @@ -1679,9 +1787,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); } } @@ -1695,8 +1803,8 @@ void *cookie) /* cookie is not used */ if(Xflag == FALSE) printf("(%s,%s) section\n", SEG_DATA, SECT_DATA); if(sect != NULL) - print_sect(mh_cputype, ofile->object_byte_sex, sect, sect_size, - sect_addr); + print_sect(mh_cputype, ofile->object_byte_sex, sect, + sect_size, sect_addr); } } @@ -1818,10 +1926,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); @@ -1830,9 +1938,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: @@ -1894,15 +2015,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, @@ -1932,12 +2055,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{ /* @@ -1980,12 +2108,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); } } } @@ -2010,6 +2143,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); + } } /* @@ -2030,7 +2169,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, @@ -2067,7 +2206,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: @@ -2110,8 +2249,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; @@ -2123,8 +2262,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; @@ -2162,7 +2301,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) { @@ -2187,8 +2326,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; @@ -2212,7 +2351,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) @@ -2240,8 +2379,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; @@ -2251,8 +2390,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; @@ -2276,7 +2415,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) { @@ -2300,8 +2439,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; @@ -2324,7 +2463,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) { @@ -2348,8 +2487,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; @@ -2391,7 +2531,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: @@ -2442,7 +2582,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) { @@ -2467,8 +2607,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; @@ -2510,7 +2650,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: @@ -2560,7 +2700,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) { @@ -2584,7 +2724,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; @@ -2626,7 +2766,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: @@ -2678,7 +2818,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) { @@ -2703,8 +2843,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 / @@ -2747,7 +2887,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: @@ -2843,7 +2983,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, @@ -2887,7 +3027,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: @@ -2908,7 +3048,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); @@ -2950,7 +3090,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); @@ -2988,6 +3128,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; @@ -3020,8 +3162,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; @@ -3030,6 +3172,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; @@ -3062,8 +3206,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; @@ -3074,6 +3218,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( @@ -3082,7 +3369,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, @@ -3111,8 +3398,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; @@ -3128,8 +3415,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; @@ -3149,16 +3436,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; @@ -3175,8 +3464,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; @@ -3188,6 +3479,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 @@ -3211,7 +3505,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){ @@ -3238,13 +3532,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: @@ -3301,7 +3638,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); @@ -3345,7 +3682,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); @@ -3385,10 +3722,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); @@ -3404,13 +3752,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, @@ -3428,6 +3878,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, @@ -3437,7 +3888,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) @@ -3452,17 +3903,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); } } @@ -3472,7 +3924,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, @@ -3490,6 +3942,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, @@ -3499,7 +3952,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) @@ -3549,7 +4002,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; @@ -3584,8 +4037,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); @@ -3603,6 +4060,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); @@ -3617,11 +4076,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"); @@ -3629,6 +4090,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; @@ -3663,19 +4126,21 @@ uint64_t seg_addr) if((qflag == FALSE || (cputype == CPU_TYPE_POWERPC || cputype == CPU_TYPE_POWERPC64)) && - 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, @@ -3685,19 +4150,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, @@ -3707,32 +4174,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, @@ -3740,15 +4212,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); @@ -3794,10 +4267,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, @@ -3808,7 +4282,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, @@ -3897,7 +4372,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; @@ -3944,7 +4419,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 94941864..6ba1795a 100644 --- a/cctools/otool/ofile_print.c +++ b/cctools/otool/ofile_print.c @@ -237,6 +237,9 @@ static void print_arch( 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 @@ -268,7 +271,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, @@ -664,6 +667,17 @@ cpu_subtype_t cpusubtype) 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; } @@ -979,6 +993,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; } @@ -1010,6 +1038,34 @@ cpu_subtype_t cpusubtype) } } +/* + * 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 @@ -1064,7 +1120,7 @@ enum bool print_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); @@ -1081,7 +1137,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); @@ -1224,6 +1280,9 @@ enum bool verbose) host_byte_sex = get_host_byte_sex(); toc_offset = 0; strings = NULL; + ran_size = 0; + ran_size64 = 0; + string_size = 0; if(strncmp(toc_name, SYMDEF_64, sizeof(SYMDEF_64)-1) == 0 || strncmp(toc_name, SYMDEF_64_SORTED, sizeof(SYMDEF_64_SORTED)-1) == 0) @@ -1295,7 +1354,7 @@ enum bool verbose) 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); + swap_ranlib(ranlibs, (uint32_t)nranlibs, host_byte_sex); sizeof_rans = ran_size; toc_offset += ran_size; } @@ -1401,7 +1460,7 @@ enum bool verbose) 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') @@ -1512,7 +1571,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 @@ -1521,16 +1580,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 - @@ -1582,8 +1642,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++){ @@ -2016,6 +2076,20 @@ enum bool verbose) 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; @@ -2144,18 +2218,26 @@ enum bool verbose) 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_PIE){ - printf(" PIE"); - f &= ~MH_PIE; + 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_DEAD_STRIPPABLE_DYLIB){ + printf(" DEAD_STRIPPABLE_DYLIB"); + f &= ~MH_DEAD_STRIPPABLE_DYLIB; + } if(f & MH_HAS_TLV_DESCRIPTORS){ printf(" MH_HAS_TLV_DESCRIPTORS"); f &= ~MH_HAS_TLV_DESCRIPTORS; @@ -2168,6 +2250,14 @@ enum bool verbose) 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"); @@ -2194,7 +2284,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) { @@ -2231,8 +2321,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(); @@ -2254,7 +2347,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: @@ -2275,7 +2368,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); @@ -2311,7 +2404,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); @@ -2565,6 +2658,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); @@ -2642,6 +2737,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) ? @@ -2652,6 +2777,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) ? @@ -2731,7 +2866,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: @@ -2842,7 +2977,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; @@ -2945,6 +3080,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 @@ -2975,7 +3114,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; @@ -3116,7 +3255,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; @@ -3172,7 +3311,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; @@ -3314,7 +3453,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; @@ -3424,17 +3563,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); } /* @@ -3740,7 +3879,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; @@ -3815,7 +3954,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; @@ -3831,6 +3970,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); @@ -3875,28 +4018,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 + 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{ - 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); + 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); } /* @@ -3930,6 +4153,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. @@ -3940,7 +4195,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"); @@ -3981,13 +4236,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"); @@ -4013,13 +4268,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"); @@ -4052,7 +4307,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"); @@ -4092,7 +4348,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; @@ -4101,7 +4357,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"); @@ -4229,7 +4485,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)); @@ -4265,7 +4521,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)); @@ -4297,7 +4553,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)); @@ -4359,7 +4615,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)); @@ -4402,7 +4658,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)); @@ -4432,7 +4688,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)); @@ -4506,7 +4762,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)); @@ -4544,7 +4800,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)); @@ -4633,7 +4889,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)); @@ -4678,7 +4934,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)); @@ -4721,7 +4977,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)); @@ -4753,7 +5009,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)); @@ -4836,7 +5092,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)); @@ -4879,7 +5135,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)); @@ -4985,7 +5241,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)); @@ -5009,7 +5265,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)); @@ -5124,7 +5380,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)); @@ -5246,7 +5502,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)); @@ -5282,7 +5538,7 @@ enum byte_sex thread_states_byte_sex) 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)){ @@ -5448,7 +5704,7 @@ enum byte_sex thread_states_byte_sex) 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)); @@ -5477,7 +5733,7 @@ enum byte_sex thread_states_byte_sex) 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)); @@ -5507,7 +5763,7 @@ enum byte_sex thread_states_byte_sex) 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)); @@ -5545,7 +5801,7 @@ enum byte_sex thread_states_byte_sex) 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)); @@ -5704,7 +5960,7 @@ enum byte_sex thread_states_byte_sex) 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)); @@ -5731,7 +5987,7 @@ enum byte_sex thread_states_byte_sex) 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)); @@ -5761,7 +6017,7 @@ enum byte_sex thread_states_byte_sex) 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)); @@ -5808,7 +6064,7 @@ enum byte_sex thread_states_byte_sex) 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)); @@ -5855,7 +6111,7 @@ enum byte_sex thread_states_byte_sex) 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)); @@ -5904,7 +6160,7 @@ enum byte_sex thread_states_byte_sex) 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)); @@ -5955,7 +6211,7 @@ enum byte_sex thread_states_byte_sex) 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)); @@ -6100,7 +6356,7 @@ enum byte_sex thread_states_byte_sex) 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)); @@ -6148,7 +6404,7 @@ enum byte_sex thread_states_byte_sex) 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)); @@ -6207,7 +6463,7 @@ enum byte_sex thread_states_byte_sex) 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)); @@ -6242,8 +6498,9 @@ enum byte_sex thread_states_byte_sex) } } } - 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)); @@ -6279,7 +6536,7 @@ enum byte_sex thread_states_byte_sex) 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)); @@ -6316,6 +6573,31 @@ enum byte_sex thread_states_byte_sex) 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); @@ -6409,7 +6691,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)); @@ -6444,7 +6726,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, @@ -6488,7 +6770,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: @@ -6518,7 +6800,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); @@ -6563,7 +6845,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); @@ -6669,7 +6951,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, @@ -7025,7 +7307,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); @@ -7120,7 +7403,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 @@ -7169,6 +7454,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: @@ -7186,7 +7472,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, @@ -7539,7 +7825,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: @@ -7565,7 +7851,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); @@ -7609,7 +7895,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); @@ -7666,7 +7952,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); @@ -7786,7 +8072,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: @@ -8003,11 +8289,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){ @@ -8068,14 +8354,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(); @@ -8094,7 +8380,7 @@ enum bool print_addresses) f = SWAP_FLOAT(f); l = SWAP_INT(l); } - print_literal4(l, f); + print_literal4((uint32_t)l, f); } } @@ -8124,14 +8410,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(); @@ -8194,14 +8481,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; @@ -8245,14 +8533,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, @@ -8265,8 +8555,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; @@ -8283,7 +8573,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; @@ -8307,7 +8597,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: @@ -8325,7 +8615,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); @@ -8360,7 +8650,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; @@ -8388,7 +8678,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); @@ -8423,10 +8713,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++; } @@ -8464,6 +8755,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)); @@ -8599,18 +8907,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; @@ -8639,22 +8957,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"); @@ -8696,8 +9048,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, @@ -8711,7 +9063,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 */ @@ -8727,13 +9079,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); @@ -8783,7 +9136,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); @@ -8818,7 +9171,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 @@ -8976,7 +9330,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 && @@ -9016,7 +9371,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 && diff --git a/cctools/otool/ofile_print.h b/cctools/otool/ofile_print.h index d056695d..97b9ae3b 100644 --- a/cctools/otool/ofile_print.h +++ b/cctools/otool/ofile_print.h @@ -98,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); @@ -117,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, @@ -131,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, @@ -221,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( @@ -239,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, @@ -311,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); @@ -321,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); @@ -338,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, @@ -351,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, @@ -362,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); @@ -377,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); @@ -385,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, @@ -413,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, @@ -485,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, @@ -510,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); @@ -520,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, @@ -531,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( @@ -539,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( @@ -549,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( @@ -559,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, @@ -575,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( @@ -593,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, @@ -608,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, @@ -622,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, @@ -636,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( @@ -659,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, @@ -667,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 0a87f65c..617a1424 100644 --- a/cctools/otool/print_bitcode.c +++ b/cctools/otool/print_bitcode.c @@ -38,7 +38,6 @@ #include #include #include "mach-o/loader.h" -#include "objc/objc-runtime.h" #include "stuff/allocate.h" #include "stuff/bytesex.h" #include "stuff/symbol.h" @@ -207,6 +206,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); @@ -446,7 +446,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 e8253f40..2018bd1c 100644 --- a/cctools/otool/print_objc.c +++ b/cctools/otool/print_objc.c @@ -31,7 +31,6 @@ #include "stdio.h" #include "string.h" #include "mach-o/loader.h" -#include "objc/objc-runtime.h" #include "stuff/allocate.h" #include "stuff/bytesex.h" #include "stuff/symbol.h" @@ -75,6 +74,14 @@ struct objc_class_t { uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */ }; +#ifndef CLS_GETINFO +# define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask)) +// class is not a metaclass +#define CLS_CLASS 0x1 +// class is a metaclass +#define CLS_META 0x2 +#endif + struct objc_category_t { uint32_t category_name; /* char * (32-bit pointer) */ uint32_t class_name; /* char * (32-bit pointer) */ @@ -331,7 +338,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, @@ -345,7 +352,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( @@ -511,7 +518,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) @@ -564,7 +571,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); @@ -893,7 +900,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; @@ -920,7 +927,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); @@ -945,7 +952,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; @@ -975,7 +982,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); @@ -1017,7 +1024,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) { @@ -1104,7 +1111,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, @@ -1146,7 +1153,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: @@ -1164,7 +1171,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); @@ -1191,7 +1198,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; @@ -1298,7 +1305,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; @@ -1327,7 +1334,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: @@ -1345,7 +1352,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); @@ -1366,7 +1373,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 e5dba9cd..c578cb59 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; - 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_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", "__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", "__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", "__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"); - 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); + + 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; + + 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"); + 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"); + 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"); + 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"); + 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", "__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, + "__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; - - printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname); - for(i = 0; i < s->size; i += sizeof(uint32_t)){ - - 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(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); - - if(info->swapped) - p = SWAP_INT(p); - printf("0x%x", p); - - 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(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); + for(i = 0; i < s->size; i += sizeof(uint32_t)){ + + 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(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); + + 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; - - 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); - - if(! is_meta_class) - { - printf("Meta Class\n"); - print_class_t(c.isa, info); - } + 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); + + 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; - - 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; + 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); + + 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; - - 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); - - 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); - - 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"); - - p += sizeof(struct method_t); - offset += sizeof(struct method_t); - } + 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); + 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); + + indent_push(info, sizeof("entsize") - 1); + + print_field_scalar(info, "entsize", "%u\n", ml.entsize); + print_field_scalar(info, "count", "%u\n", ml.count); + + 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; - - 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); - - 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); - - 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); + 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); + + 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("\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); - - p += sizeof(struct ivar_t); - offset += sizeof(struct ivar_t); - } + } + 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); + + 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; - - 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); - - 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); - - 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); - - 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); - - p += sizeof(uint32_t); - offset += sizeof(uint32_t); - } + 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); + + indent_push(info, sizeof("list[99]") - 1); + + print_field_scalar(info, "count", "%llu\n", pl.count); + + 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; - - 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); - - 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); - - 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"); - - p += sizeof(struct objc_property); - offset += sizeof(struct objc_property); - } + 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); + + indent_push(info, sizeof("attributes") - 1); + + 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); + + /* + * 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); +} - 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); +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; - - 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_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); - } + uint32_t n_value; + + 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); + + 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; - - 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"); + + 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); + + 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; + + 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); + } +} - 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)); +/* + * 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 720355d6..666e66a6 100644 --- a/cctools/otool/print_objc2_64bit.c +++ b/cctools/otool/print_objc2_64bit.c @@ -33,6 +33,7 @@ #include "stddef.h" #include "string.h" #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 +41,8 @@ #include "dyld_bind_info.h" #include "ofile_print.h" +#include + extern char *oname; /* @@ -65,11 +68,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 +95,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 +126,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 +142,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 +159,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 +177,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 +195,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 +217,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 +239,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 +254,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 +274,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 +293,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 +329,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,26 +348,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; - uint32_t object_size; + 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; @@ -373,9 +379,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 { @@ -413,8 +421,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, @@ -432,6 +439,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); @@ -446,9 +457,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( @@ -463,7 +475,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( @@ -475,13 +487,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. @@ -489,12 +532,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, @@ -507,105 +551,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.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); - - 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_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", "__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", "__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", "__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); + + 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; + + 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"); + 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"); + 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"); + 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"); + 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"); + 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 @@ -616,52 +684,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; - - 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)){ - - memset(&p, '\0', 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; - 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); - } + int64_t addend; + + 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); + 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); + + memset(&p, '\0', sizeof(uint64_t)); + memcpy(&p, s->contents + i, size); + if(info->swapped) + p = SWAP_LONG_LONG(p); + + print_field_value(i, p, FALSE, NULL, "\n", info, s, &n_value, &addend); + + if(func != NULL) + func(n_value + addend, info); + } } /* @@ -676,7 +732,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, @@ -685,54 +741,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; - - get_sections_64(load_commands, ncmds, sizeofcmds, object_byte_sex, - object_addr, object_size, §ions, &nsections, - &database); - - 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; - } - - name = get_pointer_64(cfs_characters, NULL, &left, NULL, - sections, nsections); - - if(sections != NULL) - free(sections); - - return(name); + 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, + &textbase, &database); + + 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()); + + 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; + + name = get_pointer_64(cfs_characters, NULL, &left, NULL, + sections, nsections); + + if(sections != NULL) + free(sections); + + return(name); } /* @@ -751,7 +805,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, @@ -760,7 +814,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; @@ -768,84 +823,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; - - 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); - } - } - - 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); + 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, + &textbase, &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, textbase, database, + address_of_p, s->relocs, s->nrelocs, + &info, &n_value, &addend); + if(symbol_name == NULL){ + 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); + 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); + } + } + + 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); + } + + 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); } /* @@ -864,7 +925,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, @@ -873,38 +934,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; - - 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); + 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, + &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 @@ -917,90 +981,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; - - 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"); - - 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); - - 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); - } + 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); + + 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 @@ -1014,152 +1066,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; - - 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); - - 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"); - - 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, ""); - - 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); - - 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); - - 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); - - 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); - - if(is_meta_class) - *is_meta_class = (cro.flags & RO_META) ? TRUE : FALSE; + 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); + + 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_scalar(info, "reserved", "0x%x\n", cro.reserved); + + 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); + + 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 @@ -1172,131 +1175,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; + + 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); + + indent_push(info, sizeof("entsize") - 1); + + print_field_scalar(info, "entsize", "%u\n", ml.entsize); + print_field_scalar(info, "count", "%u\n", ml.count); + + 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; + + 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, &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); - 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); - - 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); - - 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"); - - 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"); - - 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"); - - p += sizeof(struct method_t); - offset += sizeof(struct method_t); - } + p += sizeof(struct method_t); + offset += sizeof(struct method_t); + } + + indent_pop(info); } static @@ -1310,114 +1274,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; - - - 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); - - 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); - - 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); + 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); + + 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_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("\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"); - - 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"); - - printf("\t\t\talignment %u\n", i.alignment); - printf("\t\t\t size %u\n", i.size); - - p += sizeof(struct ivar_t); - offset += sizeof(struct ivar_t); - } + } + 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); + + print_field_label(info, "type"); + print_field_value(offset + offsetof(struct ivar_t, type), + i.type, TRUE, NULL, "\n", info, s, &n_value, &addend); + + 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 @@ -1428,149 +1358,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; - - 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); - - 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); - - 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"); - - 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); - - printf("\t\t\t isa 0x%llx\n", pc.isa); - - 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"); - - printf("\t\t\tprotocols 0x%llx\n", pc.protocols); - - 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); - } + 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); + + indent_push(info, sizeof("list[99]") - 1); + + print_field_scalar(info, "count", "%llu\n", pl.count); + + 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; + + 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); + + 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); + } + + indent_pop(info); } static @@ -1584,89 +1433,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; - - 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); - - 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); - - 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"); - - 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); - offset += sizeof(struct objc_property); - } + int64_t addend; + + 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); + + indent_push(info, sizeof("attributes") - 1); + + 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_64(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, &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 @@ -1679,136 +1502,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); + + /* + * 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, &addend); + + 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); + } + + 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); + } + + 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); +} - 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); - - 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"); - - 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); - - 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, ""); - - 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, ""); - - 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); - - 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); +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 @@ -1819,68 +1685,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; - - 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); - - 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(" 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"); - - offset += sizeof(struct message_ref); - } + 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); + + 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_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 @@ -1894,40 +1742,60 @@ struct info *info) struct objc_image_info o; void *r; - 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"); + 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_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 @@ -1938,7 +1806,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, @@ -1952,74 +1820,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.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; - 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); - - 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((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)); - - 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); - } + 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; + + get_sections_64(load_commands, ncmds, sizeofcmds, object_byte_sex, + object_addr, object_size, &info.sections, + &info.nsections, &info.textbase, &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); + + 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 @@ -2030,15 +1913,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; @@ -2046,197 +1931,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; - - *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_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); - - *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)++; - - 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; - } - } - } - } + host_byte_sex = get_host_byte_sex(); + swapped = host_byte_sex != object_byte_sex; + + *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 - (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 && + 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 = + (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(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 @@ -2248,14 +2136,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 @@ -2266,102 +2154,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; - - 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); - - 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 - (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; - } + host_byte_sex = get_host_byte_sex(); + swapped = host_byte_sex != object_byte_sex; + + 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 - (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); + + 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); + + 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 @@ -2377,97 +2266,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(addend != NULL) + *addend = value; + has_auth = FALSE; + + /* + * 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. + */ + + /* + * 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; +} - if(n_value != NULL) - *n_value = 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->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)); +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 0a1e2972..933d2d64 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/cmake/config-ix.cmake b/cmake/config-ix.cmake index 720255c8..00f1171b 100644 --- a/cmake/config-ix.cmake +++ b/cmake/config-ix.cmake @@ -38,6 +38,8 @@ endif() check_function_exists(strnlen XTOOLS_HAS_STRNLEN) check_function_exists(strndup XTOOLS_HAS_STRNDUP) +check_function_exists(clock_gettime XTOOLS_HAS_CLOCK_GETTIME) +check_function_exists(utimensat XTOOLS_HAS_UTIMENSAT) if((NOT XTOOLS_HAS_STRNLEN) OR (NOT XTOOLS_HAS_STRNDUP)) set(XTOOLS_NEEDS_STRLIB ON) diff --git a/ld64/src/CMakeLists.txt b/ld64/src/CMakeLists.txt index 1be1a5e7..87faf399 100644 --- a/ld64/src/CMakeLists.txt +++ b/ld64/src/CMakeLists.txt @@ -3,6 +3,11 @@ if(XTOOLS_LTO_SUPPORT) set(LTO_SUPPORT_INFO "(with LLVM LTO support)") endif() +if(XTOOLS_TAPI_SUPPORT) + add_definitions(-DTAPI_SUPPORT) + set(TAPI_SUPPORT_INFO "(with TAPI support)") +endif() + if(XTOOLS_BUGURL) add_definitions(-DXTOOLS_BUGURL="${XTOOLS_BUGURL}") endif() @@ -76,4 +81,4 @@ include_directories("${CMAKE_CURRENT_SOURCE_DIR}/abstraction") add_subdirectory(ld) add_subdirectory(other) -add_library(prunetrie other/PruneTrie.cpp) +add_library(prunetrie STATIC other/PruneTrie.cpp) diff --git a/ld64/src/ld/CMakeLists.txt b/ld64/src/ld/CMakeLists.txt index c314ff45..7a3fdc59 100644 --- a/ld64/src/ld/CMakeLists.txt +++ b/ld64/src/ld/CMakeLists.txt @@ -51,8 +51,13 @@ configure_file ( ) if(XTOOLS_TAPI_SUPPORT) - include_directories("${XTOOLS_TAPI_PATH}/include") - message(STATUS "*LD64* including ${XTOOLS_TAPI_PATH}/include") + if(XTOOLS_USE_TAPILITE) + include_directories("${CMAKE_SOURCE_DIR}/tapilite/include") + message(STATUS "*LD64* including ${CMAKE_SOURCE_DIR}/tapilite/include") + else() + include_directories("${XTOOLS_TAPI_PATH}/include") + message(STATUS "*LD64* including ${XTOOLS_TAPI_PATH}/include") + endif() endif() include_directories("${CMAKE_CURRENT_SOURCE_DIR}") @@ -62,10 +67,6 @@ if(XTOOLS_LTO_SUPPORT) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lLTO") endif() -if(XTOOLS_TAPI_SUPPORT) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ltapi") -endif() - add_definitions(-DLD_VERS="xtools-ld64-${LD64_VERSION_NUM}") add_executable(ld ${LD64_SOURCES}) @@ -73,4 +74,12 @@ if(NOT XTOOLS_HAS_MODERNXAR) target_link_libraries(ld xarextralib) endif() +if(XTOOLS_TAPI_SUPPORT) + if(XTOOLS_USE_TAPILITE) + target_link_libraries(ld tapilite yaml) + else() + target_link_libraries(ld tapi) + endif() +endif() + install(TARGETS ld DESTINATION bin) diff --git a/ld64/src/ld/InputFiles.cpp b/ld64/src/ld/InputFiles.cpp index 5d5a9687..10ba632d 100644 --- a/ld64/src/ld/InputFiles.cpp +++ b/ld64/src/ld/InputFiles.cpp @@ -908,6 +908,8 @@ void InputFiles::inferArchitecture(Options& opts, const char** archName) opts.setArchitecture(CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL, Options::kPlatformOSX); #elif __arm__ opts.setArchitecture(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6, Options::kPlatformOSX); +#elif __arm64__ + opts.setArchitecture(CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL, Options::kPlatformOSX); #else #error unknown default architecture #endif diff --git a/ld64/src/ld/Options.cpp b/ld64/src/ld/Options.cpp index 0ab643d6..776d5ff0 100644 --- a/ld64/src/ld/Options.cpp +++ b/ld64/src/ld/Options.cpp @@ -36,7 +36,9 @@ #include #include #include +#ifdef TAPI_SUPPORT #include +#endif #include #include @@ -860,6 +862,7 @@ bool Options::findFile(const std::string &path, const std::vector & break; } +#ifdef TAPI_SUPPORT // If we found a text-based stub file, check if it should be used. if ( !tbdInfo.missing() ) { if (tapi::LinkerInterfaceFile::shouldPreferTextBasedStubFile(tbdInfo.path)) { @@ -867,6 +870,7 @@ bool Options::findFile(const std::string &path, const std::vector & return true; } } +#endif FileInfo dylibInfo; { bool found = dylibInfo.checkFileExists(*this, path.c_str()); @@ -884,6 +888,7 @@ bool Options::findFile(const std::string &path, const std::vector & result = dylibInfo; return true; } +#ifdef TAPI_SUPPORT // There are both - a text-based stub file and a dynamic library file. else if ( !tbdInfo.missing() && !dylibInfo.missing() ) { // If the files are still in synv we can use and should use the text-based stub file. @@ -898,6 +903,7 @@ bool Options::findFile(const std::string &path, const std::vector & } return true; } +#endif return false; } @@ -3992,15 +3998,24 @@ void Options::buildSearchPaths(int argc, const char* argv[]) FILE *out = isVersion ? stdout : stderr; fVerbose = true; extern const char ldVersionString[]; - fprintf(out, "%s", ldVersionString); + /* skip backwards compatible header on GNU-style --version, + * keep it on -v for tools like meson */ + const char *ldvers; + if (isVersion) + ldvers = strchr(ldVersionString, '\n') + 1; + else + ldvers = ldVersionString; + fprintf(out, "%s", ldvers); fprintf(out, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS); #ifdef LTO_SUPPORT const char* ltoVers = lto::version(); if ( ltoVers != NULL ) fprintf(out, "LTO support using: %s\n", ltoVers); #endif +#ifdef TAPI_SUPPORT fprintf(out, "TAPI support using: %s\n", tapi::Version::getFullVersionAsString().c_str()); +#endif // if only -v specified or --version, exit cleanly if ( argc == 2 || isVersion ) { exitAfterOptionsParsing = true; diff --git a/ld64/src/ld/ld_vers.c.in b/ld64/src/ld/ld_vers.c.in index 1d5e3207..9dc69965 100644 --- a/ld64/src/ld/ld_vers.c.in +++ b/ld64/src/ld/ld_vers.c.in @@ -1,4 +1,4 @@ const unsigned char ldVersionString[] __attribute__ ((used)) = -"xtools-@XTOOLS_VERSION@ ld (@PACKAGE_VERSION@)\nBased on Apple Inc. ld64-@LD64_VERSION_NUM@ @LTO_SUPPORT_INFO@\n"; +"@(#)PROGRAM:ld PROJECT:ld64-@LD64_VERSION_NUM@\nxtools-@XTOOLS_VERSION@ ld (@PACKAGE_VERSION@)\nBased on Apple Inc. ld64-@LD64_VERSION_NUM@ @LTO_SUPPORT_INFO@\n"; const double ldVersionNumber __attribute__ ((used)) = (double)@LD64_VERSION_DBL@; diff --git a/ld64/src/ld/parsers/archive_file.cpp b/ld64/src/ld/parsers/archive_file.cpp index c09c40a3..f13d3d67 100644 --- a/ld64/src/ld/parsers/archive_file.cpp +++ b/ld64/src/ld/parsers/archive_file.cpp @@ -514,6 +514,7 @@ bool File::forEachAtom(ld::File::AtomHandler& handler) const } } } +#ifdef LTO_SUPPORT else if ( validLTOFile(member->content(), member->contentSize(), _objOpts) ) { if ( lto::hasObjCCategory(member->content(), member->contentSize()) ) { MemberState& state = this->makeObjectFileForMember(member); @@ -525,6 +526,7 @@ bool File::forEachAtom(ld::File::AtomHandler& handler) const } } } +#endif } } return didSome; diff --git a/ld64/src/ld/parsers/libunwind/Registers.hpp b/ld64/src/ld/parsers/libunwind/Registers.hpp index ceacc286..c1119477 100644 --- a/ld64/src/ld/parsers/libunwind/Registers.hpp +++ b/ld64/src/ld/parsers/libunwind/Registers.hpp @@ -43,6 +43,55 @@ namespace libunwind { +#ifndef i386_thread_state_t +struct _i386_thread_state_t +{ + 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; +}; +#define i386_thread_state_t _i386_thread_state_t +#endif +#ifndef x86_thread_state64_t +struct _x86_thread_state64_t +{ + __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; +}; +#define x86_thread_state64_t _x86_thread_state64_t +#endif /// /// Registers_x86 holds the register state of a thread in a 32-bit intel process. /// diff --git a/ld64/src/ld/parsers/textstub_dylib_file.cpp b/ld64/src/ld/parsers/textstub_dylib_file.cpp index 63858ba7..a3d2258c 100644 --- a/ld64/src/ld/parsers/textstub_dylib_file.cpp +++ b/ld64/src/ld/parsers/textstub_dylib_file.cpp @@ -23,6 +23,7 @@ */ +#ifdef TAPI_SUPPORT #include #include #include @@ -35,12 +36,14 @@ #include "MachOFileAbstraction.hpp" #include "MachOTrie.hpp" #include "generic_dylib_file.hpp" +#endif #include "textstub_dylib_file.hpp" namespace textstub { namespace dylib { +#ifdef TAPI_SUPPORT // // The reader for a dylib extracts all exported symbols names from the memory-mapped // dylib, builds a hash table, then unmaps the file. This is an important memory @@ -252,6 +255,7 @@ class Parser indirectDylib); } }; +#endif // // main function used by linker to instantiate ld::Files @@ -261,6 +265,7 @@ ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength, const ch bool bundleLoader, bool indirectDylib) { +#ifdef TAPI_SUPPORT switch ( opts.architecture() ) { #if SUPPORT_ARCH_x86_64 case CPU_TYPE_X86_64: @@ -293,6 +298,7 @@ ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength, const ch return Parser::parse(path, fileContent, fileLength, modTime, ordinal, opts, indirectDylib); #endif } +#endif return nullptr; } diff --git a/ld64/src/other/unwinddump.cpp b/ld64/src/other/unwinddump.cpp index 2c13b83c..d8f9f28e 100644 --- a/ld64/src/other/unwinddump.cpp +++ b/ld64/src/other/unwinddump.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include diff --git a/tapilite/CMakeLists.txt b/tapilite/CMakeLists.txt new file mode 100644 index 00000000..c83334c5 --- /dev/null +++ b/tapilite/CMakeLists.txt @@ -0,0 +1,26 @@ + +set(TAPI_FULL_VERSION "2.0.3" CACHE STRING "Specify tapi version.") +message(STATUS "TAPI version: ${TAPI_FULL_VERSION}") + +set(TAPI_APPLE_VERSION "1000.10.8" CACHE STRING "Specify tapi version.") +message(STATUS "APPLE Tapi version: ${TAPI_APPLE_VERSION}") + +set(TAPI_REPOSITORY_STRING "https://github.com/grobian/darwin-xtools.git" CACHE STRING + "Vendor-specific text for showing the repository the source is taken from.") + +if(TAPI_REPOSITORY_STRING) + add_definitions(-DTAPI_REPOSITORY_STRING="${TAPI_REPOSITORY_STRING}") +endif() + +set(TAPI_VENDOR "tapilite" CACHE STRING + "Vendor-specific text for showing with version information.") + +if (TAPI_VENDOR) + add_definitions( -DTAPI_VENDOR="${TAPI_VENDOR} ") +endif() + +if (TAPI_APPLE_VERSION) + add_definitions( -DAPPLE_VERSION="${TAPI_APPLE_VERSION}") +endif () + +add_subdirectory(src) diff --git a/tapilite/LICENSE.TXT b/tapilite/LICENSE.TXT new file mode 100644 index 00000000..06e331e3 --- /dev/null +++ b/tapilite/LICENSE.TXT @@ -0,0 +1,62 @@ +============================================================================== +tapi License +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2011-2014 by the contributors listed in CREDITS.TXT +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +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: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +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 +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +============================================================================== +The lld software contains code written by third parties. Such software will +have its own individual LICENSE.TXT file in the directory in which it appears. +This file will describe the copyrights, license, and restrictions which apply +to that code. + +The disclaimer of warranty in the University of Illinois Open Source License +applies to all code in the lld Distribution, and nothing in any of the +other licenses gives permission to use the names of the LLVM Team or the +University of Illinois to endorse or promote products derived from this +Software. + +The following pieces of software have additional or alternate copyrights, +licenses, and/or restrictions: + +Program Directory +------- --------- + diff --git a/tapilite/README b/tapilite/README new file mode 100644 index 00000000..a28fe137 --- /dev/null +++ b/tapilite/README @@ -0,0 +1,6 @@ +This is a very minimal, LLVM-independent implementation of TAPI, such +that we can compile (and bootstrap) a linker that will be usable on +recent macOS without the need for LLVM. + +dependencies: libyaml +provides: required interfaces from ld64/src/ld/parsers/textstub_dylib_file diff --git a/tapilite/include/tapi/Defines.h b/tapilite/include/tapi/Defines.h new file mode 100644 index 00000000..00f6f2f9 --- /dev/null +++ b/tapilite/include/tapi/Defines.h @@ -0,0 +1,32 @@ +//===-- tapi/Defines.h - TAPI C++ Library Defines ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief TAPI C++ library defines. +/// \since 1.0 +/// +//===----------------------------------------------------------------------===// +// +// Modified version for "tapilite", a standalone just enough +// implementation for use without LLVM +// +#ifndef TAPI_DEFINES_H +#define TAPI_DEFINES_H + +#define TAPI_INTERNAL tapi::internal +#define TAPI_NAMESPACE_INTERNAL_BEGIN namespace tapi { namespace internal { +#define TAPI_NAMESPACE_INTERNAL_END } } + +#define TAPI_NAMESPACE_V1_BEGIN namespace tapi { inline namespace v1 { +#define TAPI_NAMESPACE_V1_END } } + +#define TAPI_PUBLIC __attribute__((visibility ("default"))) + +#endif // TAPI_DEFINES_H + diff --git a/tapilite/include/tapi/LinkerInterfaceFile.h b/tapilite/include/tapi/LinkerInterfaceFile.h new file mode 100644 index 00000000..51b82637 --- /dev/null +++ b/tapilite/include/tapi/LinkerInterfaceFile.h @@ -0,0 +1,496 @@ +//===-- tapi/LinkerInterfaceFile.h - TAPI File Interface --------*- C++ -*-===*\ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief API for reading TAPI files. +/// \since 1.0 +/// +//===----------------------------------------------------------------------===// +// +// Modified version for "tapilite", a standalone just enough +// implementation for use without LLVM +// +#ifndef TAPI_LINKER_INTERFACE_FILE_H +#define TAPI_LINKER_INTERFACE_FILE_H + +#include +#include +#include +#include + +/// +/// \defgroup TAPI_LINKER_INTERFACE_FILE TAPI File APIs +/// \ingroup TAPI_CPP_API +/// +/// @{ +/// + +using cpu_type_t = int; +using cpu_subtype_t = int; + +TAPI_NAMESPACE_V1_BEGIN + +class PackedVersion32; +class Symbol; + +/// +/// \brief Defines a list of supported platforms. +/// \since 1.0 +/// +enum class Platform : unsigned { + /// \brief Unknown platform + /// \since 1.0 + Unknown = 0, + + /// \brief Mac OS X + /// \since 1.0 + OSX = 1, + + /// \brief iOS + /// \since 1.0 + iOS = 2, + + /// \brief watchOS + /// \since 1.0 + watchOS = 3, + + /// \brief tvOS + /// \since 1.0 + tvOS = 4, + + /// \brief bridgeOS + /// \since 1.2 + bridgeOS = 5, + + /// \brief zippered + /// \since 2.0 + zippered = 6, +}; + +/// +/// \brief Defines a list of Objective-C constraints. +/// \since 1.0 +/// +enum class ObjCConstraint : unsigned { + /// \brief No constraint. + /// \since 1.0 + None = 0, + + /// \brief Retain/Release. + /// \since 1.0 + Retain_Release = 1, + + /// \brief Retain/Release for Simulator. + /// \since 1.0 + Retain_Release_For_Simulator = 2, + + /// \brief Retain/Release or Garbage Collection. + /// \since 1.0 + Retain_Release_Or_GC = 3, + + /// \brief Garbage Collection. + /// \since 1.0 + GC = 4, +}; + +/// +/// \brief Defines a list of supported file types. +/// \since 1.0 +/// +enum class FileType : unsigned { + /// \brief Unsupported file type. + /// \since 1.0 + Unsupported = 0, + + /// \brief Text-based Dynamic Library Stub File (.tbd) version 1.0 + /// \since 1.0 + TBD_V1 = 1, + + /// \brief Text-based stub file (.tbd) version 2.0 + /// \since 1.0 + TBD_V2 = 2, + + /// \brief Text-based stub file (.tbd) version 3.0 + /// \since 1.3 + TBD_V3 = 3, + + /// format as seen on Big Sur + TBD_V4 = 4, +}; + +/// +/// \brief Defines the cpu subtype matching mode. +/// \since 1.0 +/// +enum class CpuSubTypeMatching : unsigned { + /// \brief Fall-back to an ABI compatible slice if an exact match cannot be + /// found. + /// \since 1.0 + ABI_Compatible = 0, + + /// \brief Only accept a slice if the sub type matches. + /// \since 1.0 + Exact = 1, +}; + +/// +/// \brief Defines flags that control the parsing of text-based stub files. +/// \since 1.1 +/// +enum ParsingFlags : unsigned { + /// \brief Default flags. + /// \since 1.1 + None = 0, + + /// \brief Only accept a slice if the sub type matches. ABI fall-back mode is + /// the default. + /// \since 1.1 + ExactCpuSubType = 1U << 0, + + /// \brief Disallow weak imported symbols. This adds weak imported symbols to + /// the ignore exports list. + /// \since 1.1 + DisallowWeakImports = 1U << 1, +}; + +inline ParsingFlags operator|(ParsingFlags lhs, ParsingFlags rhs) noexcept { + return static_cast(static_cast(lhs) | + static_cast(rhs)); +} + +inline ParsingFlags operator|=(ParsingFlags &lhs, ParsingFlags rhs) noexcept { + lhs = lhs | rhs; + return lhs; +} + +/// +/// \brief TAPI File APIs +/// \since 1.0 +/// +class TAPI_PUBLIC LinkerInterfaceFile { +public: + /// + /// \brief Returns a list of supported file extensions. + /// + /// \returns a list of supported file extensions. + /// \since 1.0 + /// + static std::vector getSupportedFileExtensions() noexcept; + + /// + /// \brief Indicate if the provided buffer is a supported Text-based Dynamic + /// Library Stub file. + /// + /// Checks if the buffer is a supported format. This doesn't check for + /// malformed buffer content. + /// + /// \param[in] path full path to the file. + /// \param[in] data raw pointer to start of buffer. + /// \param[in] size size of the buffer in bytes. + /// \returns true if the format is supported. + /// \since 1.0 + /// + static bool isSupported(const std::string &path, const uint8_t *data, + size_t size) noexcept; + + /// + /// \brief Check if we should prefer the text-based stub file. + /// + /// \param[in] path full path to the text-based stub file. + /// \returns true if the tex-based stub file should be prefered over any + /// dynamic library. + /// \since 1.0 + /// + static bool shouldPreferTextBasedStubFile(const std::string &path) noexcept; + + /// + /// \brief Check if the text-based stub file and the MachO dynamic library + /// file are in sync. + /// + /// This validates both files against each other and checks if both files are + /// still in sync. + /// + /// \param[in] tbdPath full path to the text-based stub file. + /// \param[in] dylibPath full path to the MachO dynamic library file. + /// \returns true if both files are in sync. + /// \since 1.0 + /// + static bool areEquivalent(const std::string &tbdPath, + const std::string &dylibPath) noexcept; + + /// + /// \brief Create a LinkerInterfaceFile from the provided buffer. + /// + /// Parses the content of the provided buffer with the given constrains for + /// cpu type, cpu sub-type, matching requirement, and minimum deployment + /// version. + /// + /// \param[in] path path to the file (for error message only). + /// \param[in] data raw pointer to start of buffer. + /// \param[in] size size of the buffer in bytes. + /// \param[in] cpuType The cpu type / architecture to check the file for. + /// \param[in] cpuSubType The cpu sub type / sub architecture to check the + /// file for. + /// \param[in] matchingMode Specified the cpu subtype matching mode. + /// \param[in] minOSVersion The minimum OS version / deployment target. + /// \param[out] errorMessage holds an error message when the return value is a + /// nullptr. + /// \return nullptr on error + /// \since 1.0 + /// \deprecated 1.1 + /// + static LinkerInterfaceFile * + create(const std::string &path, const uint8_t *data, size_t size, + cpu_type_t cpuType, cpu_subtype_t cpuSubType, + CpuSubTypeMatching matchingMode, PackedVersion32 minOSVersion, + std::string &errorMessage) noexcept; + + /// + /// \brief Create a LinkerInterfaceFile from the provided buffer. + /// + /// Parses the content of the provided buffer with the given constrains for + /// cpu type, cpu sub-type, flags, and minimum deployment version. + /// + /// \param[in] path path to the file (for error message only). + /// \param[in] data raw pointer to start of buffer. + /// \param[in] size size of the buffer in bytes. + /// \param[in] cpuType The cpu type / architecture to check the file for. + /// \param[in] cpuSubType The cpu sub type / sub architecture to check the + /// file for. + /// \param[in] flags Flags that control the parsing behavior. + /// \param[in] minOSVersion The minimum OS version / deployment target. + /// \param[out] errorMessage holds an error message when the return value is a + /// nullptr. + /// \return nullptr on error + /// \since 1.1 + /// \deprecated 1.3 + /// + static LinkerInterfaceFile * + create(const std::string &path, const uint8_t *data, size_t size, + cpu_type_t cpuType, cpu_subtype_t cpuSubType, ParsingFlags flags, + PackedVersion32 minOSVersion, std::string &errorMessage) noexcept; + + /// + /// \brief Create a LinkerInterfaceFile from a file. + /// + /// Parses the content of the file with the given constrains for cpu type, + /// cpu sub-type, flags, and minimum deployment version. + /// + /// \param[in] path path to the file. + /// \param[in] cpuType The cpu type / architecture to check the file for. + /// \param[in] cpuSubType The cpu sub type / sub architecture to check the + /// file for. + /// \param[in] flags Flags that control the parsing behavior. + /// \param[in] minOSVersion The minimum OS version / deployment target. + /// \param[out] errorMessage holds an error message when the return value is a + /// nullptr. + /// \return nullptr on error + /// \since 1.3 + /// + static LinkerInterfaceFile * + create(const std::string &path, cpu_type_t cpuType, cpu_subtype_t cpuSubType, + ParsingFlags flags, PackedVersion32 minOSVersion, + std::string &errorMessage) noexcept; + + /// + /// \brief Query the file type. + /// \return Returns the file type this TAPI file represents. + /// \since 1.0 + /// + FileType getFileType() const noexcept; + + /// + /// \brief Query the platform + /// \return Returns the platform supported by the TAPI file. + /// \since 1.0 + /// + Platform getPlatform() const noexcept; + + /// + /// \brief Query the install name. + /// \return Returns the install name of the TAPI file. + /// \since 1.0 + /// + const std::string &getInstallName() const noexcept; + + /// + /// \brief Query the install name is version specifc. + /// \return True if the install name has been adjusted for the provided + /// minimum OS version. + /// \since 1.0 + /// + bool isInstallNameVersionSpecific() const noexcept; + + /// + /// \brief Query the current library version. + /// \return Returns the current library version as 32bit packed version. + /// \since 1.0 + /// + PackedVersion32 getCurrentVersion() const noexcept; + + /// + /// \brief Query the compatibility library version. + /// \return Returns the compatibility library version as 32bit packed version. + /// \since 1.0 + /// + PackedVersion32 getCompatibilityVersion() const noexcept; + + /// + /// \brief Query the Swift ABI version. + /// \return Returns the Swift ABI version as unsigned integer. + /// \since 1.0 + /// + unsigned getSwiftVersion() const noexcept; + + /// + /// \brief Query the Objective-C Constraint. + /// \return Returns the Objetive-C constraint. + /// \since 1.0 + /// + ObjCConstraint getObjCConstraint() const noexcept; + + /// + /// \brief Query if the library has two level namespace. + /// \return Returns true if the library has two level namespace. + /// \since 1.0 + /// + bool hasTwoLevelNamespace() const noexcept; + + /// + /// \brief Query if the library is Applicatiuon Extension Safe. + /// \return Returns true if the library is Application Extension Safe. + /// \since 1.0 + /// + bool isApplicationExtensionSafe() const noexcept; + + /// + /// \brief Query if the library has any allowable clients. + /// \return Return true if there are any allowable clients. + /// \since 1.0 + /// + bool hasAllowableClients() const noexcept; + + /// + /// \brief Query if the library has any re-exported libraries. + /// \return Return true if there are any re-exported libraries. + /// \since 1.0 + /// + bool hasReexportedLibraries() const noexcept; + + /// + /// \brief Query if the library has any weak defined exports. + /// \return Return true if there are any weak defined exports. + /// \since 1.0 + /// + bool hasWeakDefinedExports() const noexcept; + + /// + /// \brief Obtain the name of the parent framework (umbrella framework). + /// \return Returns the name of the parent framework (if it exists), otherwise + /// an empty string. + /// \since 1.0 + /// + const std::string &getParentFrameworkName() const noexcept; + + /// + /// \brief Obtain the list of allowable clients. + /// \return Returns a list of allowable clients. + /// \since 1.0 + /// + const std::vector &allowableClients() const noexcept; + + /// + /// \brief Obtain the list of re-exported libraries. + /// \return Returns a list of re-exported libraries. + /// \since 1.0 + /// + const std::vector &reexportedLibraries() const noexcept; + + /// + /// \brief Obtain a list of all symbols to be ignored. + /// \return Returns a list of all symbols that should be ignored. + /// \since 1.0 + /// + const std::vector &ignoreExports() const noexcept; + + /// + /// \brief Obtain a list of all exported symbols. + /// \return Returns a list of all exported symbols. + /// \since 1.0 + /// + const std::vector &exports() const noexcept; + + /// + /// \brief Obtain a list of all undefined symbols. + /// \return Returns a list of all undefined symbols. + /// \since 1.0 + /// + const std::vector &undefineds() const noexcept; + + /// + /// \brief Obtain a list of all inlined frameworks. + /// \return Returns a list of install names of all inlined frameworks. + /// \since 1.3 + /// + const std::vector &inlinedFrameworkNames() const noexcept; + + /// + /// \brief Create a LinkerInterfaceFile from the specified inlined framework. + /// + /// Creates a LinkerInterfaceFile with the given constrains for cpu type, + /// cpu sub-type, flags, and minimum deployment version. + /// + /// \param[in] installName install name of the inlined framework. + /// \param[in] cpuType The cpu type / architecture to check the file for. + /// \param[in] cpuSubType The cpu sub type / sub architecture to check the + /// file for. + /// \param[in] flags Flags that control the parsing behavior. + /// \param[in] minOSVersion The minimum OS version / deployment target. + /// \param[out] errorMessage holds an error message when the return value is a + /// nullptr. + /// \return nullptr on error + /// \since 1.3 + /// + LinkerInterfaceFile * + getInlinedFramework(const std::string &installName, cpu_type_t cpuType, + cpu_subtype_t cpuSubType, ParsingFlags flags, + PackedVersion32 minOSVersion, + std::string &errorMessage) const noexcept; + + /// + /// \brief Destructor. + /// \since 1.0 + /// + ~LinkerInterfaceFile() noexcept; + + /// + /// \brief Copy constructor (deleted). + /// \since 1.0 + /// + LinkerInterfaceFile(const LinkerInterfaceFile &) noexcept = delete; + LinkerInterfaceFile &operator=(const LinkerInterfaceFile &) noexcept = delete; + + /// + /// \brief Move constructor. + /// \since 1.0 + /// + LinkerInterfaceFile(LinkerInterfaceFile &&) noexcept; + LinkerInterfaceFile &operator=(LinkerInterfaceFile &&) noexcept; + +private: + LinkerInterfaceFile() noexcept; + + class Impl; + class ImplData; + std::unique_ptr _pImpl; +}; + +TAPI_NAMESPACE_V1_END + +#endif // TAPI_LINKER_INTERFACE_FILE_H diff --git a/tapilite/include/tapi/PackedVersion32.h b/tapilite/include/tapi/PackedVersion32.h new file mode 100644 index 00000000..f8d96d0c --- /dev/null +++ b/tapilite/include/tapi/PackedVersion32.h @@ -0,0 +1,109 @@ +//===-- tapi/PackedVersion32.h - TAPI Packed Version 32 ---------*- C++ -*-===*\ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines the packed version number. +/// \since 1.0 +/// +//===----------------------------------------------------------------------===// +// +// Modified version for "tapilite", a standalone just enough +// implementation for use without LLVM +// +#ifndef TAPI_PACKED_VERSION_32_H +#define TAPI_PACKED_VERSION_32_H + +#include + +/// +/// \defgroup TAPI_PACKED_VERSION_32 Packed Version handling +/// \ingroup TAPI_CPP_API +/// +/// @{ +/// + +TAPI_NAMESPACE_V1_BEGIN + +/// +/// \brief Packed Version Number Encoding. +/// +/// The Mach-O version numbers are commonly encoded as a 32bit value, where the +/// upper 16 bit quantity is used for the major version number and the lower two +/// 8 bit quantities as minor version number and patch version number. +/// +/// \since 1.0 +/// +class TAPI_PUBLIC PackedVersion32 { +private: + uint32_t _version; + +public: + /// + /// \brief Default construct a PackedVersion32. + /// \since 1.0 + /// + PackedVersion32() = default; + + /// + /// \brief Construct a PackedVersion32 with a raw value. + /// \since 1.0 + /// + PackedVersion32(uint32_t rawVersion) : _version(rawVersion) {} + + /// + /// \brief Construct a PackedVersion32 with the provided major, minor, and + /// patch version number. + /// \since 1.0 + /// + PackedVersion32(unsigned major, unsigned minor, unsigned patch) + : _version((major << 16) | ((minor & 0xff) << 8) | (patch & 0xff)) {} + + /// + /// \brief Get the major version number. + /// \return The major version number as unsigned integer. + /// \since 1.0 + /// + unsigned getMajor() const { return _version >> 16; } + + /// + /// \brief Get the minor version number. + /// \return The minor version number as unsigned integer. + /// \since 1.0 + /// + unsigned getMinor() const { return (_version >> 8) & 0xff; } + + /// + /// \brief Get the patch version number. + /// \return The patch version number as unsigned integer. + /// \since 1.0 + /// + unsigned getPatch() const { return _version & 0xff; } + + bool operator<(const PackedVersion32 &rhs) const { + return _version < rhs._version; + } + + bool operator==(const PackedVersion32 &rhs) const { + return _version == rhs._version; + } + + bool operator!=(const PackedVersion32 &rhs) const { + return _version != rhs._version; + } + + operator unsigned() const { return _version; } +}; + +TAPI_NAMESPACE_V1_END + +/// +/// @} +/// + +#endif // TAPI_PACKED_VERSION_32_H diff --git a/tapilite/include/tapi/Symbol.h b/tapilite/include/tapi/Symbol.h new file mode 100644 index 00000000..cb799196 --- /dev/null +++ b/tapilite/include/tapi/Symbol.h @@ -0,0 +1,136 @@ +//===-- tapi/Symbol.h - TAPI Symbol -----------------------------*- C++ -*-===*\ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines a symbol. +/// \since 1.0 +/// +//===----------------------------------------------------------------------===// +// +// Modified version for "tapilite", a standalone just enough +// implementation for use without LLVM +// +#ifndef TAPI_SYMBOL_H +#define TAPI_SYMBOL_H + +#include + +/// +/// \defgroup TAPI_SYMBOL Symbol API +/// \ingroup TAPI_CPP_API +/// +/// @{ +/// + +TAPI_NAMESPACE_V1_BEGIN + +/// +/// \brief Symbol flags. +/// \since 1.0 +/// +enum class SymbolFlags : unsigned { + /// \brief No flags + /// \since 1.0 + None = 0, + + /// \brief Thread-local value symbol + /// \since 1.0 + ThreadLocalValue = 1U << 0, + + /// \brief Weak defined symbol + /// \since 1.0 + WeakDefined = 1U << 1, + + /// \brief Weak referenced symbol + /// \since 1.0 + WeakReferenced = 1U << 2, +}; + +enum class SymbolKind : unsigned { + GlobalSymbol, + ObjectiveCClass, + ObjectiveCClassEHType, + ObjectiveCInstanceVariable, +}; + +inline SymbolFlags operator&(const SymbolFlags &lhs, + const SymbolFlags &rhs) noexcept { + return static_cast(static_cast(lhs) & + static_cast(rhs)); +} + +/// +/// \brief Provides query methods for symbols. +/// \since 1.0 +/// +class TAPI_PUBLIC Symbol { +public: + template + Symbol(Tp &&name, SymbolFlags flags = SymbolFlags::None, + SymbolKind kind = SymbolKind::GlobalSymbol) + : _name(std::forward(name)), _flags(flags), _kind(kind) {} + + SymbolKind getKind() const { return _kind; } + + /// + /// \brief Get the symbol name as string. + /// \return A string with the symbol name. + /// \since 1.0 + /// + inline const std::string &getName() const noexcept { return _name; } + + /// + /// \brief Obtain the symbol flags. + /// \return Returns the symbol flags. + /// \since 1.0 + /// + inline SymbolFlags getFlags() const noexcept { return _flags; } + + /// + /// \brief Query if the symbol is thread-local. + /// \return True if the symbol is a thread-local value, false otherwise. + /// \since 1.0 + /// + inline bool isThreadLocalValue() const noexcept { + return (_flags & SymbolFlags::ThreadLocalValue) == + SymbolFlags::ThreadLocalValue; + } + + /// + /// \brief Query if the symbol is weak defined. + /// \return True if the symbol is weak defined, false otherwise. + /// \since 1.0 + /// + inline bool isWeakDefined() const noexcept { + return (_flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined; + } + + /// + /// \brief Query if the symbol is weak referenced. + /// \return True if the symbol is weak referenced, false otherwise. + /// \since 1.0 + /// + inline bool isWeakReferenced() const noexcept { + return (_flags & SymbolFlags::WeakReferenced) == + SymbolFlags::WeakReferenced; + } + +private: + SymbolKind _kind; + std::string _name; + SymbolFlags _flags; +}; + +TAPI_NAMESPACE_V1_END + +/// +/// @} +/// + +#endif // TAPI_SYMBOL_H diff --git a/tapilite/include/tapi/Version.h b/tapilite/include/tapi/Version.h new file mode 100644 index 00000000..6fcbda43 --- /dev/null +++ b/tapilite/include/tapi/Version.h @@ -0,0 +1,63 @@ +//===-- tapi/Version.h - TAPI Version Interface -----------------*- C++ -*-===*\ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Access the TAPI version information. +/// \since 1.0 +/// +//===----------------------------------------------------------------------===// +// +// Modified version for "tapilite", a standalone just enough +// implementation for use without LLVM +// +#ifndef TAPI_VERSION_H +#define TAPI_VERSION_H + +#include +#include + +/// +/// \defgroup TAPI_VERSION Version methods +/// \ingroup TAPI_CPP_API +/// +/// @{ +/// + +namespace tapi { + +/// +/// \brief Access to version related information about the TAPI dynamic library. +/// \since 1.0 +/// +class TAPI_PUBLIC Version { +public: + /// + /// \name Version Number Methods + /// @{ + /// + + /// + /// \brief Get the full library name and version as string. + /// \return A string with the program name and version number. + /// \since 1.0 + /// + static std::string getFullVersionAsString() noexcept; + + /// + /// @} + /// +}; + +} // namespace tapi + +/// +/// @} +/// + +#endif // TAPI_VERSION_H diff --git a/tapilite/include/tapi/tapi.h b/tapilite/include/tapi/tapi.h new file mode 100644 index 00000000..6cc2fd6e --- /dev/null +++ b/tapilite/include/tapi/tapi.h @@ -0,0 +1,34 @@ +//===-- tapi/tapi.h - TAPI C++ Library Interface ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This is the umbrella header for the TAPI C++ Library Interface. +/// \since 1.0 +/// +//===----------------------------------------------------------------------===// +// +// Modified version for "tapilite", a standalone just enough +// implementation for use without LLVM +// +#ifndef TAPI_H +#define TAPI_H + +/// +/// \defgroup TAPI_CPP_API TAPI C++ API +/// +/// The C++ Application Programming Interface (API) for the TAPI library +/// + +#include +#include +#include +#include +#include + +#endif // TAPI_H diff --git a/tapilite/src/CMakeLists.txt b/tapilite/src/CMakeLists.txt new file mode 100644 index 00000000..d8c83eec --- /dev/null +++ b/tapilite/src/CMakeLists.txt @@ -0,0 +1,12 @@ + +set(TAPILITE_SOURCES + LinkerInterfaceFile.cpp + Version.cpp +) + +add_library(tapilite STATIC ${TAPILITE_SOURCES}) + +include_directories("${CMAKE_SOURCE_DIR}/tapilite/include") +include_directories("${CMAKE_SOURCE_DIR}/ld64/src/abstraction") +# for configure.h +include_directories("${CMAKE_BINARY_DIR}/ld64") diff --git a/tapilite/src/LinkerInterfaceFile.cpp b/tapilite/src/LinkerInterfaceFile.cpp new file mode 100644 index 00000000..d579a129 --- /dev/null +++ b/tapilite/src/LinkerInterfaceFile.cpp @@ -0,0 +1,1087 @@ +//===- libtapi/LinkerInterfaceFile.cpp - TAPI File Interface ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Implements the C++ linker interface file API. +/// +//===----------------------------------------------------------------------===// +// +// Modified version for "tapilite", a standalone just enough +// implementation for use without LLVM +// +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +TAPI_NAMESPACE_V1_BEGIN + +//using namespace tapi::internal; + +static PackedVersion32 parseVersion32(std::string str) { + size_t len = 0; + uint32_t version = 0; + size_t num = 0; + + if (str.empty()) + return 0; + + len = str.find_first_of("."); + if (len == std::string::npos) + return 0; + + num = std::stoull(str, &len, 10); + if (len == 0) + return 0; + + if (num > UINT16_MAX) + return 0; + + version = num << 16; + str = str.substr(len + 1); + + len = str.find_first_of("."); + if (len != std::string::npos) { + num = std::stoull(str, &len, 10); + if (len == 0) + return 0; + + if (num > UINT8_MAX) + return 0; + + version |= (num << 8); + str = str.substr(len + 1); + } + + if (!str.empty()) { + num = std::stoull(str, &len, 10); + if (len == 0) + return 0; + + if (num > UINT8_MAX) + return 0; + + version |= num; + } + + return version; +} + +class LinkerInterfaceFile::ImplData { +public: + std::string _path; + FileType _fileType{FileType::Unsupported}; + Platform _platform{Platform::Unknown}; + std::string _installName; + + PackedVersion32 _currentVersion; + PackedVersion32 _compatibilityVersion; + unsigned _swiftABIVersion; + ObjCConstraint _objcConstraint; + + std::vector _reexportedLibraries; + std::vector _allowableClients; + std::vector _exports; + std::vector _undefineds; + + std::vector _arches; + std::string _selectedArch; + + LinkerInterfaceFile::ImplData *next; + + ImplData() noexcept = default; + + static LinkerInterfaceFile::ImplData * + loadFile(const std::string &path, const uint8_t *data, size_t size, + cpu_type_t cpuType, cpu_subtype_t cpuSubType, + std::string &errorMessage); +}; + +class LinkerInterfaceFile::Impl { +public: + std::shared_ptr _data; + + std::string _installName; + std::string _parentFrameworkName; + PackedVersion32 _compatibilityVersion; + std::vector _ignoreExports; + std::vector _inlinedFrameworkNames; + std::vector _exports; + std::vector _undefineds; + + bool _hasTwoLevelNamespace{false}; + bool _isAppExtensionSafe{false}; + bool _hasWeakDefExports{false}; + bool _installPathOverride{false}; + + Impl() noexcept = default; + + bool init(const std::shared_ptr &data, + cpu_type_t cpuType, cpu_subtype_t cpuSubType, ParsingFlags flags, + PackedVersion32 minOSVersion, std::string &errorMessage) noexcept; + + template void addSymbol(T &&name, SymbolFlags flags) { + if (std::find(_ignoreExports.begin(), _ignoreExports.end(), + name) == _ignoreExports.end()) + _exports.emplace_back(std::forward(name), flags); + } + + void processSymbol(std::string name, PackedVersion32 minOSVersion, + bool disallowWeakImports) { + // $ld$ $ $ + if (name.substr(0, sizeof("$ld$") - 1).compare("$ld$") != 0) + return; + + name = name.substr(sizeof("$ld$") - 1); + + size_t pos = name.find_first_of("$"); + if (pos == std::string::npos) + return; + auto action = name.substr(0, pos); + name = name.substr(pos + 1); + + pos = name.find_first_of("$"); + if (pos == std::string::npos) + return; + auto condition = name.substr(0, pos); + name = name.substr(pos + 1); + + if (name.empty()) + return; + auto symbolName = name; + + if (condition.substr(0, sizeof("os") - 1).compare("os") != 0) + return; + + auto version = parseVersion32(condition.substr(sizeof("os") - 1)); + if (version != minOSVersion) + return; + + if (action.compare("hide") == 0) { + _ignoreExports.emplace_back(symbolName); + return; + } + + if (action.compare("add") == 0) { + _exports.emplace_back(symbolName); + return; + } + + if (action.compare("weak") == 0) { + if (disallowWeakImports) + _ignoreExports.emplace_back(symbolName); + + return; + } + + if (action.compare("install_name") == 0) { + _installName = symbolName; + _installPathOverride = true; + if (_installName == "/System/Library/Frameworks/" + "ApplicationServices.framework/Versions/A/" + "ApplicationServices") { + _compatibilityVersion = parseVersion32("1.0"); + } + return; + } + + if (action.compare("compatibility_version") == 0) { + _compatibilityVersion = parseVersion32(symbolName); + return; + } + } +}; + +static std::string getArchForCPU(cpu_type_t cpuType, cpu_subtype_t cpuSubType, + bool enforceCpuSubType) { + /* this function is deliberately stupid, for the fine details of + * subtypes we need more checking, which isn't necessary for the + * general case */ + + switch (cpuType) { + case CPU_TYPE_I386: + return "i386"; + case CPU_TYPE_X86_64: + return "x86_64"; + case CPU_TYPE_ARM: + return "arm"; + case CPU_TYPE_POWERPC: + return "ppc"; + case CPU_TYPE_POWERPC64: + return "ppc64"; + case CPU_TYPE_ARM64: + return "arm64"; + case CPU_TYPE_ANY: + return ""; /* meant to match first arch */ + default: + return "unsupported"; + } +} + +LinkerInterfaceFile::LinkerInterfaceFile() noexcept + : _pImpl{new LinkerInterfaceFile::Impl} {} +LinkerInterfaceFile::~LinkerInterfaceFile() noexcept = default; +LinkerInterfaceFile::LinkerInterfaceFile(LinkerInterfaceFile &&) noexcept = + default; +LinkerInterfaceFile & +LinkerInterfaceFile::operator=(LinkerInterfaceFile &&) noexcept = default; + +std::vector +LinkerInterfaceFile::getSupportedFileExtensions() noexcept { + return {".tbd"}; +} + + +/// \brief Load and parse the provided TBD file in the buffer and return on +/// success the interface file. +LinkerInterfaceFile::ImplData *LinkerInterfaceFile::ImplData::loadFile( + const std::string &path, const uint8_t *data, size_t size, + cpu_type_t cpuType, cpu_subtype_t cpuSubType, + std::string &errorMessage) { + yaml_parser_t parser; + yaml_event_t event; + yaml_char_t *p; + bool selectSection = false; + bool inList = false; + + LinkerInterfaceFile::ImplData *ret = nullptr; + LinkerInterfaceFile::ImplData *cur = nullptr; + + /* Because platform isn't passed onto us by ld, we cannot know what to + * select -- this is probably the problem meant to be solved by TAPIv4 + * which explicitly refers to targets such that arm64-macos is + * different from arm64-ios. Alas, for now it seems this mix isn't + * there for (system) tbd files, so we just ignore platform, and + * return the first one that matches the cpu specification. */ + std::string myarch = getArchForCPU(cpuType, cpuSubType, false); + + enum { + TAPILITE_INIT, + TAPILITE_HEADER, + TAPILITE_EXPORTS, + TAPILITE_UNDEFINEDS, + TAPILITE_REEXPORTS, + TAPILITE_DONE + } state = TAPILITE_INIT; + enum { + TAPILITE_FINDKEY, + TAPILITE_ARCHS, + TAPILITE_UUIDS, + TAPILITE_PLATFORM, + TAPILITE_FLAGS, + TAPILITE_INSTALLNAME, + TAPILITE_CURVERSION, + TAPILITE_COMPATVERSION, + TAPILITE_SWIFTVERSION, + TAPILITE_OBJCCONSTR, + TAPILITE_PARENTUMBR, + TAPILITE_ALLOWED_CLNTS, + TAPILITE_SYMBOLS, + TAPILITE_RE_EXPORTS, + TAPILITE_OBJCCLASSES, + TAPILITE_OBJCEHTYPES, + TAPILITE_OBJCIVARS, + TAPILITE_WEAKDEFSYMS, + TAPILITE_THRLOCSYMS, + TAPILITE_VERSION + } substate = TAPILITE_FINDKEY; + enum { + TAPILITE_V_INVALID, + TAPILITE_V1, + TAPILITE_V2, + TAPILITE_V3, + TAPILITE_V4_OR_LATER, + TAPILITE_V4 + } version = TAPILITE_V1; /* default for tagless */ + + yaml_parser_initialize(&parser); + yaml_parser_set_input_string(&parser, + reinterpret_cast(data), size); + +#define error(...) { \ + char errbuf[256]; \ + snprintf(errbuf, sizeof(errbuf), __VA_ARGS__); \ + errorMessage = errbuf; \ + return nullptr; \ +} +#ifdef tapilite_debug +# define dprintf(...) printf(__VA_ARGS) +#else +# define dprintf(...) +#endif + /* syntax: + * https://github.com/apple/llvm-project/blob/apple/main/llvm/lib/TextAPI/MachO/TextStub.cpp */ + while (state != TAPILITE_DONE) { + if (state != TAPILITE_INIT) + yaml_event_delete(&event); + else + state = TAPILITE_HEADER; + + if (!yaml_parser_parse(&parser, &event)) + break; + + dprintf("yaml: %d\n", event.type); +#define ymlcmp(X, Y) strcmp((char *)X, Y) +#define ymlncmp(X, Y, Z) strncmp((char *)X, Y, Z) + /* process */ + switch (event.type) { + case YAML_DOCUMENT_START_EVENT: + if (cur == nullptr) { + ret = cur = new LinkerInterfaceFile::ImplData; + } else { + cur = cur->next = new LinkerInterfaceFile::ImplData; + } + cur->_path = path; + cur->next = nullptr; + break; + case YAML_STREAM_END_EVENT: + state = TAPILITE_DONE; + break; + case YAML_SCALAR_EVENT: +#define yamlscalar event.data.scalar + if (yamlscalar.value != NULL && substate == TAPILITE_FINDKEY) { + switch (state) { + case TAPILITE_HEADER: + dprintf("header| key: %s\n", yamlscalar.value); + if (ymlcmp(yamlscalar.value, "archs") == 0) + substate = TAPILITE_ARCHS; + if (ymlcmp(yamlscalar.value, "targets") == 0) + substate = TAPILITE_ARCHS; + else if (ymlcmp(yamlscalar.value, "platform") == 0) + substate = TAPILITE_PLATFORM; + else if (ymlcmp(yamlscalar.value, "install-name") == 0) + substate = TAPILITE_INSTALLNAME; + else if (ymlcmp(yamlscalar.value, "current-version") == 0) + substate = TAPILITE_CURVERSION; + else if (ymlcmp(yamlscalar.value, "compatibility-version") == 0) + substate = TAPILITE_COMPATVERSION; + else if (ymlcmp(yamlscalar.value, "swift-version") == 0) + substate = TAPILITE_SWIFTVERSION; + else if (ymlcmp(yamlscalar.value, "swift-abi-version") == 0) + substate = TAPILITE_SWIFTVERSION; + else if (ymlcmp(yamlscalar.value, "objc-constraint") == 0) + substate = TAPILITE_OBJCCONSTR; + else if (ymlcmp(yamlscalar.value, "uuids") == 0) + substate = TAPILITE_UUIDS; + else if (ymlcmp(yamlscalar.value, "parent-umbrella") == 0) + substate = TAPILITE_PARENTUMBR; + else if (ymlcmp(yamlscalar.value, "allowable-clients") == 0) + substate = TAPILITE_ALLOWED_CLNTS; + else if (ymlcmp(yamlscalar.value, "flags") == 0) + substate = TAPILITE_FLAGS; + else if (ymlcmp(yamlscalar.value, "tbd-version") == 0) + substate = TAPILITE_VERSION; + else if (ymlcmp(yamlscalar.value, "exports") == 0) + state = TAPILITE_EXPORTS; + else if (ymlcmp(yamlscalar.value, "reexported-libraries") == 0) + state = TAPILITE_REEXPORTS; + else if (ymlcmp(yamlscalar.value, "undefineds") == 0) + state = TAPILITE_UNDEFINEDS; + break; + case TAPILITE_EXPORTS: + case TAPILITE_REEXPORTS: + dprintf("exports| key: %s\n", yamlscalar.value); + if (ymlcmp(yamlscalar.value, "archs") == 0) + substate = TAPILITE_ARCHS; + if (ymlcmp(yamlscalar.value, "targets") == 0) + substate = TAPILITE_ARCHS; + else if (ymlcmp(yamlscalar.value, "allowed-clients") == 0) + substate = TAPILITE_ALLOWED_CLNTS; + else if (ymlcmp(yamlscalar.value, "re-exports") == 0) + substate = TAPILITE_RE_EXPORTS; + else if (ymlcmp(yamlscalar.value, "libraries") == 0) + substate = TAPILITE_RE_EXPORTS; + else if (ymlcmp(yamlscalar.value, "symbols") == 0) + substate = TAPILITE_SYMBOLS; + else if (ymlcmp(yamlscalar.value, "objc-classes") == 0) + substate = TAPILITE_OBJCCLASSES; + else if (ymlcmp(yamlscalar.value, "objc-eh-types") == 0) + substate = TAPILITE_OBJCEHTYPES; + else if (ymlcmp(yamlscalar.value, "objc-ivars") == 0) + substate = TAPILITE_OBJCIVARS; + else if (ymlcmp(yamlscalar.value, "weak-def-symbols") == 0) + substate = TAPILITE_WEAKDEFSYMS; + else if (ymlcmp(yamlscalar.value, "weak-symbols") == 0) + substate = TAPILITE_WEAKDEFSYMS; + else if (ymlcmp(yamlscalar.value, "thread-local-symbols") == 0) + substate = TAPILITE_THRLOCSYMS; + break; + case TAPILITE_UNDEFINEDS: + if (ymlcmp(yamlscalar.value, "archs") == 0) + substate = TAPILITE_ARCHS; + if (ymlcmp(yamlscalar.value, "targets") == 0) + substate = TAPILITE_ARCHS; + else if (ymlcmp(yamlscalar.value, "symbols") == 0) + substate = TAPILITE_SYMBOLS; + else if (ymlcmp(yamlscalar.value, "objc-classes") == 0) + substate = TAPILITE_OBJCCLASSES; + else if (ymlcmp(yamlscalar.value, "objc-eh-types") == 0) + substate = TAPILITE_OBJCEHTYPES; + else if (ymlcmp(yamlscalar.value, "objc-ivars") == 0) + substate = TAPILITE_OBJCIVARS; + else if (ymlcmp(yamlscalar.value, "weak-ref-symbols") == 0) + substate = TAPILITE_WEAKDEFSYMS; + else if (ymlcmp(yamlscalar.value, "weak-symbols") == 0) + substate = TAPILITE_WEAKDEFSYMS; + break; + } + + /* reset selection selector */ + if (substate == TAPILITE_ARCHS) + selectSection = false; + } else if (substate != TAPILITE_FINDKEY) { + /* we have a real value, need to append it to whatever is + * currently the open thing we're writing for */ + switch (state) { + case TAPILITE_HEADER: + dprintf("header|%d val: %s\n", substate, yamlscalar.value); + switch (substate) { + case TAPILITE_VERSION: + if (version == TAPILITE_V4_OR_LATER) { + if (ymlcmp(yamlscalar.value, "4") == 0) + version = TAPILITE_V4; + else + error("unsupported TAPI version %s", yamlscalar.value); + } else { + error("found tbd-version for TAPI version _fileType == FileType::Unsupported) { + /* apply defaults for various settings based on the + * TAPI version */ + switch (version) { + case TAPILITE_V1: + cur->_currentVersion = parseVersion32("1.0"); + cur->_compatibilityVersion = parseVersion32("1.0"); + cur->_swiftABIVersion = 0; + cur->_objcConstraint = ObjCConstraint::None; + break; + case TAPILITE_V2: + case TAPILITE_V3: + case TAPILITE_V4: + cur->_currentVersion = parseVersion32("1.0"); + cur->_compatibilityVersion = parseVersion32("1.0"); + cur->_swiftABIVersion = 0; + cur->_objcConstraint = ObjCConstraint::Retain_Release; + break; + } + + if (version == TAPILITE_V1) + cur->_fileType = FileType::TBD_V1; + else if (version == TAPILITE_V2) + cur->_fileType = FileType::TBD_V2; + else if (version == TAPILITE_V3) + cur->_fileType = FileType::TBD_V3; + else if (version == TAPILITE_V4) + cur->_fileType = FileType::TBD_V4; + } + + cur->_arches.emplace_back( + std::string((const char *)yamlscalar.value)); + if (!cur->_selectedArch.empty()) + break; /* take first matching arch */ + + switch (version) { + case TAPILITE_V4: + { + /* extract arch, platform out of target, set + * platform if arch matches */ + size_t len = myarch.length(); + if (ymlncmp(yamlscalar.value, myarch.c_str(), len) == 0 + && (len == 0 || yamlscalar.value[len] == '-')) + { + const char *p = (const char *)yamlscalar.value; + cur->_selectedArch = std::string(p); + if (len == 0) + len = cur->_selectedArch.find_first_of('-'); + /* this almost is a copy of the PLATFORM case below */ + if (cur->_selectedArch. + substr(len + 1).compare("macos") == 0) + cur->_platform = Platform::OSX; + else if (cur->_selectedArch. + substr(len + 1).compare("ios") == 0) + cur->_platform = Platform::iOS; + /* TODO: see below */ + } + } + break; + default: + if (myarch.empty()) { + cur->_selectedArch = + std::string((const char *)yamlscalar.value); + } else { + /* see if arch matches */ + if (ymlcmp(yamlscalar.value, myarch.c_str())) + cur->_selectedArch = myarch; + } + break; + } + break; + case TAPILITE_PLATFORM: + if (ymlcmp(yamlscalar.value, "macosx") == 0) + cur->_platform = Platform::OSX; + else if (ymlcmp(yamlscalar.value, "ios") == 0) + cur->_platform = Platform::iOS; + /* TODO: does it really make a difference to check for + * the rest? */ + break; + case TAPILITE_INSTALLNAME: + cur->_installName = + std::string((const char *)yamlscalar.value); + break; + case TAPILITE_CURVERSION: + cur->_currentVersion = + parseVersion32((const char *)yamlscalar.value); + break; + case TAPILITE_COMPATVERSION: + cur->_compatibilityVersion = + parseVersion32((const char *)yamlscalar.value); + break; + case TAPILITE_SWIFTVERSION: + cur->_swiftABIVersion = + std::stoull((const char *)yamlscalar.value, NULL, 10); + break; + case TAPILITE_OBJCCONSTR: + if (ymlcmp(yamlscalar.value, "none") == 0) + cur->_objcConstraint = ObjCConstraint::None; + else if (ymlcmp(yamlscalar.value, "retain_release") == 0) + cur->_objcConstraint = ObjCConstraint::Retain_Release; + else if (ymlcmp(yamlscalar.value, + "retain_release_for_simulator") == 0) + cur->_objcConstraint = + ObjCConstraint::Retain_Release_For_Simulator; + else if (ymlcmp(yamlscalar.value, + "retain_release_or_gc") == 0) + cur->_objcConstraint = + ObjCConstraint::Retain_Release_Or_GC; + else if (ymlcmp(yamlscalar.value, "gc") == 0) + cur->_objcConstraint = ObjCConstraint::GC; + break; + case TAPILITE_ALLOWED_CLNTS: + cur->_allowableClients.emplace_back( + std::string((const char *)yamlscalar.value)); + break; + case TAPILITE_UUIDS: + case TAPILITE_PARENTUMBR: + case TAPILITE_FLAGS: + /* ignored: there's currently no consumer for it from + * ld64 */ + break; + } + break; + case TAPILITE_EXPORTS: + case TAPILITE_REEXPORTS: + dprintf("exports|%d val: %s\n", substate, yamlscalar.value); + switch (substate) { + case TAPILITE_ARCHS: + /* remember: for V4, we store target in selectedArch */ + if (ymlcmp(yamlscalar.value, cur->_selectedArch.c_str()) == 0) + selectSection = true; + break; + case TAPILITE_ALLOWED_CLNTS: + /* should respect this, but for now we just ignore it */ + break; + case TAPILITE_RE_EXPORTS: + if (!selectSection) + break; + cur->_reexportedLibraries.emplace_back( + std::string((const char *)yamlscalar.value)); + break; + case TAPILITE_SYMBOLS: + if (!selectSection) + break; + cur->_exports.emplace_back(new Symbol( + std::string((const char *)yamlscalar.value), + SymbolFlags::None, SymbolKind::GlobalSymbol)); + break; + case TAPILITE_OBJCCLASSES: + if (!selectSection) + break; + cur->_exports.emplace_back(new Symbol( + std::string((const char *)yamlscalar.value), + SymbolFlags::None, SymbolKind::ObjectiveCClass)); + break; + case TAPILITE_OBJCEHTYPES: + if (!selectSection) + break; + cur->_exports.emplace_back(new Symbol( + std::string((const char *)yamlscalar.value), + SymbolFlags::None, SymbolKind::ObjectiveCClassEHType)); + break; + case TAPILITE_OBJCIVARS: + if (!selectSection) + break; + cur->_exports.emplace_back(new Symbol( + std::string((const char *)yamlscalar.value), + SymbolFlags::None, + SymbolKind::ObjectiveCInstanceVariable)); + break; + case TAPILITE_WEAKDEFSYMS: + if (!selectSection) + break; + cur->_exports.emplace_back(new Symbol( + std::string((const char *)yamlscalar.value), + SymbolFlags::WeakDefined, SymbolKind::GlobalSymbol)); + break; + case TAPILITE_THRLOCSYMS: + if (!selectSection) + break; + cur->_exports.emplace_back(new Symbol( + std::string((const char *)yamlscalar.value), + SymbolFlags::ThreadLocalValue, SymbolKind::GlobalSymbol)); + break; + } + break; + case TAPILITE_UNDEFINEDS: + switch (substate) { + case TAPILITE_ARCHS: + /* remember: for V4, we store target in selectedArch */ + if (ymlcmp(yamlscalar.value, cur->_selectedArch.c_str()) == 0) + selectSection = true; + break; + case TAPILITE_SYMBOLS: + if (!selectSection) + break; + cur->_undefineds.emplace_back(new Symbol( + std::string((const char *)yamlscalar.value), + SymbolFlags::None, SymbolKind::GlobalSymbol)); + break; + case TAPILITE_OBJCCLASSES: + if (!selectSection) + break; + cur->_undefineds.emplace_back(new Symbol( + std::string((const char *)yamlscalar.value), + SymbolFlags::None, SymbolKind::ObjectiveCClass)); + break; + case TAPILITE_OBJCEHTYPES: + if (!selectSection) + break; + cur->_undefineds.emplace_back(new Symbol( + std::string((const char *)yamlscalar.value), + SymbolFlags::None, SymbolKind::ObjectiveCClassEHType)); + break; + case TAPILITE_OBJCIVARS: + if (!selectSection) + break; + cur->_undefineds.emplace_back(new Symbol( + std::string((const char *)yamlscalar.value), + SymbolFlags::None, + SymbolKind::ObjectiveCInstanceVariable)); + break; + case TAPILITE_WEAKDEFSYMS: + if (!selectSection) + break; + cur->_undefineds.emplace_back(new Symbol( + std::string((const char *)yamlscalar.value), + SymbolFlags::WeakReferenced, SymbolKind::GlobalSymbol)); + break; + } + break; + } + if (!inList) + substate = TAPILITE_FINDKEY; + } + break; + case YAML_SEQUENCE_START_EVENT: + inList = true; + break; + case YAML_SEQUENCE_END_EVENT: + substate = TAPILITE_FINDKEY; + inList = false; + break; + case YAML_MAPPING_START_EVENT: +#define yamlms event.data.mapping_start + switch (state) { + case TAPILITE_HEADER: + if (yamlms.tag == NULL) + break; + if (ymlncmp(yamlms.tag, "!tapi-tbd", + sizeof("!tapi-tbd") - 1) != 0) + break; + p = yamlms.tag + sizeof("!tapi-tbd") - 1; + if (*p == '\0') { + /* this could be version 4 or later, in which case we + * expect a tbd-version key */ + version = TAPILITE_V4_OR_LATER; + } else if (*p == '-' && p[1] == 'v') { + p += 2; + switch (*p) { + case '1': + /* technically shouldn't be in use */ + version = TAPILITE_V1; + break; + case '2': + version = TAPILITE_V2; + break; + case '3': + version = TAPILITE_V3; + break; + default: + version = TAPILITE_V_INVALID; + break; + } + } + break; + default: + /* ignore */ + break; + } + substate = TAPILITE_FINDKEY; + inList = false; + break; + case YAML_MAPPING_END_EVENT: + inList = false; + /* TODO: could use this to close list pointers or something */ + break; + default: + break; + } + } + + yaml_event_delete(&event); + yaml_parser_delete(&parser); +#undef error + + return ret; +} + +bool LinkerInterfaceFile::isSupported(const std::string &path, + const uint8_t *data, + size_t size) noexcept { + std::string err; + auto file = LinkerInterfaceFile::ImplData::loadFile( + path, data, size, CPU_TYPE_ANY, CPU_SUBTYPE_MULTIPLE, err); + + return file && file->_platform != Platform::Unknown; +} + +bool LinkerInterfaceFile::shouldPreferTextBasedStubFile( + const std::string &path) noexcept { + // Never prefer this, if a dylib exists, take it because it will be + // more reliable than this "lite" stub, see also below + return false; +} + +bool LinkerInterfaceFile::areEquivalent(const std::string &tbdPath, + const std::string &dylibPath) noexcept { + // Simple decision, always prefer dylib over textstub if it exists, + // don't check anything, so we don't have to implement Mach-O reading + // to check that UUIDs match + return false; +} + +bool LinkerInterfaceFile::Impl::init( + const std::shared_ptr &data, + cpu_type_t cpuType, cpu_subtype_t cpuSubType, ParsingFlags flags, + PackedVersion32 minOSVersion, std::string &errorMessage) noexcept { + _data = data; + bool enforceCpuSubType = flags & ParsingFlags::ExactCpuSubType; + auto arch = getArchForCPU(cpuType, cpuSubType, enforceCpuSubType); + if (arch.compare("unsupported") == 0) { + auto count = data->_arches.size(); + if (count > 1) + errorMessage = "missing required architecture " + + arch + " in file " + + data->_path + " (" + std::to_string(count) + + " slices)"; + else + errorMessage = "missing required architecture " + + arch + " in file " + + data->_path; + return false; + } + + _compatibilityVersion = data->_compatibilityVersion; + _installName = data->_installName; + + // Remove the patch level. + minOSVersion = + PackedVersion32(minOSVersion.getMajor(), minOSVersion.getMinor(), 0); + + // Pre-scan for special linker symbols. + for (auto *symbol : _data->_exports) { + if (symbol->getKind() != SymbolKind::GlobalSymbol) + continue; + + processSymbol(symbol->getName(), minOSVersion, + flags & ParsingFlags::DisallowWeakImports); + } + std::sort(_ignoreExports.begin(), _ignoreExports.end()); + auto last = std::unique(_ignoreExports.begin(), _ignoreExports.end()); + _ignoreExports.erase(last, _ignoreExports.end()); + + bool useObjC1ABI = + (data->_platform == Platform::OSX) && (arch.compare("i386") == 0); + for (const auto *symbol : data->_exports) { + switch (symbol->getKind()) { + case SymbolKind::GlobalSymbol: + if (symbol->getName().substr(0, 4).compare("$ld$") == 0) + continue; + addSymbol(symbol->getName(), symbol->getFlags()); + break; + case SymbolKind::ObjectiveCClass: + if (useObjC1ABI) { + addSymbol(".objc_class_name_" + symbol->getName(), + symbol->getFlags()); + } else { + addSymbol("_OBJC_CLASS_$_" + symbol->getName(), + symbol->getFlags()); + addSymbol("_OBJC_METACLASS_$_" + symbol->getName(), + symbol->getFlags()); + } + break; + case SymbolKind::ObjectiveCClassEHType: + addSymbol("_OBJC_EHTYPE_$_" + symbol->getName(), + symbol->getFlags()); + break; + case SymbolKind::ObjectiveCInstanceVariable: + addSymbol("_OBJC_IVAR_$_" + symbol->getName(), symbol->getFlags()); + break; + } + + if (symbol->isWeakDefined()) + _hasWeakDefExports = true; + } + + for (const auto *symbol : data->_undefineds) { + switch (symbol->getKind()) { + case SymbolKind::GlobalSymbol: + _undefineds.emplace_back(symbol->getName(), symbol->getFlags()); + break; + case SymbolKind::ObjectiveCClass: + if (useObjC1ABI) { + _undefineds.emplace_back(".objc_class_name_" + symbol->getName(), + symbol->getFlags()); + } else { + _undefineds.emplace_back("_OBJC_CLASS_$_" + symbol->getName(), + symbol->getFlags()); + _undefineds.emplace_back("_OBJC_METACLASS_$_" + symbol->getName(), + symbol->getFlags()); + } + break; + case SymbolKind::ObjectiveCClassEHType: + _undefineds.emplace_back("_OBJC_EHTYPE_$_" + symbol->getName(), + symbol->getFlags()); + break; + case SymbolKind::ObjectiveCInstanceVariable: + _undefineds.emplace_back("_OBJC_IVAR_$_" + symbol->getName(), + symbol->getFlags()); + break; + } + } + + for (auto *file = data->next; file != nullptr; file = file->next) + _inlinedFrameworkNames.emplace_back(file->_installName); + + return true; +} + +LinkerInterfaceFile *LinkerInterfaceFile::create( + const std::string &path, const uint8_t *data, size_t size, + cpu_type_t cpuType, cpu_subtype_t cpuSubType, + CpuSubTypeMatching matchingMode, PackedVersion32 minOSVersion, + std::string &errorMessage) noexcept { + + ParsingFlags flags = (matchingMode == CpuSubTypeMatching::Exact) + ? ParsingFlags::ExactCpuSubType + : ParsingFlags::None; + + return create(path, data, size, cpuType, cpuSubType, flags, minOSVersion, + errorMessage); +} + +LinkerInterfaceFile *LinkerInterfaceFile::create( + const std::string &path, const uint8_t *data, size_t size, + cpu_type_t cpuType, cpu_subtype_t cpuSubType, ParsingFlags flags, + PackedVersion32 minOSVersion, std::string &errorMessage) noexcept { + + if (path.empty() || data == nullptr || size < 8) { + errorMessage = "invalid argument"; + return nullptr; + } + + auto impldata = LinkerInterfaceFile::ImplData::loadFile( + path, data, size, cpuType, cpuSubType, errorMessage); + if (impldata == nullptr) + return nullptr; + + auto file = new LinkerInterfaceFile; + if (file == nullptr) { + errorMessage = "could not allocate memory"; + return nullptr; + } + + if (file->_pImpl->init( + std::shared_ptr(impldata), + cpuType, cpuSubType, flags, minOSVersion, errorMessage)) { + return file; + } + + delete file; + return nullptr; +} + +LinkerInterfaceFile * +LinkerInterfaceFile::create(const std::string &path, cpu_type_t cpuType, + cpu_subtype_t cpuSubType, ParsingFlags flags, + PackedVersion32 minOSVersion, + std::string &errorMessage) noexcept { + std::ifstream ifs; + ifs.open(path, std::ifstream::in); + auto buf = std::string(std::istreambuf_iterator{ifs}, {}); + auto data = LinkerInterfaceFile::ImplData::loadFile( + path, (const uint8_t *)buf.c_str(), buf.length(), + cpuType, cpuSubType, errorMessage); + if (data == nullptr) + return nullptr; + + auto file = new LinkerInterfaceFile; + if (file == nullptr) { + errorMessage = "could not allocate memory"; + return nullptr; + } + + if (file->_pImpl->init( + std::shared_ptr(data), + cpuType, cpuSubType, flags, minOSVersion, errorMessage)) { + return file; + } + + delete file; + return nullptr; +} + +FileType LinkerInterfaceFile::getFileType() const noexcept { + return _pImpl->_data->_fileType; +} + +Platform LinkerInterfaceFile::getPlatform() const noexcept { + return _pImpl->_data->_platform; +} + +const std::string &LinkerInterfaceFile::getInstallName() const noexcept { + return _pImpl->_installName; +} + +bool LinkerInterfaceFile::isInstallNameVersionSpecific() const noexcept { + return _pImpl->_installPathOverride; +} + +PackedVersion32 LinkerInterfaceFile::getCurrentVersion() const noexcept { + return _pImpl->_data->_currentVersion; +} + +PackedVersion32 LinkerInterfaceFile::getCompatibilityVersion() const noexcept { + return _pImpl->_compatibilityVersion; +} + +unsigned LinkerInterfaceFile::getSwiftVersion() const noexcept { + return _pImpl->_data->_swiftABIVersion; +} + +ObjCConstraint LinkerInterfaceFile::getObjCConstraint() const noexcept { + return _pImpl->_data->_objcConstraint; +} + +bool LinkerInterfaceFile::hasTwoLevelNamespace() const noexcept { + return _pImpl->_hasTwoLevelNamespace; +} + +bool LinkerInterfaceFile::isApplicationExtensionSafe() const noexcept { + return _pImpl->_isAppExtensionSafe; +} + +bool LinkerInterfaceFile::hasAllowableClients() const noexcept { + return !_pImpl->_data->_allowableClients.empty(); +} + +bool LinkerInterfaceFile::hasReexportedLibraries() const noexcept { + return !_pImpl->_data->_reexportedLibraries.empty(); +} + +bool LinkerInterfaceFile::hasWeakDefinedExports() const noexcept { + return _pImpl->_hasWeakDefExports; +} + +const std::string &LinkerInterfaceFile::getParentFrameworkName() const + noexcept { + return _pImpl->_parentFrameworkName; +} + +const std::vector &LinkerInterfaceFile::allowableClients() const + noexcept { + return _pImpl->_data->_allowableClients; +} + +const std::vector &LinkerInterfaceFile::reexportedLibraries() const + noexcept { + return _pImpl->_data->_reexportedLibraries; +} + +const std::vector &LinkerInterfaceFile::ignoreExports() const + noexcept { + return _pImpl->_ignoreExports; +} + +const std::vector &LinkerInterfaceFile::exports() const noexcept { + return _pImpl->_exports; +} + +const std::vector &LinkerInterfaceFile::undefineds() const noexcept { + return _pImpl->_undefineds; +} + +const std::vector & +LinkerInterfaceFile::inlinedFrameworkNames() const noexcept { + return _pImpl->_inlinedFrameworkNames; +} + +LinkerInterfaceFile *LinkerInterfaceFile::getInlinedFramework( + const std::string &installName, cpu_type_t cpuType, + cpu_subtype_t cpuSubType, ParsingFlags flags, PackedVersion32 minOSVersion, + std::string &errorMessage) const noexcept { + + for (auto *it = _pImpl->_data->next; it != nullptr; it = it->next) { + if (it->_installName.compare(installName) != 0) + continue; + + auto file = new LinkerInterfaceFile; + if (file == nullptr) { + errorMessage = "could not allocate memory"; + return nullptr; + } + + if (file->_pImpl->init( + std::shared_ptr(it), + cpuType, cpuSubType, flags, minOSVersion, errorMessage)) { + return file; + } + } + + errorMessage = "no such inlined framework"; + return nullptr; +} + +TAPI_NAMESPACE_V1_END + +/* vim:set ts=2 sw=2 expandtab: */ diff --git a/tapilite/src/Version.cpp b/tapilite/src/Version.cpp new file mode 100644 index 00000000..6ae2c26e --- /dev/null +++ b/tapilite/src/Version.cpp @@ -0,0 +1,48 @@ +//===- libtapi/Version.cpp - TAPI Version Interface -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Implements the C++ version interface. +/// +//===----------------------------------------------------------------------===// +// +// Modified version for "tapilite", a standalone just enough +// implementation for use without LLVM +// +#include +#include + +/// \brief Helper macro for TAPI_VERSION_STRING. +#define TAPI_MAKE_STRING2(X) #X + +/// \brief A string that describes the TAPI version number, e.g., "1.0.0". +#define TAPI_MAKE_STRING(X) TAPI_MAKE_STRING2(X) + +namespace tapi { + +std::string Version::getFullVersionAsString() noexcept { + std::string result; +#ifdef TAPI_VENDOR + result += TAPI_VENDOR; +#endif +#ifdef TAPI_VERSION + result += TAPI_MAKE_STRING(TAPI_VERSION); +#endif + result += " based on Apple TAPI"; +#ifdef APPLE_VERSION + result += " version " APPLE_VERSION; +#endif +#ifdef TAPI_REPOSITORY_STRING + result += " (" TAPI_REPOSITORY_STRING ")"; +#endif + + return result; +} + +} // end namespace tapi.