├── .gitignore ├── LICENSE ├── README.md ├── intrude ├── src └── insert_dylib_to_macho │ ├── .gitignore │ ├── gflags │ ├── include │ │ ├── gflags │ │ │ ├── gflags.h │ │ │ ├── gflags_completions.h │ │ │ └── gflags_declare.h │ │ └── google │ │ │ ├── gflags.h │ │ │ └── gflags_completions.h │ └── lib │ │ ├── libgflags.2.dylib │ │ ├── libgflags.a │ │ ├── libgflags.dylib │ │ ├── libgflags_nothreads.2.dylib │ │ ├── libgflags_nothreads.a │ │ ├── libgflags_nothreads.dylib │ │ └── pkgconfig │ │ ├── libgflags.pc │ │ └── libgflags_nothreads.pc │ ├── insert_dylib_to_macho.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata │ ├── insert_dylib_to_macho │ ├── exception.cpp │ ├── exception.h │ ├── macho_brief_info.h │ ├── main.cpp │ ├── record.h │ ├── util.cpp │ ├── util.h │ └── workflow.h │ └── mach-o │ ├── arch.h │ ├── arm │ └── reloc.h │ ├── arm64 │ └── reloc.h │ ├── compact_unwind_encoding.h │ ├── fat.h │ ├── loader.h │ ├── nlist.h │ ├── ranlib.h │ ├── reloc.h │ ├── swap.h │ └── x86_64 │ └── reloc.h └── toolchain ├── insert_dylib_to_binary └── insert_dylib_to_macho /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 oldman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # intrude 2 | 3 | ## 什么是intrude 4 | 5 | 由于各种原因,iOS越狱现状越来越满足不了实际需求。但有时候我们又想研究某第三方`App`的实现,因此如何在一个非越狱`iOS`设备上实现这个目的就变成了一个需要解决的需求。`intrude`的设计初衷就是用来做这个事情的。 6 | 7 | `intrude`是一个小巧的工具,其作用是在未越狱机器上给一个`iOS App`嵌入一个或多个`dylib`。 8 | 9 | ## 如何使用 10 | 11 | 1. 首先该工具只能运行在`Mac OS X`系统上,因此你得准备一台`Mac`。 12 | 13 | 1. 将目标`App`从目标设备上导出,成`ipa`文件。 14 | 15 | 1. 使用如下命令将`/path/to/bar.dylib`嵌入到`/path/to/foo.ipa`中 16 | 17 | ./intrude --ipa "/path/to/foo.ipa" \ 18 | --dylib "/path/to/bar.dylib" \ 19 | --bundle "li.oldman.test" 20 | --sign "iPhone Developer: Oldman Li (QNRMA23W53)" \ 21 | --provision "/path/to/li.oldman.test.mobileprovision" 22 | 23 | 其中,`bundle`, `sign`, `privision` 为嵌入过程所必须的重签名参数,这三者必须互相对应 24 | 25 | 1. 上步骤会生成一个ipa文件`/path/to/foo.ipa.modified.ipa`,此`ipa`文件即包含了`bar.dylib`, 将其重新导入设备即可。 26 | 27 | ## 已知问题 28 | 29 | 1. 注意,原始`ipa`中可执行二进制文件必须为无加密版本(即俗称的砸壳版本)。 30 | 31 | 1. 简易起见,目前本工具重新生成`ipa`文件时未将`Plugins`目录包含在内。 32 | 33 | 34 | ## 实现原理 35 | 如果你对实现原理感兴趣,这里的简短说明可以作为参考。 36 | 37 | 本质上,一个二进制文件需要依赖哪些`dylib`,这些信息是记录在`Mach O`结构中的。而`intrude`便是改写了`Mach O`结构,增加了一条加载`dylib`的指令,使之能够在运行时即加载它。这部分实现可参阅[这里](https://github.com/imoldman/intrude/tree/master/src/insert_dylib_to_macho/insert_dylib_to_macho)。 38 | -------------------------------------------------------------------------------- /intrude: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import argparse 4 | import json 5 | import os.path 6 | import plistlib 7 | import subprocess 8 | import sys 9 | import StringIO 10 | 11 | THIS_DIR = os.path.dirname(os.path.abspath(__file__)) 12 | SRC_IPA_PATH_PARAM = 'src_ipa_path_param' 13 | DEST_IPA_PATH_PARAM = 'dest_ipa_path_param' 14 | NEW_BUNDLE_ID_PARAM = 'new_bundle_id' 15 | DYLIB_FILE_PARAM = 'dylib_file' 16 | CODESIGN_NAME_PARAM = 'codesign_name' 17 | EMBEDDED_PATH_PARAM = 'embedded_path' 18 | 19 | UNZIPPED_DIR = 'unzipped_dir' 20 | APP_PACKAGE_DIR = 'app_pacakge_dir' 21 | EXECUTABLE_FILE = 'executable_file' 22 | ENTITLEMENTS_PATH = 'entitlements_path' 23 | DYLIB_NEW_NAME = 'dylib_new_name' 24 | 25 | def make_sure_dir_exist(dir_path): 26 | if not os.path.exists(dir_path): 27 | os.makedirs(dir_path) 28 | 29 | def do_unzip_src_ipa(context): 30 | unzipped_dir = context[UNZIPPED_DIR] 31 | make_sure_dir_exist(unzipped_dir) 32 | command = ['/usr/bin/unzip', '-q', context[SRC_IPA_PATH_PARAM], '-d', unzipped_dir] 33 | print ' '.join(command) 34 | subprocess.check_call(command) 35 | 36 | def do_fill_app_package_dir_to_context(context): 37 | path = os.path.join(context[UNZIPPED_DIR], 'Payload') 38 | output = subprocess.check_output(['ls', '-1'], cwd=path).strip() 39 | for line in output.split('\n'): 40 | if line.endswith('.app'): 41 | context[APP_PACKAGE_DIR] = os.path.join(path, line) 42 | return 43 | assert(False) 44 | 45 | def do_fill_package_executable_path_to_context(context): 46 | plist_path = os.path.join(context[APP_PACKAGE_DIR], 'Info.plist') 47 | command = ['/usr/libexec/PlistBuddy', '-c', 'Print :CFBundleExecutable', plist_path] 48 | print ' '.join(command) 49 | context[EXECUTABLE_FILE] = subprocess.check_output(command).strip() 50 | 51 | def do_remove_plugins_dir(context): 52 | src_path = os.path.join(context[APP_PACKAGE_DIR], 'Plugins') 53 | dest_path = os.path.join(context[APP_PACKAGE_DIR], 'Plugins.save') 54 | if os.path.exists(src_path): 55 | command = ['mv', '-f', src_path, dest_path] 56 | print ' '.join(command) 57 | subprocess.check_call(command) 58 | 59 | def do_change_bundle_id_in_app(context): 60 | plist_path = os.path.join(context[APP_PACKAGE_DIR], 'Info.plist') 61 | param = 'Set :CFBundleIdentifier %s' % context[NEW_BUNDLE_ID_PARAM] 62 | command = ['/usr/libexec/PlistBuddy', '-c', param, plist_path] 63 | print ' '.join(command) 64 | subprocess.check_call(command) 65 | 66 | def do_change_bundle_id_in_metadata_plist(context): 67 | param = 'Set :softwareVersionBundleId %s' % context[NEW_BUNDLE_ID_PARAM] 68 | plist_file = os.path.join(context[UNZIPPED_DIR], 'iTunesMetadata.plist') 69 | if os.path.exists(plist_file): 70 | command = ['/usr/libexec/PlistBuddy', '-c', param, plist_file] 71 | print ' '.join(command) 72 | subprocess.check_call(command) 73 | 74 | def do_insert_load_dylib_command_to_excutable_file(context): 75 | exe_file = os.path.join(context[APP_PACKAGE_DIR], context[EXECUTABLE_FILE]) 76 | command = [os.path.join(THIS_DIR, 'toolchain', 'insert_dylib_to_binary'), '--file', exe_file] 77 | print ' '.join(command) 78 | filename = subprocess.check_output(command).strip() 79 | context[DYLIB_NEW_NAME] = filename 80 | 81 | def do_replace_provision(context): 82 | embedded_provision = os.path.join(context[APP_PACKAGE_DIR], 'embedded.mobileprovision') 83 | if os.path.exists(embedded_provision): 84 | os.remove(embedded_provision) 85 | command = ['cp', context[EMBEDDED_PATH_PARAM], embedded_provision] 86 | print ' '.join(command) 87 | subprocess.check_call(command) 88 | 89 | def do_replace_entitlements(context): 90 | command = ['/usr/bin/security', 'cms', '-D', '-i', context[EMBEDDED_PATH_PARAM]] 91 | print' '.join(command) 92 | output = subprocess.check_output(command, cwd=context[UNZIPPED_DIR]).strip() 93 | entitlements_file = os.path.join(context[UNZIPPED_DIR], 'entitlements.plist') 94 | plistlib.writePlist(plistlib.readPlist(StringIO.StringIO(output))['Entitlements'], entitlements_file) 95 | context[ENTITLEMENTS_PATH] = entitlements_file 96 | 97 | def do_copy_dylib_into_app(context): 98 | dylib_new_file = os.path.join(context[APP_PACKAGE_DIR], context[DYLIB_NEW_NAME]) 99 | command = ['cp', '-f', context[DYLIB_FILE_PARAM], dylib_new_file] 100 | print ' '.join(command) 101 | subprocess.check_call(command) 102 | command = ['/usr/bin/codesign', '-f', '-s', context[CODESIGN_NAME_PARAM], dylib_new_file] 103 | print ' '.join(command) 104 | subprocess.check_call(command) 105 | 106 | def do_codesign_app_package(context): 107 | entitlements_param = '--entitlements=%s' % context[ENTITLEMENTS_PATH] 108 | command = ['/usr/bin/codesign', '-f', '-s', context[CODESIGN_NAME_PARAM], '--no-strict', entitlements_param, context[APP_PACKAGE_DIR]] 109 | print ' '.join(command) 110 | subprocess.check_call(command) 111 | 112 | def do_zip_to_dest_ipa(context): 113 | dest_ipa_path = os.path.realpath(context[DEST_IPA_PATH_PARAM]) 114 | command = ['/usr/bin/zip', '-y', '-r', dest_ipa_path, '.'] 115 | print ' '.join(command) 116 | subprocess.check_call(command, cwd=context[UNZIPPED_DIR]) 117 | 118 | def build_config(): 119 | config = [{ 120 | 'name' : 'unzip ipa', 121 | 'method' : do_unzip_src_ipa 122 | }, { 123 | 'name' : 'get package dir', 124 | 'method' : do_fill_app_package_dir_to_context 125 | }, { 126 | 'name' : 'get executable file\'s name', 127 | 'method' : do_fill_package_executable_path_to_context 128 | }, { 129 | 'name' : 'remove plugins dir', 130 | 'method' : do_remove_plugins_dir 131 | }, { 132 | 'name' : 'change bundle id, part 1', 133 | 'method' : do_change_bundle_id_in_app 134 | }, { 135 | 'name' : 'change bundle id, part 2', 136 | 'method' : do_change_bundle_id_in_metadata_plist 137 | }, { 138 | 'name' : 'modify executable file', 139 | 'method' : do_insert_load_dylib_command_to_excutable_file 140 | }, { 141 | 'name' : 'replace embedded provision', 142 | 'method' : do_replace_provision 143 | }, { 144 | 'name' : 'replace entitlements file', 145 | 'method' : do_replace_entitlements 146 | }, { 147 | 'name' : 'copy dylib to app package', 148 | 'method' : do_copy_dylib_into_app 149 | }, { 150 | 'name' : 'resign app package', 151 | 'method' : do_codesign_app_package 152 | }, { 153 | 'name' : 'zip to ipa', 154 | 'method' : do_zip_to_dest_ipa 155 | }]; 156 | 157 | return config 158 | 159 | def init_context_with_args(args): 160 | return { 161 | SRC_IPA_PATH_PARAM : args.ipa, 162 | DEST_IPA_PATH_PARAM : args.ipa + '.modified.ipa', 163 | NEW_BUNDLE_ID_PARAM : args.bundle_id, 164 | DYLIB_FILE_PARAM : args.dylib, 165 | CODESIGN_NAME_PARAM : args.sign_id, 166 | EMBEDDED_PATH_PARAM : args.provision, 167 | 168 | UNZIPPED_DIR : os.path.join(THIS_DIR, 'temp') 169 | } 170 | 171 | def run(context, config): 172 | for index, command in enumerate(config): 173 | index += 1 174 | print '=' * 50 175 | print 'ACTION %d: %s' %(index, command['name']) 176 | method = command.get('method') 177 | method(context) 178 | 179 | def main(): 180 | description = ''' intrude a dylib libary to a ipa package. 181 | 182 | {self_name} --ipa /path/to/some.ipa --dylib /path/to/executable/some.dylib'''.format(self_name=sys.argv[0]) 183 | 184 | parser = argparse.ArgumentParser(description=description, formatter_class=argparse.RawDescriptionHelpFormatter,) 185 | parser.add_argument('--ipa', action='store', dest='ipa', required=True, help='full path for ipa file') 186 | parser.add_argument('--dylib', action='store', dest='dylib', required=True, help='full path for dylib library') 187 | parser.add_argument('--bundle', action='store', dest='bundle_id', required=True, help='new bundle id for ipa file') 188 | parser.add_argument('--sign', action='store', dest='sign_id', required=True, help='identify for code sign') 189 | parser.add_argument('--provision', action='store', dest='provision', required=True, help='embedded provision for new ipa') 190 | args = parser.parse_args() 191 | 192 | context = init_context_with_args(args) 193 | config = build_config() 194 | run(context, config) 195 | 196 | if __name__ == '__main__': 197 | main() 198 | 199 | # vim: number list tabstop=2 shiftwidth=2 expandtab 200 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/.gitignore: -------------------------------------------------------------------------------- 1 | ######################### 2 | # .gitignore file for Xcode4 / OS X Source projects 3 | # 4 | # Version 2.0 5 | # For latest version, see: http://stackoverflow.com/questions/49478/git-ignore-file-for-xcode-projects 6 | # 7 | # 2013 updates: 8 | # - fixed the broken "save personal Schemes" 9 | # 10 | # NB: if you are storing "built" products, this WILL NOT WORK, 11 | # and you should use a different .gitignore (or none at all) 12 | # This file is for SOURCE projects, where there are many extra 13 | # files that we want to exclude 14 | # 15 | ######################### 16 | 17 | ##### 18 | # OS X temporary files that should never be committed 19 | 20 | .DS_Store 21 | *.swp 22 | *.lock 23 | profile 24 | 25 | 26 | #### 27 | # Xcode temporary files that should never be committed 28 | # 29 | # NB: NIB/XIB files still exist even on Storyboard projects, so we want this... 30 | 31 | *~.nib 32 | 33 | 34 | #### 35 | # Xcode build files - 36 | # 37 | # NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "DerivedData" 38 | 39 | DerivedData/ 40 | 41 | # NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "build" 42 | 43 | build/ 44 | 45 | 46 | ##### 47 | # Xcode private settings (window sizes, bookmarks, breakpoints, custom executables, smart groups) 48 | # 49 | # This is complicated: 50 | # 51 | # SOMETIMES you need to put this file in version control. 52 | # Apple designed it poorly - if you use "custom executables", they are 53 | # saved in this file. 54 | # 99% of projects do NOT use those, so they do NOT want to version control this file. 55 | # ..but if you're in the 1%, comment out the line "*.pbxuser" 56 | 57 | *.pbxuser 58 | *.mode1v3 59 | *.mode2v3 60 | *.perspectivev3 61 | # NB: also, whitelist the default ones, some projects need to use these 62 | !default.pbxuser 63 | !default.mode1v3 64 | !default.mode2v3 65 | !default.perspectivev3 66 | 67 | 68 | #### 69 | # Xcode 4 - semi-personal settings 70 | # 71 | # 72 | # OPTION 1: --------------------------------- 73 | # throw away ALL personal settings (including custom schemes! 74 | # - unless they are "shared") 75 | # 76 | # NB: this is exclusive with OPTION 2 below 77 | xcuserdata 78 | 79 | # OPTION 2: --------------------------------- 80 | # get rid of ALL personal settings, but KEEP SOME OF THEM 81 | # - NB: you must manually uncomment the bits you want to keep 82 | # 83 | # NB: this is exclusive with OPTION 1 above 84 | # 85 | #xcuserdata/**/* 86 | 87 | # (requires option 2 above): Personal Schemes 88 | # 89 | #!xcuserdata/**/xcschemes/* 90 | 91 | #### 92 | # XCode 4 workspaces - more detailed 93 | # 94 | # Workspaces are important! They are a core feature of Xcode - don't exclude them :) 95 | # 96 | # Workspace layout is quite spammy. For reference: 97 | # 98 | # /(root)/ 99 | # /(project-name).xcodeproj/ 100 | # project.pbxproj 101 | # /project.xcworkspace/ 102 | # contents.xcworkspacedata 103 | # /xcuserdata/ 104 | # /(your name)/xcuserdatad/ 105 | # UserInterfaceState.xcuserstate 106 | # /xcsshareddata/ 107 | # /xcschemes/ 108 | # (shared scheme name).xcscheme 109 | # /xcuserdata/ 110 | # /(your name)/xcuserdatad/ 111 | # (private scheme).xcscheme 112 | # xcschememanagement.plist 113 | # 114 | # 115 | 116 | #### 117 | # Xcode 4 - Deprecated classes 118 | # 119 | # Allegedly, if you manually "deprecate" your classes, they get moved here. 120 | # 121 | # We're using source-control, so this is a "feature" that we do not want! 122 | 123 | *.moved-aside 124 | 125 | 126 | #### 127 | # UNKNOWN: recommended by others, but I can't discover what these files are 128 | # 129 | # ...none. Everything is now explained. 130 | # 131 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/gflags/include/gflags/gflags.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2006, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // --- 31 | // Revamped and reorganized by Craig Silverstein 32 | // 33 | // This is the file that should be included by any file which declares 34 | // or defines a command line flag or wants to parse command line flags 35 | // or print a program usage message (which will include information about 36 | // flags). Executive summary, in the form of an example foo.cc file: 37 | // 38 | // #include "foo.h" // foo.h has a line "DECLARE_int32(start);" 39 | // #include "validators.h" // hypothetical file defining ValidateIsFile() 40 | // 41 | // DEFINE_int32(end, 1000, "The last record to read"); 42 | // 43 | // DEFINE_string(filename, "my_file.txt", "The file to read"); 44 | // // Crash if the specified file does not exist. 45 | // static bool dummy = RegisterFlagValidator(&FLAGS_filename, 46 | // &ValidateIsFile); 47 | // 48 | // DECLARE_bool(verbose); // some other file has a DEFINE_bool(verbose, ...) 49 | // 50 | // void MyFunc() { 51 | // if (FLAGS_verbose) printf("Records %d-%d\n", FLAGS_start, FLAGS_end); 52 | // } 53 | // 54 | // Then, at the command-line: 55 | // ./foo --noverbose --start=5 --end=100 56 | // 57 | // For more details, see 58 | // doc/gflags.html 59 | // 60 | // --- A note about thread-safety: 61 | // 62 | // We describe many functions in this routine as being thread-hostile, 63 | // thread-compatible, or thread-safe. Here are the meanings we use: 64 | // 65 | // thread-safe: it is safe for multiple threads to call this routine 66 | // (or, when referring to a class, methods of this class) 67 | // concurrently. 68 | // thread-hostile: it is not safe for multiple threads to call this 69 | // routine (or methods of this class) concurrently. In gflags, 70 | // most thread-hostile routines are intended to be called early in, 71 | // or even before, main() -- that is, before threads are spawned. 72 | // thread-compatible: it is safe for multiple threads to read from 73 | // this variable (when applied to variables), or to call const 74 | // methods of this class (when applied to classes), as long as no 75 | // other thread is writing to the variable or calling non-const 76 | // methods of this class. 77 | 78 | #ifndef BASE_COMMANDLINEFLAGS_H_ 79 | #define BASE_COMMANDLINEFLAGS_H_ 80 | 81 | #include 82 | #include 83 | #include // IWYU pragma: export 84 | namespace google { 85 | 86 | // 87 | // NOTE: all functions below MUST have an explicit 'extern' before 88 | // them. Our automated opensourcing tools use this as a signal to do 89 | // appropriate munging for windows, which needs to add GFLAGS_DLL_DECL. 90 | // 91 | #define GFLAGS_DLL_DECL /* rewritten to be non-empty in windows dir */ 92 | #define GFLAGS_DLL_DEFINE_FLAG /* rewritten to be non-empty in windows dir */ 93 | 94 | 95 | // -------------------------------------------------------------------- 96 | // To actually define a flag in a file, use DEFINE_bool, 97 | // DEFINE_string, etc. at the bottom of this file. You may also find 98 | // it useful to register a validator with the flag. This ensures that 99 | // when the flag is parsed from the commandline, or is later set via 100 | // SetCommandLineOption, we call the validation function. It is _not_ 101 | // called when you assign the value to the flag directly using the = operator. 102 | // 103 | // The validation function should return true if the flag value is valid, and 104 | // false otherwise. If the function returns false for the new setting of the 105 | // flag, the flag will retain its current value. If it returns false for the 106 | // default value, ParseCommandLineFlags() will die. 107 | // 108 | // This function is safe to call at global construct time (as in the 109 | // example below). 110 | // 111 | // Example use: 112 | // static bool ValidatePort(const char* flagname, int32 value) { 113 | // if (value > 0 && value < 32768) // value is ok 114 | // return true; 115 | // printf("Invalid value for --%s: %d\n", flagname, (int)value); 116 | // return false; 117 | // } 118 | // DEFINE_int32(port, 0, "What port to listen on"); 119 | // static bool dummy = RegisterFlagValidator(&FLAGS_port, &ValidatePort); 120 | 121 | // Returns true if successfully registered, false if not (because the 122 | // first argument doesn't point to a command-line flag, or because a 123 | // validator is already registered for this flag). 124 | extern bool RegisterFlagValidator(const bool* flag, 125 | bool (*validate_fn)(const char*, bool)); 126 | extern bool RegisterFlagValidator(const int32* flag, 127 | bool (*validate_fn)(const char*, int32)); 128 | extern bool RegisterFlagValidator(const int64* flag, 129 | bool (*validate_fn)(const char*, int64)); 130 | extern bool RegisterFlagValidator(const uint64* flag, 131 | bool (*validate_fn)(const char*, uint64)); 132 | extern bool RegisterFlagValidator(const double* flag, 133 | bool (*validate_fn)(const char*, double)); 134 | extern bool RegisterFlagValidator(const std::string* flag, 135 | bool (*validate_fn)(const char*, 136 | const std::string&)); 137 | 138 | 139 | // -------------------------------------------------------------------- 140 | // These methods are the best way to get access to info about the 141 | // list of commandline flags. Note that these routines are pretty slow. 142 | // GetAllFlags: mostly-complete info about the list, sorted by file. 143 | // ShowUsageWithFlags: pretty-prints the list to stdout (what --help does) 144 | // ShowUsageWithFlagsRestrict: limit to filenames with restrict as a substr 145 | // 146 | // In addition to accessing flags, you can also access argv[0] (the program 147 | // name) and argv (the entire commandline), which we sock away a copy of. 148 | // These variables are static, so you should only set them once. 149 | 150 | struct GFLAGS_DLL_DECL CommandLineFlagInfo { 151 | std::string name; // the name of the flag 152 | std::string type; // the type of the flag: int32, etc 153 | std::string description; // the "help text" associated with the flag 154 | std::string current_value; // the current value, as a string 155 | std::string default_value; // the default value, as a string 156 | std::string filename; // 'cleaned' version of filename holding the flag 157 | bool has_validator_fn; // true if RegisterFlagValidator called on this flag 158 | bool is_default; // true if the flag has the default value and 159 | // has not been set explicitly from the cmdline 160 | // or via SetCommandLineOption 161 | const void* flag_ptr; // pointer to the flag's current value (i.e. FLAGS_foo) 162 | }; 163 | 164 | // Using this inside of a validator is a recipe for a deadlock. 165 | // TODO(user) Fix locking when validators are running, to make it safe to 166 | // call validators during ParseAllFlags. 167 | // Also make sure then to uncomment the corresponding unit test in 168 | // gflags_unittest.sh 169 | extern void GetAllFlags(std::vector* OUTPUT); 170 | // These two are actually defined in gflags_reporting.cc. 171 | extern void ShowUsageWithFlags(const char *argv0); // what --help does 172 | extern void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict); 173 | 174 | // Create a descriptive string for a flag. 175 | // Goes to some trouble to make pretty line breaks. 176 | extern std::string DescribeOneFlag(const CommandLineFlagInfo& flag); 177 | 178 | // Thread-hostile; meant to be called before any threads are spawned. 179 | extern void SetArgv(int argc, const char** argv); 180 | 181 | // The following functions are thread-safe as long as SetArgv() is 182 | // only called before any threads start. 183 | extern const std::vector& GetArgvs(); 184 | extern const char* GetArgv(); // all of argv as a string 185 | extern const char* GetArgv0(); // only argv0 186 | extern uint32 GetArgvSum(); // simple checksum of argv 187 | extern const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set 188 | extern const char* ProgramInvocationShortName(); // basename(argv0) 189 | 190 | // ProgramUsage() is thread-safe as long as SetUsageMessage() is only 191 | // called before any threads start. 192 | extern const char* ProgramUsage(); // string set by SetUsageMessage() 193 | 194 | // VersionString() is thread-safe as long as SetVersionString() is only 195 | // called before any threads start. 196 | extern const char* VersionString(); // string set by SetVersionString() 197 | 198 | 199 | 200 | // -------------------------------------------------------------------- 201 | // Normally you access commandline flags by just saying "if (FLAGS_foo)" 202 | // or whatever, and set them by calling "FLAGS_foo = bar" (or, more 203 | // commonly, via the DEFINE_foo macro). But if you need a bit more 204 | // control, we have programmatic ways to get/set the flags as well. 205 | // These programmatic ways to access flags are thread-safe, but direct 206 | // access is only thread-compatible. 207 | 208 | // Return true iff the flagname was found. 209 | // OUTPUT is set to the flag's value, or unchanged if we return false. 210 | extern bool GetCommandLineOption(const char* name, std::string* OUTPUT); 211 | 212 | // Return true iff the flagname was found. OUTPUT is set to the flag's 213 | // CommandLineFlagInfo or unchanged if we return false. 214 | extern bool GetCommandLineFlagInfo(const char* name, 215 | CommandLineFlagInfo* OUTPUT); 216 | 217 | // Return the CommandLineFlagInfo of the flagname. exit() if name not found. 218 | // Example usage, to check if a flag's value is currently the default value: 219 | // if (GetCommandLineFlagInfoOrDie("foo").is_default) ... 220 | extern CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name); 221 | 222 | enum GFLAGS_DLL_DECL FlagSettingMode { 223 | // update the flag's value (can call this multiple times). 224 | SET_FLAGS_VALUE, 225 | // update the flag's value, but *only if* it has not yet been updated 226 | // with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef". 227 | SET_FLAG_IF_DEFAULT, 228 | // set the flag's default value to this. If the flag has not yet updated 229 | // yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef") 230 | // change the flag's current value to the new default value as well. 231 | SET_FLAGS_DEFAULT 232 | }; 233 | 234 | // Set a particular flag ("command line option"). Returns a string 235 | // describing the new value that the option has been set to. The 236 | // return value API is not well-specified, so basically just depend on 237 | // it to be empty if the setting failed for some reason -- the name is 238 | // not a valid flag name, or the value is not a valid value -- and 239 | // non-empty else. 240 | 241 | // SetCommandLineOption uses set_mode == SET_FLAGS_VALUE (the common case) 242 | extern std::string SetCommandLineOption(const char* name, const char* value); 243 | extern std::string SetCommandLineOptionWithMode(const char* name, const char* value, 244 | FlagSettingMode set_mode); 245 | 246 | 247 | // -------------------------------------------------------------------- 248 | // Saves the states (value, default value, whether the user has set 249 | // the flag, registered validators, etc) of all flags, and restores 250 | // them when the FlagSaver is destroyed. This is very useful in 251 | // tests, say, when you want to let your tests change the flags, but 252 | // make sure that they get reverted to the original states when your 253 | // test is complete. 254 | // 255 | // Example usage: 256 | // void TestFoo() { 257 | // FlagSaver s1; 258 | // FLAG_foo = false; 259 | // FLAG_bar = "some value"; 260 | // 261 | // // test happens here. You can return at any time 262 | // // without worrying about restoring the FLAG values. 263 | // } 264 | // 265 | // Note: This class is marked with ATTRIBUTE_UNUSED because all the 266 | // work is done in the constructor and destructor, so in the standard 267 | // usage example above, the compiler would complain that it's an 268 | // unused variable. 269 | // 270 | // This class is thread-safe. However, its destructor writes to 271 | // exactly the set of flags that have changed value during its 272 | // lifetime, so concurrent _direct_ access to those flags 273 | // (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe. 274 | 275 | class GFLAGS_DLL_DECL FlagSaver { 276 | public: 277 | FlagSaver(); 278 | ~FlagSaver(); 279 | 280 | private: 281 | class FlagSaverImpl* impl_; // we use pimpl here to keep API steady 282 | 283 | FlagSaver(const FlagSaver&); // no copying! 284 | void operator=(const FlagSaver&); 285 | } 286 | __attribute__ ((unused)); 287 | 288 | // -------------------------------------------------------------------- 289 | // Some deprecated or hopefully-soon-to-be-deprecated functions. 290 | 291 | // This is often used for logging. TODO(csilvers): figure out a better way 292 | extern std::string CommandlineFlagsIntoString(); 293 | // Usually where this is used, a FlagSaver should be used instead. 294 | extern bool ReadFlagsFromString(const std::string& flagfilecontents, 295 | const char* prog_name, 296 | bool errors_are_fatal); // uses SET_FLAGS_VALUE 297 | 298 | // These let you manually implement --flagfile functionality. 299 | // DEPRECATED. 300 | extern bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name); 301 | extern bool ReadFromFlagsFile(const std::string& filename, const char* prog_name, 302 | bool errors_are_fatal); // uses SET_FLAGS_VALUE 303 | 304 | 305 | // -------------------------------------------------------------------- 306 | // Useful routines for initializing flags from the environment. 307 | // In each case, if 'varname' does not exist in the environment 308 | // return defval. If 'varname' does exist but is not valid 309 | // (e.g., not a number for an int32 flag), abort with an error. 310 | // Otherwise, return the value. NOTE: for booleans, for true use 311 | // 't' or 'T' or 'true' or '1', for false 'f' or 'F' or 'false' or '0'. 312 | 313 | extern bool BoolFromEnv(const char *varname, bool defval); 314 | extern int32 Int32FromEnv(const char *varname, int32 defval); 315 | extern int64 Int64FromEnv(const char *varname, int64 defval); 316 | extern uint64 Uint64FromEnv(const char *varname, uint64 defval); 317 | extern double DoubleFromEnv(const char *varname, double defval); 318 | extern const char *StringFromEnv(const char *varname, const char *defval); 319 | 320 | 321 | // -------------------------------------------------------------------- 322 | // The next two functions parse gflags from main(): 323 | 324 | // Set the "usage" message for this program. For example: 325 | // string usage("This program does nothing. Sample usage:\n"); 326 | // usage += argv[0] + " "; 327 | // SetUsageMessage(usage); 328 | // Do not include commandline flags in the usage: we do that for you! 329 | // Thread-hostile; meant to be called before any threads are spawned. 330 | extern void SetUsageMessage(const std::string& usage); 331 | 332 | // Sets the version string, which is emitted with --version. 333 | // For instance: SetVersionString("1.3"); 334 | // Thread-hostile; meant to be called before any threads are spawned. 335 | extern void SetVersionString(const std::string& version); 336 | 337 | 338 | // Looks for flags in argv and parses them. Rearranges argv to put 339 | // flags first, or removes them entirely if remove_flags is true. 340 | // If a flag is defined more than once in the command line or flag 341 | // file, the last definition is used. Returns the index (into argv) 342 | // of the first non-flag argument. 343 | // See top-of-file for more details on this function. 344 | #ifndef SWIG // In swig, use ParseCommandLineFlagsScript() instead. 345 | extern uint32 ParseCommandLineFlags(int *argc, char*** argv, bool remove_flags); 346 | #endif 347 | 348 | 349 | // Calls to ParseCommandLineNonHelpFlags and then to 350 | // HandleCommandLineHelpFlags can be used instead of a call to 351 | // ParseCommandLineFlags during initialization, in order to allow for 352 | // changing default values for some FLAGS (via 353 | // e.g. SetCommandLineOptionWithMode calls) between the time of 354 | // command line parsing and the time of dumping help information for 355 | // the flags as a result of command line parsing. If a flag is 356 | // defined more than once in the command line or flag file, the last 357 | // definition is used. Returns the index (into argv) of the first 358 | // non-flag argument. (If remove_flags is true, will always return 1.) 359 | extern uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv, 360 | bool remove_flags); 361 | // This is actually defined in gflags_reporting.cc. 362 | // This function is misnamed (it also handles --version, etc.), but 363 | // it's too late to change that now. :-( 364 | extern void HandleCommandLineHelpFlags(); // in gflags_reporting.cc 365 | 366 | // Allow command line reparsing. Disables the error normally 367 | // generated when an unknown flag is found, since it may be found in a 368 | // later parse. Thread-hostile; meant to be called before any threads 369 | // are spawned. 370 | extern void AllowCommandLineReparsing(); 371 | 372 | // Reparse the flags that have not yet been recognized. Only flags 373 | // registered since the last parse will be recognized. Any flag value 374 | // must be provided as part of the argument using "=", not as a 375 | // separate command line argument that follows the flag argument. 376 | // Intended for handling flags from dynamically loaded libraries, 377 | // since their flags are not registered until they are loaded. 378 | extern void ReparseCommandLineNonHelpFlags(); 379 | 380 | // Clean up memory allocated by flags. This is only needed to reduce 381 | // the quantity of "potentially leaked" reports emitted by memory 382 | // debugging tools such as valgrind. It is not required for normal 383 | // operation, or for the google perftools heap-checker. It must only 384 | // be called when the process is about to exit, and all threads that 385 | // might access flags are quiescent. Referencing flags after this is 386 | // called will have unexpected consequences. This is not safe to run 387 | // when multiple threads might be running: the function is 388 | // thread-hostile. 389 | extern void ShutDownCommandLineFlags(); 390 | 391 | 392 | // -------------------------------------------------------------------- 393 | // Now come the command line flag declaration/definition macros that 394 | // will actually be used. They're kind of hairy. A major reason 395 | // for this is initialization: we want people to be able to access 396 | // variables in global constructors and have that not crash, even if 397 | // their global constructor runs before the global constructor here. 398 | // (Obviously, we can't guarantee the flags will have the correct 399 | // default value in that case, but at least accessing them is safe.) 400 | // The only way to do that is have flags point to a static buffer. 401 | // So we make one, using a union to ensure proper alignment, and 402 | // then use placement-new to actually set up the flag with the 403 | // correct default value. In the same vein, we have to worry about 404 | // flag access in global destructors, so FlagRegisterer has to be 405 | // careful never to destroy the flag-values it constructs. 406 | // 407 | // Note that when we define a flag variable FLAGS_, we also 408 | // preemptively define a junk variable, FLAGS_no. This is to 409 | // cause a link-time error if someone tries to define 2 flags with 410 | // names like "logging" and "nologging". We do this because a bool 411 | // flag FLAG can be set from the command line to true with a "-FLAG" 412 | // argument, and to false with a "-noFLAG" argument, and so this can 413 | // potentially avert confusion. 414 | // 415 | // We also put flags into their own namespace. It is purposefully 416 | // named in an opaque way that people should have trouble typing 417 | // directly. The idea is that DEFINE puts the flag in the weird 418 | // namespace, and DECLARE imports the flag from there into the current 419 | // namespace. The net result is to force people to use DECLARE to get 420 | // access to a flag, rather than saying "extern bool FLAGS_whatever;" 421 | // or some such instead. We want this so we can put extra 422 | // functionality (like sanity-checking) in DECLARE if we want, and 423 | // make sure it is picked up everywhere. 424 | // 425 | // We also put the type of the variable in the namespace, so that 426 | // people can't DECLARE_int32 something that they DEFINE_bool'd 427 | // elsewhere. 428 | 429 | class GFLAGS_DLL_DECL FlagRegisterer { 430 | public: 431 | FlagRegisterer(const char* name, const char* type, 432 | const char* help, const char* filename, 433 | void* current_storage, void* defvalue_storage); 434 | }; 435 | 436 | // If your application #defines STRIP_FLAG_HELP to a non-zero value 437 | // before #including this file, we remove the help message from the 438 | // binary file. This can reduce the size of the resulting binary 439 | // somewhat, and may also be useful for security reasons. 440 | 441 | extern const char kStrippedFlagHelp[]; 442 | 443 | } 444 | 445 | #ifndef SWIG // In swig, ignore the main flag declarations 446 | 447 | #if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0 448 | // Need this construct to avoid the 'defined but not used' warning. 449 | #define MAYBE_STRIPPED_HELP(txt) \ 450 | (false ? (txt) : ::google::kStrippedFlagHelp) 451 | #else 452 | #define MAYBE_STRIPPED_HELP(txt) txt 453 | #endif 454 | 455 | // Each command-line flag has two variables associated with it: one 456 | // with the current value, and one with the default value. However, 457 | // we have a third variable, which is where value is assigned; it's a 458 | // constant. This guarantees that FLAG_##value is initialized at 459 | // static initialization time (e.g. before program-start) rather than 460 | // than global construction time (which is after program-start but 461 | // before main), at least when 'value' is a compile-time constant. We 462 | // use a small trick for the "default value" variable, and call it 463 | // FLAGS_no. This serves the second purpose of assuring a 464 | // compile error if someone tries to define a flag named no 465 | // which is illegal (--foo and --nofoo both affect the "foo" flag). 466 | #define DEFINE_VARIABLE(type, shorttype, name, value, help) \ 467 | namespace fL##shorttype { \ 468 | static const type FLAGS_nono##name = value; \ 469 | /* We always want to export defined variables, dll or no */ \ 470 | GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name; \ 471 | type FLAGS_no##name = FLAGS_nono##name; \ 472 | static ::google::FlagRegisterer o_##name( \ 473 | #name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \ 474 | &FLAGS_##name, &FLAGS_no##name); \ 475 | } \ 476 | using fL##shorttype::FLAGS_##name 477 | 478 | // For DEFINE_bool, we want to do the extra check that the passed-in 479 | // value is actually a bool, and not a string or something that can be 480 | // coerced to a bool. These declarations (no definition needed!) will 481 | // help us do that, and never evaluate From, which is important. 482 | // We'll use 'sizeof(IsBool(val))' to distinguish. This code requires 483 | // that the compiler have different sizes for bool & double. Since 484 | // this is not guaranteed by the standard, we check it with a 485 | // COMPILE_ASSERT. 486 | namespace fLB { 487 | struct CompileAssert {}; 488 | typedef CompileAssert expected_sizeof_double_neq_sizeof_bool[ 489 | (sizeof(double) != sizeof(bool)) ? 1 : -1]; 490 | template double GFLAGS_DLL_DECL IsBoolFlag(const From& from); 491 | GFLAGS_DLL_DECL bool IsBoolFlag(bool from); 492 | } // namespace fLB 493 | 494 | // Here are the actual DEFINE_*-macros. The respective DECLARE_*-macros 495 | // are in a separate include, gflags_declare.h, for reducing 496 | // the physical transitive size for DECLARE use. 497 | #define DEFINE_bool(name, val, txt) \ 498 | namespace fLB { \ 499 | typedef ::fLB::CompileAssert FLAG_##name##_value_is_not_a_bool[ \ 500 | (sizeof(::fLB::IsBoolFlag(val)) != sizeof(double)) ? 1 : -1]; \ 501 | } \ 502 | DEFINE_VARIABLE(bool, B, name, val, txt) 503 | 504 | #define DEFINE_int32(name, val, txt) \ 505 | DEFINE_VARIABLE(::google::int32, I, \ 506 | name, val, txt) 507 | 508 | #define DEFINE_int64(name, val, txt) \ 509 | DEFINE_VARIABLE(::google::int64, I64, \ 510 | name, val, txt) 511 | 512 | #define DEFINE_uint64(name,val, txt) \ 513 | DEFINE_VARIABLE(::google::uint64, U64, \ 514 | name, val, txt) 515 | 516 | #define DEFINE_double(name, val, txt) \ 517 | DEFINE_VARIABLE(double, D, name, val, txt) 518 | 519 | // Strings are trickier, because they're not a POD, so we can't 520 | // construct them at static-initialization time (instead they get 521 | // constructed at global-constructor time, which is much later). To 522 | // try to avoid crashes in that case, we use a char buffer to store 523 | // the string, which we can static-initialize, and then placement-new 524 | // into it later. It's not perfect, but the best we can do. 525 | 526 | namespace fLS { 527 | 528 | inline clstring* dont_pass0toDEFINE_string(char *stringspot, 529 | const char *value) { 530 | return new(stringspot) clstring(value); 531 | } 532 | inline clstring* dont_pass0toDEFINE_string(char *stringspot, 533 | const clstring &value) { 534 | return new(stringspot) clstring(value); 535 | } 536 | inline clstring* dont_pass0toDEFINE_string(char *stringspot, 537 | int value); 538 | } // namespace fLS 539 | 540 | // We need to define a var named FLAGS_no##name so people don't define 541 | // --string and --nostring. And we need a temporary place to put val 542 | // so we don't have to evaluate it twice. Two great needs that go 543 | // great together! 544 | // The weird 'using' + 'extern' inside the fLS namespace is to work around 545 | // an unknown compiler bug/issue with the gcc 4.2.1 on SUSE 10. See 546 | // http://code.google.com/p/google-gflags/issues/detail?id=20 547 | #define DEFINE_string(name, val, txt) \ 548 | namespace fLS { \ 549 | using ::fLS::clstring; \ 550 | static union { void* align; char s[sizeof(clstring)]; } s_##name[2]; \ 551 | clstring* const FLAGS_no##name = ::fLS:: \ 552 | dont_pass0toDEFINE_string(s_##name[0].s, \ 553 | val); \ 554 | static ::google::FlagRegisterer o_##name( \ 555 | #name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \ 556 | s_##name[0].s, new (s_##name[1].s) clstring(*FLAGS_no##name)); \ 557 | extern GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name; \ 558 | using fLS::FLAGS_##name; \ 559 | clstring& FLAGS_##name = *FLAGS_no##name; \ 560 | } \ 561 | using fLS::FLAGS_##name 562 | 563 | #endif // SWIG 564 | 565 | #endif // BASE_COMMANDLINEFLAGS_H_ 566 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/gflags/include/gflags/gflags_completions.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // --- 31 | 32 | // 33 | // Implement helpful bash-style command line flag completions 34 | // 35 | // ** Functional API: 36 | // HandleCommandLineCompletions() should be called early during 37 | // program startup, but after command line flag code has been 38 | // initialized, such as the beginning of HandleCommandLineHelpFlags(). 39 | // It checks the value of the flag --tab_completion_word. If this 40 | // flag is empty, nothing happens here. If it contains a string, 41 | // however, then HandleCommandLineCompletions() will hijack the 42 | // process, attempting to identify the intention behind this 43 | // completion. Regardless of the outcome of this deduction, the 44 | // process will be terminated, similar to --helpshort flag 45 | // handling. 46 | // 47 | // ** Overview of Bash completions: 48 | // Bash can be told to programatically determine completions for the 49 | // current 'cursor word'. It does this by (in this case) invoking a 50 | // command with some additional arguments identifying the command 51 | // being executed, the word being completed, and the previous word 52 | // (if any). Bash then expects a sequence of output lines to be 53 | // printed to stdout. If these lines all contain a common prefix 54 | // longer than the cursor word, bash will replace the cursor word 55 | // with that common prefix, and display nothing. If there isn't such 56 | // a common prefix, bash will display the lines in pages using 'more'. 57 | // 58 | // ** Strategy taken for command line completions: 59 | // If we can deduce either the exact flag intended, or a common flag 60 | // prefix, we'll output exactly that. Otherwise, if information 61 | // must be displayed to the user, we'll take the opportunity to add 62 | // some helpful information beyond just the flag name (specifically, 63 | // we'll include the default flag value and as much of the flag's 64 | // description as can fit on a single terminal line width, as specified 65 | // by the flag --tab_completion_columns). Furthermore, we'll try to 66 | // make bash order the output such that the most useful or relevent 67 | // flags are the most likely to be shown at the top. 68 | // 69 | // ** Additional features: 70 | // To assist in finding that one really useful flag, substring matching 71 | // was implemented. Before pressing a to get completion for the 72 | // current word, you can append one or more '?' to the flag to do 73 | // substring matching. Here's the semantics: 74 | // --foo Show me all flags with names prefixed by 'foo' 75 | // --foo? Show me all flags with 'foo' somewhere in the name 76 | // --foo?? Same as prior case, but also search in module 77 | // definition path for 'foo' 78 | // --foo??? Same as prior case, but also search in flag 79 | // descriptions for 'foo' 80 | // Finally, we'll trim the output to a relatively small number of 81 | // flags to keep bash quiet about the verbosity of output. If one 82 | // really wanted to see all possible matches, appending a '+' to the 83 | // search word will force the exhaustive list of matches to be printed. 84 | // 85 | // ** How to have bash accept completions from a binary: 86 | // Bash requires that it be informed about each command that programmatic 87 | // completion should be enabled for. Example addition to a .bashrc 88 | // file would be (your path to gflags_completions.sh file may differ): 89 | 90 | /* 91 | $ complete -o bashdefault -o default -o nospace -C \ 92 | '/home/build/eng/bash/bash_completions.sh --tab_completion_columns $COLUMNS' \ 93 | time env binary_name another_binary [...] 94 | */ 95 | 96 | // This would allow the following to work: 97 | // $ /path/to/binary_name --vmodule 98 | // Or: 99 | // $ ./bin/path/another_binary --gfs_u 100 | // (etc) 101 | // 102 | // Sadly, it appears that bash gives no easy way to force this behavior for 103 | // all commands. That's where the "time" in the above example comes in. 104 | // If you haven't specifically added a command to the list of completion 105 | // supported commands, you can still get completions by prefixing the 106 | // entire command with "env". 107 | // $ env /some/brand/new/binary --vmod 108 | // Assuming that "binary" is a newly compiled binary, this should still 109 | // produce the expected completion output. 110 | 111 | 112 | #ifndef BASE_COMMANDLINEFLAGS_COMPLETIONS_H_ 113 | #define BASE_COMMANDLINEFLAGS_COMPLETIONS_H_ 114 | 115 | // Annoying stuff for windows -- makes sure clients can import these functions 116 | // 117 | // NOTE: all functions below MUST have an explicit 'extern' before 118 | // them. Our automated opensourcing tools use this as a signal to do 119 | // appropriate munging for windows, which needs to add GFLAGS_DLL_DECL. 120 | // 121 | #define GFLAGS_DLL_DECL /* rewritten to be non-empty in windows dir */ 122 | 123 | 124 | namespace google { 125 | 126 | extern void HandleCommandLineCompletions(void); 127 | 128 | } 129 | 130 | #endif // BASE_COMMANDLINEFLAGS_COMPLETIONS_H_ 131 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/gflags/include/gflags/gflags_declare.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 1999, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // --- 31 | // 32 | // Revamped and reorganized by Craig Silverstein 33 | // 34 | // This is the file that should be included by any file which declares 35 | // command line flag. 36 | 37 | #ifndef BASE_COMMANDLINEFLAGS_DECLARE_H_ 38 | #define BASE_COMMANDLINEFLAGS_DECLARE_H_ 39 | 40 | #include 41 | #if 1 42 | #include // the normal place uint16_t is defined 43 | #endif 44 | #if 1 45 | #include // the normal place u_int16_t is defined 46 | #endif 47 | #if 1 48 | #include // a third place for uint16_t or u_int16_t 49 | #endif 50 | 51 | namespace google { 52 | #if 1 // the C99 format 53 | typedef int32_t int32; 54 | typedef uint32_t uint32; 55 | typedef int64_t int64; 56 | typedef uint64_t uint64; 57 | #elif 1 // the BSD format 58 | typedef int32_t int32; 59 | typedef u_int32_t uint32; 60 | typedef int64_t int64; 61 | typedef u_int64_t uint64; 62 | #elif 0 // the windows (vc7) format 63 | typedef __int32 int32; 64 | typedef unsigned __int32 uint32; 65 | typedef __int64 int64; 66 | typedef unsigned __int64 uint64; 67 | #else 68 | #error Do not know how to define a 32-bit integer quantity on your system 69 | #endif 70 | } 71 | 72 | 73 | #define GFLAGS_DLL_DECLARE_FLAG /* rewritten to be non-empty in windows dir */ 74 | 75 | namespace fLS { 76 | 77 | // The meaning of "string" might be different between now and when the 78 | // macros below get invoked (e.g., if someone is experimenting with 79 | // other string implementations that get defined after this file is 80 | // included). Save the current meaning now and use it in the macros. 81 | typedef std::string clstring; 82 | 83 | } 84 | 85 | #define DECLARE_VARIABLE(type, shorttype, name) \ 86 | /* We always want to import declared variables, dll or no */ \ 87 | namespace fL##shorttype { extern GFLAGS_DLL_DECLARE_FLAG type FLAGS_##name; } \ 88 | using fL##shorttype::FLAGS_##name 89 | 90 | #define DECLARE_bool(name) \ 91 | DECLARE_VARIABLE(bool, B, name) 92 | 93 | #define DECLARE_int32(name) \ 94 | DECLARE_VARIABLE(::google::int32, I, name) 95 | 96 | #define DECLARE_int64(name) \ 97 | DECLARE_VARIABLE(::google::int64, I64, name) 98 | 99 | #define DECLARE_uint64(name) \ 100 | DECLARE_VARIABLE(::google::uint64, U64, name) 101 | 102 | #define DECLARE_double(name) \ 103 | DECLARE_VARIABLE(double, D, name) 104 | 105 | #define DECLARE_string(name) \ 106 | namespace fLS { \ 107 | using ::fLS::clstring; \ 108 | extern GFLAGS_DLL_DECLARE_FLAG ::fLS::clstring& FLAGS_##name; \ 109 | } \ 110 | using fLS::FLAGS_##name 111 | 112 | #endif // BASE_COMMANDLINEFLAGS_DECLARE_H_ 113 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/gflags/include/google/gflags.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2006, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // Header files have moved from the google directory to the gflags 31 | // directory. This forwarding file is provided only for backwards 32 | // compatibility. Use gflags/gflags.h in all new code. 33 | 34 | #include 35 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/gflags/include/google/gflags_completions.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // Header files have moved from the google directory to the gflags 31 | // directory. This forwarding file is provided only for backwards 32 | // compatibility. Use gflags/gflags_completions.h in all new code. 33 | 34 | #include 35 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/gflags/lib/libgflags.2.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/intrude/94b5c06ea03cb93ffd62ebe20251956d0a74c4e2/src/insert_dylib_to_macho/gflags/lib/libgflags.2.dylib -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/gflags/lib/libgflags.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/intrude/94b5c06ea03cb93ffd62ebe20251956d0a74c4e2/src/insert_dylib_to_macho/gflags/lib/libgflags.a -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/gflags/lib/libgflags.dylib: -------------------------------------------------------------------------------- 1 | libgflags.2.dylib -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/gflags/lib/libgflags_nothreads.2.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/intrude/94b5c06ea03cb93ffd62ebe20251956d0a74c4e2/src/insert_dylib_to_macho/gflags/lib/libgflags_nothreads.2.dylib -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/gflags/lib/libgflags_nothreads.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/intrude/94b5c06ea03cb93ffd62ebe20251956d0a74c4e2/src/insert_dylib_to_macho/gflags/lib/libgflags_nothreads.a -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/gflags/lib/libgflags_nothreads.dylib: -------------------------------------------------------------------------------- 1 | libgflags_nothreads.2.dylib -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/gflags/lib/pkgconfig/libgflags.pc: -------------------------------------------------------------------------------- 1 | prefix=/usr/local/Cellar/gflags/2.0 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/lib 4 | includedir=${prefix}/include 5 | 6 | Name: gflags 7 | Version: 2.0 8 | Description: A commandline flags library that allows for distributed flags 9 | URL: http://code.google.com/p/gflags 10 | Requires: 11 | Libs: -L${libdir} -lgflags 12 | Libs.private: -D_THREAD_SAFE 13 | Cflags: -I${includedir} 14 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/gflags/lib/pkgconfig/libgflags_nothreads.pc: -------------------------------------------------------------------------------- 1 | prefix=/usr/local/Cellar/gflags/2.0 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/lib 4 | includedir=${prefix}/include 5 | 6 | Name: gflags 7 | Version: 2.0 8 | Description: A commandline flags library that allows for distributed flags 9 | URL: http://code.google.com/p/gflags 10 | Requires: 11 | Libs: -L${libdir} -lgflags_nothreads 12 | Cflags: -I${includedir} 13 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/insert_dylib_to_macho.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7F064EEF1B256861009937FD /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F064EEE1B256861009937FD /* main.cpp */; }; 11 | 7F064F1D1B25CCCE009937FD /* libgflags.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F064F141B25CCCE009937FD /* libgflags.a */; }; 12 | 7F064F301B26F119009937FD /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F064F2E1B26F118009937FD /* util.cpp */; }; 13 | 7F8C4C511B2BE1A80050CD1B /* exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F8C4C4F1B2BE1A80050CD1B /* exception.cpp */; }; 14 | /* End PBXBuildFile section */ 15 | 16 | /* Begin PBXCopyFilesBuildPhase section */ 17 | 7F064EE91B256861009937FD /* CopyFiles */ = { 18 | isa = PBXCopyFilesBuildPhase; 19 | buildActionMask = 2147483647; 20 | dstPath = /usr/share/man/man1/; 21 | dstSubfolderSpec = 0; 22 | files = ( 23 | ); 24 | runOnlyForDeploymentPostprocessing = 1; 25 | }; 26 | /* End PBXCopyFilesBuildPhase section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 7F064EEB1B256861009937FD /* insert_dylib_to_macho */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = insert_dylib_to_macho; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | 7F064EEE1B256861009937FD /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; 31 | 7F064EF61B2576BB009937FD /* arch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arch.h; sourceTree = ""; }; 32 | 7F064EF81B2576BB009937FD /* reloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; 33 | 7F064EFA1B2576BB009937FD /* reloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; 34 | 7F064EFB1B2576BB009937FD /* compact_unwind_encoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = compact_unwind_encoding.h; sourceTree = ""; }; 35 | 7F064EFC1B2576BB009937FD /* fat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fat.h; sourceTree = ""; }; 36 | 7F064EFD1B2576BB009937FD /* loader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = loader.h; sourceTree = ""; }; 37 | 7F064EFE1B2576BB009937FD /* nlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nlist.h; sourceTree = ""; }; 38 | 7F064EFF1B2576BB009937FD /* ranlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ranlib.h; sourceTree = ""; }; 39 | 7F064F001B2576BB009937FD /* reloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; 40 | 7F064F011B2576BB009937FD /* swap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = swap.h; sourceTree = ""; }; 41 | 7F064F031B2576BB009937FD /* reloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; 42 | 7F064F0C1B25CCCE009937FD /* gflags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gflags.h; sourceTree = ""; }; 43 | 7F064F0D1B25CCCE009937FD /* gflags_completions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gflags_completions.h; sourceTree = ""; }; 44 | 7F064F0E1B25CCCE009937FD /* gflags_declare.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gflags_declare.h; sourceTree = ""; }; 45 | 7F064F101B25CCCE009937FD /* gflags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gflags.h; sourceTree = ""; }; 46 | 7F064F111B25CCCE009937FD /* gflags_completions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gflags_completions.h; sourceTree = ""; }; 47 | 7F064F141B25CCCE009937FD /* libgflags.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgflags.a; sourceTree = ""; }; 48 | 7F064F231B25D026009937FD /* record.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = record.h; sourceTree = ""; }; 49 | 7F064F261B25D1A2009937FD /* macho_brief_info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = macho_brief_info.h; sourceTree = ""; }; 50 | 7F064F291B25D4BF009937FD /* workflow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = workflow.h; sourceTree = ""; }; 51 | 7F064F2E1B26F118009937FD /* util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = util.cpp; sourceTree = ""; }; 52 | 7F064F2F1B26F119009937FD /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = ""; }; 53 | 7F8C4C4F1B2BE1A80050CD1B /* exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = exception.cpp; sourceTree = ""; }; 54 | 7F8C4C501B2BE1A80050CD1B /* exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = exception.h; sourceTree = ""; }; 55 | /* End PBXFileReference section */ 56 | 57 | /* Begin PBXFrameworksBuildPhase section */ 58 | 7F064EE81B256861009937FD /* Frameworks */ = { 59 | isa = PBXFrameworksBuildPhase; 60 | buildActionMask = 2147483647; 61 | files = ( 62 | 7F064F1D1B25CCCE009937FD /* libgflags.a in Frameworks */, 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | 7F064EE21B256861009937FD = { 70 | isa = PBXGroup; 71 | children = ( 72 | 7F064F091B25CCCE009937FD /* gflags */, 73 | 7F064EF51B2576BB009937FD /* mach-o */, 74 | 7F064EED1B256861009937FD /* insert_dylib_to_macho */, 75 | 7F064EEC1B256861009937FD /* Products */, 76 | ); 77 | sourceTree = ""; 78 | }; 79 | 7F064EEC1B256861009937FD /* Products */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 7F064EEB1B256861009937FD /* insert_dylib_to_macho */, 83 | ); 84 | name = Products; 85 | sourceTree = ""; 86 | }; 87 | 7F064EED1B256861009937FD /* insert_dylib_to_macho */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 7F064EEE1B256861009937FD /* main.cpp */, 91 | 7F064F231B25D026009937FD /* record.h */, 92 | 7F064F261B25D1A2009937FD /* macho_brief_info.h */, 93 | 7F064F291B25D4BF009937FD /* workflow.h */, 94 | 7F064F2E1B26F118009937FD /* util.cpp */, 95 | 7F064F2F1B26F119009937FD /* util.h */, 96 | 7F8C4C4F1B2BE1A80050CD1B /* exception.cpp */, 97 | 7F8C4C501B2BE1A80050CD1B /* exception.h */, 98 | ); 99 | path = insert_dylib_to_macho; 100 | sourceTree = ""; 101 | }; 102 | 7F064EF51B2576BB009937FD /* mach-o */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 7F064EF61B2576BB009937FD /* arch.h */, 106 | 7F064EF71B2576BB009937FD /* arm */, 107 | 7F064EF91B2576BB009937FD /* arm64 */, 108 | 7F064EFB1B2576BB009937FD /* compact_unwind_encoding.h */, 109 | 7F064EFC1B2576BB009937FD /* fat.h */, 110 | 7F064EFD1B2576BB009937FD /* loader.h */, 111 | 7F064EFE1B2576BB009937FD /* nlist.h */, 112 | 7F064EFF1B2576BB009937FD /* ranlib.h */, 113 | 7F064F001B2576BB009937FD /* reloc.h */, 114 | 7F064F011B2576BB009937FD /* swap.h */, 115 | 7F064F021B2576BB009937FD /* x86_64 */, 116 | ); 117 | path = "mach-o"; 118 | sourceTree = ""; 119 | }; 120 | 7F064EF71B2576BB009937FD /* arm */ = { 121 | isa = PBXGroup; 122 | children = ( 123 | 7F064EF81B2576BB009937FD /* reloc.h */, 124 | ); 125 | path = arm; 126 | sourceTree = ""; 127 | }; 128 | 7F064EF91B2576BB009937FD /* arm64 */ = { 129 | isa = PBXGroup; 130 | children = ( 131 | 7F064EFA1B2576BB009937FD /* reloc.h */, 132 | ); 133 | path = arm64; 134 | sourceTree = ""; 135 | }; 136 | 7F064F021B2576BB009937FD /* x86_64 */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 7F064F031B2576BB009937FD /* reloc.h */, 140 | ); 141 | path = x86_64; 142 | sourceTree = ""; 143 | }; 144 | 7F064F091B25CCCE009937FD /* gflags */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | 7F064F0A1B25CCCE009937FD /* include */, 148 | 7F064F121B25CCCE009937FD /* lib */, 149 | ); 150 | path = gflags; 151 | sourceTree = ""; 152 | }; 153 | 7F064F0A1B25CCCE009937FD /* include */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | 7F064F0B1B25CCCE009937FD /* gflags */, 157 | 7F064F0F1B25CCCE009937FD /* google */, 158 | ); 159 | path = include; 160 | sourceTree = ""; 161 | }; 162 | 7F064F0B1B25CCCE009937FD /* gflags */ = { 163 | isa = PBXGroup; 164 | children = ( 165 | 7F064F0C1B25CCCE009937FD /* gflags.h */, 166 | 7F064F0D1B25CCCE009937FD /* gflags_completions.h */, 167 | 7F064F0E1B25CCCE009937FD /* gflags_declare.h */, 168 | ); 169 | path = gflags; 170 | sourceTree = ""; 171 | }; 172 | 7F064F0F1B25CCCE009937FD /* google */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | 7F064F101B25CCCE009937FD /* gflags.h */, 176 | 7F064F111B25CCCE009937FD /* gflags_completions.h */, 177 | ); 178 | path = google; 179 | sourceTree = ""; 180 | }; 181 | 7F064F121B25CCCE009937FD /* lib */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | 7F064F141B25CCCE009937FD /* libgflags.a */, 185 | ); 186 | path = lib; 187 | sourceTree = ""; 188 | }; 189 | /* End PBXGroup section */ 190 | 191 | /* Begin PBXNativeTarget section */ 192 | 7F064EEA1B256861009937FD /* insert_dylib_to_macho */ = { 193 | isa = PBXNativeTarget; 194 | buildConfigurationList = 7F064EF21B256861009937FD /* Build configuration list for PBXNativeTarget "insert_dylib_to_macho" */; 195 | buildPhases = ( 196 | 7F064EE71B256861009937FD /* Sources */, 197 | 7F064EE81B256861009937FD /* Frameworks */, 198 | 7F064EE91B256861009937FD /* CopyFiles */, 199 | ); 200 | buildRules = ( 201 | ); 202 | dependencies = ( 203 | ); 204 | name = insert_dylib_to_macho; 205 | productName = insert_dylib_to_macho; 206 | productReference = 7F064EEB1B256861009937FD /* insert_dylib_to_macho */; 207 | productType = "com.apple.product-type.tool"; 208 | }; 209 | /* End PBXNativeTarget section */ 210 | 211 | /* Begin PBXProject section */ 212 | 7F064EE31B256861009937FD /* Project object */ = { 213 | isa = PBXProject; 214 | attributes = { 215 | LastUpgradeCheck = 0630; 216 | ORGANIZATIONNAME = imoldman; 217 | TargetAttributes = { 218 | 7F064EEA1B256861009937FD = { 219 | CreatedOnToolsVersion = 6.3; 220 | }; 221 | }; 222 | }; 223 | buildConfigurationList = 7F064EE61B256861009937FD /* Build configuration list for PBXProject "insert_dylib_to_macho" */; 224 | compatibilityVersion = "Xcode 3.2"; 225 | developmentRegion = English; 226 | hasScannedForEncodings = 0; 227 | knownRegions = ( 228 | en, 229 | ); 230 | mainGroup = 7F064EE21B256861009937FD; 231 | productRefGroup = 7F064EEC1B256861009937FD /* Products */; 232 | projectDirPath = ""; 233 | projectRoot = ""; 234 | targets = ( 235 | 7F064EEA1B256861009937FD /* insert_dylib_to_macho */, 236 | ); 237 | }; 238 | /* End PBXProject section */ 239 | 240 | /* Begin PBXSourcesBuildPhase section */ 241 | 7F064EE71B256861009937FD /* Sources */ = { 242 | isa = PBXSourcesBuildPhase; 243 | buildActionMask = 2147483647; 244 | files = ( 245 | 7F064EEF1B256861009937FD /* main.cpp in Sources */, 246 | 7F064F301B26F119009937FD /* util.cpp in Sources */, 247 | 7F8C4C511B2BE1A80050CD1B /* exception.cpp in Sources */, 248 | ); 249 | runOnlyForDeploymentPostprocessing = 0; 250 | }; 251 | /* End PBXSourcesBuildPhase section */ 252 | 253 | /* Begin XCBuildConfiguration section */ 254 | 7F064EF01B256861009937FD /* Debug */ = { 255 | isa = XCBuildConfiguration; 256 | buildSettings = { 257 | ALWAYS_SEARCH_USER_PATHS = NO; 258 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 259 | CLANG_CXX_LIBRARY = "libc++"; 260 | CLANG_ENABLE_MODULES = YES; 261 | CLANG_ENABLE_OBJC_ARC = YES; 262 | CLANG_WARN_BOOL_CONVERSION = YES; 263 | CLANG_WARN_CONSTANT_CONVERSION = YES; 264 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 265 | CLANG_WARN_EMPTY_BODY = YES; 266 | CLANG_WARN_ENUM_CONVERSION = YES; 267 | CLANG_WARN_INT_CONVERSION = YES; 268 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 269 | CLANG_WARN_UNREACHABLE_CODE = YES; 270 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 271 | COPY_PHASE_STRIP = NO; 272 | DEBUG_INFORMATION_FORMAT = dwarf; 273 | ENABLE_STRICT_OBJC_MSGSEND = YES; 274 | GCC_C_LANGUAGE_STANDARD = gnu99; 275 | GCC_DYNAMIC_NO_PIC = NO; 276 | GCC_NO_COMMON_BLOCKS = YES; 277 | GCC_OPTIMIZATION_LEVEL = 0; 278 | GCC_PREPROCESSOR_DEFINITIONS = ( 279 | "DEBUG=1", 280 | "$(inherited)", 281 | ); 282 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 283 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 284 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 285 | GCC_WARN_UNDECLARED_SELECTOR = YES; 286 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 287 | GCC_WARN_UNUSED_FUNCTION = YES; 288 | GCC_WARN_UNUSED_VARIABLE = YES; 289 | MACOSX_DEPLOYMENT_TARGET = 10.10; 290 | MTL_ENABLE_DEBUG_INFO = YES; 291 | ONLY_ACTIVE_ARCH = YES; 292 | SDKROOT = macosx; 293 | }; 294 | name = Debug; 295 | }; 296 | 7F064EF11B256861009937FD /* Release */ = { 297 | isa = XCBuildConfiguration; 298 | buildSettings = { 299 | ALWAYS_SEARCH_USER_PATHS = NO; 300 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 301 | CLANG_CXX_LIBRARY = "libc++"; 302 | CLANG_ENABLE_MODULES = YES; 303 | CLANG_ENABLE_OBJC_ARC = YES; 304 | CLANG_WARN_BOOL_CONVERSION = YES; 305 | CLANG_WARN_CONSTANT_CONVERSION = YES; 306 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 307 | CLANG_WARN_EMPTY_BODY = YES; 308 | CLANG_WARN_ENUM_CONVERSION = YES; 309 | CLANG_WARN_INT_CONVERSION = YES; 310 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 311 | CLANG_WARN_UNREACHABLE_CODE = YES; 312 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 313 | COPY_PHASE_STRIP = NO; 314 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 315 | ENABLE_NS_ASSERTIONS = NO; 316 | ENABLE_STRICT_OBJC_MSGSEND = YES; 317 | GCC_C_LANGUAGE_STANDARD = gnu99; 318 | GCC_NO_COMMON_BLOCKS = YES; 319 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 320 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 321 | GCC_WARN_UNDECLARED_SELECTOR = YES; 322 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 323 | GCC_WARN_UNUSED_FUNCTION = YES; 324 | GCC_WARN_UNUSED_VARIABLE = YES; 325 | MACOSX_DEPLOYMENT_TARGET = 10.10; 326 | MTL_ENABLE_DEBUG_INFO = NO; 327 | SDKROOT = macosx; 328 | }; 329 | name = Release; 330 | }; 331 | 7F064EF31B256861009937FD /* Debug */ = { 332 | isa = XCBuildConfiguration; 333 | buildSettings = { 334 | HEADER_SEARCH_PATHS = ( 335 | "$(inherited)", 336 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 337 | ./gflags/include, 338 | ); 339 | LIBRARY_SEARCH_PATHS = ( 340 | "$(inherited)", 341 | "$(PROJECT_DIR)/gflags/lib", 342 | ); 343 | PRODUCT_NAME = "$(TARGET_NAME)"; 344 | }; 345 | name = Debug; 346 | }; 347 | 7F064EF41B256861009937FD /* Release */ = { 348 | isa = XCBuildConfiguration; 349 | buildSettings = { 350 | HEADER_SEARCH_PATHS = ( 351 | "$(inherited)", 352 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 353 | ./gflags/include, 354 | ); 355 | LIBRARY_SEARCH_PATHS = ( 356 | "$(inherited)", 357 | "$(PROJECT_DIR)/gflags/lib", 358 | ); 359 | PRODUCT_NAME = "$(TARGET_NAME)"; 360 | }; 361 | name = Release; 362 | }; 363 | /* End XCBuildConfiguration section */ 364 | 365 | /* Begin XCConfigurationList section */ 366 | 7F064EE61B256861009937FD /* Build configuration list for PBXProject "insert_dylib_to_macho" */ = { 367 | isa = XCConfigurationList; 368 | buildConfigurations = ( 369 | 7F064EF01B256861009937FD /* Debug */, 370 | 7F064EF11B256861009937FD /* Release */, 371 | ); 372 | defaultConfigurationIsVisible = 0; 373 | defaultConfigurationName = Release; 374 | }; 375 | 7F064EF21B256861009937FD /* Build configuration list for PBXNativeTarget "insert_dylib_to_macho" */ = { 376 | isa = XCConfigurationList; 377 | buildConfigurations = ( 378 | 7F064EF31B256861009937FD /* Debug */, 379 | 7F064EF41B256861009937FD /* Release */, 380 | ); 381 | defaultConfigurationIsVisible = 0; 382 | defaultConfigurationName = Release; 383 | }; 384 | /* End XCConfigurationList section */ 385 | }; 386 | rootObject = 7F064EE31B256861009937FD /* Project object */; 387 | } 388 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/insert_dylib_to_macho.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/insert_dylib_to_macho/exception.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // exception.cpp 3 | // insert_dylib_to_macho 4 | // 5 | // Created by oldman on 6/13/15. 6 | // Copyright (c) 2015 imoldman. All rights reserved. 7 | // 8 | 9 | #include "exception.h" 10 | #include 11 | 12 | Exception::Exception(ExceptionCode code, const std::string& description) : code_(code), description_(description) { 13 | std::ostringstream ss(what_); 14 | ss << "code: " << (int)code << ", detail: " << description; 15 | } 16 | 17 | const char* Exception::what() const noexcept { 18 | return what_.c_str(); 19 | } 20 | 21 | ExceptionCode Exception::code() const { 22 | return code_; 23 | } 24 | 25 | const std::string& Exception::description() const { 26 | return description_; 27 | } -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/insert_dylib_to_macho/exception.h: -------------------------------------------------------------------------------- 1 | // 2 | // exception.h 3 | // insert_dylib_to_macho 4 | // 5 | // Created by oldman on 6/13/15. 6 | // Copyright (c) 2015 imoldman. All rights reserved. 7 | // 8 | 9 | #ifndef __insert_dylib_to_macho__exception__ 10 | #define __insert_dylib_to_macho__exception__ 11 | 12 | #include 13 | #include 14 | 15 | enum class ExceptionCode 16 | { 17 | kShouldNotOccur = 1, 18 | kParamInvalid, 19 | kReadFailed, 20 | kWriteFailed, 21 | kNotImplement, 22 | }; 23 | 24 | class Exception : public std::exception { 25 | public: 26 | Exception(ExceptionCode code, const std::string& description); 27 | ExceptionCode code() const; 28 | const std::string& description() const; 29 | virtual const char* what() const noexcept; 30 | private: 31 | ExceptionCode code_; 32 | std::string description_; 33 | std::string what_; 34 | }; 35 | 36 | #endif /* defined(__insert_dylib_to_macho__exception__) */ 37 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/insert_dylib_to_macho/macho_brief_info.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by oldman on 6/8/15. 3 | // 4 | 5 | #ifndef __insert_dylib_to_macho__macho_brief_info__ 6 | #define __insert_dylib_to_macho__macho_brief_info__ 7 | 8 | #include "record.h" 9 | #include "loader.h" 10 | 11 | struct MachHeader : public mach_header {}; 12 | struct MachHeader64 : public mach_header_64 {}; 13 | struct SegmentCommand : public segment_command {}; 14 | struct SegmentCommand64 : public segment_command_64 {}; 15 | struct SectionHeader : public section {}; 16 | struct SectionHeader64 : public section_64 {}; 17 | struct DylibCommand : public dylib_command {}; 18 | struct LoadCommand : public load_command {}; 19 | 20 | class MachoBriefInfo32 21 | { 22 | public: 23 | typedef MachHeader MachHeader; 24 | typedef SegmentCommand SegmentCommand; 25 | typedef DylibCommand DylibCommand; 26 | typedef LoadCommand LoadCommand; 27 | typedef SectionHeader SectionHeader; 28 | static const uint32_t kAlignBase = 4; 29 | 30 | Record mach_header; 31 | std::vector> commands; 32 | std::vector> section_headers; 33 | }; 34 | 35 | class MachoBriefInfo64 36 | { 37 | public: 38 | typedef MachHeader64 MachHeader; 39 | typedef SegmentCommand64 SegmentCommand; 40 | typedef DylibCommand DylibCommand; 41 | typedef LoadCommand LoadCommand; 42 | typedef SectionHeader64 SectionHeader; 43 | static const uint32_t kAlignBase = 8; 44 | 45 | Record mach_header; 46 | std::vector> commands; 47 | std::vector> section_headers; 48 | }; 49 | 50 | #endif /* defined(__insert_dylib_to_macho__macho_brief_info__) */ 51 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/insert_dylib_to_macho/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by oldman on 6/8/15. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "exception.h" 10 | #include "macho_brief_info.h" 11 | #include "util.h" 12 | #include "workflow.h" 13 | 14 | 15 | // insert_dylib_to_macho --src src_path --dest dest_path --dylib dylib_path 16 | 17 | DEFINE_string(file, "", "full path of macho file to be modified"); 18 | 19 | 20 | void init_gflag_config(int& argc, char**& argv) { 21 | std::string usage("insert a dylib load command to a macho file, result is the dylib file name, e.g.\n"); 22 | usage += std::string("\t") + argv[0] + " --file ./some.app/some\n"; 23 | usage += std::string("the result is:\n"); 24 | usage += std::string("\t{\"error\":0, \"filename\":\"a.dylib\"}"); 25 | ::google::SetUsageMessage(usage); 26 | 27 | ::google::ParseCommandLineFlags(&argc, &argv, true); 28 | 29 | if (FLAGS_file.length() == 0) { 30 | throw Exception(ExceptionCode::kParamInvalid, "invalid param, please check the usage"); 31 | } 32 | } 33 | 34 | bool is_64bit_macho_file(const std::string& file) { 35 | uint32_t magic_number = 0; 36 | util::read(file, 0, sizeof(magic_number), &magic_number); 37 | assert(magic_number == MH_MAGIC || magic_number == MH_CIGAM || magic_number == MH_MAGIC_64 || magic_number == MH_CIGAM_64); 38 | if (magic_number == MH_MAGIC || magic_number == MH_CIGAM) { 39 | return false; 40 | } else if (magic_number == MH_MAGIC_64 || magic_number == MH_CIGAM_64) { 41 | return true; 42 | } else { 43 | throw Exception(ExceptionCode::kShouldNotOccur, util::build_string([&](std::ostringstream& ss) { 44 | ss << "invalid macho file, magic number is " << std::hex << magic_number; 45 | })); 46 | } 47 | } 48 | 49 | template 50 | std::string run_workflow_and_get_dylib_name(Workflow& wf) { 51 | wf.run(); 52 | return wf.fresh_dylib_name(); 53 | } 54 | 55 | std::string build_success_result(const std::string& dylib_name) { 56 | return util::build_string([&](std::ostringstream& ss) { 57 | ss << "{\"error\":0, \"filename\":\"" << dylib_name << "\"}"; 58 | }); 59 | } 60 | 61 | std::string build_failed_result(const Exception& exception) { 62 | return util::build_string([&](std::ostringstream& ss) { 63 | ss << "{\"error\":" << (int)exception.code() << ", \"description\":\"" << exception.description() << "\"}"; 64 | }); 65 | } 66 | 67 | int main(int argc, char* argv[]) { 68 | 69 | try { 70 | init_gflag_config(argc, argv); 71 | 72 | std::string fresh_dylib_name; 73 | if (is_64bit_macho_file(FLAGS_file)) { 74 | Workflow workflow(FLAGS_file); 75 | fresh_dylib_name = run_workflow_and_get_dylib_name(workflow); 76 | } else { 77 | Workflow workflow(FLAGS_file); 78 | fresh_dylib_name = run_workflow_and_get_dylib_name(workflow); 79 | } 80 | std::cout << build_success_result(fresh_dylib_name); 81 | return 0; 82 | } catch (Exception& e) { 83 | std::cerr << build_failed_result(e); 84 | return (int)e.code(); 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/insert_dylib_to_macho/record.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by oldman on 6/8/15. 3 | // 4 | 5 | #ifndef __insert_dylib_to_macho__record__ 6 | #define __insert_dylib_to_macho__record__ 7 | 8 | #include 9 | 10 | template 11 | class Record { 12 | public: 13 | Record() {}; 14 | Record(uint32_t offset, T&& v) : offset(offset), value(v) {}; 15 | ~Record() {}; 16 | 17 | uint32_t offset; 18 | T value; 19 | }; 20 | 21 | #endif /* defined(__insert_dylib_to_macho__record__) */ 22 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/insert_dylib_to_macho/util.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by oldman on 6/9/15. 3 | // 4 | 5 | #include "util.h" 6 | #include "exception.h" 7 | 8 | namespace util { 9 | bool string_start_with(const std::string& str, const std::string& prefix) { 10 | if (str.length() < prefix.length()) { 11 | return false; 12 | } 13 | return str.substr(0, prefix.length()) == prefix; 14 | } 15 | 16 | std::string build_string(std::function f) { 17 | std::ostringstream ss; 18 | f(ss); 19 | return ss.str(); 20 | } 21 | 22 | void read(FILE* file, uint32_t from, uint32_t size, void* buffer) { 23 | int err = fseek(file, from, SEEK_SET); 24 | if (err == 0) { 25 | size_t readed_size = fread(buffer, sizeof(char), size, file); 26 | if (size == readed_size) { 27 | return; 28 | } 29 | } 30 | throw Exception(ExceptionCode::kReadFailed, util::build_string([=](std::ostringstream& ss) { 31 | ss << "read failed, from: " << from << ", size: " << size; 32 | })); 33 | } 34 | 35 | void write(FILE* file, uint32_t from, uint32_t size, void* buffer) { 36 | int err = fseek(file, from, SEEK_SET); 37 | if (err == 0) { 38 | size_t wroted_size = fwrite(buffer, sizeof(char), size, file); 39 | if (size == wroted_size) { 40 | return; 41 | } 42 | } 43 | throw Exception(ExceptionCode::kWriteFailed, util::build_string([=](std::ostringstream& ss) { 44 | ss << "write failed, from: " << from << ", size: " << size; 45 | })); 46 | } 47 | 48 | void read(const std::string& file, uint32_t from, uint32_t size, void* buffer) { 49 | FILE* handler = fopen(file.c_str(), "rb"); 50 | if (handler == NULL) { 51 | throw Exception(ExceptionCode::kShouldNotOccur, util::build_string([&](std::ostringstream& ss) { 52 | ss << "open file failed, file: " << file << ", errno: " << errno; 53 | })); 54 | } 55 | return read(handler, from, size, buffer); 56 | } 57 | 58 | void write(const std::string& file, uint32_t from, uint32_t size, void* buffer) { 59 | FILE* handler = fopen(file.c_str(), "wb"); 60 | if (handler == NULL) { 61 | throw Exception(ExceptionCode::kShouldNotOccur, util::build_string([&](std::ostringstream& ss) { 62 | ss << "write file failed, file: " << file << ", errno: " << errno; 63 | })); 64 | } 65 | return read(handler, from, size, buffer); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/insert_dylib_to_macho/util.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by oldman on 6/9/15. 3 | // 4 | 5 | #ifndef __insert_dylib_to_macho__util__ 6 | #define __insert_dylib_to_macho__util__ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace util { 13 | bool string_start_with(const std::string& str, const std::string& prefix); 14 | 15 | std::string build_string(std::function f); 16 | 17 | void read(FILE* file, uint32_t from, uint32_t size, void* buffer); 18 | 19 | void write(FILE* file, uint32_t from, uint32_t size, void* buffer); 20 | 21 | void read(const std::string& file, uint32_t from, uint32_t size, void* buffer); 22 | 23 | void write(const std::string& file, uint32_t from, uint32_t size, void* buffer); 24 | } 25 | #endif /* defined(__insert_dylib_to_macho__util__) */ 26 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/insert_dylib_to_macho/workflow.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by oldman on 6/8/15. 3 | // 4 | 5 | #ifndef __insert_dylib_to_macho__runner__ 6 | #define __insert_dylib_to_macho__runner__ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "loader.h" 15 | #include "util.h" 16 | #include "exception.h" 17 | 18 | static const std::string kExecutablePathWithSlashPrefix = "@executable_path/"; 19 | static const std::string kDylibExtensionWithDot = ".dylib"; 20 | 21 | template 22 | class Workflow { 23 | public: 24 | Workflow(const std::string& macho_path) : macho_path_(macho_path) {} 25 | 26 | ~Workflow() {}; 27 | 28 | void run() { 29 | file_ = fopen(macho_path_.c_str(), "rb+"); 30 | if (file_ != NULL) { 31 | // 读取所需的Macho结构 32 | MachoBriefInfo info = do_read_macho_brief_info(); 33 | // 计算要插入的dylib名字 34 | dylib_name_ = calc_fresh_dylib_name_by_macho_info(info); 35 | // 根据dylib名字构建要插入的command 36 | DylibCommandToWrite dylib_command = make_dylib_command_by_name(dylib_name_); 37 | // 将command写入文件 38 | insert_command_to_dest_file(dylib_command, info); 39 | // 修改MachHeder 40 | MachHeader mach_header = get_modified_header(info, dylib_command); 41 | // 写入MachHeader 42 | write_mach_header_to_dest_file(mach_header); 43 | // 结束 44 | fclose(file_); 45 | return; 46 | } 47 | throw Exception(ExceptionCode::kShouldNotOccur, util::build_string([&](std::ostringstream& ss) { 48 | ss << "open file failed, file: " << macho_path_ << ", errno: " << errno; 49 | })); 50 | } 51 | 52 | std::string fresh_dylib_name() const { 53 | return dylib_name_; 54 | } 55 | 56 | private: 57 | #pragma mark - types 58 | typedef typename MachoBriefInfo::MachHeader MachHeader; 59 | typedef typename MachoBriefInfo::SegmentCommand SegmentCommand; 60 | typedef typename MachoBriefInfo::DylibCommand DylibCommand; 61 | typedef typename MachoBriefInfo::LoadCommand LoadCommand; 62 | typedef typename MachoBriefInfo::SectionHeader SectionHeader; 63 | static const uint32_t kAlignBase = MachoBriefInfo::kAlignBase; 64 | 65 | struct DylibCommandToWrite : public DylibCommand { 66 | std::string path; 67 | }; 68 | 69 | 70 | #pragma mark - actions 71 | MachoBriefInfo do_read_macho_brief_info() { 72 | MachoBriefInfo info; 73 | 74 | // read mach header 75 | info.mach_header = read_record(0); 76 | uint32_t offset = sizeof(MachHeader); 77 | 78 | // read commands and sections 79 | for (uint32_t index = 0; index < info.mach_header.value.ncmds; ++index) { 80 | auto command = read_record(offset); 81 | info.commands.push_back(command); 82 | if (command.value.cmd == LC_SEGMENT || command.value.cmd == LC_SEGMENT_64) { 83 | auto segment_command = read_record(offset); 84 | uint32_t section_header_offset = offset + sizeof(SegmentCommand); 85 | for (uint32_t section_index = 0; section_index < segment_command.value.nsects; ++section_index) { 86 | auto section_header = read_record(section_header_offset); 87 | info.section_headers.push_back(section_header); 88 | section_header_offset += sizeof(SectionHeader); 89 | } 90 | } 91 | offset += command.value.cmdsize; 92 | } 93 | 94 | // save 95 | return info; 96 | } 97 | 98 | std::string calc_fresh_dylib_name_by_macho_info(const MachoBriefInfo& macho_info) { 99 | std::set names; 100 | for (auto command : macho_info.commands) { 101 | if (command.value.cmd == LC_LOAD_DYLIB || command.value.cmd == LC_LOAD_WEAK_DYLIB || command.value.cmd == LC_REEXPORT_DYLIB) { 102 | auto dylib_command = read_record(command.offset); 103 | auto name_offset = dylib_command.value.dylib.name.offset; 104 | std::string name = read_cstring(command.offset + name_offset, dylib_command.value.cmdsize - name_offset); 105 | if (util::string_start_with(name, kExecutablePathWithSlashPrefix)) { 106 | names.insert(name.substr(kExecutablePathWithSlashPrefix.length())); 107 | } 108 | } 109 | } 110 | uint32_t try_max_count = (uint32_t)names.size() + 1; 111 | for (uint32_t try_index = 0; try_index < try_max_count; ++try_index) { 112 | std::string name; 113 | const uint32_t kScale = 26; 114 | for (uint32_t index = try_index; index != 0; index /= kScale) { 115 | name.push_back('a' + (index % kScale)); 116 | } 117 | if (name.size() == 0) { 118 | name.push_back('a'); 119 | } 120 | name += kDylibExtensionWithDot; 121 | if (names.find(name) == names.end()) { 122 | return name; // no conflict 123 | } 124 | } 125 | throw Exception(ExceptionCode::kShouldNotOccur, "can not find a suitable name for the dylib"); 126 | return std::string(); 127 | } 128 | 129 | DylibCommandToWrite make_dylib_command_by_name(const std::string& dylib_name) { 130 | DylibCommandToWrite result; 131 | result.cmd = LC_LOAD_DYLIB; 132 | result.dylib.timestamp = 2; 133 | result.dylib.current_version = 0; 134 | result.dylib.compatibility_version = 0; 135 | 136 | // path and length 137 | result.path = kExecutablePathWithSlashPrefix + dylib_name; 138 | result.path.push_back('\0'); 139 | 140 | // align to 32bit or 64bit 141 | uint32_t length = ((uint32_t)result.path.length() + kAlignBase - 1) / kAlignBase * kAlignBase; 142 | result.dylib.name.offset = 24; // 4 * 6 143 | result.cmdsize = result.dylib.name.offset + length; 144 | 145 | return result; 146 | } 147 | 148 | MachHeader get_modified_header(const MachoBriefInfo& macho_info, const DylibCommandToWrite& dylib_command) { 149 | MachHeader result = macho_info.mach_header.value; 150 | result.ncmds += 1; 151 | result.sizeofcmds += dylib_command.cmdsize; 152 | return result; 153 | } 154 | 155 | void insert_command_to_dest_file(const DylibCommandToWrite& new_command, const MachoBriefInfo& src_macho_info) { 156 | // find position to insert 157 | // find last command end position 158 | uint32_t insert_position = 0; 159 | uint32_t last_command_end_position = 0; 160 | for (auto command : src_macho_info.commands) { 161 | uint32_t command_end_position = command.offset + command.value.cmdsize; 162 | if (command.value.cmd == LC_LOAD_DYLIB || command.value.cmd == LC_LOAD_WEAK_DYLIB) { 163 | insert_position = std::max(insert_position, command_end_position); 164 | } 165 | last_command_end_position = std::max(last_command_end_position, command_end_position); 166 | 167 | } 168 | 169 | // find section 1 position 170 | uint32_t section_1_postion = UINT32_MAX; 171 | for (auto section_header : src_macho_info.section_headers) { 172 | if (section_header.value.offset != 0) { 173 | section_1_postion = section_header.value.offset; 174 | break; 175 | } 176 | } 177 | 178 | // check the space for new command 179 | if (section_1_postion - last_command_end_position < new_command.cmdsize) { 180 | throw Exception(ExceptionCode::kNotImplement, "now we counldn't move the sections"); 181 | } 182 | 183 | // write 184 | std::vector buffer(section_1_postion - insert_position); 185 | util::read(file_, insert_position, section_1_postion - insert_position - new_command.cmdsize, &buffer[0] + new_command.cmdsize); 186 | std::memcpy(&buffer[0], &new_command, sizeof(DylibCommand)); 187 | std::memcpy(&buffer[0] + sizeof(DylibCommand), &new_command.path[0], new_command.path.length()); 188 | util::write(file_, insert_position, (uint32_t)buffer.size(), &buffer[0]); 189 | } 190 | 191 | void write_mach_header_to_dest_file(const MachHeader& mach_header) { 192 | util::write(file_, 0, sizeof(MachHeader), (void*)&mach_header); 193 | } 194 | 195 | #pragma mark - util 196 | template T read(uint32_t from) { 197 | T result; 198 | util::read(file_, from, sizeof(T), &result); 199 | return result; 200 | } 201 | 202 | template Record read_record(uint32_t from) { 203 | T result = read(from); 204 | return Record(from, std::move(result)); 205 | } 206 | 207 | std::string read_cstring(uint32_t from, uint32_t max_size) { 208 | std::string buffer(max_size, 0); 209 | util::read(file_, from, max_size, &buffer[0]); 210 | return std::string(&buffer[0]); 211 | } 212 | 213 | std::string dylib_name_; 214 | std::string macho_path_; 215 | FILE* file_; 216 | }; 217 | 218 | #endif /* defined(__insert_dylib_to_macho__runner__) */ 219 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/mach-o/arch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | #ifndef _MACH_O_ARCH_H_ 24 | #define _MACH_O_ARCH_H_ 25 | /* 26 | * Copyright (c) 1997 Apple Computer, Inc. 27 | * 28 | * Functions that deal with information about architectures. 29 | * 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | /* The NXArchInfo structs contain the architectures symbolic name 37 | * (such as "ppc"), its CPU type and CPU subtype as defined in 38 | * mach/machine.h, the byte order for the architecture, and a 39 | * describing string (such as "PowerPC"). 40 | * There will both be entries for specific CPUs (such as ppc604e) as 41 | * well as generic "family" entries (such as ppc). 42 | */ 43 | typedef struct { 44 | const char *name; 45 | cpu_type_t cputype; 46 | cpu_subtype_t cpusubtype; 47 | enum NXByteOrder byteorder; 48 | const char *description; 49 | } NXArchInfo; 50 | 51 | #ifdef __cplusplus 52 | extern "C" { 53 | #endif /* __cplusplus */ 54 | 55 | /* NXGetAllArchInfos() returns a pointer to an array of all known 56 | * NXArchInfo structures. The last NXArchInfo is marked by a NULL name. 57 | */ 58 | extern const NXArchInfo *NXGetAllArchInfos(void); 59 | 60 | /* NXGetLocalArchInfo() returns the NXArchInfo for the local host, or NULL 61 | * if none is known. 62 | */ 63 | extern const NXArchInfo *NXGetLocalArchInfo(void); 64 | 65 | /* NXGetArchInfoFromName() and NXGetArchInfoFromCpuType() return the 66 | * NXArchInfo from the architecture's name or cputype/cpusubtype 67 | * combination. A cpusubtype of CPU_SUBTYPE_MULTIPLE can be used 68 | * to request the most general NXArchInfo known for the given cputype. 69 | * NULL is returned if no matching NXArchInfo can be found. 70 | */ 71 | extern const NXArchInfo *NXGetArchInfoFromName(const char *name); 72 | extern const NXArchInfo *NXGetArchInfoFromCpuType(cpu_type_t cputype, 73 | cpu_subtype_t cpusubtype); 74 | 75 | /* NXFindBestFatArch() is passed a cputype and cpusubtype and a set of 76 | * fat_arch structs and selects the best one that matches (if any) and returns 77 | * a pointer to that fat_arch struct (or NULL). The fat_arch structs must be 78 | * in the host byte order and correct such that the fat_archs really points to 79 | * enough memory for nfat_arch structs. It is possible that this routine could 80 | * fail if new cputypes or cpusubtypes are added and an old version of this 81 | * routine is used. But if there is an exact match between the cputype and 82 | * cpusubtype and one of the fat_arch structs this routine will always succeed. 83 | */ 84 | extern struct fat_arch *NXFindBestFatArch(cpu_type_t cputype, 85 | cpu_subtype_t cpusubtype, 86 | struct fat_arch *fat_archs, 87 | uint32_t nfat_archs); 88 | 89 | /* NXCombineCpuSubtypes() returns the resulting cpusubtype when combining two 90 | * different cpusubtypes for the specified cputype. If the two cpusubtypes 91 | * can't be combined (the specific subtypes are mutually exclusive) -1 is 92 | * returned indicating it is an error to combine them. This can also fail and 93 | * return -1 if new cputypes or cpusubtypes are added and an old version of 94 | * this routine is used. But if the cpusubtypes are the same they can always 95 | * be combined and this routine will return the cpusubtype pass in. 96 | */ 97 | extern cpu_subtype_t NXCombineCpuSubtypes(cpu_type_t cputype, 98 | cpu_subtype_t cpusubtype1, 99 | cpu_subtype_t cpusubtype2); 100 | 101 | #ifdef __cplusplus 102 | } 103 | #endif /* __cplusplus */ 104 | 105 | #endif /* _MACH_O_ARCH_H_ */ 106 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/mach-o/arm/reloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | /* 24 | * Relocation types used in the arm implementation. Relocation entries for 25 | * things other than instructions use the same generic relocation as discribed 26 | * in and their r_type is ARM_RELOC_VANILLA, one of the 27 | * *_SECTDIFF or the *_PB_LA_PTR types. The rest of the relocation types are 28 | * for instructions. Since they are for instructions the r_address field 29 | * indicates the 32 bit instruction that the relocation is to be preformed on. 30 | */ 31 | enum reloc_type_arm 32 | { 33 | ARM_RELOC_VANILLA, /* generic relocation as discribed above */ 34 | ARM_RELOC_PAIR, /* the second relocation entry of a pair */ 35 | ARM_RELOC_SECTDIFF, /* a PAIR follows with subtract symbol value */ 36 | ARM_RELOC_LOCAL_SECTDIFF, /* like ARM_RELOC_SECTDIFF, but the symbol 37 | referenced was local. */ 38 | ARM_RELOC_PB_LA_PTR,/* prebound lazy pointer */ 39 | ARM_RELOC_BR24, /* 24 bit branch displacement (to a word address) */ 40 | ARM_THUMB_RELOC_BR22, /* 22 bit branch displacement (to a half-word 41 | address) */ 42 | ARM_THUMB_32BIT_BRANCH, /* obsolete - a thumb 32-bit branch instruction 43 | possibly needing page-spanning branch workaround */ 44 | 45 | /* 46 | * For these two r_type relocations they always have a pair following them 47 | * and the r_length bits are used differently. The encoding of the 48 | * r_length is as follows: 49 | * low bit of r_length: 50 | * 0 - :lower16: for movw instructions 51 | * 1 - :upper16: for movt instructions 52 | * high bit of r_length: 53 | * 0 - arm instructions 54 | * 1 - thumb instructions 55 | * the other half of the relocated expression is in the following pair 56 | * relocation entry in the the low 16 bits of r_address field. 57 | */ 58 | ARM_RELOC_HALF, 59 | ARM_RELOC_HALF_SECTDIFF 60 | }; 61 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/mach-o/arm64/reloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | /* 24 | * Relocation types used in the arm64 implementation. 25 | */ 26 | enum reloc_type_arm64 27 | { 28 | ARM64_RELOC_UNSIGNED, // for pointers 29 | ARM64_RELOC_SUBTRACTOR, // must be followed by a ARM64_RELOC_UNSIGNED 30 | ARM64_RELOC_BRANCH26, // a B/BL instruction with 26-bit displacement 31 | ARM64_RELOC_PAGE21, // pc-rel distance to page of target 32 | ARM64_RELOC_PAGEOFF12, // offset within page, scaled by r_length 33 | ARM64_RELOC_GOT_LOAD_PAGE21, // pc-rel distance to page of GOT slot 34 | ARM64_RELOC_GOT_LOAD_PAGEOFF12, // offset within page of GOT slot, 35 | // scaled by r_length 36 | ARM64_RELOC_POINTER_TO_GOT, // for pointers to GOT slots 37 | ARM64_RELOC_TLVP_LOAD_PAGE21, // pc-rel distance to page of TLVP slot 38 | ARM64_RELOC_TLVP_LOAD_PAGEOFF12, // offset within page of TLVP slot, 39 | // scaled by r_length 40 | ARM64_RELOC_ADDEND // must be followed by PAGE21 or PAGEOFF12 41 | }; 42 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/mach-o/compact_unwind_encoding.h: -------------------------------------------------------------------------------- 1 | /* -*- mode: C; c-basic-offset: 4; tab-width: 4 -*- 2 | * 3 | * Copyright (c) 2008-2009 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 | 25 | 26 | #ifndef __COMPACT_UNWIND_ENCODING__ 27 | #define __COMPACT_UNWIND_ENCODING__ 28 | 29 | #include 30 | 31 | 32 | // 33 | // Each final linked mach-o image has an optional __TEXT, __unwind_info section. 34 | // This section is much smaller and faster to use than the __eh_frame section. 35 | // 36 | 37 | 38 | 39 | // 40 | // Compilers usually emit standard Dwarf FDEs. The linker recognizes standard FDEs and 41 | // synthesizes a matching compact_unwind_encoding_t and adds it to the __unwind_info table. 42 | // It is also possible for the compiler to emit __unwind_info entries for functions that 43 | // have different unwind requirements at different ranges in the function. 44 | // 45 | typedef uint32_t compact_unwind_encoding_t; 46 | 47 | 48 | 49 | // 50 | // The __unwind_info section is laid out for an efficient two level lookup. 51 | // The header of the section contains a coarse index that maps function address 52 | // to the page (4096 byte block) containing the unwind info for that function. 53 | // 54 | 55 | #define UNWIND_SECTION_VERSION 1 56 | struct unwind_info_section_header 57 | { 58 | uint32_t version; // UNWIND_SECTION_VERSION 59 | uint32_t commonEncodingsArraySectionOffset; 60 | uint32_t commonEncodingsArrayCount; 61 | uint32_t personalityArraySectionOffset; 62 | uint32_t personalityArrayCount; 63 | uint32_t indexSectionOffset; 64 | uint32_t indexCount; 65 | // compact_unwind_encoding_t[] 66 | // uintptr_t personalities[] 67 | // unwind_info_section_header_index_entry[] 68 | // unwind_info_section_header_lsda_index_entry[] 69 | }; 70 | 71 | struct unwind_info_section_header_index_entry 72 | { 73 | uint32_t functionOffset; 74 | uint32_t secondLevelPagesSectionOffset; // section offset to start of regular or compress page 75 | uint32_t lsdaIndexArraySectionOffset; // section offset to start of lsda_index array for this range 76 | }; 77 | 78 | struct unwind_info_section_header_lsda_index_entry 79 | { 80 | uint32_t functionOffset; 81 | uint32_t lsdaOffset; 82 | }; 83 | 84 | // 85 | // There are two kinds of second level index pages: regular and compressed. 86 | // A compressed page can hold up to 1021 entries, but it cannot be used 87 | // if too many different encoding types are used. The regular page holds 88 | // 511 entries. 89 | // 90 | 91 | struct unwind_info_regular_second_level_entry 92 | { 93 | uint32_t functionOffset; 94 | compact_unwind_encoding_t encoding; 95 | }; 96 | 97 | #define UNWIND_SECOND_LEVEL_REGULAR 2 98 | struct unwind_info_regular_second_level_page_header 99 | { 100 | uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR 101 | uint16_t entryPageOffset; 102 | uint16_t entryCount; 103 | // entry array 104 | }; 105 | 106 | #define UNWIND_SECOND_LEVEL_COMPRESSED 3 107 | struct unwind_info_compressed_second_level_page_header 108 | { 109 | uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED 110 | uint16_t entryPageOffset; 111 | uint16_t entryCount; 112 | uint16_t encodingsPageOffset; 113 | uint16_t encodingsCount; 114 | // 32-bit entry array 115 | // encodings array 116 | }; 117 | 118 | #define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF) 119 | #define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) ((entry >> 24) & 0xFF) 120 | 121 | 122 | 123 | // architecture independent bits 124 | enum { 125 | UNWIND_IS_NOT_FUNCTION_START = 0x80000000, 126 | UNWIND_HAS_LSDA = 0x40000000, 127 | UNWIND_PERSONALITY_MASK = 0x30000000, 128 | }; 129 | 130 | 131 | // x86_64 132 | // 133 | // 1-bit: start 134 | // 1-bit: has lsda 135 | // 2-bit: personality index 136 | // 137 | // 4-bits: 0=old, 1=rbp based, 2=stack-imm, 3=stack-ind, 4=dwarf 138 | // rbp based: 139 | // 15-bits (5*3-bits per reg) register permutation 140 | // 8-bits for stack offset 141 | // frameless: 142 | // 8-bits stack size 143 | // 3-bits stack adjust 144 | // 3-bits register count 145 | // 10-bits register permutation 146 | // 147 | enum { 148 | UNWIND_X86_64_MODE_MASK = 0x0F000000, 149 | UNWIND_X86_64_MODE_COMPATIBILITY = 0x00000000, 150 | UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000, 151 | UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000, 152 | UNWIND_X86_64_MODE_STACK_IND = 0x03000000, 153 | UNWIND_X86_64_MODE_DWARF = 0x04000000, 154 | 155 | UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF, 156 | UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000, 157 | 158 | UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000, 159 | UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000, 160 | UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00, 161 | UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, 162 | 163 | UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x03FFFFFF, 164 | }; 165 | 166 | enum { 167 | UNWIND_X86_64_REG_NONE = 0, 168 | UNWIND_X86_64_REG_RBX = 1, 169 | UNWIND_X86_64_REG_R12 = 2, 170 | UNWIND_X86_64_REG_R13 = 3, 171 | UNWIND_X86_64_REG_R14 = 4, 172 | UNWIND_X86_64_REG_R15 = 5, 173 | UNWIND_X86_64_REG_RBP = 6, 174 | }; 175 | 176 | 177 | // x86 178 | // 179 | // 1-bit: start 180 | // 1-bit: has lsda 181 | // 2-bit: personality index 182 | // 183 | // 4-bits: 0=old, 1=ebp based, 2=stack-imm, 3=stack-ind, 4=dwarf 184 | // ebp based: 185 | // 15-bits (5*3-bits per reg) register permutation 186 | // 8-bits for stack offset 187 | // frameless: 188 | // 8-bits stack size 189 | // 3-bits stack adjust 190 | // 3-bits register count 191 | // 10-bits register permutation 192 | // 193 | enum { 194 | UNWIND_X86_MODE_MASK = 0x0F000000, 195 | UNWIND_X86_MODE_COMPATIBILITY = 0x00000000, 196 | UNWIND_X86_MODE_EBP_FRAME = 0x01000000, 197 | UNWIND_X86_MODE_STACK_IMMD = 0x02000000, 198 | UNWIND_X86_MODE_STACK_IND = 0x03000000, 199 | UNWIND_X86_MODE_DWARF = 0x04000000, 200 | 201 | UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF, 202 | UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000, 203 | 204 | UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000, 205 | UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000, 206 | UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00, 207 | UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, 208 | 209 | UNWIND_X86_DWARF_SECTION_OFFSET = 0x03FFFFFF, 210 | }; 211 | 212 | enum { 213 | UNWIND_X86_REG_NONE = 0, 214 | UNWIND_X86_REG_EBX = 1, 215 | UNWIND_X86_REG_ECX = 2, 216 | UNWIND_X86_REG_EDX = 3, 217 | UNWIND_X86_REG_EDI = 4, 218 | UNWIND_X86_REG_ESI = 5, 219 | UNWIND_X86_REG_EBP = 6, 220 | }; 221 | 222 | 223 | #endif 224 | 225 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/mach-o/fat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | #ifndef _MACH_O_FAT_H_ 24 | #define _MACH_O_FAT_H_ 25 | /* 26 | * This header file describes the structures of the file format for "fat" 27 | * architecture specific file (wrapper design). At the begining of the file 28 | * there is one fat_header structure followed by a number of fat_arch 29 | * structures. For each architecture in the file, specified by a pair of 30 | * cputype and cpusubtype, the fat_header describes the file offset, file 31 | * size and alignment in the file of the architecture specific member. 32 | * The padded bytes in the file to place each member on it's specific alignment 33 | * are defined to be read as zeros and can be left as "holes" if the file system 34 | * can support them as long as they read as zeros. 35 | * 36 | * All structures defined here are always written and read to/from disk 37 | * in big-endian order. 38 | */ 39 | 40 | /* 41 | * is needed here for the cpu_type_t and cpu_subtype_t types 42 | * and contains the constants for the possible values of these types. 43 | */ 44 | #include 45 | #include 46 | #include 47 | 48 | #define FAT_MAGIC 0xcafebabe 49 | #define FAT_CIGAM 0xbebafeca /* NXSwapLong(FAT_MAGIC) */ 50 | 51 | struct fat_header { 52 | uint32_t magic; /* FAT_MAGIC */ 53 | uint32_t nfat_arch; /* number of structs that follow */ 54 | }; 55 | 56 | struct fat_arch { 57 | cpu_type_t cputype; /* cpu specifier (int) */ 58 | cpu_subtype_t cpusubtype; /* machine specifier (int) */ 59 | uint32_t offset; /* file offset to this object file */ 60 | uint32_t size; /* size of this object file */ 61 | uint32_t align; /* alignment as a power of 2 */ 62 | }; 63 | 64 | #endif /* _MACH_O_FAT_H_ */ 65 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/mach-o/nlist.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | #ifndef _MACHO_NLIST_H_ 24 | #define _MACHO_NLIST_H_ 25 | /* $NetBSD: nlist.h,v 1.5 1994/10/26 00:56:11 cgd Exp $ */ 26 | 27 | /*- 28 | * Copyright (c) 1991, 1993 29 | * The Regents of the University of California. All rights reserved. 30 | * (c) UNIX System Laboratories, Inc. 31 | * All or some portions of this file are derived from material licensed 32 | * to the University of California by American Telephone and Telegraph 33 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with 34 | * the permission of UNIX System Laboratories, Inc. 35 | * 36 | * Redistribution and use in source and binary forms, with or without 37 | * modification, are permitted provided that the following conditions 38 | * are met: 39 | * 1. Redistributions of source code must retain the above copyright 40 | * notice, this list of conditions and the following disclaimer. 41 | * 2. Redistributions in binary form must reproduce the above copyright 42 | * notice, this list of conditions and the following disclaimer in the 43 | * documentation and/or other materials provided with the distribution. 44 | * 3. All advertising materials mentioning features or use of this software 45 | * must display the following acknowledgement: 46 | * This product includes software developed by the University of 47 | * California, Berkeley and its contributors. 48 | * 4. Neither the name of the University nor the names of its contributors 49 | * may be used to endorse or promote products derived from this software 50 | * without specific prior written permission. 51 | * 52 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 | * SUCH DAMAGE. 63 | * 64 | * @(#)nlist.h 8.2 (Berkeley) 1/21/94 65 | */ 66 | #include 67 | 68 | /* 69 | * Format of a symbol table entry of a Mach-O file for 32-bit architectures. 70 | * Modified from the BSD format. The modifications from the original format 71 | * were changing n_other (an unused field) to n_sect and the addition of the 72 | * N_SECT type. These modifications are required to support symbols in a larger 73 | * number of sections not just the three sections (text, data and bss) in a BSD 74 | * file. 75 | */ 76 | struct nlist { 77 | union { 78 | #ifndef __LP64__ 79 | char *n_name; /* for use when in-core */ 80 | #endif 81 | uint32_t n_strx; /* index into the string table */ 82 | } n_un; 83 | uint8_t n_type; /* type flag, see below */ 84 | uint8_t n_sect; /* section number or NO_SECT */ 85 | int16_t n_desc; /* see */ 86 | uint32_t n_value; /* value of this symbol (or stab offset) */ 87 | }; 88 | 89 | /* 90 | * This is the symbol table entry structure for 64-bit architectures. 91 | */ 92 | struct nlist_64 { 93 | union { 94 | uint32_t n_strx; /* index into the string table */ 95 | } n_un; 96 | uint8_t n_type; /* type flag, see below */ 97 | uint8_t n_sect; /* section number or NO_SECT */ 98 | uint16_t n_desc; /* see */ 99 | uint64_t n_value; /* value of this symbol (or stab offset) */ 100 | }; 101 | 102 | /* 103 | * Symbols with a index into the string table of zero (n_un.n_strx == 0) are 104 | * defined to have a null, "", name. Therefore all string indexes to non null 105 | * names must not have a zero string index. This is bit historical information 106 | * that has never been well documented. 107 | */ 108 | 109 | /* 110 | * The n_type field really contains four fields: 111 | * unsigned char N_STAB:3, 112 | * N_PEXT:1, 113 | * N_TYPE:3, 114 | * N_EXT:1; 115 | * which are used via the following masks. 116 | */ 117 | #define N_STAB 0xe0 /* if any of these bits set, a symbolic debugging entry */ 118 | #define N_PEXT 0x10 /* private external symbol bit */ 119 | #define N_TYPE 0x0e /* mask for the type bits */ 120 | #define N_EXT 0x01 /* external symbol bit, set for external symbols */ 121 | 122 | /* 123 | * Only symbolic debugging entries have some of the N_STAB bits set and if any 124 | * of these bits are set then it is a symbolic debugging entry (a stab). In 125 | * which case then the values of the n_type field (the entire field) are given 126 | * in 127 | */ 128 | 129 | /* 130 | * Values for N_TYPE bits of the n_type field. 131 | */ 132 | #define N_UNDF 0x0 /* undefined, n_sect == NO_SECT */ 133 | #define N_ABS 0x2 /* absolute, n_sect == NO_SECT */ 134 | #define N_SECT 0xe /* defined in section number n_sect */ 135 | #define N_PBUD 0xc /* prebound undefined (defined in a dylib) */ 136 | #define N_INDR 0xa /* indirect */ 137 | 138 | /* 139 | * If the type is N_INDR then the symbol is defined to be the same as another 140 | * symbol. In this case the n_value field is an index into the string table 141 | * of the other symbol's name. When the other symbol is defined then they both 142 | * take on the defined type and value. 143 | */ 144 | 145 | /* 146 | * If the type is N_SECT then the n_sect field contains an ordinal of the 147 | * section the symbol is defined in. The sections are numbered from 1 and 148 | * refer to sections in order they appear in the load commands for the file 149 | * they are in. This means the same ordinal may very well refer to different 150 | * sections in different files. 151 | * 152 | * The n_value field for all symbol table entries (including N_STAB's) gets 153 | * updated by the link editor based on the value of it's n_sect field and where 154 | * the section n_sect references gets relocated. If the value of the n_sect 155 | * field is NO_SECT then it's n_value field is not changed by the link editor. 156 | */ 157 | #define NO_SECT 0 /* symbol is not in any section */ 158 | #define MAX_SECT 255 /* 1 thru 255 inclusive */ 159 | 160 | /* 161 | * Common symbols are represented by undefined (N_UNDF) external (N_EXT) types 162 | * who's values (n_value) are non-zero. In which case the value of the n_value 163 | * field is the size (in bytes) of the common symbol. The n_sect field is set 164 | * to NO_SECT. The alignment of a common symbol may be set as a power of 2 165 | * between 2^1 and 2^15 as part of the n_desc field using the macros below. If 166 | * the alignment is not set (a value of zero) then natural alignment based on 167 | * the size is used. 168 | */ 169 | #define GET_COMM_ALIGN(n_desc) (((n_desc) >> 8) & 0x0f) 170 | #define SET_COMM_ALIGN(n_desc,align) \ 171 | (n_desc) = (((n_desc) & 0xf0ff) | (((align) & 0x0f) << 8)) 172 | 173 | /* 174 | * To support the lazy binding of undefined symbols in the dynamic link-editor, 175 | * the undefined symbols in the symbol table (the nlist structures) are marked 176 | * with the indication if the undefined reference is a lazy reference or 177 | * non-lazy reference. If both a non-lazy reference and a lazy reference is 178 | * made to the same symbol the non-lazy reference takes precedence. A reference 179 | * is lazy only when all references to that symbol are made through a symbol 180 | * pointer in a lazy symbol pointer section. 181 | * 182 | * The implementation of marking nlist structures in the symbol table for 183 | * undefined symbols will be to use some of the bits of the n_desc field as a 184 | * reference type. The mask REFERENCE_TYPE will be applied to the n_desc field 185 | * of an nlist structure for an undefined symbol to determine the type of 186 | * undefined reference (lazy or non-lazy). 187 | * 188 | * The constants for the REFERENCE FLAGS are propagated to the reference table 189 | * in a shared library file. In that case the constant for a defined symbol, 190 | * REFERENCE_FLAG_DEFINED, is also used. 191 | */ 192 | /* Reference type bits of the n_desc field of undefined symbols */ 193 | #define REFERENCE_TYPE 0x7 194 | /* types of references */ 195 | #define REFERENCE_FLAG_UNDEFINED_NON_LAZY 0 196 | #define REFERENCE_FLAG_UNDEFINED_LAZY 1 197 | #define REFERENCE_FLAG_DEFINED 2 198 | #define REFERENCE_FLAG_PRIVATE_DEFINED 3 199 | #define REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY 4 200 | #define REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY 5 201 | 202 | /* 203 | * To simplify stripping of objects that use are used with the dynamic link 204 | * editor, the static link editor marks the symbols defined an object that are 205 | * referenced by a dynamicly bound object (dynamic shared libraries, bundles). 206 | * With this marking strip knows not to strip these symbols. 207 | */ 208 | #define REFERENCED_DYNAMICALLY 0x0010 209 | 210 | /* 211 | * For images created by the static link editor with the -twolevel_namespace 212 | * option in effect the flags field of the mach header is marked with 213 | * MH_TWOLEVEL. And the binding of the undefined references of the image are 214 | * determined by the static link editor. Which library an undefined symbol is 215 | * bound to is recorded by the static linker in the high 8 bits of the n_desc 216 | * field using the SET_LIBRARY_ORDINAL macro below. The ordinal recorded 217 | * references the libraries listed in the Mach-O's LC_LOAD_DYLIB, 218 | * LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_LOAD_UPWARD_DYLIB, and 219 | * LC_LAZY_LOAD_DYLIB, etc. load commands in the order they appear in the 220 | * headers. The library ordinals start from 1. 221 | * For a dynamic library that is built as a two-level namespace image the 222 | * undefined references from module defined in another use the same nlist struct 223 | * an in that case SELF_LIBRARY_ORDINAL is used as the library ordinal. For 224 | * defined symbols in all images they also must have the library ordinal set to 225 | * SELF_LIBRARY_ORDINAL. The EXECUTABLE_ORDINAL refers to the executable 226 | * image for references from plugins that refer to the executable that loads 227 | * them. 228 | * 229 | * The DYNAMIC_LOOKUP_ORDINAL is for undefined symbols in a two-level namespace 230 | * image that are looked up by the dynamic linker with flat namespace semantics. 231 | * This ordinal was added as a feature in Mac OS X 10.3 by reducing the 232 | * value of MAX_LIBRARY_ORDINAL by one. So it is legal for existing binaries 233 | * or binaries built with older tools to have 0xfe (254) dynamic libraries. In 234 | * this case the ordinal value 0xfe (254) must be treated as a library ordinal 235 | * for compatibility. 236 | */ 237 | #define GET_LIBRARY_ORDINAL(n_desc) (((n_desc) >> 8) & 0xff) 238 | #define SET_LIBRARY_ORDINAL(n_desc,ordinal) \ 239 | (n_desc) = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8)) 240 | #define SELF_LIBRARY_ORDINAL 0x0 241 | #define MAX_LIBRARY_ORDINAL 0xfd 242 | #define DYNAMIC_LOOKUP_ORDINAL 0xfe 243 | #define EXECUTABLE_ORDINAL 0xff 244 | 245 | /* 246 | * The bit 0x0020 of the n_desc field is used for two non-overlapping purposes 247 | * and has two different symbolic names, N_NO_DEAD_STRIP and N_DESC_DISCARDED. 248 | */ 249 | 250 | /* 251 | * The N_NO_DEAD_STRIP bit of the n_desc field only ever appears in a 252 | * relocatable .o file (MH_OBJECT filetype). And is used to indicate to the 253 | * static link editor it is never to dead strip the symbol. 254 | */ 255 | #define N_NO_DEAD_STRIP 0x0020 /* symbol is not to be dead stripped */ 256 | 257 | /* 258 | * The N_DESC_DISCARDED bit of the n_desc field never appears in linked image. 259 | * But is used in very rare cases by the dynamic link editor to mark an in 260 | * memory symbol as discared and longer used for linking. 261 | */ 262 | #define N_DESC_DISCARDED 0x0020 /* symbol is discarded */ 263 | 264 | /* 265 | * The N_WEAK_REF bit of the n_desc field indicates to the dynamic linker that 266 | * the undefined symbol is allowed to be missing and is to have the address of 267 | * zero when missing. 268 | */ 269 | #define N_WEAK_REF 0x0040 /* symbol is weak referenced */ 270 | 271 | /* 272 | * The N_WEAK_DEF bit of the n_desc field indicates to the static and dynamic 273 | * linkers that the symbol definition is weak, allowing a non-weak symbol to 274 | * also be used which causes the weak definition to be discared. Currently this 275 | * is only supported for symbols in coalesed sections. 276 | */ 277 | #define N_WEAK_DEF 0x0080 /* coalesed symbol is a weak definition */ 278 | 279 | /* 280 | * The N_REF_TO_WEAK bit of the n_desc field indicates to the dynamic linker 281 | * that the undefined symbol should be resolved using flat namespace searching. 282 | */ 283 | #define N_REF_TO_WEAK 0x0080 /* reference to a weak symbol */ 284 | 285 | /* 286 | * The N_ARM_THUMB_DEF bit of the n_desc field indicates that the symbol is 287 | * a defintion of a Thumb function. 288 | */ 289 | #define N_ARM_THUMB_DEF 0x0008 /* symbol is a Thumb function (ARM) */ 290 | 291 | /* 292 | * The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the 293 | * that the function is actually a resolver function and should 294 | * be called to get the address of the real function to use. 295 | * This bit is only available in .o files (MH_OBJECT filetype) 296 | */ 297 | #define N_SYMBOL_RESOLVER 0x0100 298 | 299 | #ifndef __STRICT_BSD__ 300 | #ifdef __cplusplus 301 | extern "C" { 302 | #endif /* __cplusplus */ 303 | /* 304 | * The function nlist(3) from the C library. 305 | */ 306 | extern int nlist (const char *filename, struct nlist *list); 307 | #ifdef __cplusplus 308 | } 309 | #endif /* __cplusplus */ 310 | #endif /* __STRICT_BSD__ */ 311 | 312 | #endif /* _MACHO_LIST_H_ */ 313 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/mach-o/ranlib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | /* ranlib.h 4.1 83/05/03 */ 24 | #ifndef _MACH_O_RANLIB_H_ 25 | #define _MACH_O_RANLIB_H_ 26 | 27 | #include 28 | #include /* off_t */ 29 | 30 | /* 31 | * There are two known orders of table of contents for archives. The first is 32 | * the order ranlib(1) originally produced and still produces without any 33 | * options. This table of contents has the archive member name "__.SYMDEF" 34 | * This order has the ranlib structures in the order the objects appear in the 35 | * archive and the symbol names of those objects in the order of symbol table. 36 | * The second know order is sorted by symbol name and is produced with the -s 37 | * option to ranlib(1). This table of contents has the archive member name 38 | * "__.SYMDEF SORTED" and many programs (notably the 1.0 version of ld(1) can't 39 | * tell the difference between names because of the imbedded blank in the name 40 | * and works with either table of contents). This second order is used by the 41 | * post 1.0 link editor to produce faster linking. The original 1.0 version of 42 | * ranlib(1) gets confused when it is run on a archive with the second type of 43 | * table of contents because it and ar(1) which it uses use different ways to 44 | * determined the member name (ar(1) treats all blanks in the name as 45 | * significant and ranlib(1) only checks for the first one). 46 | */ 47 | #define SYMDEF "__.SYMDEF" 48 | #define SYMDEF_SORTED "__.SYMDEF SORTED" 49 | 50 | /* 51 | * Structure of the __.SYMDEF table of contents for an archive. 52 | * __.SYMDEF begins with a long giving the size in bytes of the ranlib 53 | * structures which immediately follow, and then continues with a string 54 | * table consisting of a long giving the number of bytes of strings which 55 | * follow and then the strings themselves. The ran_strx fields index the 56 | * string table whose first byte is numbered 0. 57 | */ 58 | struct ranlib { 59 | union { 60 | uint32_t ran_strx; /* string table index of */ 61 | #ifndef __LP64__ 62 | char *ran_name; /* symbol defined by */ 63 | #endif 64 | } ran_un; 65 | uint32_t ran_off; /* library member at this offset */ 66 | }; 67 | #endif /* _MACH_O_RANLIB_H_ */ 68 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/mach-o/reloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | /* $NetBSD: exec.h,v 1.6 1994/10/27 04:16:05 cgd Exp $ */ 24 | 25 | /* 26 | * Copyright (c) 1993 Christopher G. Demetriou 27 | * All rights reserved. 28 | * 29 | * Redistribution and use in source and binary forms, with or without 30 | * modification, are permitted provided that the following conditions 31 | * are met: 32 | * 1. Redistributions of source code must retain the above copyright 33 | * notice, this list of conditions and the following disclaimer. 34 | * 2. Redistributions in binary form must reproduce the above copyright 35 | * notice, this list of conditions and the following disclaimer in the 36 | * documentation and/or other materials provided with the distribution. 37 | * 3. The name of the author may not be used to endorse or promote products 38 | * derived from this software without specific prior written permission 39 | * 40 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 41 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 42 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 43 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 44 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 46 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 47 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 48 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 49 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 50 | */ 51 | 52 | #ifndef _MACHO_RELOC_H_ 53 | #define _MACHO_RELOC_H_ 54 | #include 55 | 56 | /* 57 | * Format of a relocation entry of a Mach-O file. Modified from the 4.3BSD 58 | * format. The modifications from the original format were changing the value 59 | * of the r_symbolnum field for "local" (r_extern == 0) relocation entries. 60 | * This modification is required to support symbols in an arbitrary number of 61 | * sections not just the three sections (text, data and bss) in a 4.3BSD file. 62 | * Also the last 4 bits have had the r_type tag added to them. 63 | */ 64 | struct relocation_info { 65 | int32_t r_address; /* offset in the section to what is being 66 | relocated */ 67 | uint32_t r_symbolnum:24, /* symbol index if r_extern == 1 or section 68 | ordinal if r_extern == 0 */ 69 | r_pcrel:1, /* was relocated pc relative already */ 70 | r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */ 71 | r_extern:1, /* does not include value of sym referenced */ 72 | r_type:4; /* if not 0, machine specific relocation type */ 73 | }; 74 | #define R_ABS 0 /* absolute relocation type for Mach-O files */ 75 | 76 | /* 77 | * The r_address is not really the address as it's name indicates but an offset. 78 | * In 4.3BSD a.out objects this offset is from the start of the "segment" for 79 | * which relocation entry is for (text or data). For Mach-O object files it is 80 | * also an offset but from the start of the "section" for which the relocation 81 | * entry is for. See comments in about the r_address feild 82 | * in images for used with the dynamic linker. 83 | * 84 | * In 4.3BSD a.out objects if r_extern is zero then r_symbolnum is an ordinal 85 | * for the segment the symbol being relocated is in. These ordinals are the 86 | * symbol types N_TEXT, N_DATA, N_BSS or N_ABS. In Mach-O object files these 87 | * ordinals refer to the sections in the object file in the order their section 88 | * structures appear in the headers of the object file they are in. The first 89 | * section has the ordinal 1, the second 2, and so on. This means that the 90 | * same ordinal in two different object files could refer to two different 91 | * sections. And further could have still different ordinals when combined 92 | * by the link-editor. The value R_ABS is used for relocation entries for 93 | * absolute symbols which need no further relocation. 94 | */ 95 | 96 | /* 97 | * For RISC machines some of the references are split across two instructions 98 | * and the instruction does not contain the complete value of the reference. 99 | * In these cases a second, or paired relocation entry, follows each of these 100 | * relocation entries, using a PAIR r_type, which contains the other part of the 101 | * reference not contained in the instruction. This other part is stored in the 102 | * pair's r_address field. The exact number of bits of the other part of the 103 | * reference store in the r_address field is dependent on the particular 104 | * relocation type for the particular architecture. 105 | */ 106 | 107 | /* 108 | * To make scattered loading by the link editor work correctly "local" 109 | * relocation entries can't be used when the item to be relocated is the value 110 | * of a symbol plus an offset (where the resulting expresion is outside the 111 | * block the link editor is moving, a blocks are divided at symbol addresses). 112 | * In this case. where the item is a symbol value plus offset, the link editor 113 | * needs to know more than just the section the symbol was defined. What is 114 | * needed is the actual value of the symbol without the offset so it can do the 115 | * relocation correctly based on where the value of the symbol got relocated to 116 | * not the value of the expression (with the offset added to the symbol value). 117 | * So for the NeXT 2.0 release no "local" relocation entries are ever used when 118 | * there is a non-zero offset added to a symbol. The "external" and "local" 119 | * relocation entries remain unchanged. 120 | * 121 | * The implemention is quite messy given the compatibility with the existing 122 | * relocation entry format. The ASSUMPTION is that a section will never be 123 | * bigger than 2**24 - 1 (0x00ffffff or 16,777,215) bytes. This assumption 124 | * allows the r_address (which is really an offset) to fit in 24 bits and high 125 | * bit of the r_address field in the relocation_info structure to indicate 126 | * it is really a scattered_relocation_info structure. Since these are only 127 | * used in places where "local" relocation entries are used and not where 128 | * "external" relocation entries are used the r_extern field has been removed. 129 | * 130 | * For scattered loading to work on a RISC machine where some of the references 131 | * are split across two instructions the link editor needs to be assured that 132 | * each reference has a unique 32 bit reference (that more than one reference is 133 | * NOT sharing the same high 16 bits for example) so it move each referenced 134 | * item independent of each other. Some compilers guarantees this but the 135 | * compilers don't so scattered loading can be done on those that do guarantee 136 | * this. 137 | */ 138 | #if defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__) 139 | /* 140 | * The reason for the ifdef's of __BIG_ENDIAN__ and __LITTLE_ENDIAN__ are that 141 | * when stattered relocation entries were added the mistake of using a mask 142 | * against a structure that is made up of bit fields was used. To make this 143 | * design work this structure must be laid out in memory the same way so the 144 | * mask can be applied can check the same bit each time (r_scattered). 145 | */ 146 | #endif /* defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__) */ 147 | #define R_SCATTERED 0x80000000 /* mask to be applied to the r_address field 148 | of a relocation_info structure to tell that 149 | is is really a scattered_relocation_info 150 | stucture */ 151 | struct scattered_relocation_info { 152 | #ifdef __BIG_ENDIAN__ 153 | uint32_t r_scattered:1, /* 1=scattered, 0=non-scattered (see above) */ 154 | r_pcrel:1, /* was relocated pc relative already */ 155 | r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */ 156 | r_type:4, /* if not 0, machine specific relocation type */ 157 | r_address:24; /* offset in the section to what is being 158 | relocated */ 159 | int32_t r_value; /* the value the item to be relocated is 160 | refering to (without any offset added) */ 161 | #endif /* __BIG_ENDIAN__ */ 162 | #ifdef __LITTLE_ENDIAN__ 163 | uint32_t 164 | r_address:24, /* offset in the section to what is being 165 | relocated */ 166 | r_type:4, /* if not 0, machine specific relocation type */ 167 | r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */ 168 | r_pcrel:1, /* was relocated pc relative already */ 169 | r_scattered:1; /* 1=scattered, 0=non-scattered (see above) */ 170 | int32_t r_value; /* the value the item to be relocated is 171 | refering to (without any offset added) */ 172 | #endif /* __LITTLE_ENDIAN__ */ 173 | }; 174 | 175 | /* 176 | * Relocation types used in a generic implementation. Relocation entries for 177 | * normal things use the generic relocation as discribed above and their r_type 178 | * is GENERIC_RELOC_VANILLA (a value of zero). 179 | * 180 | * Another type of generic relocation, GENERIC_RELOC_SECTDIFF, is to support 181 | * the difference of two symbols defined in different sections. That is the 182 | * expression "symbol1 - symbol2 + constant" is a relocatable expression when 183 | * both symbols are defined in some section. For this type of relocation the 184 | * both relocations entries are scattered relocation entries. The value of 185 | * symbol1 is stored in the first relocation entry's r_value field and the 186 | * value of symbol2 is stored in the pair's r_value field. 187 | * 188 | * A special case for a prebound lazy pointer is needed to beable to set the 189 | * value of the lazy pointer back to its non-prebound state. This is done 190 | * using the GENERIC_RELOC_PB_LA_PTR r_type. This is a scattered relocation 191 | * entry where the r_value feild is the value of the lazy pointer not prebound. 192 | */ 193 | enum reloc_type_generic 194 | { 195 | GENERIC_RELOC_VANILLA, /* generic relocation as discribed above */ 196 | GENERIC_RELOC_PAIR, /* Only follows a GENERIC_RELOC_SECTDIFF */ 197 | GENERIC_RELOC_SECTDIFF, 198 | GENERIC_RELOC_PB_LA_PTR, /* prebound lazy pointer */ 199 | GENERIC_RELOC_LOCAL_SECTDIFF, 200 | GENERIC_RELOC_TLV /* thread local variables */ 201 | }; 202 | 203 | #endif /* _MACHO_RELOC_H_ */ 204 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/mach-o/swap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | #ifndef _MACH_O_SWAP_H_ 24 | #define _MACH_O_SWAP_H_ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif /* __cplusplus */ 37 | 38 | extern void swap_fat_header( 39 | struct fat_header *fat_header, 40 | enum NXByteOrder target_byte_order); 41 | 42 | extern void swap_fat_arch( 43 | struct fat_arch *fat_archs, 44 | uint32_t nfat_arch, 45 | enum NXByteOrder target_byte_order); 46 | 47 | extern void swap_mach_header( 48 | struct mach_header *mh, 49 | enum NXByteOrder target_byte_order); 50 | 51 | extern void swap_mach_header_64( 52 | struct mach_header_64 *mh, 53 | enum NXByteOrder target_byte_order); 54 | 55 | extern void swap_load_command( 56 | struct load_command *lc, 57 | enum NXByteOrder target_byte_order); 58 | 59 | extern void swap_segment_command( 60 | struct segment_command *sg, 61 | enum NXByteOrder target_byte_order); 62 | 63 | extern void swap_segment_command_64( 64 | struct segment_command_64 *sg, 65 | enum NXByteOrder target_byte_order); 66 | 67 | extern void swap_section( 68 | struct section *s, 69 | uint32_t nsects, 70 | enum NXByteOrder target_byte_order); 71 | 72 | extern void swap_section_64( 73 | struct section_64 *s, 74 | uint32_t nsects, 75 | enum NXByteOrder target_byte_order); 76 | 77 | extern void swap_symtab_command( 78 | struct symtab_command *st, 79 | enum NXByteOrder target_byte_order); 80 | 81 | extern void swap_dysymtab_command( 82 | struct dysymtab_command *dyst, 83 | enum NXByteOrder target_byte_sex); 84 | 85 | extern void swap_symseg_command( 86 | struct symseg_command *ss, 87 | enum NXByteOrder target_byte_order); 88 | 89 | extern void swap_fvmlib_command( 90 | struct fvmlib_command *fl, 91 | enum NXByteOrder target_byte_order); 92 | 93 | extern void swap_dylib_command( 94 | struct dylib_command *dl, 95 | enum NXByteOrder target_byte_sex); 96 | 97 | extern void swap_sub_framework_command( 98 | struct sub_framework_command *sub, 99 | enum NXByteOrder target_byte_sex); 100 | 101 | extern void swap_sub_umbrella_command( 102 | struct sub_umbrella_command *usub, 103 | enum NXByteOrder target_byte_sex); 104 | 105 | extern void swap_sub_library_command( 106 | struct sub_library_command *lsub, 107 | enum NXByteOrder target_byte_sex); 108 | 109 | extern void swap_sub_client_command( 110 | struct sub_client_command *csub, 111 | enum NXByteOrder target_byte_sex); 112 | 113 | extern void swap_prebound_dylib_command( 114 | struct prebound_dylib_command *pbdylib, 115 | enum NXByteOrder target_byte_sex); 116 | 117 | extern void swap_dylinker_command( 118 | struct dylinker_command *dyld, 119 | enum NXByteOrder target_byte_sex); 120 | 121 | extern void swap_fvmfile_command( 122 | struct fvmfile_command *ff, 123 | enum NXByteOrder target_byte_order); 124 | 125 | extern void swap_thread_command( 126 | struct thread_command *ut, 127 | enum NXByteOrder target_byte_order); 128 | 129 | extern void swap_ident_command( 130 | struct ident_command *ident, 131 | enum NXByteOrder target_byte_order); 132 | 133 | extern void swap_routines_command( 134 | struct routines_command *r_cmd, 135 | enum NXByteOrder target_byte_sex); 136 | 137 | extern void swap_routines_command_64( 138 | struct routines_command_64 *r_cmd, 139 | enum NXByteOrder target_byte_sex); 140 | 141 | extern void swap_twolevel_hints_command( 142 | struct twolevel_hints_command *hints_cmd, 143 | enum NXByteOrder target_byte_sex); 144 | 145 | extern void swap_prebind_cksum_command( 146 | struct prebind_cksum_command *cksum_cmd, 147 | enum NXByteOrder target_byte_sex); 148 | 149 | extern void swap_uuid_command( 150 | struct uuid_command *uuid_cmd, 151 | enum NXByteOrder target_byte_sex); 152 | 153 | extern void swap_linkedit_data_command( 154 | struct linkedit_data_command *ld, 155 | enum NXByteOrder target_byte_sex); 156 | 157 | extern void swap_version_min_command( 158 | struct version_min_command *ver_cmd, 159 | enum NXByteOrder target_byte_sex); 160 | 161 | extern void swap_rpath_command( 162 | struct rpath_command *rpath_cmd, 163 | enum NXByteOrder target_byte_sex); 164 | 165 | extern void swap_encryption_command( 166 | struct encryption_info_command *ec, 167 | enum NXByteOrder target_byte_sex); 168 | 169 | extern void swap_encryption_command_64( 170 | struct encryption_info_command_64 *ec, 171 | enum NXByteOrder target_byte_sex); 172 | 173 | extern void swap_linker_option_command( 174 | struct linker_option_command *lo, 175 | enum NXByteOrder target_byte_sex); 176 | 177 | extern void swap_dyld_info_command( 178 | struct dyld_info_command *ed, 179 | enum NXByteOrder target_byte_sex); 180 | 181 | extern void swap_entry_point_command( 182 | struct entry_point_command *ep, 183 | enum NXByteOrder target_byte_sex); 184 | 185 | extern void swap_source_version_command( 186 | struct source_version_command *sv, 187 | enum NXByteOrder target_byte_sex); 188 | 189 | extern void swap_prebind_cksum_command( 190 | struct prebind_cksum_command *cksum_cmd, 191 | enum NXByteOrder target_byte_sex); 192 | 193 | extern void swap_uuid_command( 194 | struct uuid_command *uuid_cmd, 195 | enum NXByteOrder target_byte_sex); 196 | 197 | extern void swap_twolevel_hint( 198 | struct twolevel_hint *hints, 199 | uint32_t nhints, 200 | enum NXByteOrder target_byte_sex); 201 | 202 | extern void swap_nlist( 203 | struct nlist *symbols, 204 | uint32_t nsymbols, 205 | enum NXByteOrder target_byte_order); 206 | 207 | extern void swap_nlist_64( 208 | struct nlist_64 *symbols, 209 | uint32_t nsymbols, 210 | enum NXByteOrder target_byte_order); 211 | 212 | extern void swap_ranlib( 213 | struct ranlib *ranlibs, 214 | uint32_t nranlibs, 215 | enum NXByteOrder target_byte_order); 216 | 217 | extern void swap_relocation_info( 218 | struct relocation_info *relocs, 219 | uint32_t nrelocs, 220 | enum NXByteOrder target_byte_order); 221 | 222 | extern void swap_indirect_symbols( 223 | uint32_t *indirect_symbols, 224 | uint32_t nindirect_symbols, 225 | enum NXByteOrder target_byte_sex); 226 | 227 | extern void swap_dylib_reference( 228 | struct dylib_reference *refs, 229 | uint32_t nrefs, 230 | enum NXByteOrder target_byte_sex); 231 | 232 | extern void swap_dylib_module( 233 | struct dylib_module *mods, 234 | uint32_t nmods, 235 | enum NXByteOrder target_byte_sex); 236 | 237 | extern void swap_dylib_module_64( 238 | struct dylib_module_64 *mods, 239 | uint32_t nmods, 240 | enum NXByteOrder target_byte_sex); 241 | 242 | extern void swap_dylib_table_of_contents( 243 | struct dylib_table_of_contents *tocs, 244 | uint32_t ntocs, 245 | enum NXByteOrder target_byte_sex); 246 | 247 | #ifdef __cplusplus 248 | } 249 | #endif /* __cplusplus */ 250 | 251 | #endif /* _MACH_O_SWAP_H_ */ 252 | -------------------------------------------------------------------------------- /src/insert_dylib_to_macho/mach-o/x86_64/reloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | /* 24 | * Relocations for x86_64 are a bit different than for other architectures in 25 | * Mach-O: Scattered relocations are not used. Almost all relocations produced 26 | * by the compiler are external relocations. An external relocation has the 27 | * r_extern bit set to 1 and the r_symbolnum field contains the symbol table 28 | * index of the target label. 29 | * 30 | * When the assembler is generating relocations, if the target label is a local 31 | * label (begins with 'L'), then the previous non-local label in the same 32 | * section is used as the target of the external relocation. An addend is used 33 | * with the distance from that non-local label to the target label. Only when 34 | * there is no previous non-local label in the section is an internal 35 | * relocation used. 36 | * 37 | * The addend (i.e. the 4 in _foo+4) is encoded in the instruction (Mach-O does 38 | * not have RELA relocations). For PC-relative relocations, the addend is 39 | * stored directly in the instruction. This is different from other Mach-O 40 | * architectures, which encode the addend minus the current section offset. 41 | * 42 | * The relocation types are: 43 | * 44 | * X86_64_RELOC_UNSIGNED // for absolute addresses 45 | * X86_64_RELOC_SIGNED // for signed 32-bit displacement 46 | * X86_64_RELOC_BRANCH // a CALL/JMP instruction with 32-bit displacement 47 | * X86_64_RELOC_GOT_LOAD // a MOVQ load of a GOT entry 48 | * X86_64_RELOC_GOT // other GOT references 49 | * X86_64_RELOC_SUBTRACTOR // must be followed by a X86_64_RELOC_UNSIGNED 50 | * 51 | * The following are sample assembly instructions, followed by the relocation 52 | * and section content they generate in an object file: 53 | * 54 | * call _foo 55 | * r_type=X86_64_RELOC_BRANCH, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo 56 | * E8 00 00 00 00 57 | * 58 | * call _foo+4 59 | * r_type=X86_64_RELOC_BRANCH, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo 60 | * E8 04 00 00 00 61 | * 62 | * movq _foo@GOTPCREL(%rip), %rax 63 | * r_type=X86_64_RELOC_GOT_LOAD, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo 64 | * 48 8B 05 00 00 00 00 65 | * 66 | * pushq _foo@GOTPCREL(%rip) 67 | * r_type=X86_64_RELOC_GOT, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo 68 | * FF 35 00 00 00 00 69 | * 70 | * movl _foo(%rip), %eax 71 | * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo 72 | * 8B 05 00 00 00 00 73 | * 74 | * movl _foo+4(%rip), %eax 75 | * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo 76 | * 8B 05 04 00 00 00 77 | * 78 | * movb $0x12, _foo(%rip) 79 | * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo 80 | * C6 05 FF FF FF FF 12 81 | * 82 | * movl $0x12345678, _foo(%rip) 83 | * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo 84 | * C7 05 FC FF FF FF 78 56 34 12 85 | * 86 | * .quad _foo 87 | * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo 88 | * 00 00 00 00 00 00 00 00 89 | * 90 | * .quad _foo+4 91 | * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo 92 | * 04 00 00 00 00 00 00 00 93 | * 94 | * .quad _foo - _bar 95 | * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar 96 | * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo 97 | * 00 00 00 00 00 00 00 00 98 | * 99 | * .quad _foo - _bar + 4 100 | * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar 101 | * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo 102 | * 04 00 00 00 00 00 00 00 103 | * 104 | * .long _foo - _bar 105 | * r_type=X86_64_RELOC_SUBTRACTOR, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_bar 106 | * r_type=X86_64_RELOC_UNSIGNED, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo 107 | * 00 00 00 00 108 | * 109 | * lea L1(%rip), %rax 110 | * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_prev 111 | * 48 8d 05 12 00 00 00 112 | * // assumes _prev is the first non-local label 0x12 bytes before L1 113 | * 114 | * lea L0(%rip), %rax 115 | * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=0, r_pcrel=1, r_symbolnum=3 116 | * 48 8d 05 56 00 00 00 117 | * // assumes L0 is in third section and there is no previous non-local label. 118 | * // The rip-relative-offset of 0x00000056 is L0-address_of_next_instruction. 119 | * // address_of_next_instruction is the address of the relocation + 4. 120 | * 121 | * add $6,L0(%rip) 122 | * r_type=X86_64_RELOC_SIGNED_1, r_length=2, r_extern=0, r_pcrel=1, r_symbolnum=3 123 | * 83 05 18 00 00 00 06 124 | * // assumes L0 is in third section and there is no previous non-local label. 125 | * // The rip-relative-offset of 0x00000018 is L0-address_of_next_instruction. 126 | * // address_of_next_instruction is the address of the relocation + 4 + 1. 127 | * // The +1 comes from SIGNED_1. This is used because the relocation is not 128 | * // at the end of the instruction. 129 | * 130 | * .quad L1 131 | * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev 132 | * 12 00 00 00 00 00 00 00 133 | * // assumes _prev is the first non-local label 0x12 bytes before L1 134 | * 135 | * .quad L0 136 | * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=0, r_pcrel=0, r_symbolnum=3 137 | * 56 00 00 00 00 00 00 00 138 | * // assumes L0 is in third section, has an address of 0x00000056 in .o 139 | * // file, and there is no previous non-local label 140 | * 141 | * .quad _foo - . 142 | * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev 143 | * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo 144 | * EE FF FF FF FF FF FF FF 145 | * // assumes _prev is the first non-local label 0x12 bytes before this 146 | * // .quad 147 | * 148 | * .quad _foo - L1 149 | * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev 150 | * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo 151 | * EE FF FF FF FF FF FF FF 152 | * // assumes _prev is the first non-local label 0x12 bytes before L1 153 | * 154 | * .quad L1 - _prev 155 | * // No relocations. This is an assembly time constant. 156 | * 12 00 00 00 00 00 00 00 157 | * // assumes _prev is the first non-local label 0x12 bytes before L1 158 | * 159 | * 160 | * 161 | * In final linked images, there are only two valid relocation kinds: 162 | * 163 | * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_pcrel=0, r_extern=1, r_symbolnum=sym_index 164 | * This tells dyld to add the address of a symbol to a pointer sized (8-byte) 165 | * piece of data (i.e on disk the 8-byte piece of data contains the addend). The 166 | * r_symbolnum contains the index into the symbol table of the target symbol. 167 | * 168 | * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_pcrel=0, r_extern=0, r_symbolnum=0 169 | * This tells dyld to adjust the pointer sized (8-byte) piece of data by the amount 170 | * the containing image was loaded from its base address (e.g. slide). 171 | * 172 | */ 173 | enum reloc_type_x86_64 174 | { 175 | X86_64_RELOC_UNSIGNED, // for absolute addresses 176 | X86_64_RELOC_SIGNED, // for signed 32-bit displacement 177 | X86_64_RELOC_BRANCH, // a CALL/JMP instruction with 32-bit displacement 178 | X86_64_RELOC_GOT_LOAD, // a MOVQ load of a GOT entry 179 | X86_64_RELOC_GOT, // other GOT references 180 | X86_64_RELOC_SUBTRACTOR, // must be followed by a X86_64_RELOC_UNSIGNED 181 | X86_64_RELOC_SIGNED_1, // for signed 32-bit displacement with a -1 addend 182 | X86_64_RELOC_SIGNED_2, // for signed 32-bit displacement with a -2 addend 183 | X86_64_RELOC_SIGNED_4, // for signed 32-bit displacement with a -4 addend 184 | X86_64_RELOC_TLV, // for thread local variables 185 | }; 186 | -------------------------------------------------------------------------------- /toolchain/insert_dylib_to_binary: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import argparse 4 | import json 5 | import os 6 | import subprocess 7 | import sys 8 | import StringIO 9 | 10 | THIS_DIR = os.path.dirname(os.path.abspath(__file__)) 11 | ARCH_PREFIX = 'architecture ' 12 | COUNT_PREFIX = 'nfat_arch ' 13 | 14 | def is_fat(file_path): 15 | command = ['lipo', '-info', file_path] 16 | output = subprocess.check_output(command).strip() 17 | return output.find('Non-fat') == -1 18 | 19 | def get_all_architecture_for_fat_file(file_path): 20 | command = ['lipo', '-detailed_info', file_path] 21 | output = subprocess.check_output(command).strip() 22 | result = [] 23 | count = 0 24 | for line in output.split('\n'): 25 | if line.startswith(ARCH_PREFIX): 26 | result.append(line[len(ARCH_PREFIX):]) 27 | elif line.startswith(COUNT_PREFIX): 28 | count = int(line[len(COUNT_PREFIX):]) 29 | assert(count == len(result)) 30 | return result 31 | 32 | def insert_dylib_to_macho_and_get_fresh_dylib_name(file_path, dry_run): 33 | command = [os.path.join(THIS_DIR, 'insert_dylib_to_macho'), '--file', file_path] 34 | if dry_run: 35 | return "a.dylib" 36 | else: 37 | output = subprocess.check_output(command).strip() 38 | result = json.load(StringIO.StringIO(output)) 39 | assert(result["error"] == 0) 40 | return result["filename"] 41 | 42 | def insert_dylib_to_universal_and_get_fresh_dylib_names(file_path, temp_dir, dry_run): 43 | result = set() 44 | 45 | archs = get_all_architecture_for_fat_file(file_path) 46 | thin_file_paths = [os.path.join(temp_dir, arch) for arch in archs] 47 | 48 | # extract 49 | for arch, thin_file_path in zip(archs, thin_file_paths): 50 | command = ['lipo', file_path, '-thin', arch, '-output', thin_file_path] 51 | if not dry_run: 52 | subprocess.check_call(command) 53 | 54 | # insert 55 | for thin_file_path in thin_file_paths: 56 | dylib_name = insert_dylib_to_macho_and_get_fresh_dylib_name(thin_file_path, dry_run) 57 | result.add(dylib_name) 58 | 59 | # pack again 60 | command = ['lipo'] 61 | command.extend(thin_file_paths) 62 | command.extend(['-create', '-output', file_path]) 63 | if not dry_run: 64 | subprocess.check_call(command) 65 | 66 | return list(result) 67 | 68 | def main(): 69 | description = ''' insert a dylib command to a binary file, the file must be macho or fat. 70 | 71 | {self_name} --file /path/to/some/binary'''.format(self_name=sys.argv[0]) 72 | 73 | 74 | parser = argparse.ArgumentParser(description=description, formatter_class=argparse.RawDescriptionHelpFormatter,) 75 | parser.add_argument('--file', action='store', dest='file_path', required=True, help='full path for the binary file') 76 | parser.add_argument('--dry_run', action='store_true', help='dry run, only show the action command line') 77 | args = parser.parse_args() 78 | 79 | names = [] 80 | if not is_fat(args.file_path): 81 | names.append(insert_dylib_to_macho_and_get_fresh_dylib_name(args.file_path, args.dry_run)) 82 | else: 83 | temp_dir = os.path.join(THIS_DIR, 'temp') 84 | if not os.path.exists(temp_dir): 85 | os.makedirs(temp_dir) 86 | names = insert_dylib_to_universal_and_get_fresh_dylib_names(args.file_path, temp_dir, args.dry_run) 87 | 88 | assert(len(names) == 1) 89 | print names[0], 90 | 91 | if __name__ == '__main__': 92 | main() 93 | 94 | # vim: number list tabstop=2 shiftwidth=2 expandtab 95 | -------------------------------------------------------------------------------- /toolchain/insert_dylib_to_macho: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/intrude/94b5c06ea03cb93ffd62ebe20251956d0a74c4e2/toolchain/insert_dylib_to_macho --------------------------------------------------------------------------------