├── Dependencies ├── PLPatchMaster.framework.dSYM │ └── Contents │ │ ├── Info.plist │ │ └── Resources │ │ └── DWARF │ │ └── PLPatchMaster ├── PLPatchMaster.framework │ ├── Headers │ ├── PLPatchMaster │ ├── PrivateHeaders │ ├── Resources │ └── Versions │ │ ├── A │ │ ├── Frameworks │ │ │ └── PLBlockIMP.framework │ │ │ │ ├── Headers │ │ │ │ ├── PLBlockIMP │ │ │ │ ├── Resources │ │ │ │ └── Versions │ │ │ │ ├── A │ │ │ │ ├── Headers │ │ │ │ │ ├── PLBlockIMP.h │ │ │ │ │ ├── blockimp.h │ │ │ │ │ └── trampoline_table.h │ │ │ │ ├── PLBlockIMP │ │ │ │ └── Resources │ │ │ │ │ ├── English.lproj │ │ │ │ │ └── InfoPlist.strings │ │ │ │ │ ├── Info.plist │ │ │ │ │ └── gentramp.sh │ │ │ │ └── Current │ │ ├── Headers │ │ │ ├── NSObject+PLPatchMaster.h │ │ │ └── PLPatchMaster.h │ │ ├── PLPatchMaster │ │ ├── PrivateHeaders │ │ │ ├── PMLog.h │ │ │ ├── SymbolBinder.hpp │ │ │ └── SymbolName.hpp │ │ └── Resources │ │ │ └── Info.plist │ │ └── Current └── README.txt ├── LICENSE.txt ├── README.md ├── XcodePostFacto.xcodeproj └── project.pbxproj ├── XcodePostFacto ├── Info.plist ├── XPFDebugMenu.h ├── XPFDebugMenu.m ├── XPFLog.h ├── XPFViewController.m ├── XcodePostFacto.h ├── XcodePostFacto.m └── XcodePostFacto.xcplugindata ├── xpf-bootstrap ├── DVTPlugInManager.h ├── Info.plist ├── NSVisualEffectView.m ├── cfbundle_rebind.cpp ├── cfbundle_rebind.h ├── dyld_priv.h ├── rebind_table.cpp ├── rebind_table.h ├── xpf_bootstrap.h ├── xpf_bootstrap.mm ├── yosemite_objc_stubs.h └── yosemite_objc_stubs.m └── xpf-bootstrapTests └── Info.plist /Dependencies/PLPatchMaster.framework.dSYM/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleIdentifier 8 | com.apple.xcode.dsym.coop.plausible.PLPatchMaster 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundlePackageType 12 | dSYM 13 | CFBundleSignature 14 | ???? 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleVersion 18 | 1 19 | 20 | 21 | -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework.dSYM/Contents/Resources/DWARF/PLPatchMaster: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landonf/XcodePostFacto/9987e9f13041956651f6c9bee1243f95da3e3178/Dependencies/PLPatchMaster.framework.dSYM/Contents/Resources/DWARF/PLPatchMaster -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/PLPatchMaster: -------------------------------------------------------------------------------- 1 | Versions/Current/PLPatchMaster -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/PrivateHeaders: -------------------------------------------------------------------------------- 1 | Versions/Current/PrivateHeaders -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Resources: -------------------------------------------------------------------------------- 1 | Versions/Current/Resources -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/Frameworks/PLBlockIMP.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/Frameworks/PLBlockIMP.framework/PLBlockIMP: -------------------------------------------------------------------------------- 1 | Versions/Current/PLBlockIMP -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/Frameworks/PLBlockIMP.framework/Resources: -------------------------------------------------------------------------------- 1 | Versions/Current/Resources -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/Frameworks/PLBlockIMP.framework/Versions/A/Headers/PLBlockIMP.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright 2010-2011 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, 8 | * to any person obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without restriction, 10 | * including without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to permit 12 | * persons to whom the Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #pragma once 28 | #include "blockimp.h" -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/Frameworks/PLBlockIMP.framework/Versions/A/Headers/blockimp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright 2010-2011 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, 8 | * to any person obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without restriction, 10 | * including without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to permit 12 | * persons to whom the Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | extern IMP pl_imp_implementationWithBlock(void *block); 30 | extern void *pl_imp_getBlock(IMP anImp); 31 | extern BOOL pl_imp_removeBlock(IMP anImp); -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/Frameworks/PLBlockIMP.framework/Versions/A/Headers/trampoline_table.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright 2010-2011 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, 8 | * to any person obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without restriction, 10 | * including without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to permit 12 | * persons to whom the Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #pragma once 28 | 29 | #ifdef PL_BLOCKIMP_PRIVATE 30 | 31 | #include 32 | #include 33 | 34 | typedef struct pl_trampoline_table pl_trampoline_table; 35 | typedef struct pl_trampoline pl_trampoline; 36 | 37 | /* 38 | * Trampoline table configuration 39 | */ 40 | typedef struct pl_trampoline_table_config { 41 | /* The trampoline size */ 42 | uint32_t trampoline_size; 43 | 44 | /* The page offset at which the trampolines are located. */ 45 | uint32_t page_offset; 46 | 47 | /* The number of trampolines allocated per page. */ 48 | uint32_t trampoline_count; 49 | 50 | /** The template code page. */ 51 | void *template_page; 52 | } pl_trampoline_table_config; 53 | 54 | /* 55 | * A double-linked list of trampoline table entries. 56 | */ 57 | struct pl_trampoline_table { 58 | /* Table configuration */ 59 | pl_trampoline_table_config *config; 60 | 61 | /* Contigious writable and executable pages */ 62 | vm_address_t data_page; 63 | vm_address_t trampoline_page; 64 | 65 | /* free list tracking */ 66 | uint16_t free_count; 67 | pl_trampoline *free_list; 68 | pl_trampoline *free_list_pool; 69 | 70 | pl_trampoline_table *prev; 71 | pl_trampoline_table *next; 72 | }; 73 | 74 | /* 75 | * A linked list of trampoline table entries. 76 | */ 77 | struct pl_trampoline { 78 | /* The actual trampoline. */ 79 | void *(*trampoline)(); 80 | 81 | /** The table in which the entry is allocated. */ 82 | pl_trampoline_table *table; 83 | 84 | /* Next entry in the trampoline list. */ 85 | pl_trampoline *next; 86 | }; 87 | 88 | pl_trampoline *pl_trampoline_alloc (pl_trampoline_table_config *config, pthread_mutex_t *lock, pl_trampoline_table **table_head); 89 | void pl_trampoline_free (pthread_mutex_t *lock, pl_trampoline_table **table_head, pl_trampoline *tramp); 90 | void *pl_trampoline_data_ptr (void *code_ptr); 91 | 92 | #endif /* PL_BLOCKIMP_PRIVATE */ -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/Frameworks/PLBlockIMP.framework/Versions/A/PLBlockIMP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landonf/XcodePostFacto/9987e9f13041956651f6c9bee1243f95da3e3178/Dependencies/PLPatchMaster.framework/Versions/A/Frameworks/PLBlockIMP.framework/Versions/A/PLBlockIMP -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/Frameworks/PLBlockIMP.framework/Versions/A/Resources/English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landonf/XcodePostFacto/9987e9f13041956651f6c9bee1243f95da3e3178/Dependencies/PLPatchMaster.framework/Versions/A/Frameworks/PLBlockIMP.framework/Versions/A/Resources/English.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/Frameworks/PLBlockIMP.framework/Versions/A/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 13B42 7 | CFBundleDevelopmentRegion 8 | English 9 | CFBundleExecutable 10 | PLBlockIMP 11 | CFBundleIdentifier 12 | com.yourcompany.PLBlockIMP 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | PLBlockIMP 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | DTCompiler 26 | com.apple.compilers.llvm.clang.1_0 27 | DTPlatformBuild 28 | 5A3005 29 | DTPlatformVersion 30 | GM 31 | DTSDKBuild 32 | 13A595 33 | DTSDKName 34 | macosx10.9 35 | DTXcode 36 | 0502 37 | DTXcodeBuild 38 | 5A3005 39 | 40 | 41 | -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/Frameworks/PLBlockIMP.framework/Versions/A/Resources/gentramp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # ----------------------------------------------------------------------- 4 | # gentramp.sh - Copyright (c) 2010-2011, Plausible Labs Cooperative, Inc. 5 | # 6 | # Trampoline Page Generator 7 | # Author: Landon Fuller 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining 10 | # a copy of this software and associated documentation files (the 11 | # ``Software''), to deal in the Software without restriction, including 12 | # without limitation the rights to use, copy, modify, merge, publish, 13 | # distribute, sublicense, and/or sell copies of the Software, and to 14 | # permit persons to whom the Software is furnished to do so, subject to 15 | # the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included 18 | # in all copies or substantial portions of the Software. 19 | # 20 | # THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 21 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 27 | # DEALINGS IN THE SOFTWARE. 28 | # ----------------------------------------------------------------------- 29 | 30 | PROGNAME="$0" 31 | 32 | INPUT_FILE_PATH="$1" 33 | CURRENT_ARCH="$2" 34 | PLATFORM_NAME="$3" 35 | OUTPUT_FILE_PREFIX="$4" 36 | OUTPUT_DIR="$5" 37 | 38 | if [ -z "${INPUT_FILE_PATH}" ] || [ -z "${CURRENT_ARCH}" ] || [ -z "${PLATFORM_NAME}" ] || [ -z "${OUTPUT_FILE_PREFIX}" ] || [ -z "${OUTPUT_DIR}" ]; then 39 | echo "USAGE: $PROGNAME " 40 | echo " For example, '$PROGNAME blockimp_arm.tramp armv7 iphoneos bli_arm build' would read 'blockimp_arm.tramp'" 41 | echo " and generate the following files in 'build':" 42 | echo " - bli_arm_config.c" 43 | echo " - bli_arm.s" 44 | echo " - bli_arm.h" 45 | 46 | exit 1 47 | fi 48 | 49 | SRC_C_OUTPUT="${OUTPUT_DIR}/${OUTPUT_FILE_PREFIX}_config.c" 50 | SRC_OUTPUT="${OUTPUT_DIR}/${OUTPUT_FILE_PREFIX}.s" 51 | HEADER_OUTPUT="${OUTPUT_DIR}/${OUTPUT_FILE_PREFIX}.h" 52 | 53 | # Default implementation 54 | trampoline_prefix () { 55 | return 0 56 | } 57 | 58 | # Import the trampoline definition 59 | . "${INPUT_FILE_PATH}" 60 | 61 | check_required () { 62 | local name=$1 63 | eval "local var=\${$1}" 64 | 65 | if [ -z "${var}" ]; then 66 | echo "Required variable ${name} not defined." 67 | exit 1 68 | fi 69 | } 70 | 71 | check_required PAGE_SIZE 72 | check_required PAGE_NAME 73 | 74 | # Write a header line 75 | header () { 76 | echo "$1" >> "${HEADER_OUTPUT}" 77 | } 78 | 79 | # Write a C source line 80 | src () { 81 | echo "$1" >> "${SRC_C_OUTPUT}" 82 | } 83 | 84 | # Flush the assembler output buffer to disk 85 | ASM_BUFFER="" 86 | asm_flush () { 87 | echo "${ASM_BUFFER}" >> "${SRC_OUTPUT}" 88 | asm_discard 89 | } 90 | 91 | # Write the assembler buffer to disk, but don't discard the contents 92 | asm_write () { 93 | echo "${ASM_BUFFER}" >> "${SRC_OUTPUT}" 94 | } 95 | 96 | # Discard the current assembler output buffer 97 | asm_discard () { 98 | ASM_BUFFER='' 99 | return 0; 100 | } 101 | 102 | # Append data to the assembler output buffer 103 | asm () { 104 | local line="" 105 | while read -r line; do 106 | ASM_BUFFER+=$line 107 | ASM_BUFFER+="\n" 108 | done 109 | } 110 | 111 | # Compute the assembled size of the current assembler buffer 112 | compute_asm_size () { 113 | # Create the temporary assembler file 114 | local output=".globl _byte_count_start\n" 115 | output+="_byte_count_start:\n" 116 | output+="${ASM_BUFFER}" 117 | output+=".globl _byte_count_end\n" 118 | output+="_byte_count_end:\n" 119 | 120 | # Apple's ARM64 as(1) handling is a thin shim to clang's arm64 integrated 121 | # assembler, which does not support documented as(1) behavior. We work 122 | # around clang's file extension assumptions via an explicit -x option; 123 | # see rdar://15162294 for more details. 124 | if [ "${CURRENT_ARCH}" == "arm64" ]; then 125 | local asm_args_extra="-x assembler" 126 | else 127 | local asm_args_extra="" 128 | fi 129 | 130 | local tempfile=`mktemp /tmp/as_bytecount.XXXXXXXX` 131 | echo "${output}" | xcrun --sdk "${PLATFORM_NAME}" as -arch "${CURRENT_ARCH}" $asm_args_extra -o "${tempfile}" - 132 | if [ $? != 0 ]; then 133 | echo "Assembling the trampoline failed" 134 | exit 1 135 | fi 136 | 137 | local byte_size=`xcrun --sdk "${PLATFORM_NAME}" nm -t d -P "${tempfile}" | grep ^_byte_count_end | awk '{print $3}'` 138 | rm -f "${tempfile}" 139 | 140 | echo $byte_size 141 | } 142 | 143 | 144 | # Write out the page header 145 | write_page_decl () { 146 | # Calculate the required alignment 147 | local align=`perl -l -e "print log(${PAGE_SIZE})/log(2)"` 148 | asm << EOF 149 | # GENERATED CODE - DO NOT EDIT" 150 | # This file was generated by $PROGNAME on `date` 151 | 152 | # Write out the trampoline table, aligned to the page boundary 153 | .text 154 | .align ${align} 155 | .globl _${PAGE_NAME} 156 | _${PAGE_NAME}: 157 | EOF 158 | } 159 | 160 | main () { 161 | echo '' > "${SRC_OUTPUT}" 162 | echo '' > "${SRC_C_OUTPUT}" 163 | echo '' > "${HEADER_OUTPUT}" 164 | 165 | # Write out the trampoline header file 166 | header "extern void *${PAGE_NAME};" 167 | header "extern struct pl_trampoline_table_config ${PAGE_NAME}_config;" 168 | 169 | # Don't generate tables for an unsupported arch 170 | check_architecture "${CURRENT_ARCH}" 171 | if [ "$?" != "1" ]; then 172 | return 173 | fi 174 | 175 | # Determine the trampoline prefix size 176 | trampoline_prefix 177 | local prefix_size=$(compute_asm_size) 178 | asm_discard 179 | 180 | # Compute the size of the remaining code page. 181 | local page_avail=`expr $PAGE_SIZE - $prefix_size` 182 | 183 | # Determine the trampoline size 184 | trampoline 185 | local tramp_size=$(compute_asm_size) 186 | asm_discard 187 | if [ "${tramp_size}" = 0 ]; then 188 | echo "Error occured calculating trampoline size; received size of 0" 189 | exit 1 190 | fi 191 | 192 | # Compute the number of of available trampolines. 193 | local trampoline_count=`expr $page_avail / $tramp_size` 194 | echo "Prefix size: ${prefix_size}" 195 | echo "Trampoline size: ${tramp_size}" 196 | echo "Trampolines per page: ${trampoline_count}" 197 | 198 | # Write out the page declaration 199 | write_page_decl 200 | asm_flush 201 | 202 | # Write out the prefix 203 | trampoline_prefix 204 | asm_flush 205 | 206 | # Write out the trampolines 207 | trampoline 208 | local i=0 209 | while [ $i -lt ${trampoline_count} ]; do 210 | asm_write 211 | local i=`expr $i + 1` 212 | done 213 | asm_discard 214 | 215 | # Write out the table configuration 216 | local config_src=`cat << EOF 217 | #define PL_BLOCKIMP_PRIVATE 1 218 | #include 219 | 220 | extern void *${PAGE_NAME}; 221 | pl_trampoline_table_config ${PAGE_NAME}_config = { 222 | .trampoline_size = ${tramp_size}, 223 | .page_offset = ${prefix_size}, 224 | .trampoline_count = ${trampoline_count}, 225 | .template_page = &${PAGE_NAME} 226 | }; 227 | EOF` 228 | src "${config_src}" 229 | } 230 | 231 | main -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/Frameworks/PLBlockIMP.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/Headers/NSObject+PLPatchMaster.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2013-2015 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #import 30 | 31 | @interface NSObject (PLPatchMaster) 32 | 33 | + (BOOL) pl_patchSelector: (SEL) selector withReplacementBlock: (id) replacementBlock; 34 | + (BOOL) pl_patchInstanceSelector: (SEL) selector withReplacementBlock: (id) replacementBlock; 35 | 36 | + (void) pl_patchFutureSelector: (SEL) selector withReplacementBlock: (id) replacementBlock; 37 | + (void) pl_patchFutureInstanceSelector: (SEL) selector withReplacementBlock: (id) replacementBlock; 38 | 39 | @end -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/Headers/PLPatchMaster.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2013-2015 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #import 30 | #import "NSObject+PLPatchMaster.h" 31 | 32 | /** 33 | * IMP patch state, as passed to a replacement block. 34 | */ 35 | typedef struct PLPatchIMP { 36 | /** The original message target. */ 37 | void *self; 38 | 39 | /** The original IMP (eg, the IMP prior to patching) */ 40 | IMP origIMP; 41 | 42 | /** The original SEL. */ 43 | SEL selector; 44 | } PLPatchIMP; 45 | 46 | /** 47 | * Forward a message received by a PLPatchMaster patch block. 48 | * 49 | * @param patch The PLPatchIMP patch argument. 50 | * @param func_type The function type to which the IMP should be cast. 51 | * @param ... All method arguments (Do not include self or _cmd). 52 | */ 53 | #define PLPatchIMPFoward(patch, func_type, ...) ((func_type)patch->origIMP)((__bridge id) patch->self, patch->selector, ##__VA_ARGS__) 54 | 55 | /** 56 | * Return the original 'self' instance from a PLPatchMaster patch block. 57 | * 58 | * @param patch The PLPatchIMP patch argument. 59 | */ 60 | #define PLPatchGetSelf(patch) ((__bridge id) patch->self) 61 | 62 | @class PLPatchMasterImpl; 63 | 64 | @interface PLPatchMaster : NSObject { 65 | PLPatchMasterImpl *_impl; 66 | } 67 | 68 | + (instancetype) master; 69 | 70 | - (BOOL) patchClass: (Class) cls selector: (SEL) selector replacementBlock: (id) replacementBlock; 71 | - (BOOL) patchInstancesWithClass: (Class) cls selector: (SEL) selector replacementBlock: (id) replacementBlock; 72 | 73 | - (void) patchFutureClassWithName: (NSString *) className selector: (SEL) selector replacementBlock: (id) replacementBlock; 74 | - (void) patchInstancesWithFutureClassName: (NSString *) className selector: (SEL) selector replacementBlock: (id) replacementBlock; 75 | 76 | - (void) rebindSymbol: (NSString *) symbol fromImage: (NSString *) library replacementAddress: (uintptr_t) replacementAddress; 77 | - (void) rebindSymbol: (NSString *) symbol replacementAddress: (uintptr_t) replacementAddress; 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/PLPatchMaster: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landonf/XcodePostFacto/9987e9f13041956651f6c9bee1243f95da3e3178/Dependencies/PLPatchMaster.framework/Versions/A/PLPatchMaster -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/PrivateHeaders/PMLog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller . 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #include 32 | 33 | #define PMDoLog(_prefix, fmt, ...) do { \ 34 | fprintf(stderr, _prefix fmt "\n", ## __VA_ARGS__); \ 35 | } while(0) 36 | 37 | #define PMDebug(fmt, ...) do { \ 38 | PMDoLog("[PLPatchMaster] ", fmt, ## __VA_ARGS__); \ 39 | } while(0) 40 | 41 | #define PMLog(fmt, ...) do { \ 42 | PMDoLog("[PLPatchMaster] ", fmt, ## __VA_ARGS__); \ 43 | } while(0) 44 | 45 | #define PMFatal(fmt, ...) do { \ 46 | PMDoLog("[PLPatchMaster] FATAL ERROR: ", fmt, ## __VA_ARGS__); \ 47 | abort(); \ 48 | } while(0) -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/PrivateHeaders/SymbolBinder.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller . 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #include "PMLog.h" 32 | 33 | #include 34 | #include 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | #include 45 | 46 | #include "SymbolName.hpp" 47 | 48 | namespace patchmaster { 49 | 50 | /* Architecture-specific Mach-O types and constants */ 51 | #ifdef __LP64__ 52 | typedef struct mach_header_64 pl_mach_header_t; 53 | typedef struct segment_command_64 pl_segment_command_t; 54 | typedef struct section_64 pl_section_t; 55 | typedef struct nlist_64 pl_nlist_t; 56 | static constexpr uint32_t PL_LC_SEGMENT = LC_SEGMENT_64; 57 | #else 58 | typedef struct mach_header pl_mach_header_t; 59 | typedef struct segment_command pl_segment_command_t; 60 | typedef struct section pl_section_t; 61 | typedef struct nlist pl_nlist_t; 62 | static constexpr uint32_t PL_LC_SEGMENT = LC_SEGMENT; 63 | #endif 64 | 65 | 66 | uint64_t read_uleb128 (const void *location, std::size_t *size); 67 | int64_t read_sleb128 (const void *location, std::size_t *size); 68 | 69 | /* Forward declaration */ 70 | class LocalImage; 71 | 72 | /** 73 | * A simple byte-based opcode stream reader. 74 | * 75 | * This was adapted from our DWARF opcode evaluation code in PLCrashReporter. 76 | */ 77 | class bind_opstream { 78 | public: 79 | class symbol_proc; 80 | 81 | private: 82 | /** Current position within the op stream */ 83 | const uint8_t *_p; 84 | 85 | /** Starting address. */ 86 | const uint8_t *_instr; 87 | 88 | /** Ending address. */ 89 | const uint8_t *_instr_max; 90 | 91 | /** Current immediate value */ 92 | uint8_t _immd = 0; 93 | 94 | /** 95 | * If true, this is a lazy opcode section; BIND_OPCODE_DONE is automatically skipped at the end of 96 | * each entry (the lazy section is written to terminate evaluation after each entry, as each symbol within 97 | * the lazy section is by dyld on-demand, and is supposed to terminate after resolving one symbol). 98 | */ 99 | bool _isLazy; 100 | 101 | /** 102 | * Opcode evaluation state. 103 | */ 104 | struct evaluation_state { 105 | /* dylib path from which the symbol will be resolved, or an empty string if unspecified or flat binding. */ 106 | const char *sym_image = ""; 107 | 108 | /* bind type (one of BIND_TYPE_POINTER, BIND_TYPE_TEXT_ABSOLUTE32, or BIND_TYPE_TEXT_PCREL32) */ 109 | uint8_t bind_type = BIND_TYPE_POINTER; 110 | 111 | /* symbol name */ 112 | const char *sym_name = ""; 113 | 114 | /* symbol flags (one of BIND_SYMBOL_FLAGS_WEAK_IMPORT, BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) */ 115 | uint8_t sym_flags = 0; 116 | 117 | /* A value to be added to the resolved symbol's address before binding. */ 118 | int64_t addend = 0; 119 | 120 | /* The actual in-memory bind target address. */ 121 | uintptr_t bind_address = 0; 122 | 123 | /** 124 | * Return symbol_proc representation of the current evaluation state. 125 | */ 126 | symbol_proc symbol_proc () { 127 | return symbol_proc::symbol_proc( 128 | SymbolName(sym_image, sym_name), 129 | bind_type, 130 | sym_flags, 131 | addend, 132 | bind_address 133 | ); 134 | } 135 | }; 136 | 137 | /** The current evaluation state. */ 138 | evaluation_state _eval_state; 139 | 140 | public: 141 | bind_opstream (const uint8_t *opcodes, const size_t opcodes_len, bool isLazy) : _p(opcodes), _instr(_p), _instr_max(_p + opcodes_len), _isLazy(isLazy) {} 142 | 143 | bind_opstream (const bind_opstream &other) : _p(other._p), _instr(other._instr), _instr_max(other._instr_max), _isLazy(other._isLazy), _eval_state(other._eval_state) {} 144 | 145 | /** 146 | * The parsed bind procedure for a single symbol. 147 | */ 148 | class symbol_proc { 149 | public: 150 | /** 151 | * Construct a new symbol procedure record. 152 | * 153 | * @param name The two-level symbol name bound by this procedure. 154 | * @param type The bind type for this symbol. 155 | * @param flags The bind flags for this symbol. 156 | * @param addend A value to be added to the resolved symbol's address before binding. 157 | * @param bind_address The actual in-memory bind target address. 158 | */ 159 | symbol_proc (const SymbolName &name, uint8_t type, uint8_t flags, int64_t addend, uintptr_t bind_address) : 160 | _name(name), _type(type), _flags(flags), _addend(addend), _bind_address(bind_address) {} 161 | 162 | symbol_proc (SymbolName &&name, uint8_t type, uint8_t flags, int64_t addend, uintptr_t bind_address) : 163 | _name(std::move(name)), _type(type), _flags(flags), _addend(addend), _bind_address(bind_address) {} 164 | 165 | /** The two-level symbol name bound by this procedure. */ 166 | const SymbolName &name () const { return _name; } 167 | 168 | /* The bind type for this symbol (one of BIND_TYPE_POINTER, BIND_TYPE_TEXT_ABSOLUTE32, or BIND_TYPE_TEXT_PCREL32) */ 169 | uint8_t type () const { return _type; } 170 | 171 | /* The bind flags for this symbol (one of BIND_SYMBOL_FLAGS_WEAK_IMPORT, BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) */ 172 | uint8_t flags () const { return _flags; } 173 | 174 | /* A value to be added to the resolved symbol's address before binding. */ 175 | int64_t addend () const { return _addend; } 176 | 177 | /* The actual in-memory bind target address. */ 178 | uintptr_t bind_address () const { return _bind_address; } 179 | 180 | private: 181 | /** The two-level symbol name bound by this procedure. */ 182 | SymbolName _name; 183 | 184 | /* The bind type for this symbol (one of BIND_TYPE_POINTER, BIND_TYPE_TEXT_ABSOLUTE32, or BIND_TYPE_TEXT_PCREL32) */ 185 | uint8_t _type; 186 | 187 | /* The bind flags for this symbol (one of BIND_SYMBOL_FLAGS_WEAK_IMPORT, BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) */ 188 | uint8_t _flags = 0; 189 | 190 | /* A value to be added to the resolved symbol's address before binding. */ 191 | int64_t _addend = 0; 192 | 193 | /* The actual in-memory bind target address. */ 194 | uintptr_t _bind_address = 0; 195 | }; 196 | 197 | void evaluate (const LocalImage &image, const std::function &bind); 198 | uint8_t step (const LocalImage &image, const std::function &bind); 199 | 200 | /** Read a ULEB128 value and advance the stream */ 201 | inline uint64_t uleb128 () { 202 | size_t len; 203 | uint64_t result = read_uleb128(_p, &len); 204 | 205 | _p += len; 206 | assert(_p <= _instr_max); 207 | return result; 208 | } 209 | 210 | /** Read a SLEB128 value and advance the stream */ 211 | inline int64_t sleb128 () { 212 | size_t len; 213 | int64_t result = read_sleb128(_p, &len); 214 | 215 | _p += len; 216 | assert(_p <= _instr_max); 217 | return result; 218 | } 219 | 220 | /** Skip @a offset bytes. */ 221 | inline void skip (size_t offset) { 222 | _p += offset; 223 | assert(_p <= _instr_max); 224 | } 225 | 226 | /** Read a single opcode from the stream. */ 227 | inline uint8_t opcode () { 228 | assert(_p < _instr_max); 229 | uint8_t value = (*_p) & BIND_OPCODE_MASK; 230 | _immd = (*_p) & BIND_IMMEDIATE_MASK; 231 | _p++; 232 | 233 | /* Skip BIND_OPCODE_DONE if it occurs within a lazy binding opcode stream */ 234 | if (_isLazy && *_p == BIND_OPCODE_DONE && !isEmpty()) 235 | skip(1); 236 | 237 | return value; 238 | }; 239 | 240 | /** Return the current stream position. */ 241 | inline const uint8_t *position () { return _p; }; 242 | 243 | /** Return true if there are no additional opcodes to be read. */ 244 | inline bool isEmpty () { return _p >= _instr_max; } 245 | 246 | /** Return true if this is a lazy opcode stream. */ 247 | inline bool isLazy () { return _isLazy; } 248 | 249 | /** Read a NUL-terminated C string from the stream, advancing the current position past the string. */ 250 | inline const char *cstring () { 251 | const char *result = (const char *) _p; 252 | skip(strlen(result) + 1); 253 | return result; 254 | } 255 | 256 | /** Return the immediate value from the last opcode */ 257 | inline uint8_t immd () { return _immd; } 258 | 259 | /** Return the signed representation of immd */ 260 | inline int8_t signed_immd () { 261 | /* All other constants are negative */ 262 | if (immd() == 0) 263 | return 0; 264 | 265 | /* Sign-extend the immediate value */ 266 | return (~BIND_IMMEDIATE_MASK) | (immd() & BIND_IMMEDIATE_MASK); 267 | } 268 | 269 | }; 270 | 271 | /** 272 | * An in-memory Mach-O image. 273 | */ 274 | class LocalImage { 275 | private: 276 | friend class bind_opstream; 277 | 278 | /** 279 | * Construct a new local image. 280 | */ 281 | LocalImage ( 282 | const std::string &path, 283 | const pl_mach_header_t *header, 284 | const intptr_t vmaddr_slide, 285 | std::shared_ptr> &libraries, 286 | std::shared_ptr> &segments, 287 | std::shared_ptr> &bindings 288 | ) : _header(header), _vmaddr_slide(vmaddr_slide), _libraries(libraries), _segments(segments), _bindOpcodes(bindings), _path(path) {} 289 | 290 | public: 291 | static const std::string &MainExecutablePath (); 292 | static LocalImage Analyze (const std::string &path, const pl_mach_header_t *header); 293 | void rebind_symbols (const std::function &bind); 294 | 295 | /** 296 | * Return a borrowed reference to the image's path. 297 | */ 298 | const std::string &path () const { return _path; } 299 | 300 | /** 301 | * Return the image's vm_slide. 302 | */ 303 | intptr_t vmaddr_slide () const { return _vmaddr_slide; } 304 | 305 | /** 306 | * Return the image's symbol binding opcode streams. 307 | */ 308 | std::shared_ptr> bindOpcodes () const { return _bindOpcodes; } 309 | 310 | /** 311 | * Return the image's defined segments. 312 | */ 313 | std::shared_ptr> segments () const { return _segments; } 314 | 315 | private: 316 | /** Mach-O image header */ 317 | const pl_mach_header_t *_header; 318 | 319 | /** Offset applied when the image was loaded; required to compute in-memory addresses from on-disk VM addresses.. */ 320 | const intptr_t _vmaddr_slide; 321 | 322 | /** Linked libraries, indexed by reference order. */ 323 | std::shared_ptr> _libraries; 324 | 325 | /** Segment commands, indexed by declaration order. */ 326 | std::shared_ptr> _segments; 327 | 328 | /** All symbol binding opcodes. */ 329 | std::shared_ptr> _bindOpcodes; 330 | 331 | /** Image path */ 332 | const std::string _path; 333 | }; 334 | 335 | } /* namespace patchmaster */ -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/PrivateHeaders/SymbolName.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller . 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #include "PMLog.h" 32 | 33 | #include 34 | #include 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | #include 45 | 46 | namespace patchmaster { 47 | /** 48 | * A single-level or two-level namespaced symbol reference. 49 | */ 50 | class SymbolName { 51 | public: 52 | /** 53 | * Construct a new symbol name. 54 | * 55 | * @param image The absolute or relative path of the image that exports this symbol, or an empty path to signify 56 | * single-level lookup. 57 | * @param symbol The symbol name. 58 | */ 59 | SymbolName (const char *image, const char *symbol) : _image(image), _symbol(symbol) {} 60 | 61 | /** Return the absolute or relative path of the image that exports this symbol. If the path is empty, single-level 62 | * namespacing is assumed. */ 63 | const char *image () const { return _image; } 64 | 65 | /** Return the symbol name. */ 66 | const char *symbol () const { return _symbol; } 67 | 68 | /** 69 | * Return true if this symbol name matches the provided name. 70 | */ 71 | bool match (const SymbolName &other) const { 72 | /* If symbol names don't match, there's nothing else to test. */ 73 | if (strcmp(other._symbol, _symbol) != 0) 74 | return false; 75 | 76 | /* If either image is zero-length, they'll match on the first matching symbol regardless of the image. */ 77 | if (*other._image == '\0' || *_image == '\0') 78 | return true; 79 | 80 | /* Check for a suffix match */ 81 | size_t image_len = strlen(_image); 82 | size_t other_image_len = strlen(other._image); 83 | if (*other._image != '/' && other_image_len < image_len) { 84 | return strcmp(other._image, _image + image_len - other_image_len) == 0; 85 | } else if (*_image != '/' && image_len < other_image_len) { 86 | return strcmp(_image, other._image + other_image_len - image_len) == 0; 87 | } else { 88 | return strcmp(_image, other._image) == 0; 89 | } 90 | } 91 | 92 | private: 93 | /** Image, or empty string */ 94 | const char *_image; 95 | 96 | /** Symbol name. */ 97 | const char *_symbol; 98 | }; 99 | } /* namespace patchmaster */ -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/A/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 13F1077 7 | CFBundleDevelopmentRegion 8 | English 9 | CFBundleExecutable 10 | PLPatchMaster 11 | CFBundleIdentifier 12 | coop.plausible.PLPatchMaster 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | PLPatchMaster 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | DTCompiler 26 | com.apple.compilers.llvm.clang.1_0 27 | DTPlatformBuild 28 | 6D570 29 | DTPlatformVersion 30 | GM 31 | DTSDKBuild 32 | 14D125 33 | DTSDKName 34 | macosx10.10 35 | DTXcode 36 | 0630 37 | DTXcodeBuild 38 | 6D570 39 | 40 | 41 | -------------------------------------------------------------------------------- /Dependencies/PLPatchMaster.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /Dependencies/README.txt: -------------------------------------------------------------------------------- 1 | This directory contains source and binary dependencies: 2 | 3 | PLPatchMaster.framework 4 | Description: 5 | Provides a block-based swizzling API used to implement runtime patching 6 | of Xcode and system APIs. 7 | 8 | Version: 9 | PLPatchMaster revision f1d85eaf4e28d686e01b4410644ef243c078cf13 built from https://opensource.plausible.coop/src/projects/PLTP/repos/plpatchmaster 10 | 11 | License: 12 | MIT 13 | 14 | Modifications: 15 | None 16 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Landon Fuller 2 | Copyright (c) 2010-2013 Plausible Labs Cooperative, Inc. 3 | All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | 26 | Additionally, the dyld_priv.h header is subject to the following 27 | license: 28 | 29 | Copyright (c) 2003-2010 Apple Inc. All rights reserved. 30 | 31 | This file contains Original Code and/or Modifications of Original Code 32 | as defined in and that are subject to the Apple Public Source License 33 | Version 2.0 (the 'License'). You may not use this file except in 34 | compliance with the License. Please obtain a copy of the License at 35 | http://www.opensource.apple.com/apsl/ and read it before using this 36 | file. 37 | 38 | The Original Code and all software distributed under the License are 39 | distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 40 | EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 41 | INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 42 | FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 43 | Please see the License for the specific language governing rights and 44 | limitations under the License. 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XCodePostFacto 2 | 3 | XcodePostFacto enables the use of Yosemite-only Xcode 6.3 on Mac OS X 10.9 Mavericks. 4 | 5 | The name is, of course, a nod to the original [XPostFacto](https://en.wikipedia.org/wiki/XPostFacto). 6 | 7 | ## Why 8 | 9 | It seems a bit gratitious to break compatibility with an OS release that was current less than 6 months ago, and while the the Yosemite upgrade is free, it has its own inherent costs -- especially in terms of [privacy](https://fix-macosx.com/) and [quality](http://mjtsai.com/blog/2015/01/06/apples-software-quality-continued/) [issues](http://mjtsai.com/blog/2014/10/11/apples-software-quality-decline/). 10 | 11 | Plus, I don't like being told what to do :-) 12 | 13 | ## Usage 14 | 15 | After building the `xpf-bootstrap.framework`, Xcode can be launched from the command-line: 16 | 17 | env DYLD_INSERT_LIBRARIES=$ABSOLUTE_PATH_TO_FRAMEWORK/xpf-bootstrap.framework/xpf-bootstrap /Applications/Xcode.app/Contents/MacOS/Xcode 18 | 19 | Contribution of a wrapping launch application would be most appreciated, especially one that supports drag-and-drop of the Xcode binary to create a new launcher :-) 20 | 21 | ## Status 22 | 23 | XcodePostFacto is fully self-hosting, and is being used for full-time Mac development work. However, 24 | issues certainly still remain, and I expect to find and fix issues during day-to-day use of Xcode. 25 | 26 | ## How 27 | 28 | There are a number of hurdles to getting Xcode 6.3 running on an earlier release: 29 | 30 | * Xcode declares a minimum system version of 10.10, preventing launch via `LaunchServices` and triggering an abort() in `HIServices` if you bypass the initial `LaunchServices` check. 31 | * Xcode continues to ship with no-longer functional 10.9 compatibity code, and enables that code if it detects it's running on Mavericks. This results in crashes -- and even if you got past those, the result wouldn't actually be Xcode 6.3. 32 | * Xcode links against 10.10-only APIs, which trigger both link-time and runtime crashes. 33 | 34 | To resolve these issues, we must patch Xcode and system libraries: disabling the legacy compatibility code, all version checks, and performing runtime rebinding of missing symbols. 35 | 36 | XcodePostFacto leverages the following mechanisms to achieve this: 37 | 38 | * Prior to Xcode's main(), the private `dyld_register_image_state_change_handler` API is used to hook `dyld` and modify library symbol references that are critical to bootstrapping the process: 39 | * After the library has been rebased, but before it has been linked, we use a custom single-stepping implementation of dyld symbol rebinding to find strong references to Yosemite-only symbols and rewrite them as weak references. 40 | * Once the library has been linked, but before it has been initialized, we use the same `BIND_OPCODE_*` evaluator to rebind symbols to our custom replacements. 41 | * Before handing control back to Xcode, the bootstrap code uses my [PLPatchMaster](https://opensource.plausible.coop/src/projects/PLTP/repos/plpatchmaster/browse) library to register a future patch on Xcode's `DVTPlugInManager` class. This patch adds `xpf_bootstrap.framework/Contents/Resources/Xcode` to `DVTPlugInManager`'s plugin search path. 42 | * A custom plugin in `xpf_bootstrap.framework/Contents/Resources/Xcode` uses Xcode's standard plugin mechanisms to hook the `IDEInitialize` step, performing a final set of bootstrap operations within the now-initialized Xcode process. 43 | -------------------------------------------------------------------------------- /XcodePostFacto.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 05B0264D1AB4E17500F6BF2B /* XcodePostFacto.xcplugindata in Resources */ = {isa = PBXBuildFile; fileRef = 05B0264C1AB4E17500F6BF2B /* XcodePostFacto.xcplugindata */; }; 11 | 05B026501AB4E1D000F6BF2B /* XPFDebugMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B0264F1AB4E1D000F6BF2B /* XPFDebugMenu.m */; }; 12 | 05B026BA1AB4F64F00F6BF2B /* PLPatchMaster.framework in Copy Files */ = {isa = PBXBuildFile; fileRef = 05B026A51AB4EA7B00F6BF2B /* PLPatchMaster.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 13 | 05B026BB1AB4F65300F6BF2B /* PLPatchMaster.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05B026A51AB4EA7B00F6BF2B /* PLPatchMaster.framework */; }; 14 | 05B026BE1AB4F68300F6BF2B /* XcodePostFacto.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B026BD1AB4F68300F6BF2B /* XcodePostFacto.m */; }; 15 | 05C258AE1AB8202F007DD20C /* XcodePostFacto.ideplugin in CopyFiles */ = {isa = PBXBuildFile; fileRef = 05B026421AB4E14C00F6BF2B /* XcodePostFacto.ideplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 16 | 05C258B31AB8A667007DD20C /* cfbundle_rebind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05C258B11AB8A667007DD20C /* cfbundle_rebind.cpp */; }; 17 | 05C258B41AB8A667007DD20C /* cfbundle_rebind.h in Headers */ = {isa = PBXBuildFile; fileRef = 05C258B21AB8A667007DD20C /* cfbundle_rebind.h */; }; 18 | 05CD7F911ABA849400169305 /* XPFViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 05CD7F901ABA849400169305 /* XPFViewController.m */; }; 19 | 05EEA0BC1AB7B3A6000C8B89 /* xpf_bootstrap.mm in Sources */ = {isa = PBXBuildFile; fileRef = 05EEA0851AB7AA21000C8B89 /* xpf_bootstrap.mm */; }; 20 | 05EEA0BD1AB7B3B3000C8B89 /* PLPatchMaster.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05B026A51AB4EA7B00F6BF2B /* PLPatchMaster.framework */; }; 21 | 05EEA0BF1AB7B3C3000C8B89 /* PLPatchMaster.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 05B026A51AB4EA7B00F6BF2B /* PLPatchMaster.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 22 | 05EEA0C41AB7BFEC000C8B89 /* dyld_priv.h in Headers */ = {isa = PBXBuildFile; fileRef = 05EEA0C31AB7BFEC000C8B89 /* dyld_priv.h */; }; 23 | 05EEA0D21AB7EBEB000C8B89 /* rebind_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05EEA0D01AB7EBEB000C8B89 /* rebind_table.cpp */; }; 24 | 05EEA0D31AB7EBEB000C8B89 /* rebind_table.h in Headers */ = {isa = PBXBuildFile; fileRef = 05EEA0D11AB7EBEB000C8B89 /* rebind_table.h */; }; 25 | 05EEA0D61AB7F028000C8B89 /* yosemite_objc_stubs.m in Sources */ = {isa = PBXBuildFile; fileRef = 05EEA0D41AB7F028000C8B89 /* yosemite_objc_stubs.m */; }; 26 | 05EEA0D71AB7F028000C8B89 /* yosemite_objc_stubs.h in Headers */ = {isa = PBXBuildFile; fileRef = 05EEA0D51AB7F028000C8B89 /* yosemite_objc_stubs.h */; }; 27 | 05EEA0DA1AB80D1C000C8B89 /* NSVisualEffectView.m in Sources */ = {isa = PBXBuildFile; fileRef = 05EEA0D91AB80D1C000C8B89 /* NSVisualEffectView.m */; }; 28 | /* End PBXBuildFile section */ 29 | 30 | /* Begin PBXContainerItemProxy section */ 31 | 05EEA0C01AB7B3D5000C8B89 /* PBXContainerItemProxy */ = { 32 | isa = PBXContainerItemProxy; 33 | containerPortal = 05B0263A1AB4E14C00F6BF2B /* Project object */; 34 | proxyType = 1; 35 | remoteGlobalIDString = 05B026411AB4E14C00F6BF2B; 36 | remoteInfo = XcodePostFacto; 37 | }; 38 | /* End PBXContainerItemProxy section */ 39 | 40 | /* Begin PBXCopyFilesBuildPhase section */ 41 | 05B026B81AB4EAA600F6BF2B /* Copy Files */ = { 42 | isa = PBXCopyFilesBuildPhase; 43 | buildActionMask = 2147483647; 44 | dstPath = ""; 45 | dstSubfolderSpec = 10; 46 | files = ( 47 | 05B026BA1AB4F64F00F6BF2B /* PLPatchMaster.framework in Copy Files */, 48 | ); 49 | name = "Copy Files"; 50 | runOnlyForDeploymentPostprocessing = 0; 51 | }; 52 | 05C258AD1AB82013007DD20C /* CopyFiles */ = { 53 | isa = PBXCopyFilesBuildPhase; 54 | buildActionMask = 2147483647; 55 | dstPath = Xcode; 56 | dstSubfolderSpec = 7; 57 | files = ( 58 | 05C258AE1AB8202F007DD20C /* XcodePostFacto.ideplugin in CopyFiles */, 59 | ); 60 | runOnlyForDeploymentPostprocessing = 0; 61 | }; 62 | 05EEA0BE1AB7B3BA000C8B89 /* CopyFiles */ = { 63 | isa = PBXCopyFilesBuildPhase; 64 | buildActionMask = 2147483647; 65 | dstPath = ""; 66 | dstSubfolderSpec = 10; 67 | files = ( 68 | 05EEA0BF1AB7B3C3000C8B89 /* PLPatchMaster.framework in CopyFiles */, 69 | ); 70 | runOnlyForDeploymentPostprocessing = 0; 71 | }; 72 | /* End PBXCopyFilesBuildPhase section */ 73 | 74 | /* Begin PBXFileReference section */ 75 | 05B026421AB4E14C00F6BF2B /* XcodePostFacto.ideplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XcodePostFacto.ideplugin; sourceTree = BUILT_PRODUCTS_DIR; }; 76 | 05B026461AB4E14C00F6BF2B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 77 | 05B0264C1AB4E17500F6BF2B /* XcodePostFacto.xcplugindata */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = XcodePostFacto.xcplugindata; sourceTree = ""; }; 78 | 05B0264E1AB4E1D000F6BF2B /* XPFDebugMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XPFDebugMenu.h; sourceTree = ""; }; 79 | 05B0264F1AB4E1D000F6BF2B /* XPFDebugMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XPFDebugMenu.m; sourceTree = ""; }; 80 | 05B026511AB4E30B00F6BF2B /* XPFLog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPFLog.h; sourceTree = ""; }; 81 | 05B026A51AB4EA7B00F6BF2B /* PLPatchMaster.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = PLPatchMaster.framework; sourceTree = ""; }; 82 | 05B026A61AB4EA7B00F6BF2B /* PLPatchMaster.framework.dSYM */ = {isa = PBXFileReference; lastKnownFileType = wrapper.dsym; path = PLPatchMaster.framework.dSYM; sourceTree = ""; }; 83 | 05B026A71AB4EA7B00F6BF2B /* README.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.txt; sourceTree = ""; }; 84 | 05B026BC1AB4F68300F6BF2B /* XcodePostFacto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XcodePostFacto.h; sourceTree = ""; }; 85 | 05B026BD1AB4F68300F6BF2B /* XcodePostFacto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XcodePostFacto.m; sourceTree = ""; }; 86 | 05C258AF1AB89EED007DD20C /* DVTPlugInManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DVTPlugInManager.h; sourceTree = ""; }; 87 | 05C258B11AB8A667007DD20C /* cfbundle_rebind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cfbundle_rebind.cpp; sourceTree = ""; }; 88 | 05C258B21AB8A667007DD20C /* cfbundle_rebind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cfbundle_rebind.h; sourceTree = ""; }; 89 | 05CD7F901ABA849400169305 /* XPFViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XPFViewController.m; sourceTree = ""; }; 90 | 05EEA0831AB7AA21000C8B89 /* xpf_bootstrap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = xpf_bootstrap.h; sourceTree = ""; }; 91 | 05EEA0851AB7AA21000C8B89 /* xpf_bootstrap.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = xpf_bootstrap.mm; sourceTree = ""; }; 92 | 05EEA08B1AB7AA22000C8B89 /* xpf-bootstrapTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "xpf-bootstrapTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 93 | 05EEA0911AB7AA22000C8B89 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 94 | 05EEA0A31AB7B354000C8B89 /* xpf-bootstrap.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = "xpf-bootstrap.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; 95 | 05EEA0A61AB7B354000C8B89 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 96 | 05EEA0C31AB7BFEC000C8B89 /* dyld_priv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dyld_priv.h; sourceTree = ""; }; 97 | 05EEA0D01AB7EBEB000C8B89 /* rebind_table.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rebind_table.cpp; sourceTree = ""; }; 98 | 05EEA0D11AB7EBEB000C8B89 /* rebind_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rebind_table.h; sourceTree = ""; }; 99 | 05EEA0D41AB7F028000C8B89 /* yosemite_objc_stubs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = yosemite_objc_stubs.m; sourceTree = ""; }; 100 | 05EEA0D51AB7F028000C8B89 /* yosemite_objc_stubs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = yosemite_objc_stubs.h; sourceTree = ""; }; 101 | 05EEA0D91AB80D1C000C8B89 /* NSVisualEffectView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSVisualEffectView.m; sourceTree = ""; }; 102 | /* End PBXFileReference section */ 103 | 104 | /* Begin PBXFrameworksBuildPhase section */ 105 | 05B0263F1AB4E14C00F6BF2B /* Frameworks */ = { 106 | isa = PBXFrameworksBuildPhase; 107 | buildActionMask = 2147483647; 108 | files = ( 109 | 05B026BB1AB4F65300F6BF2B /* PLPatchMaster.framework in Frameworks */, 110 | ); 111 | runOnlyForDeploymentPostprocessing = 0; 112 | }; 113 | 05EEA0881AB7AA22000C8B89 /* Frameworks */ = { 114 | isa = PBXFrameworksBuildPhase; 115 | buildActionMask = 2147483647; 116 | files = ( 117 | ); 118 | runOnlyForDeploymentPostprocessing = 0; 119 | }; 120 | 05EEA09F1AB7B354000C8B89 /* Frameworks */ = { 121 | isa = PBXFrameworksBuildPhase; 122 | buildActionMask = 2147483647; 123 | files = ( 124 | 05EEA0BD1AB7B3B3000C8B89 /* PLPatchMaster.framework in Frameworks */, 125 | ); 126 | runOnlyForDeploymentPostprocessing = 0; 127 | }; 128 | /* End PBXFrameworksBuildPhase section */ 129 | 130 | /* Begin PBXGroup section */ 131 | 05B026391AB4E14C00F6BF2B = { 132 | isa = PBXGroup; 133 | children = ( 134 | 05B026441AB4E14C00F6BF2B /* XcodePostFacto */, 135 | 05B026521AB4EA7B00F6BF2B /* Dependencies */, 136 | 05EEA0821AB7AA21000C8B89 /* xpf-bootstrap */, 137 | 05EEA08F1AB7AA22000C8B89 /* xpf-bootstrapTests */, 138 | 05B026431AB4E14C00F6BF2B /* Products */, 139 | ); 140 | indentWidth = 4; 141 | sourceTree = ""; 142 | tabWidth = 4; 143 | usesTabs = 0; 144 | }; 145 | 05B026431AB4E14C00F6BF2B /* Products */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 05B026421AB4E14C00F6BF2B /* XcodePostFacto.ideplugin */, 149 | 05EEA08B1AB7AA22000C8B89 /* xpf-bootstrapTests.xctest */, 150 | 05EEA0A31AB7B354000C8B89 /* xpf-bootstrap.framework */, 151 | ); 152 | name = Products; 153 | sourceTree = ""; 154 | }; 155 | 05B026441AB4E14C00F6BF2B /* XcodePostFacto */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | 05B026BC1AB4F68300F6BF2B /* XcodePostFacto.h */, 159 | 05B026BD1AB4F68300F6BF2B /* XcodePostFacto.m */, 160 | 05B0264E1AB4E1D000F6BF2B /* XPFDebugMenu.h */, 161 | 05B0264F1AB4E1D000F6BF2B /* XPFDebugMenu.m */, 162 | 05B026511AB4E30B00F6BF2B /* XPFLog.h */, 163 | 05CD7F8F1ABA846B00169305 /* Yosemite Compat */, 164 | 05B026451AB4E14C00F6BF2B /* Supporting Files */, 165 | ); 166 | path = XcodePostFacto; 167 | sourceTree = ""; 168 | }; 169 | 05B026451AB4E14C00F6BF2B /* Supporting Files */ = { 170 | isa = PBXGroup; 171 | children = ( 172 | 05B0264C1AB4E17500F6BF2B /* XcodePostFacto.xcplugindata */, 173 | 05B026461AB4E14C00F6BF2B /* Info.plist */, 174 | ); 175 | name = "Supporting Files"; 176 | sourceTree = ""; 177 | }; 178 | 05B026521AB4EA7B00F6BF2B /* Dependencies */ = { 179 | isa = PBXGroup; 180 | children = ( 181 | 05B026A51AB4EA7B00F6BF2B /* PLPatchMaster.framework */, 182 | 05B026A61AB4EA7B00F6BF2B /* PLPatchMaster.framework.dSYM */, 183 | 05B026A71AB4EA7B00F6BF2B /* README.txt */, 184 | ); 185 | path = Dependencies; 186 | sourceTree = ""; 187 | }; 188 | 05C258B01AB89EF2007DD20C /* Xcode API */ = { 189 | isa = PBXGroup; 190 | children = ( 191 | 05C258AF1AB89EED007DD20C /* DVTPlugInManager.h */, 192 | ); 193 | name = "Xcode API"; 194 | sourceTree = ""; 195 | }; 196 | 05CD7F8F1ABA846B00169305 /* Yosemite Compat */ = { 197 | isa = PBXGroup; 198 | children = ( 199 | 05CD7F901ABA849400169305 /* XPFViewController.m */, 200 | ); 201 | name = "Yosemite Compat"; 202 | sourceTree = ""; 203 | }; 204 | 05EEA0821AB7AA21000C8B89 /* xpf-bootstrap */ = { 205 | isa = PBXGroup; 206 | children = ( 207 | 05EEA0831AB7AA21000C8B89 /* xpf_bootstrap.h */, 208 | 05EEA0851AB7AA21000C8B89 /* xpf_bootstrap.mm */, 209 | 05EEA0D11AB7EBEB000C8B89 /* rebind_table.h */, 210 | 05EEA0D01AB7EBEB000C8B89 /* rebind_table.cpp */, 211 | 05C258B21AB8A667007DD20C /* cfbundle_rebind.h */, 212 | 05C258B11AB8A667007DD20C /* cfbundle_rebind.cpp */, 213 | 05C258B01AB89EF2007DD20C /* Xcode API */, 214 | 05EEA0D81AB80CE9000C8B89 /* Yosemite Bootstrap Compat */, 215 | 05EEA0C31AB7BFEC000C8B89 /* dyld_priv.h */, 216 | 05EEA0A51AB7B354000C8B89 /* Supporting Files */, 217 | ); 218 | path = "xpf-bootstrap"; 219 | sourceTree = ""; 220 | }; 221 | 05EEA08F1AB7AA22000C8B89 /* xpf-bootstrapTests */ = { 222 | isa = PBXGroup; 223 | children = ( 224 | 05EEA0901AB7AA22000C8B89 /* Supporting Files */, 225 | ); 226 | path = "xpf-bootstrapTests"; 227 | sourceTree = ""; 228 | }; 229 | 05EEA0901AB7AA22000C8B89 /* Supporting Files */ = { 230 | isa = PBXGroup; 231 | children = ( 232 | 05EEA0911AB7AA22000C8B89 /* Info.plist */, 233 | ); 234 | name = "Supporting Files"; 235 | sourceTree = ""; 236 | }; 237 | 05EEA0A51AB7B354000C8B89 /* Supporting Files */ = { 238 | isa = PBXGroup; 239 | children = ( 240 | 05EEA0A61AB7B354000C8B89 /* Info.plist */, 241 | ); 242 | name = "Supporting Files"; 243 | sourceTree = ""; 244 | }; 245 | 05EEA0D81AB80CE9000C8B89 /* Yosemite Bootstrap Compat */ = { 246 | isa = PBXGroup; 247 | children = ( 248 | 05EEA0D51AB7F028000C8B89 /* yosemite_objc_stubs.h */, 249 | 05EEA0D41AB7F028000C8B89 /* yosemite_objc_stubs.m */, 250 | 05EEA0D91AB80D1C000C8B89 /* NSVisualEffectView.m */, 251 | ); 252 | name = "Yosemite Bootstrap Compat"; 253 | sourceTree = ""; 254 | }; 255 | /* End PBXGroup section */ 256 | 257 | /* Begin PBXHeadersBuildPhase section */ 258 | 05EEA0A01AB7B354000C8B89 /* Headers */ = { 259 | isa = PBXHeadersBuildPhase; 260 | buildActionMask = 2147483647; 261 | files = ( 262 | 05EEA0C41AB7BFEC000C8B89 /* dyld_priv.h in Headers */, 263 | 05C258B41AB8A667007DD20C /* cfbundle_rebind.h in Headers */, 264 | 05EEA0D71AB7F028000C8B89 /* yosemite_objc_stubs.h in Headers */, 265 | 05EEA0D31AB7EBEB000C8B89 /* rebind_table.h in Headers */, 266 | ); 267 | runOnlyForDeploymentPostprocessing = 0; 268 | }; 269 | /* End PBXHeadersBuildPhase section */ 270 | 271 | /* Begin PBXNativeTarget section */ 272 | 05B026411AB4E14C00F6BF2B /* XcodePostFacto */ = { 273 | isa = PBXNativeTarget; 274 | buildConfigurationList = 05B026491AB4E14C00F6BF2B /* Build configuration list for PBXNativeTarget "XcodePostFacto" */; 275 | buildPhases = ( 276 | 05B0263E1AB4E14C00F6BF2B /* Sources */, 277 | 05B0263F1AB4E14C00F6BF2B /* Frameworks */, 278 | 05B026401AB4E14C00F6BF2B /* Resources */, 279 | 05B026B81AB4EAA600F6BF2B /* Copy Files */, 280 | ); 281 | buildRules = ( 282 | ); 283 | dependencies = ( 284 | ); 285 | name = XcodePostFacto; 286 | productName = XcodePostFacto; 287 | productReference = 05B026421AB4E14C00F6BF2B /* XcodePostFacto.ideplugin */; 288 | productType = "com.apple.product-type.bundle"; 289 | }; 290 | 05EEA08A1AB7AA22000C8B89 /* xpf-bootstrapTests */ = { 291 | isa = PBXNativeTarget; 292 | buildConfigurationList = 05EEA0951AB7AA22000C8B89 /* Build configuration list for PBXNativeTarget "xpf-bootstrapTests" */; 293 | buildPhases = ( 294 | 05EEA0871AB7AA22000C8B89 /* Sources */, 295 | 05EEA0881AB7AA22000C8B89 /* Frameworks */, 296 | 05EEA0891AB7AA22000C8B89 /* Resources */, 297 | ); 298 | buildRules = ( 299 | ); 300 | dependencies = ( 301 | ); 302 | name = "xpf-bootstrapTests"; 303 | productName = "xpf-bootstrapTests"; 304 | productReference = 05EEA08B1AB7AA22000C8B89 /* xpf-bootstrapTests.xctest */; 305 | productType = "com.apple.product-type.bundle.unit-test"; 306 | }; 307 | 05EEA0A21AB7B354000C8B89 /* xpf-bootstrap */ = { 308 | isa = PBXNativeTarget; 309 | buildConfigurationList = 05EEA0B61AB7B354000C8B89 /* Build configuration list for PBXNativeTarget "xpf-bootstrap" */; 310 | buildPhases = ( 311 | 05EEA09E1AB7B354000C8B89 /* Sources */, 312 | 05EEA09F1AB7B354000C8B89 /* Frameworks */, 313 | 05EEA0A01AB7B354000C8B89 /* Headers */, 314 | 05EEA0A11AB7B354000C8B89 /* Resources */, 315 | 05EEA0BE1AB7B3BA000C8B89 /* CopyFiles */, 316 | 05C258AD1AB82013007DD20C /* CopyFiles */, 317 | ); 318 | buildRules = ( 319 | ); 320 | dependencies = ( 321 | 05EEA0C11AB7B3D5000C8B89 /* PBXTargetDependency */, 322 | ); 323 | name = "xpf-bootstrap"; 324 | productName = "xpf-bootstrap"; 325 | productReference = 05EEA0A31AB7B354000C8B89 /* xpf-bootstrap.framework */; 326 | productType = "com.apple.product-type.framework"; 327 | }; 328 | /* End PBXNativeTarget section */ 329 | 330 | /* Begin PBXProject section */ 331 | 05B0263A1AB4E14C00F6BF2B /* Project object */ = { 332 | isa = PBXProject; 333 | attributes = { 334 | LastUpgradeCheck = 0620; 335 | ORGANIZATIONNAME = "Landon Fuller"; 336 | TargetAttributes = { 337 | 05B026411AB4E14C00F6BF2B = { 338 | CreatedOnToolsVersion = 6.2; 339 | }; 340 | 05EEA08A1AB7AA22000C8B89 = { 341 | CreatedOnToolsVersion = 6.2; 342 | }; 343 | 05EEA0A21AB7B354000C8B89 = { 344 | CreatedOnToolsVersion = 6.2; 345 | }; 346 | }; 347 | }; 348 | buildConfigurationList = 05B0263D1AB4E14C00F6BF2B /* Build configuration list for PBXProject "XcodePostFacto" */; 349 | compatibilityVersion = "Xcode 3.2"; 350 | developmentRegion = English; 351 | hasScannedForEncodings = 0; 352 | knownRegions = ( 353 | en, 354 | Base, 355 | ); 356 | mainGroup = 05B026391AB4E14C00F6BF2B; 357 | productRefGroup = 05B026431AB4E14C00F6BF2B /* Products */; 358 | projectDirPath = ""; 359 | projectRoot = ""; 360 | targets = ( 361 | 05B026411AB4E14C00F6BF2B /* XcodePostFacto */, 362 | 05EEA08A1AB7AA22000C8B89 /* xpf-bootstrapTests */, 363 | 05EEA0A21AB7B354000C8B89 /* xpf-bootstrap */, 364 | ); 365 | }; 366 | /* End PBXProject section */ 367 | 368 | /* Begin PBXResourcesBuildPhase section */ 369 | 05B026401AB4E14C00F6BF2B /* Resources */ = { 370 | isa = PBXResourcesBuildPhase; 371 | buildActionMask = 2147483647; 372 | files = ( 373 | 05B0264D1AB4E17500F6BF2B /* XcodePostFacto.xcplugindata in Resources */, 374 | ); 375 | runOnlyForDeploymentPostprocessing = 0; 376 | }; 377 | 05EEA0891AB7AA22000C8B89 /* Resources */ = { 378 | isa = PBXResourcesBuildPhase; 379 | buildActionMask = 2147483647; 380 | files = ( 381 | ); 382 | runOnlyForDeploymentPostprocessing = 0; 383 | }; 384 | 05EEA0A11AB7B354000C8B89 /* Resources */ = { 385 | isa = PBXResourcesBuildPhase; 386 | buildActionMask = 2147483647; 387 | files = ( 388 | ); 389 | runOnlyForDeploymentPostprocessing = 0; 390 | }; 391 | /* End PBXResourcesBuildPhase section */ 392 | 393 | /* Begin PBXSourcesBuildPhase section */ 394 | 05B0263E1AB4E14C00F6BF2B /* Sources */ = { 395 | isa = PBXSourcesBuildPhase; 396 | buildActionMask = 2147483647; 397 | files = ( 398 | 05CD7F911ABA849400169305 /* XPFViewController.m in Sources */, 399 | 05B026BE1AB4F68300F6BF2B /* XcodePostFacto.m in Sources */, 400 | 05B026501AB4E1D000F6BF2B /* XPFDebugMenu.m in Sources */, 401 | ); 402 | runOnlyForDeploymentPostprocessing = 0; 403 | }; 404 | 05EEA0871AB7AA22000C8B89 /* Sources */ = { 405 | isa = PBXSourcesBuildPhase; 406 | buildActionMask = 2147483647; 407 | files = ( 408 | ); 409 | runOnlyForDeploymentPostprocessing = 0; 410 | }; 411 | 05EEA09E1AB7B354000C8B89 /* Sources */ = { 412 | isa = PBXSourcesBuildPhase; 413 | buildActionMask = 2147483647; 414 | files = ( 415 | 05EEA0DA1AB80D1C000C8B89 /* NSVisualEffectView.m in Sources */, 416 | 05EEA0D21AB7EBEB000C8B89 /* rebind_table.cpp in Sources */, 417 | 05C258B31AB8A667007DD20C /* cfbundle_rebind.cpp in Sources */, 418 | 05EEA0BC1AB7B3A6000C8B89 /* xpf_bootstrap.mm in Sources */, 419 | 05EEA0D61AB7F028000C8B89 /* yosemite_objc_stubs.m in Sources */, 420 | ); 421 | runOnlyForDeploymentPostprocessing = 0; 422 | }; 423 | /* End PBXSourcesBuildPhase section */ 424 | 425 | /* Begin PBXTargetDependency section */ 426 | 05EEA0C11AB7B3D5000C8B89 /* PBXTargetDependency */ = { 427 | isa = PBXTargetDependency; 428 | target = 05B026411AB4E14C00F6BF2B /* XcodePostFacto */; 429 | targetProxy = 05EEA0C01AB7B3D5000C8B89 /* PBXContainerItemProxy */; 430 | }; 431 | /* End PBXTargetDependency section */ 432 | 433 | /* Begin XCBuildConfiguration section */ 434 | 05B026471AB4E14C00F6BF2B /* Debug */ = { 435 | isa = XCBuildConfiguration; 436 | buildSettings = { 437 | ALWAYS_SEARCH_USER_PATHS = NO; 438 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 439 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 440 | CLANG_CXX_LIBRARY = "libc++"; 441 | CLANG_ENABLE_MODULES = YES; 442 | CLANG_ENABLE_OBJC_ARC = NO; 443 | CLANG_WARN_BOOL_CONVERSION = YES; 444 | CLANG_WARN_CONSTANT_CONVERSION = YES; 445 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 446 | CLANG_WARN_EMPTY_BODY = YES; 447 | CLANG_WARN_ENUM_CONVERSION = YES; 448 | CLANG_WARN_INT_CONVERSION = YES; 449 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 450 | CLANG_WARN_UNREACHABLE_CODE = YES; 451 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 452 | COPY_PHASE_STRIP = NO; 453 | ENABLE_STRICT_OBJC_MSGSEND = YES; 454 | GCC_C_LANGUAGE_STANDARD = gnu99; 455 | GCC_DYNAMIC_NO_PIC = NO; 456 | GCC_OPTIMIZATION_LEVEL = 0; 457 | GCC_PREPROCESSOR_DEFINITIONS = ( 458 | "DEBUG=1", 459 | "$(inherited)", 460 | ); 461 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 462 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 463 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 464 | GCC_WARN_UNDECLARED_SELECTOR = YES; 465 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 466 | GCC_WARN_UNUSED_FUNCTION = YES; 467 | GCC_WARN_UNUSED_VARIABLE = YES; 468 | MACOSX_DEPLOYMENT_TARGET = 10.9; 469 | MTL_ENABLE_DEBUG_INFO = YES; 470 | SDKROOT = macosx; 471 | WARNING_CFLAGS = ( 472 | "-Wall", 473 | "-Wextra", 474 | "-Werror", 475 | "-Wno-unused-parameter", 476 | "-Wno-undeclared-selector", 477 | ); 478 | }; 479 | name = Debug; 480 | }; 481 | 05B026481AB4E14C00F6BF2B /* Release */ = { 482 | isa = XCBuildConfiguration; 483 | buildSettings = { 484 | ALWAYS_SEARCH_USER_PATHS = NO; 485 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 486 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 487 | CLANG_CXX_LIBRARY = "libc++"; 488 | CLANG_ENABLE_MODULES = YES; 489 | CLANG_ENABLE_OBJC_ARC = NO; 490 | CLANG_WARN_BOOL_CONVERSION = YES; 491 | CLANG_WARN_CONSTANT_CONVERSION = YES; 492 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 493 | CLANG_WARN_EMPTY_BODY = YES; 494 | CLANG_WARN_ENUM_CONVERSION = YES; 495 | CLANG_WARN_INT_CONVERSION = YES; 496 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 497 | CLANG_WARN_UNREACHABLE_CODE = YES; 498 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 499 | COPY_PHASE_STRIP = NO; 500 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 501 | ENABLE_NS_ASSERTIONS = NO; 502 | ENABLE_STRICT_OBJC_MSGSEND = YES; 503 | GCC_C_LANGUAGE_STANDARD = gnu99; 504 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 505 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 506 | GCC_WARN_UNDECLARED_SELECTOR = YES; 507 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 508 | GCC_WARN_UNUSED_FUNCTION = YES; 509 | GCC_WARN_UNUSED_VARIABLE = YES; 510 | MACOSX_DEPLOYMENT_TARGET = 10.9; 511 | MTL_ENABLE_DEBUG_INFO = NO; 512 | SDKROOT = macosx; 513 | WARNING_CFLAGS = ( 514 | "-Wall", 515 | "-Wextra", 516 | "-Werror", 517 | "-Wno-unused-parameter", 518 | "-Wno-undeclared-selector", 519 | ); 520 | }; 521 | name = Release; 522 | }; 523 | 05B0264A1AB4E14C00F6BF2B /* Debug */ = { 524 | isa = XCBuildConfiguration; 525 | buildSettings = { 526 | COMBINE_HIDPI_IMAGES = YES; 527 | FRAMEWORK_SEARCH_PATHS = ( 528 | "$(inherited)", 529 | "$(PROJECT_DIR)/Dependencies", 530 | ); 531 | INFOPLIST_FILE = XcodePostFacto/Info.plist; 532 | INSTALL_PATH = "$(HOME)/Library/Developer/Xcode/Plug-ins"; 533 | LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks @loader_path/../../Frameworks @executable_path/../SharedFrameworks @executable_path/../Frameworks @executable_path/../OtherFrameworks"; 534 | PRODUCT_NAME = "$(TARGET_NAME)"; 535 | SKIP_INSTALL = YES; 536 | WRAPPER_EXTENSION = ideplugin; 537 | }; 538 | name = Debug; 539 | }; 540 | 05B0264B1AB4E14C00F6BF2B /* Release */ = { 541 | isa = XCBuildConfiguration; 542 | buildSettings = { 543 | COMBINE_HIDPI_IMAGES = YES; 544 | FRAMEWORK_SEARCH_PATHS = ( 545 | "$(inherited)", 546 | "$(PROJECT_DIR)/Dependencies", 547 | ); 548 | INFOPLIST_FILE = XcodePostFacto/Info.plist; 549 | INSTALL_PATH = "$(HOME)/Library/Developer/Xcode/Plug-ins"; 550 | LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks @loader_path/../../Frameworks @executable_path/../SharedFrameworks @executable_path/../Frameworks @executable_path/../OtherFrameworks"; 551 | PRODUCT_NAME = "$(TARGET_NAME)"; 552 | SKIP_INSTALL = YES; 553 | WRAPPER_EXTENSION = ideplugin; 554 | }; 555 | name = Release; 556 | }; 557 | 05EEA0961AB7AA22000C8B89 /* Debug */ = { 558 | isa = XCBuildConfiguration; 559 | buildSettings = { 560 | COMBINE_HIDPI_IMAGES = YES; 561 | FRAMEWORK_SEARCH_PATHS = ( 562 | "$(DEVELOPER_FRAMEWORKS_DIR)", 563 | "$(inherited)", 564 | ); 565 | GCC_PREPROCESSOR_DEFINITIONS = ( 566 | "DEBUG=1", 567 | "$(inherited)", 568 | ); 569 | INFOPLIST_FILE = "xpf-bootstrapTests/Info.plist"; 570 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 571 | PRODUCT_NAME = "$(TARGET_NAME)"; 572 | }; 573 | name = Debug; 574 | }; 575 | 05EEA0971AB7AA22000C8B89 /* Release */ = { 576 | isa = XCBuildConfiguration; 577 | buildSettings = { 578 | COMBINE_HIDPI_IMAGES = YES; 579 | FRAMEWORK_SEARCH_PATHS = ( 580 | "$(DEVELOPER_FRAMEWORKS_DIR)", 581 | "$(inherited)", 582 | ); 583 | INFOPLIST_FILE = "xpf-bootstrapTests/Info.plist"; 584 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 585 | PRODUCT_NAME = "$(TARGET_NAME)"; 586 | }; 587 | name = Release; 588 | }; 589 | 05EEA0B71AB7B354000C8B89 /* Debug */ = { 590 | isa = XCBuildConfiguration; 591 | buildSettings = { 592 | COMBINE_HIDPI_IMAGES = YES; 593 | CURRENT_PROJECT_VERSION = 1; 594 | DYLIB_COMPATIBILITY_VERSION = 1; 595 | DYLIB_CURRENT_VERSION = 1; 596 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 597 | FRAMEWORK_SEARCH_PATHS = ( 598 | "$(inherited)", 599 | "$(PROJECT_DIR)/Dependencies", 600 | ); 601 | FRAMEWORK_VERSION = A; 602 | GCC_PREPROCESSOR_DEFINITIONS = ( 603 | "DEBUG=1", 604 | "$(inherited)", 605 | ); 606 | INFOPLIST_FILE = "xpf-bootstrap/Info.plist"; 607 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 608 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 609 | OTHER_LDFLAGS = ( 610 | "$(inherited)", 611 | "-framework", 612 | AppKit, 613 | ); 614 | PRODUCT_NAME = "$(TARGET_NAME)"; 615 | SKIP_INSTALL = YES; 616 | VERSIONING_SYSTEM = "apple-generic"; 617 | VERSION_INFO_PREFIX = ""; 618 | }; 619 | name = Debug; 620 | }; 621 | 05EEA0B81AB7B354000C8B89 /* Release */ = { 622 | isa = XCBuildConfiguration; 623 | buildSettings = { 624 | COMBINE_HIDPI_IMAGES = YES; 625 | CURRENT_PROJECT_VERSION = 1; 626 | DYLIB_COMPATIBILITY_VERSION = 1; 627 | DYLIB_CURRENT_VERSION = 1; 628 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 629 | FRAMEWORK_SEARCH_PATHS = ( 630 | "$(inherited)", 631 | "$(PROJECT_DIR)/Dependencies", 632 | ); 633 | FRAMEWORK_VERSION = A; 634 | INFOPLIST_FILE = "xpf-bootstrap/Info.plist"; 635 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 636 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 637 | OTHER_LDFLAGS = ( 638 | "$(inherited)", 639 | "-framework", 640 | AppKit, 641 | ); 642 | PRODUCT_NAME = "$(TARGET_NAME)"; 643 | SKIP_INSTALL = YES; 644 | VERSIONING_SYSTEM = "apple-generic"; 645 | VERSION_INFO_PREFIX = ""; 646 | }; 647 | name = Release; 648 | }; 649 | /* End XCBuildConfiguration section */ 650 | 651 | /* Begin XCConfigurationList section */ 652 | 05B0263D1AB4E14C00F6BF2B /* Build configuration list for PBXProject "XcodePostFacto" */ = { 653 | isa = XCConfigurationList; 654 | buildConfigurations = ( 655 | 05B026471AB4E14C00F6BF2B /* Debug */, 656 | 05B026481AB4E14C00F6BF2B /* Release */, 657 | ); 658 | defaultConfigurationIsVisible = 0; 659 | defaultConfigurationName = Release; 660 | }; 661 | 05B026491AB4E14C00F6BF2B /* Build configuration list for PBXNativeTarget "XcodePostFacto" */ = { 662 | isa = XCConfigurationList; 663 | buildConfigurations = ( 664 | 05B0264A1AB4E14C00F6BF2B /* Debug */, 665 | 05B0264B1AB4E14C00F6BF2B /* Release */, 666 | ); 667 | defaultConfigurationIsVisible = 0; 668 | defaultConfigurationName = Release; 669 | }; 670 | 05EEA0951AB7AA22000C8B89 /* Build configuration list for PBXNativeTarget "xpf-bootstrapTests" */ = { 671 | isa = XCConfigurationList; 672 | buildConfigurations = ( 673 | 05EEA0961AB7AA22000C8B89 /* Debug */, 674 | 05EEA0971AB7AA22000C8B89 /* Release */, 675 | ); 676 | defaultConfigurationIsVisible = 0; 677 | defaultConfigurationName = Release; 678 | }; 679 | 05EEA0B61AB7B354000C8B89 /* Build configuration list for PBXNativeTarget "xpf-bootstrap" */ = { 680 | isa = XCConfigurationList; 681 | buildConfigurations = ( 682 | 05EEA0B71AB7B354000C8B89 /* Debug */, 683 | 05EEA0B81AB7B354000C8B89 /* Release */, 684 | ); 685 | defaultConfigurationIsVisible = 0; 686 | defaultConfigurationName = Release; 687 | }; 688 | /* End XCConfigurationList section */ 689 | }; 690 | rootObject = 05B0263A1AB4E14C00F6BF2B /* Project object */; 691 | } 692 | -------------------------------------------------------------------------------- /XcodePostFacto/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.landonf.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | NSHumanReadableCopyright 24 | Copyright © 2015 Landon Fuller. All rights reserved. 25 | NSPrincipalClass 26 | XcodePostFacto 27 | DTXcode 28 | 0630 29 | DVTPlugInCompatibilityUUIDs 30 | 31 | 992275C1-432A-4CF7-B659-D84ED6D42D3F 32 | 9F75337B-21B4-4ADC-B558-F9CADF7073A7 33 | E969541F-E6F9-4D25-8158-72DC3545A6C6 34 | 8DC44374-2B35-4C57-A6FE-2AD66A36AAD9 35 | 36 | DVTPlugInHostRequirements 37 | 38 | foundation 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /XcodePostFacto/XPFDebugMenu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller 5 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 6 | * All rights reserved. 7 | * 8 | * Permission is hereby granted, free of charge, to any person 9 | * obtaining a copy of this software and associated documentation 10 | * files (the "Software"), to deal in the Software without 11 | * restriction, including without limitation the rights to use, 12 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the 14 | * Software is furnished to do so, subject to the following 15 | * conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | * OTHER DEALINGS IN THE SOFTWARE. 28 | */ 29 | 30 | #import 31 | 32 | @interface XPFDebugMenu : NSObject 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /XcodePostFacto/XPFDebugMenu.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller 5 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 6 | * All rights reserved. 7 | * 8 | * Permission is hereby granted, free of charge, to any person 9 | * obtaining a copy of this software and associated documentation 10 | * files (the "Software"), to deal in the Software without 11 | * restriction, including without limitation the rights to use, 12 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the 14 | * Software is furnished to do so, subject to the following 15 | * conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | * OTHER DEALINGS IN THE SOFTWARE. 28 | */ 29 | 30 | #import "XPFDebugMenu.h" 31 | #import "XPFLog.h" 32 | 33 | 34 | @implementation XPFDebugMenu { 35 | @private 36 | } 37 | 38 | /** 39 | * Return the shared handler instance; this global variable is necessitated by Xcode's 40 | * use of a class method when resolving menu handlers. 41 | */ 42 | + (instancetype) sharedHandler { 43 | static XPFDebugMenu *sharedHandler; 44 | static dispatch_once_t onceToken; 45 | dispatch_once(&onceToken, ^{ 46 | sharedHandler = [[self alloc] init]; 47 | }); 48 | 49 | return sharedHandler; 50 | } 51 | 52 | /** 53 | * Initialize a new instance. 54 | */ 55 | - (instancetype) init { 56 | if ((self = [super init]) == nil) 57 | return nil; 58 | 59 | return self; 60 | } 61 | 62 | // Returns the handler for a given action. This seemingly should already be available via 63 | // the entries 'action' value; we need to spend some time reverse engineering the menu configuration 64 | // options and how actions are mapped. 65 | + (id) handlerForAction: (SEL) action withSelectionSource: (id) src { 66 | return [self sharedHandler]; 67 | } 68 | 69 | // XcodePostFacto.CmdHandler.ViewAnalyzerMenuEntry handler. 70 | - (void) enableViewAnalyzer: (id) sender { 71 | // TODO -- pending F-Script integration 72 | 73 | #if 0 74 | /* Fire up the analyzer window */ 75 | if (_analyzerWindowController == nil) 76 | _analyzerWindowController = [[EXViewAnalyzerWindowController alloc] init]; 77 | [_analyzerWindowController showWindow: nil]; 78 | 79 | /* 80 | * F-Script compatibility patches 81 | * 82 | * Xcode's IDEInterfaceBuilderCocoaTouchIntegration includes an NSObject category that registers 83 | * an assortment of ib-related methods for abstract methods, and then triggers non-exception-based 84 | * abort() when they are called. This triggers a crash when F-Script introspects defined object 85 | * properties. This ugly hack works around the issue; we can re-evaluate this in favor for a more 86 | * surgical approach at later date. 87 | * 88 | * The IDEInterfaceBuilderCocoaTouchIntegration plugin may be loaded after our class, so we register 89 | * a future patch. 90 | */ 91 | static dispatch_once_t onceToken; 92 | dispatch_once(&onceToken, ^{ 93 | [NSObject ex_patchFutureSelector: @selector(ibExternalLastKnownCanvasFrameOrigin) withReplacementBlock: ^(EXPatchIMP *patch) { return NSZeroPoint; }]; 94 | [NSObject ex_patchInstanceSelector: @selector(ibExternalLastKnownCanvasFrameOrigin) withReplacementBlock: ^(EXPatchIMP *patch) { return NSZeroPoint; }]; 95 | }); 96 | #endif 97 | } 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /XcodePostFacto/XPFLog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #ifdef __OBJC__ 30 | 31 | #import 32 | #define XPFLog(fmt, ...) NSLog(@"[XcodePostFacto] %@", [NSString stringWithFormat: fmt, ##__VA_ARGS__]) 33 | #else 34 | 35 | #import 36 | #define XPFLog(fmt, ...) fprintf(stderr, "[XcodePostFacto] " fmt "\n", ##__VA_ARGS__) 37 | 38 | #endif -------------------------------------------------------------------------------- /XcodePostFacto/XPFViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller 5 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 6 | * All rights reserved. 7 | * 8 | * Permission is hereby granted, free of charge, to any person 9 | * obtaining a copy of this software and associated documentation 10 | * files (the "Software"), to deal in the Software without 11 | * restriction, including without limitation the rights to use, 12 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the 14 | * Software is furnished to do so, subject to the following 15 | * conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | * OTHER DEALINGS IN THE SOFTWARE. 28 | */ 29 | 30 | #import 31 | #import 32 | 33 | /* Implements enough of the 10.10 ViewController API additions to allow execution */ 34 | 35 | // TODO - We're going to need more than viewDidLoad :-) 36 | 37 | @interface NSViewController (XPFYosemite) 38 | @end 39 | @implementation NSViewController (XPFYosemite) 40 | 41 | /* We're intentionally implementing methods that *would* be implemented in 10.10 */ 42 | #pragma clang diagnostic push 43 | #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation" 44 | - (void) viewDidLoad {} 45 | - (void) viewWillAppear {} 46 | - (void) viewDidAppear {} 47 | #pragma clang diagnostic pop 48 | 49 | + (void) load { 50 | /* On 10.10, a nil nibName attempts to load a nib matching the class name. We emulate that by supplying 51 | * a non-nil nibName. */ 52 | [NSViewController pl_patchInstanceSelector: @selector(nibName) withReplacementBlock: ^(PLPatchIMP *patch) { 53 | NSViewController *self = PLPatchGetSelf(patch); 54 | 55 | NSString *nibName = PLPatchIMPFoward(patch, NSString *(*)(id, SEL)); 56 | if (nibName != nil) 57 | return nibName; 58 | 59 | return NSStringFromClass([self class]); 60 | }]; 61 | 62 | /* Inject view lifetime cycle management */ 63 | [NSViewController pl_patchInstanceSelector: @selector(setView:) withReplacementBlock: ^(PLPatchIMP *patch, NSView *view) { 64 | NSViewController *self = PLPatchGetSelf(patch); 65 | 66 | PLPatchIMPFoward(patch, void (*)(id, SEL, NSView *), view); 67 | [self viewDidLoad]; 68 | // TODO - We should probably trigger this in a smarter way 69 | [self viewWillAppear]; 70 | [self viewDidAppear]; 71 | }]; 72 | } 73 | 74 | 75 | @end -------------------------------------------------------------------------------- /XcodePostFacto/XcodePostFacto.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller 5 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 6 | * All rights reserved. 7 | * 8 | * Permission is hereby granted, free of charge, to any person 9 | * obtaining a copy of this software and associated documentation 10 | * files (the "Software"), to deal in the Software without 11 | * restriction, including without limitation the rights to use, 12 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the 14 | * Software is furnished to do so, subject to the following 15 | * conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | * OTHER DEALINGS IN THE SOFTWARE. 28 | */ 29 | 30 | #import 31 | 32 | /* Defined by IDEFoundation */ 33 | @protocol IDEInitialization 34 | + (BOOL) ide_initializeWithOptions: (int) flags error: (NSError **) arg2; 35 | @end 36 | 37 | @interface XcodePostFacto : NSObject 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /XcodePostFacto/XcodePostFacto.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller 5 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 6 | * All rights reserved. 7 | * 8 | * Permission is hereby granted, free of charge, to any person 9 | * obtaining a copy of this software and associated documentation 10 | * files (the "Software"), to deal in the Software without 11 | * restriction, including without limitation the rights to use, 12 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the 14 | * Software is furnished to do so, subject to the following 15 | * conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | * OTHER DEALINGS IN THE SOFTWARE. 28 | */ 29 | 30 | #import 31 | #import 32 | 33 | #import "XcodePostFacto.h" 34 | #import "XPFLog.h" 35 | #import 36 | 37 | /* Replacement frameworks bundled with Xcode that are required for Mavericks */ 38 | static NSString *sharedFrameworks[] = { 39 | @"SceneKit.framework", 40 | @"PhysicsKit.framework", 41 | @"SpriteKit.framework" 42 | }; 43 | 44 | /* Replacement for LSCopyDefaultApplicationURLForURL */ 45 | static CFURLRef xpf_LSCopyDefaultApplicationURLForURL (CFURLRef inURL, LSRolesMask inRoleMask, CFErrorRef *outError) { 46 | FSRef inRef; 47 | 48 | #pragma clang diagnostic push 49 | #pragma clang diagnostic ignored "-Wdeprecated" 50 | /* CFURLGetFSRef() was deprecated in 10.9, but it's unclear what we're supposed to use instead */ 51 | if (!CFURLGetFSRef(inURL, &inRef)) { 52 | if (outError != NULL) 53 | *outError = (__bridge CFErrorRef)([NSError errorWithDomain: NSCocoaErrorDomain code: NSFileNoSuchFileError userInfo: nil]); 54 | return NULL; 55 | } 56 | #pragma clang diagnostic pop 57 | 58 | CFURLRef appURL; 59 | OSStatus err = LSGetApplicationForItem(&inRef, inRoleMask, NULL, &appURL); 60 | if (err != noErr) { 61 | if (outError != NULL) 62 | *outError = (__bridge CFErrorRef)([NSError errorWithDomain: NSOSStatusErrorDomain code: err userInfo: nil]); 63 | return NULL; 64 | } 65 | 66 | return appURL; 67 | } 68 | 69 | @implementation XcodePostFacto 70 | 71 | // from IDEInitialization protocol 72 | + (BOOL) ide_initializeWithOptions: (int) flags error: (NSError **) arg2 { 73 | NSError *error; 74 | 75 | /* Since we pretend to be 10.10, we have to implement shared framework loading ourselves. 76 | * This is normally done in IDEFoundation:__IDEInitializeLoadSharedFrameworksFor10_9 */ 77 | XPFLog(@"Initializing Mavericks shared frameworks"); 78 | for (size_t i = 0; i < sizeof(sharedFrameworks) / sizeof(sharedFrameworks[0]); i++) { 79 | NSString *framework = sharedFrameworks[i]; 80 | NSString *path = [[[NSBundle bundleWithIdentifier: @"com.apple.dt.Xcode"] sharedFrameworksPath] stringByAppendingPathComponent: framework]; 81 | NSBundle *bundle = [NSBundle bundleWithPath: path]; 82 | 83 | if (bundle) { 84 | if (!([bundle loadAndReturnError: &error])) { 85 | XPFLog(@"Failed to load %@: %@", framework, error); 86 | } 87 | } else { 88 | XPFLog(@"Framework %@ not found", framework); 89 | } 90 | } 91 | 92 | /* Likewise, we need to disable IB stand-in for which runtime classes are not available on Mavericks. */ 93 | [[PLPatchMaster master] patchInstancesWithFutureClassName: @"IBCocoaPlatform" selector: @selector(standinIBNSClasses) replacementBlock: ^(PLPatchIMP *imp) { 94 | /* Fetch the default set */ 95 | NSSet *standInClasses = PLPatchIMPFoward(imp, NSSet *(*)(id, SEL)); 96 | 97 | /* Clear out unsupported classes */ 98 | NSMutableSet *result = [NSMutableSet set]; 99 | for (Class cls in standInClasses) { 100 | NSString *className = NSStringFromClass(cls); 101 | assert([className hasPrefix: @"IB"]); 102 | NSString *runtimeClassName = [className substringFromIndex: 2]; 103 | 104 | if (NSClassFromString(runtimeClassName)) { 105 | [result addObject: cls]; 106 | } else { 107 | XPFLog(@"Disabling IB stand-in class %@ (can't find runtime class)", className); 108 | } 109 | } 110 | 111 | return result; 112 | }]; 113 | 114 | /* Swap in our compatibility shims */ 115 | [[PLPatchMaster master] rebindSymbol: @"_LSCopyDefaultApplicationURLForURL" fromImage: @"CoreServices" replacementAddress: (uintptr_t) &xpf_LSCopyDefaultApplicationURLForURL]; 116 | 117 | return YES; 118 | } 119 | 120 | #if 0 121 | 122 | /** 123 | * Return the default plugin instance. 124 | */ 125 | + (instancetype) defaultPlugin { 126 | static XcodePostFactoPlugin *defaultInstance; 127 | static dispatch_once_t onceToken; 128 | dispatch_once(&onceToken, ^{ 129 | defaultInstance = [[self alloc] init]; 130 | }); 131 | 132 | return defaultInstance; 133 | } 134 | 135 | #endif 136 | 137 | @end 138 | -------------------------------------------------------------------------------- /XcodePostFacto/XcodePostFacto.xcplugindata: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | version 6 | 7 | compiler-build 8 | 3524 9 | file-format 10 | 1 11 | 12 | plug-in 13 | 14 | extensions 15 | 16 | XcodePostFacto.Xcode.Initializer 17 | 18 | id 19 | Xcode.XcodePostFacto.Initializer 20 | initializationClass 21 | XcodePostFacto 22 | name 23 | XcodePostFacto Initializer 24 | point 25 | Xcode.IDEFoundation.IDEInitialization 26 | version 27 | 0.1 28 | 29 | XcodePostFacto.CmdHandler.ViewAnalyzerMenuEntry 30 | 31 | handlerClass 32 | XPFDebugMenu 33 | id 34 | XcodePostFacto.CmdHandler.ViewAnalyzerMenuEntry 35 | cmdDefinition 36 | XcodePostFacto.CmdDefinition.ViewAnalyzerMenuEntry 37 | name 38 | Show View Analyzer Command Handler 39 | point 40 | Xcode.IDEKit.CmdHandler 41 | version 42 | 0.1 43 | 44 | XcodePostFacto.DebugMenuItemDefinition.ViewAnalyzerMenuEntry 45 | 46 | name 47 | View Analyzer Menu Item 48 | id 49 | XcodePostFacto.DebugMenuItemDefinition.ViewAnalyzerMenuEntry 50 | commandIdentifier 51 | XcodePostFacto.CmdDefinition.ViewAnalyzerMenuEntry 52 | type 53 | command 54 | point 55 | Xcode.IDEKit.InternalMenuItemDefinition 56 | version 57 | 0.1 58 | 59 | XcodePostFacto.CmdDefinition.ViewAnalyzerMenuEntry 60 | 61 | action 62 | enableViewAnalyzer: 63 | id 64 | XcodePostFacto.CmdDefinition.ViewAnalyzerMenuEntry 65 | point 66 | Xcode.IDEKit.CmdDefinition 67 | title 68 | Show View Analyzer 69 | menuItem 70 | 71 | version 72 | 0.1 73 | name 74 | Show View Analyzer 75 | 76 | 77 | extension-points 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /xpf-bootstrap/DVTPlugInManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | // Generated with class-dump 30 | 31 | @class DVTPlugInLocator; 32 | @interface DVTPlugInManager : NSObject 33 | 34 | + (void)_setDefaultPlugInManager:(id)arg1; 35 | + (BOOL)enumerateExtensionDataForPluginAtPath:(id)arg1 error:(id *)arg2 withBlock:(id /* unknown block type */)arg3; 36 | + (id)defaultPlugInManager; 37 | + (void)initialize; 38 | @property(retain) DVTPlugInLocator *plugInLocator; // @synthesize plugInLocator=_plugInLocator; 39 | @property BOOL shouldClearPlugInCaches; // @synthesize shouldClearPlugInCaches=_shouldClearPlugInCaches; 40 | - (id)_invalidExtensionWithIdentifier:(id)arg1; 41 | - (id)_plugInCachePath; 42 | - (id)_applicationCachesPath; 43 | - (id)_toolsVersionName; 44 | - (void)_createPlugInObjectsFromCache; 45 | - (BOOL)_savePlugInCacheWithScanRecords:(id)arg1 error:(id *)arg2; 46 | - (BOOL)_removePlugInCacheAndReturnError:(id *)arg1; 47 | - (BOOL)_removePlugInCacheAtPath:(id)arg1 error:(id *)arg2; 48 | - (id)_plugInCacheSaveFailedErrorWithUnderlyingError:(id)arg1; 49 | - (BOOL)_loadPlugInCache:(id *)arg1; 50 | - (BOOL)_cacheCoversPlugInsWithScanRecords:(id)arg1; 51 | - (id)_modificationDateOfFileAtPath:(id)arg1; 52 | @property(readonly) BOOL usePlugInCache; 53 | - (void)_preLoadPlugIns; 54 | - (BOOL)_checkPresenceOfRequiredPlugIns:(id)arg1 error:(id *)arg2; 55 | - (BOOL)shouldPerformConsistencyCheck; 56 | - (void)_registerPlugInsFromScanRecords:(id)arg1; 57 | - (void)_pruneUnusablePlugInsAndScanRecords:(id)arg1; 58 | - (id)_plugInsToIgnore; 59 | - (void)_recordSanitizedPluginStatus:(id)arg1 errorMessage:(id)arg2; 60 | - (void)_addSanitizedNonApplePlugInStatusForBundle:(id)arg1 reason:(id)arg2; 61 | @property(readonly) NSSet *sanitizedNonApplePlugInStatuses; 62 | - (void)_createPlugInObjectsFromScanRecords:(id)arg1; 63 | - (void)_applyActivationRulesToScanRecords:(id)arg1; 64 | - (id)_scanForPlugInsInDirectories:(id)arg1 skippingDuplicatesOfPlugIns:(id)arg2; 65 | - (BOOL)_scanForPlugIns:(id *)arg1; 66 | @property(readonly, copy) NSUUID *plugInHostUUID; 67 | @property BOOL hasScannedForPlugIns; // @dynamic hasScannedForPlugIns; 68 | - (id)_scanRecordForBundle:(id)arg1 atPath:(id)arg2; 69 | - (BOOL)_isInitialScan; 70 | - (id)_defaultPathExtensions; 71 | @property(readonly, copy) NSArray *defaultSearchPaths; 72 | - (id)_defaultApplicationSupportSubdirectory; 73 | @property(readonly, copy) NSArray *extraSearchPaths; 74 | - (id)_extensionsForExtensionPoint:(id)arg1 matchingPredicate:(id)arg2; 75 | - (id)sharedExtensionsForExtensionPoint:(id)arg1 matchingPredicate:(id)arg2; 76 | - (id)sharedExtensionWithIdentifier:(id)arg1; 77 | - (id)extensionWithIdentifier:(id)arg1; 78 | - (id)extensionPointWithIdentifier:(id)arg1; 79 | - (id)plugInWithIdentifier:(id)arg1; 80 | - (BOOL)scanForPlugIns:(id *)arg1; 81 | - (id)init; 82 | - (id)_hostAppName; 83 | - (id)_hostAppContainingPath; 84 | 85 | // Remaining properties 86 | @property(copy) NSSet *defaultPlugInCapabilities; // @dynamic defaultPlugInCapabilities; 87 | @property(copy) NSSet *exposedCapabilities; // @dynamic exposedCapabilities; 88 | @property(readonly) NSMutableSet *mutableDefaultPlugInCapabilities; // @dynamic mutableDefaultPlugInCapabilities; 89 | @property(readonly) NSMutableSet *mutableExposedCapabilities; // @dynamic mutableExposedCapabilities; 90 | @property(readonly) NSMutableSet *mutablePathExtensions; // @dynamic mutablePathExtensions; 91 | @property(readonly) NSMutableSet *mutableRequiredPlugInIdentifiers; // @dynamic mutableRequiredPlugInIdentifiers; 92 | @property(readonly) NSMutableArray *mutableSearchPaths; // @dynamic mutableSearchPaths; 93 | @property(copy) NSSet *pathExtensions; // @dynamic pathExtensions; 94 | @property(copy) NSSet *requiredPlugInIdentifiers; // @dynamic requiredPlugInIdentifiers; 95 | @property(copy) NSArray *searchPaths; // @dynamic searchPaths; 96 | 97 | @end -------------------------------------------------------------------------------- /xpf-bootstrap/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.landonf.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSHumanReadableCopyright 24 | Copyright © 2015 Landon Fuller. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /xpf-bootstrap/NSVisualEffectView.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #import 30 | 31 | @interface XPF_NSVisualEffectView : NSView { 32 | NSUInteger _material; 33 | NSUInteger _interiorBackgroundStyle; 34 | NSInteger _blendingMode; 35 | NSInteger _state; 36 | NSImage *_maskImage; 37 | } 38 | @property NSUInteger material; 39 | @property NSUInteger interiorBackgroundStyle; 40 | @property NSInteger blendingMode; 41 | @property NSInteger state; 42 | @property(retain) NSImage *maskImage; 43 | @end 44 | 45 | @implementation XPF_NSVisualEffectView 46 | 47 | @synthesize material = _material; 48 | @synthesize interiorBackgroundStyle = _interiorBackgroundStyle; 49 | @synthesize blendingMode = _blendingMode; 50 | @synthesize state = _state; 51 | @synthesize maskImage = _maskImage; 52 | 53 | @end -------------------------------------------------------------------------------- /xpf-bootstrap/cfbundle_rebind.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include "cfbundle_rebind.h" 30 | #import "rebind_table.h" 31 | 32 | namespace xpf { 33 | 34 | /* 35 | * HIServices checks for a LSMinimumSystemVersion in the application bundle, and 36 | * if out-of-range for the host, helpfully aborts. 37 | * 38 | * We patch out the relevant CFBundle* APIs here, rewriting the LSMinimumSystemVersion 39 | * to 10.9. 40 | */ 41 | static CFStringRef kLSMinimumSystemVersionKey = CFSTR("LSMinimumSystemVersion"); 42 | static CFStringRef kSupportedSystemVersion = CFSTR("10.9"); 43 | 44 | /** 45 | * Return a representation of @a infoDictionary where kLSMinimumSystemVersionKey, if set, has 46 | * been patched to be equal to 10.9. 47 | */ 48 | static CFDictionaryRef xpf_patch_info_dictionary (CFDictionaryRef info) { 49 | if (!CFDictionaryContainsKey(info, kLSMinimumSystemVersionKey)) 50 | return info; 51 | 52 | CFMutableDictionaryRef patched = CFDictionaryCreateMutableCopy(nullptr, 0, info); 53 | CFDictionarySetValue(patched, kLSMinimumSystemVersionKey, kSupportedSystemVersion); 54 | CFAutorelease(patched); 55 | 56 | return patched; 57 | } 58 | 59 | /* Patch CFBundleGetValueForInfoDictionaryKey() */ 60 | static CFTypeRef (*orig_CFBundleGetValueForInfoDictionaryKey) (CFBundleRef bundle, CFStringRef key); 61 | static CFTypeRef xpf_CFBundleGetValueForInfoDictionaryKey (CFBundleRef bundle, CFStringRef key) { 62 | if (!CFEqual(key, kLSMinimumSystemVersionKey)) 63 | return orig_CFBundleGetValueForInfoDictionaryKey(bundle, key); 64 | 65 | return kSupportedSystemVersion; 66 | } 67 | XPF_REBIND_ENTRY("_CFBundleGetValueForInfoDictionaryKey", "CoreFoundation", (void **) &orig_CFBundleGetValueForInfoDictionaryKey, (uintptr_t) &xpf_CFBundleGetValueForInfoDictionaryKey); 68 | 69 | /* Patch CFBundleGetInfoDictionary() */ 70 | static CFDictionaryRef (*orig_CFBundleGetInfoDictionary) (CFBundleRef bundle); 71 | static CFDictionaryRef xpf_CFBundleGetInfoDictionary (CFBundleRef bundle) { 72 | return xpf_patch_info_dictionary(orig_CFBundleGetInfoDictionary(bundle)); 73 | } 74 | XPF_REBIND_ENTRY("_CFBundleGetInfoDictionary", "CoreFoundation", (void **) &orig_CFBundleGetInfoDictionary, (uintptr_t) &xpf_CFBundleGetInfoDictionary); 75 | 76 | /* Patch CFBundleGetLocalInfoDictionary() */ 77 | static CFDictionaryRef (*orig_CFBundleGetLocalInfoDictionary)(CFBundleRef bundle); 78 | static CFDictionaryRef xpf_CFBundleGetLocalInfoDictionary (CFBundleRef bundle) { 79 | return xpf_patch_info_dictionary(orig_CFBundleGetInfoDictionary(bundle)); 80 | } 81 | XPF_REBIND_ENTRY("_CFBundleGetLocalInfoDictionary", "CoreFoundation", (void **) &orig_CFBundleGetLocalInfoDictionary, (uintptr_t) &xpf_CFBundleGetLocalInfoDictionary); 82 | 83 | } -------------------------------------------------------------------------------- /xpf-bootstrap/cfbundle_rebind.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #import 30 | 31 | -------------------------------------------------------------------------------- /xpf-bootstrap/dyld_priv.h: -------------------------------------------------------------------------------- 1 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 2 | * 3 | * Copyright (c) 2003-2010 Apple Inc. All rights reserved. 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | #ifndef _MACH_O_DYLD_PRIV_H_ 25 | #define _MACH_O_DYLD_PRIV_H_ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #if __cplusplus 33 | extern "C" { 34 | #endif /* __cplusplus */ 35 | 36 | 37 | 38 | // 39 | // private interface between libSystem.dylib and dyld 40 | // 41 | extern int _dyld_func_lookup(const char* dyld_func_name, void **address); 42 | 43 | // 44 | // private interface between libSystem.dylib and dyld 45 | // 46 | extern void _dyld_fork_child(); 47 | 48 | 49 | // 50 | // Possible state changes for which you can register to be notified 51 | // 52 | enum dyld_image_states 53 | { 54 | dyld_image_state_mapped = 10, // No batch notification for this 55 | dyld_image_state_dependents_mapped = 20, // Only batch notification for this 56 | dyld_image_state_rebased = 30, 57 | dyld_image_state_bound = 40, 58 | dyld_image_state_dependents_initialized = 45, // Only single notification for this 59 | dyld_image_state_initialized = 50, 60 | dyld_image_state_terminated = 60 // Only single notification for this 61 | }; 62 | 63 | // 64 | // Callback that provides a bottom-up array of images 65 | // For dyld_image_state_[dependents_]mapped state only, returning non-NULL will cause dyld to abort loading all those images 66 | // and append the returned string to its load failure error message. dyld does not free the string, so 67 | // it should be a literal string or a static buffer 68 | // 69 | typedef const char* (*dyld_image_state_change_handler)(enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info info[]); 70 | 71 | // 72 | // Register a handler to be called when any image changes to the requested state. 73 | // If 'batch' is true, the callback is called with an array of all images that are in the requested state sorted by dependency. 74 | // If 'batch' is false, the callback is called with one image at a time as each image transitions to the the requested state. 75 | // During the call to this function, the handler may be called back with existing images and the handler should 76 | // not return a string, since there is no load to abort. In batch mode, existing images at or past the request 77 | // state supplied in the callback. In non-batch mode, the callback is called for each image exactly in the 78 | // requested state. 79 | // 80 | extern void 81 | dyld_register_image_state_change_handler(enum dyld_image_states state, bool batch, dyld_image_state_change_handler handler); 82 | 83 | 84 | // 85 | // Possible thread-local variable state changes for which you can register to be notified 86 | // 87 | enum dyld_tlv_states { 88 | dyld_tlv_state_allocated = 10, // TLV range newly allocated 89 | dyld_tlv_state_deallocated = 20 // TLV range about to be deallocated 90 | }; 91 | 92 | // 93 | // Info about thread-local variable storage. 94 | // 95 | typedef struct { 96 | size_t info_size; // sizeof(dyld_tlv_info) 97 | void * tlv_addr; // Base address of TLV storage 98 | size_t tlv_size; // Byte size of TLV storage 99 | } dyld_tlv_info; 100 | 101 | #if __BLOCKS__ 102 | 103 | // 104 | // Callback that notes changes to thread-local variable storage. 105 | // 106 | typedef void (^dyld_tlv_state_change_handler)(enum dyld_tlv_states state, const dyld_tlv_info *info); 107 | 108 | // 109 | // Register a handler to be called when a thread adds or removes storage for thread-local variables. 110 | // The registered handler will only be called from and on behalf of the thread that owns the storage. 111 | // The registered handler will NOT be called for any storage that was 112 | // already allocated before dyld_register_tlv_state_change_handler() was 113 | // called. Use dyld_enumerate_tlv_storage() to get that information. 114 | // Exists in Mac OS X 10.7 and later 115 | // 116 | extern void 117 | dyld_register_tlv_state_change_handler(enum dyld_tlv_states state, dyld_tlv_state_change_handler handler); 118 | 119 | // 120 | // Enumerate the current thread-local variable storage allocated for the current thread. 121 | // Exists in Mac OS X 10.7 and later 122 | // 123 | extern void 124 | dyld_enumerate_tlv_storage(dyld_tlv_state_change_handler handler); 125 | 126 | #endif 127 | 128 | 129 | // 130 | // get slide for a given loaded mach_header 131 | // Mac OS X 10.6 and later 132 | // 133 | extern intptr_t _dyld_get_image_slide(const struct mach_header* mh); 134 | 135 | 136 | // 137 | // get pointer to this process's dyld_all_image_infos 138 | // Exists in Mac OS X 10.4 and later through _dyld_func_lookup() 139 | // Exists in Mac OS X 10.6 and later through libSystem.dylib 140 | // 141 | const struct dyld_all_image_infos* _dyld_get_all_image_infos(); 142 | 143 | 144 | 145 | struct dyld_unwind_sections 146 | { 147 | const struct mach_header* mh; 148 | const void* dwarf_section; 149 | uintptr_t dwarf_section_length; 150 | const void* compact_unwind_section; 151 | uintptr_t compact_unwind_section_length; 152 | }; 153 | 154 | 155 | // 156 | // Returns true iff some loaded mach-o image contains "addr". 157 | // info->mh mach header of image containing addr 158 | // info->dwarf_section pointer to start of __TEXT/__eh_frame section 159 | // info->dwarf_section_length length of __TEXT/__eh_frame section 160 | // info->compact_unwind_section pointer to start of __TEXT/__unwind_info section 161 | // info->compact_unwind_section_length length of __TEXT/__unwind_info section 162 | // 163 | // Exists in Mac OS X 10.6 and later 164 | extern bool _dyld_find_unwind_sections(void* addr, struct dyld_unwind_sections* info); 165 | 166 | 167 | // 168 | // This is an optimized form of dladdr() that only returns the dli_fname field. 169 | // 170 | // Exists in Mac OS X 10.6 and later 171 | extern const char* dyld_image_path_containing_address(const void* addr); 172 | 173 | 174 | 175 | // Convienence constants for return values from dyld_get_sdk_version() and friends. 176 | #define DYLD_MACOSX_VERSION_10_4 0x000A0400 177 | #define DYLD_MACOSX_VERSION_10_5 0x000A0500 178 | #define DYLD_MACOSX_VERSION_10_6 0x000A0600 179 | #define DYLD_MACOSX_VERSION_10_7 0x000A0700 180 | #define DYLD_MACOSX_VERSION_10_8 0x000A0800 181 | #define DYLD_MACOSX_VERSION_10_9 0x000A0900 182 | #define DYLD_MACOSX_VERSION_10_10 0x000A0A00 183 | 184 | #define DYLD_IOS_VERSION_2_0 0x00020000 185 | #define DYLD_IOS_VERSION_2_1 0x00020100 186 | #define DYLD_IOS_VERSION_2_2 0x00020200 187 | #define DYLD_IOS_VERSION_3_0 0x00030000 188 | #define DYLD_IOS_VERSION_3_1 0x00030100 189 | #define DYLD_IOS_VERSION_3_2 0x00030200 190 | #define DYLD_IOS_VERSION_4_0 0x00040000 191 | #define DYLD_IOS_VERSION_4_1 0x00040100 192 | #define DYLD_IOS_VERSION_4_2 0x00040200 193 | #define DYLD_IOS_VERSION_4_3 0x00040300 194 | #define DYLD_IOS_VERSION_5_0 0x00050000 195 | #define DYLD_IOS_VERSION_5_1 0x00050100 196 | #define DYLD_IOS_VERSION_6_0 0x00060000 197 | #define DYLD_IOS_VERSION_6_1 0x00060100 198 | #define DYLD_IOS_VERSION_7_0 0x00070000 199 | #define DYLD_IOS_VERSION_7_1 0x00070100 200 | #define DYLD_IOS_VERSION_8_0 0x00080000 201 | 202 | // 203 | // This is finds the SDK version a binary was built against. 204 | // Returns zero on error, or if SDK version could not be determined. 205 | // 206 | // Exists in Mac OS X 10.8 and later 207 | // Exists in iOS 6.0 and later 208 | extern uint32_t dyld_get_sdk_version(const struct mach_header* mh); 209 | 210 | 211 | // 212 | // This is finds the SDK version the main executable was built against. 213 | // Returns zero on error, or if SDK version could not be determined. 214 | // 215 | // Exists in Mac OS X 10.8 and later 216 | // Exists in iOS 6.0 and later 217 | extern uint32_t dyld_get_program_sdk_version(); 218 | 219 | 220 | // 221 | // This is finds the min OS version a binary was built to run on. 222 | // Returns zero on error, or if no min OS recorded in binary. 223 | // 224 | // Exists in Mac OS X 10.8 and later 225 | // Exists in iOS 6.0 and later 226 | extern uint32_t dyld_get_min_os_version(const struct mach_header* mh); 227 | 228 | 229 | // 230 | // This is finds the min OS version the main executable was built to run on. 231 | // Returns zero on error, or if no min OS recorded in binary. 232 | // 233 | // Exists in Mac OS X 10.8 and later 234 | // Exists in iOS 6.0 and later 235 | extern uint32_t dyld_get_program_min_os_version(); 236 | 237 | 238 | 239 | 240 | // 241 | // Returns if any OS dylib has overridden its copy in the shared cache 242 | // 243 | // Exists in iPhoneOS 3.1 and later 244 | // Exists in Mac OS X 10.10 and later 245 | extern bool dyld_shared_cache_some_image_overridden(); 246 | 247 | 248 | 249 | // 250 | // Returns if the process is setuid or is code signed with entitlements. 251 | // 252 | // Exists in Mac OS X 10.9 and later 253 | extern bool dyld_process_is_restricted(); 254 | 255 | 256 | // 257 | // for OpenGL to tell dyld it is ok to deallocate a memory based image when done. 258 | // 259 | // Exists in Mac OS X 10.9 and later 260 | #define NSLINKMODULE_OPTION_CAN_UNLOAD 0x20 261 | 262 | 263 | // 264 | // Update all bindings on specified image. 265 | // Looks for uses of 'replacement' and changes it to 'replacee'. 266 | // NOTE: this is less safe than using static interposing via DYLD_INSERT_LIBRARIES 267 | // because the running program may have already copy the pointer values to other 268 | // locations that dyld does not know about. 269 | // 270 | struct dyld_interpose_tuple { 271 | const void* replacement; 272 | const void* replacee; 273 | }; 274 | extern void dyld_dynamic_interpose(const struct mach_header* mh, const struct dyld_interpose_tuple array[], size_t count); 275 | 276 | 277 | 278 | #if __cplusplus 279 | } 280 | #endif /* __cplusplus */ 281 | 282 | #endif /* _MACH_O_DYLD_PRIV_H_ */ 283 | -------------------------------------------------------------------------------- /xpf-bootstrap/rebind_table.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include "rebind_table.h" 30 | #include "XPFLog.h" 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | namespace xpf { 38 | 39 | /* 40 | * Xcode 6.3 enables/disables broken 10.9 compatibility code based on the current system version; we supply 41 | * a patch that claims to be Yosemite 10.0.0. 42 | * 43 | * The version itself is cached in a number of locations after it is computed, necessitating that our patch 44 | * be in place before it's called by anyone. 45 | */ 46 | static unsigned int Yosemite_DVTCurrentSystemVersionAvailabilityForm () { return 101000; } 47 | XPF_REBIND_ENTRY("_DVTCurrentSystemVersionAvailabilityForm", "DVTFoundation", NULL, (uintptr_t) &Yosemite_DVTCurrentSystemVersionAvailabilityForm); 48 | 49 | /* 50 | * NSVisualEffectView is used on Yosemite to produce the ugly blended translucency views. We provide a simple 51 | * no-op replacement. 52 | */ 53 | #if !defined(__i386__) || IPHONE_OS_TARGET 54 | extern "C" void *OBJC_CLASS_$_XPF_NSVisualEffectView; 55 | XPF_REBIND_ENTRY("_OBJC_CLASS_$_NSVisualEffectView", "AppKit", NULL, (uintptr_t) &OBJC_CLASS_$_XPF_NSVisualEffectView); 56 | #endif 57 | 58 | /* 59 | * Yosemite provides QoS extensions to posix_spawn() -- we can simply no-op the implementation. 60 | */ 61 | static int xpf_posix_spawnattr_set_qos_class_np (posix_spawnattr_t *attr, qos_class_t qos_class) { return 0; } 62 | XPF_REBIND_ENTRY("_posix_spawnattr_set_qos_class_np", "libSystem.B.dylib", NULL, (uintptr_t) &xpf_posix_spawnattr_set_qos_class_np); 63 | 64 | /* 65 | * Yosemite's libdispatch provides a set of block utility functions that support creating a custom block type that allows 66 | * the assignation of operations over GCD-specific block attributes. 67 | * 68 | * While some flags are ignorable, others, such as DISPATCH_BLOCK_BARRIER, define semantic invariants that we must 69 | * emulate. Currently, we log those instances; in the future, we'll need to attach attributes to the blocks in question, 70 | * and hook additional dispatch_* APIs to implement handling of those attributes. 71 | * 72 | * Alternatively, we could actually provide a backported copy of 10.10's libdispatch :-) 73 | */ 74 | static dispatch_block_t xpf_dispatch_block_create_with_qos_class (dispatch_block_flags_t flags, dispatch_qos_class_t qos_class, int relative_priority, dispatch_block_t block) { 75 | if ((flags & DISPATCH_BLOCK_BARRIER) == DISPATCH_BLOCK_BARRIER) { 76 | XPFLog("Warning! Ignoring unimplemented DISPATCH_BLOCK_BARRIER in dispatch_block_create(); this may result in thread-safety issues (such as deadlocks and crashes)."); 77 | } 78 | return Block_copy(block); 79 | } 80 | XPF_REBIND_ENTRY("_dispatch_block_create_with_qos_class", "libSystem.B.dylib", NULL, (uintptr_t) &xpf_dispatch_block_create_with_qos_class); 81 | 82 | static dispatch_block_t xpf_dispatch_block_create (dispatch_block_flags_t flags, dispatch_block_t block) { 83 | return xpf_dispatch_block_create_with_qos_class(flags, QOS_CLASS_DEFAULT, 0, block); 84 | } 85 | XPF_REBIND_ENTRY("_dispatch_block_create", "libSystem.B.dylib", NULL, (uintptr_t) &xpf_dispatch_block_create); 86 | 87 | static void xpf_dispatch_block_cancel (dispatch_block_t block) { 88 | // TODO - emulate 89 | static dispatch_once_t onceToken; 90 | dispatch_once(&onceToken, ^{ 91 | XPFLog("Warning! Ignoring unimplemented dispatch_block_cancel(); this may result in unexpected behavior (such as deadlocks and crashes). This message will be logged only once."); 92 | }); 93 | } 94 | XPF_REBIND_ENTRY("_dispatch_block_cancel", "libSystem.B.dylib", NULL, (uintptr_t) &xpf_dispatch_block_cancel); 95 | 96 | long dispatch_block_testcancel(dispatch_block_t block) { 97 | static dispatch_once_t onceToken; 98 | dispatch_once(&onceToken, ^{ 99 | XPFLog("Warning! Ignoring unimplemented dispatch_block_testcancel(); this may result in unexpected behavior (such as deadlocks and crashes). This message will be logged only once."); 100 | }); 101 | return 0; 102 | } 103 | XPF_REBIND_ENTRY("_dispatch_block_testcancel", "libSystem.B.dylib", NULL, (uintptr_t) &dispatch_block_testcancel); 104 | 105 | } /* namespace xpf */ 106 | -------------------------------------------------------------------------------- /xpf-bootstrap/rebind_table.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | /** __DATA section containing XPF rebind data */ 35 | #define XPF_REBIND_SECTION "__xpf_rebind" 36 | 37 | /** 38 | * Rebind table entry. 39 | */ 40 | struct xpf_rebind_entry { 41 | /** Name of the symbol to rebind. */ 42 | const char *symbol; 43 | 44 | /** Image containing the symbol to be rebound. */ 45 | const char *image; 46 | 47 | /** Location to store the original symbol address, or NULL. */ 48 | void **original; 49 | 50 | /** Replacement symbol address */ 51 | uintptr_t replacement; 52 | }; 53 | 54 | /* Generate a compilation-unit-unique name for a single entry */ 55 | #define _XPF_REBIND_ENTRY_NAME_1(_prefix, _counter) _prefix ## _counter 56 | #define _XPF_REBIND_ENTRY_NAME(_prefix, _counter) _XPF_REBIND_ENTRY_NAME_1(_prefix, _counter) 57 | 58 | /** 59 | * Define an XPF rebind entry. 60 | * 61 | * @param _sym Original symbol name. 62 | * @param _img Image exporting @a _sym, or an empty string to treat all references to @a _sym as if they were single-level bound. 63 | * @param _orig If non-NULL, the location to store the original address. This value *must* be initialized to NULL, which is 64 | * used as a sentinal to avoid updating the original value more than once. 65 | * @param _replacement The new address to which all references to @a _sym will be bound. 66 | */ 67 | #define XPF_REBIND_ENTRY(_sym, _img, _orig, _replacement) \ 68 | __attribute__((used)) \ 69 | __attribute__((section(SEG_DATA ", " XPF_REBIND_SECTION))) \ 70 | static struct xpf_rebind_entry _XPF_REBIND_ENTRY_NAME(__xpf_rebind, __COUNTER__) = { \ 71 | .symbol = _sym, \ 72 | .image = _img, \ 73 | .original = _orig, \ 74 | .replacement = _replacement \ 75 | } -------------------------------------------------------------------------------- /xpf-bootstrap/xpf_bootstrap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #import 30 | -------------------------------------------------------------------------------- /xpf-bootstrap/xpf_bootstrap.mm: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #import "xpf_bootstrap.h" 30 | #import 31 | 32 | #import "rebind_table.h" 33 | #import "cfbundle_rebind.h" 34 | 35 | #import "XPFLog.h" 36 | 37 | #import "DVTPlugInManager.h" 38 | #import "dyld_priv.h" 39 | #import 40 | #import 41 | 42 | using namespace patchmaster; 43 | 44 | static const char *xpf_image_state_change (enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info info[]); 45 | static void xpf_add_image_callback (const struct mach_header *header, intptr_t vm_slide); 46 | 47 | static void image_rewrite_bind_opcodes (const LocalImage &image); 48 | static void image_rebind_required_symbols (LocalImage &image); 49 | static void image_insert_xcode_plugin_path (); 50 | 51 | /** Our own mach header */ 52 | static const pl_mach_header_t *xpf_bootstrap_mh = nullptr; 53 | 54 | /* Symbols to be marked as weak. */ 55 | static const struct weak_entry { 56 | const char *library; 57 | const char *symbol; 58 | } weak_symbols[] = { 59 | { "/System/Library/Frameworks/SceneKit.framework/Versions/A/SceneKit", "_OBJC_CLASS_$_SCNParticlePropertyController" }, 60 | { "/usr/lib/libSystem.B.dylib", "_posix_spawnattr_set_qos_class_np" } 61 | }; 62 | 63 | /** 64 | * Pre-main initialization (non-ObjC). 65 | */ 66 | __attribute__((constructor)) static void xpf_prelaunch_initializer (void) { 67 | /* Fetch a persistent reference to our image's mach header. */ 68 | Dl_info dli; 69 | if (dladdr((const void *) &xpf_prelaunch_initializer, &dli) == 0) { 70 | PMLog("Could not find our own image!"); 71 | abort(); 72 | } 73 | xpf_bootstrap_mh = (const pl_mach_header_t *) dli.dli_fbase; 74 | 75 | /* Register our state change callback */ 76 | dyld_register_image_state_change_handler(dyld_image_state_rebased, true, xpf_image_state_change); 77 | 78 | /* Use the standard dyld callback for all other rebindings */ 79 | _dyld_register_func_for_add_image(xpf_add_image_callback); 80 | } 81 | 82 | /** 83 | * Given a bound -- but not yet initialized -- image, apply symbol rebindings from the XPF_REBIND_SECTION. 84 | * 85 | * Note that this function will provide incorrect original addresses if the image has not already been bound. 86 | * 87 | * @param image Image to rebind. 88 | * @param table Rebind table to apply. 89 | */ 90 | static void image_rebind_required_symbols (LocalImage &image) { 91 | /* Fetch our rebind table, if any */ 92 | unsigned long rebind_table_size; 93 | auto rebind_table = (const struct xpf_rebind_entry *) getsectiondata(xpf_bootstrap_mh, SEG_DATA, XPF_REBIND_SECTION, &rebind_table_size); 94 | if (rebind_table == nullptr) { 95 | PMLog("No rebind table found!"); 96 | return; 97 | } 98 | 99 | /* Calculate the actual number of entries */ 100 | size_t rebind_table_len = rebind_table_size / sizeof(xpf_rebind_entry); 101 | 102 | /* Loop over all symbol references in the image */ 103 | image.rebind_symbols([&](const bind_opstream::symbol_proc &sp) { 104 | /* Iterate the bootstrap rebind table looking for a matching patch entry. */ 105 | for (size_t i = 0; i < rebind_table_len; i++) { 106 | const struct xpf_rebind_entry &entry = rebind_table[i]; 107 | 108 | /* Check for a symbol match */ 109 | if (!sp.name().match(SymbolName(entry.image, entry.symbol))) 110 | continue; 111 | 112 | // XPFLog(@"Binding %s:%s in %s:%lx to %lx", sp.name().image().c_str(), sp.name().symbol().c_str(), image.path().c_str(), sp.bind_address(), entry.replacement); 113 | 114 | /* On match, save the previous value (if it hasn't already been saved) and insert the new value */ 115 | uintptr_t *target = (uintptr_t * ) sp.bind_address(); 116 | 117 | if (entry.original != NULL && *entry.original == NULL) 118 | *entry.original = (void *) *target; 119 | 120 | if (*target != entry.replacement) 121 | *target = entry.replacement; 122 | } 123 | }); 124 | } 125 | 126 | /** 127 | * Our on-rebase state change callback; responsible for performing any modifications to the image that are necessary pre-bind. 128 | */ 129 | static const char *xpf_image_state_change (enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info info[]) { 130 | /* Rewrite all weak references. */ 131 | for (uint32_t i = 0; i < infoCount; i++) { 132 | LocalImage image = LocalImage::Analyze(info[i].imageFilePath, (const pl_mach_header_t *) info[i].imageLoadAddress); 133 | image_rewrite_bind_opcodes(image); 134 | } 135 | 136 | return NULL; 137 | } 138 | 139 | /** 140 | * Image add callback; used to perform symbol rebinding and Objective-C patching after images have been fully loaded. 141 | */ 142 | static void xpf_add_image_callback (const struct mach_header *header, intptr_t vm_slide) { 143 | const char *name = nullptr; 144 | for (uint32_t i = 0; i < _dyld_image_count(); i++) { 145 | if (_dyld_get_image_header(i) != header) 146 | continue; 147 | 148 | name = _dyld_get_image_name(i); 149 | break; 150 | } 151 | 152 | /* This would be odd ... */ 153 | if (name == nullptr) { 154 | return; 155 | } 156 | 157 | /* Perform symbol rebinding. */ 158 | auto image = LocalImage::Analyze(name, (const pl_mach_header_t *) header); 159 | image_rebind_required_symbols(image); 160 | 161 | /* Apply ObjC patch to any existing loaded images. */ 162 | image_insert_xcode_plugin_path(); 163 | } 164 | 165 | 166 | /* 167 | * This is the only Objective-C patch that /must/ be applied early on at the bootstrap level -- we swizzle DVTPlugInManager, 168 | * appending our embedded Xcode developer directory to the default path list; this ensures 169 | * that our embedded Xcode plugin gets picked up at IDEInitialization time. 170 | */ 171 | static id (*orig_DVTPlugInManager_init) (DVTPlugInManager *self, SEL _cmd); 172 | static id xpf_DVTPlugInManager_init (DVTPlugInManager *self, SEL _cmd) { 173 | if ((self = orig_DVTPlugInManager_init(self, _cmd)) == nil) 174 | return nil; 175 | 176 | NSBundle *bundle = [NSBundle bundleWithIdentifier: @"org.landonf.xpf-bootstrap"]; 177 | NSString *embeddedDevDir = [[bundle resourcePath] stringByAppendingPathComponent: @"Xcode"]; 178 | [self.mutableSearchPaths addObject: embeddedDevDir]; 179 | 180 | return self; 181 | } 182 | 183 | /** 184 | * Called upon image load to perform swizzling of DVTPlugInManager, if necessary. 185 | */ 186 | static void image_insert_xcode_plugin_path () { 187 | /* Already patched */ 188 | if (orig_DVTPlugInManager_init != nullptr) 189 | return; 190 | 191 | /* Check for the class. */ 192 | Class cls = objc_getClass("DVTPlugInManager"); 193 | if (cls == nil) 194 | return; 195 | 196 | /* If available, perform the swap */ 197 | Method m = class_getInstanceMethod(cls, @selector(init)); 198 | if (m == NULL) 199 | return; 200 | 201 | /* Save the old implementation, insert the new. */ 202 | orig_DVTPlugInManager_init = (decltype(orig_DVTPlugInManager_init)) method_getImplementation(m); 203 | IMP newIMP = (IMP) xpf_DVTPlugInManager_init; 204 | 205 | if (!class_addMethod(cls, @selector(init), newIMP, method_getTypeEncoding(m))) { 206 | /* Method already exists in subclass, we just need to swap the IMP */ 207 | method_setImplementation(m, newIMP); 208 | } 209 | } 210 | 211 | 212 | /** 213 | * Rewrite the bind instructions of a newly loaded image, detecting and marking as weak any missing 214 | * symbols. 215 | */ 216 | static void image_rewrite_bind_opcodes (const LocalImage &image) { 217 | /* Find the LINKEDIT segment; we need this to be able to reset memory protections 218 | * back to their original values. */ 219 | const pl_segment_command_t *linkedit = nullptr; 220 | { 221 | for (auto &&segment : *image.segments()) { 222 | if (strcmp(segment->segname, SEG_LINKEDIT) != 0) 223 | continue; 224 | 225 | linkedit = segment; 226 | } 227 | 228 | if (linkedit == nullptr) { 229 | PMLog("Could not find the __LINKEDIT segment; cannot rebind opcodes for %s", image.path().c_str()); 230 | return; 231 | } 232 | } 233 | 234 | /* Mark the LINKEDIT segment as writable */ 235 | if (mprotect((void *) (linkedit->vmaddr + image.vmaddr_slide()), linkedit->vmsize, linkedit->initprot|PROT_WRITE) != 0) { 236 | PMLog("mprotect(__LINKEDIT, PROT_WRITE) failed; cannot rebind opcodes for %s: %s", image.path().c_str(), strerror(errno)); 237 | return; 238 | } 239 | 240 | /* Iterate over all opcode streams in the image, looking for (and correcting) 241 | * non-weak references to undefined symbols. */ 242 | for (auto &&opcodes : *image.bindOpcodes()) { 243 | bind_opstream ops = opcodes; 244 | 245 | /* Points to the last instance of BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM (if any). */ 246 | const uint8_t *symbol_decl_pc = nullptr; 247 | 248 | /* Check for an undefined symbol */ 249 | auto check_def = [&](const bind_opstream::symbol_proc &sp) { 250 | /* Skip any symbols not explicitly marked for weak rewriting */ 251 | bool found = false; 252 | for (size_t i = 0; i < sizeof(weak_symbols) / sizeof(weak_symbols[0]); i++) { 253 | if (strcmp(weak_symbols[i].symbol, sp.name().symbol()) != 0) 254 | continue; 255 | 256 | if (strcmp(weak_symbols[i].library, sp.name().image()) != 0) 257 | continue; 258 | 259 | found = true; 260 | break; 261 | } 262 | 263 | /* Mark the sumbol as weak if it's not already */ 264 | if (!(sp.flags() & BIND_SYMBOL_FLAGS_WEAK_IMPORT)) { 265 | /* Rewrite the symbol flags */ 266 | *((uint8_t *) symbol_decl_pc) = BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | sp.flags() | BIND_SYMBOL_FLAGS_WEAK_IMPORT; 267 | } 268 | }; 269 | 270 | /* Step the VM, keeping track of symbol definition state so that we can rewrite 271 | * any SET_SYMBOL opcodes that reference unknown symbols. */ 272 | const uint8_t *last_pc = ops.position(); 273 | uint8_t opcode = BIND_OPCODE_DONE; 274 | while (!ops.isEmpty() && (opcode = ops.step(image, check_def)) != BIND_OPCODE_DONE) { 275 | /* Save the opcode address */ 276 | if (opcode == BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM) { 277 | symbol_decl_pc = last_pc; 278 | } 279 | 280 | /* Update our PC state */ 281 | last_pc = ops.position(); 282 | } 283 | } 284 | 285 | /* Restore the LINKEDIT segment's initial protections. */ 286 | if (mprotect((void *) (linkedit->vmaddr + image.vmaddr_slide()), linkedit->vmsize, linkedit->initprot) != 0) { 287 | PMLog("mprotect(__LINKEDIT, initprot) failed; could not restore expected protections for %s: %s", image.path().c_str(), strerror(errno)); 288 | return; 289 | } 290 | } 291 | -------------------------------------------------------------------------------- /xpf-bootstrap/yosemite_objc_stubs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ -------------------------------------------------------------------------------- /xpf-bootstrap/yosemite_objc_stubs.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2015 Landon Fuller 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #import 30 | #import "yosemite_objc_stubs.h" 31 | 32 | /* 33 | * This file binds (via ObjC categories) Yosemite-only methods that are required to run Xcode. 34 | */ 35 | 36 | /* We're intentionally implementing methods that *would* be implemented in 10.10 */ 37 | #pragma clang diagnostic push 38 | #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation" 39 | 40 | #define FACADE(_cls) @interface _cls (XPFYosemiteFacade) @end @implementation _cls (XPFYosemiteFacade) 41 | 42 | FACADE(NSLayoutConstraint) 43 | + (void)activateConstraints:(NSArray *)constraints { } 44 | + (void)deactivateConstraints:(NSArray *)constraints { } 45 | @end 46 | 47 | FACADE(NSColor) 48 | + (NSColor *) labelColor { return [self controlTextColor]; } 49 | + (NSColor *) secondaryLabelColor { return [self disabledControlTextColor]; } 50 | @end 51 | 52 | FACADE(NSOperationQueue) 53 | - (void) setQualityOfService:(NSQualityOfService)qualityOfService {} 54 | @end 55 | 56 | 57 | FACADE(NSOperation) 58 | - (NSQualityOfService) qualityOfService {return NSQualityOfServiceDefault; } 59 | - (void) setQualityOfService:(NSQualityOfService)qualityOfService {} 60 | @end 61 | 62 | FACADE(NSToolbarItem) 63 | - (void) setWantsToBeCentered: (BOOL) centered { } 64 | @end 65 | 66 | FACADE(NSWindow) 67 | - (void) setTitleVisibility: (BOOL) visibility {} 68 | - (void) setTitlebarAppearsTransparent: (BOOL) appearsTransparent {} 69 | - (void) setTitleMode: (NSUInteger) titleMode {} 70 | @end 71 | 72 | FACADE(NSTextView) 73 | - (void) setUsesRolloverButtonForSelection: (BOOL) usesRolloverButtonForSelection {} 74 | @end 75 | 76 | FACADE(NSScrollView) 77 | - (BOOL) automaticallyAdjustsContentInsets { return false; } 78 | - (void) setAutomaticallyAdjustsContentInsets: (BOOL) automaticallyAdjustsContentInsets { } 79 | @end 80 | 81 | #pragma clang diagnostic pop -------------------------------------------------------------------------------- /xpf-bootstrapTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.landonf.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | --------------------------------------------------------------------------------